Skip to content

Commit

Permalink
test, rename to interrupt requested
Browse files Browse the repository at this point in the history
  • Loading branch information
gelash committed Jan 17, 2025
1 parent 60262d9 commit 10c8281
Show file tree
Hide file tree
Showing 14 changed files with 157 additions and 23 deletions.
37 changes: 31 additions & 6 deletions aptos-move/aptos-gas-meter/src/algebra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use crate::traits::GasAlgebra;
use aptos_gas_algebra::{Fee, FeePerGasUnit, Gas, GasExpression, NumBytes, NumModules, Octa};
use aptos_gas_schedule::{gas_feature_versions, VMGasParameters};
use aptos_logger::error;
use aptos_vm_types::storage::{
io_pricing::IoPricing, space_pricing::DiskSpacePricing, StorageGasParameters,
use aptos_vm_types::{
resolver::BlockSynchronizationKillSwitch,
storage::{io_pricing::IoPricing, space_pricing::DiskSpacePricing, StorageGasParameters},
};
use move_binary_format::errors::{PartialVMError, PartialVMResult};
use move_core_types::{
Expand All @@ -18,7 +19,7 @@ use std::fmt::Debug;
/// Base gas algebra implementation that tracks the gas usage using its internal counters.
///
/// Abstract gas amounts are always evaluated to concrete values at the spot.
pub struct StandardGasAlgebra {
pub struct StandardGasAlgebra<'a> {
feature_version: u64,
vm_gas_params: VMGasParameters,
storage_gas_params: StorageGasParameters,
Expand All @@ -40,15 +41,18 @@ pub struct StandardGasAlgebra {

num_dependencies: NumModules,
total_dependency_size: NumBytes,

maybe_block_synchronization_view: Option<&'a dyn BlockSynchronizationKillSwitch>,
}

impl StandardGasAlgebra {
impl<'a> StandardGasAlgebra<'a> {
pub fn new(
gas_feature_version: u64,
vm_gas_params: VMGasParameters,
storage_gas_params: StorageGasParameters,
is_approved_gov_script: bool,
balance: impl Into<Gas>,
maybe_block_synchronization_view: Option<&'a dyn BlockSynchronizationKillSwitch>,
) -> Self {
let balance = balance.into().to_unit_with_params(&vm_gas_params.txn);

Expand Down Expand Up @@ -83,11 +87,12 @@ impl StandardGasAlgebra {
storage_fee_used: 0.into(),
num_dependencies: 0.into(),
total_dependency_size: 0.into(),
maybe_block_synchronization_view,
}
}
}

impl StandardGasAlgebra {
impl StandardGasAlgebra<'_> {
fn charge(&mut self, amount: InternalGas) -> (InternalGas, PartialVMResult<()>) {
match self.balance.checked_sub(amount) {
Some(new_balance) => {
Expand All @@ -106,7 +111,7 @@ impl StandardGasAlgebra {
}
}

impl GasAlgebra for StandardGasAlgebra {
impl GasAlgebra for StandardGasAlgebra<'_> {
fn feature_version(&self) -> u64 {
self.feature_version
}
Expand Down Expand Up @@ -165,6 +170,16 @@ impl GasAlgebra for StandardGasAlgebra {
&mut self,
abstract_amount: impl GasExpression<VMGasParameters, Unit = InternalGasUnit> + Debug,
) -> PartialVMResult<()> {
if self
.maybe_block_synchronization_view
.is_some_and(|view| view.interrupt_requested())
{
return Err(
PartialVMError::new(StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR)
.with_message("Interrupted from block synchronization view".to_string()),
);
}

let amount = abstract_amount.evaluate(self.feature_version, &self.vm_gas_params);

let (actual, res) = self.charge(amount);
Expand All @@ -187,6 +202,16 @@ impl GasAlgebra for StandardGasAlgebra {
&mut self,
abstract_amount: impl GasExpression<VMGasParameters, Unit = InternalGasUnit>,
) -> PartialVMResult<()> {
if self
.maybe_block_synchronization_view
.is_some_and(|view| view.interrupt_requested())
{
return Err(
PartialVMError::new(StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR)
.with_message("Interrupted from block synchronization view".to_string()),
);
}

let amount = abstract_amount.evaluate(self.feature_version, &self.vm_gas_params);

let (actual, res) = self.charge(amount);
Expand Down
22 changes: 20 additions & 2 deletions aptos-move/aptos-vm-types/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ use move_core_types::{language_storage::StructTag, value::MoveTypeLayout, vm_sta
use move_vm_types::delayed_values::delayed_field_id::DelayedFieldID;
use std::collections::{BTreeMap, HashMap};

/// Allows requesting an immediate interrupt to ongoing transaction execution. For example, this
/// allows an early return from a useless speculative execution when block execution has already
/// halted (e.g. due to gas limit, committing only a block prefix).
pub trait BlockSynchronizationKillSwitch {
fn interrupt_requested(&self) -> bool;
}

/// Allows to query resources from the state.
pub trait TResourceView {
type Key;
Expand Down Expand Up @@ -204,7 +211,8 @@ pub trait StateStorageView {
/// resolve AggregatorV2 via the state-view based default implementation, as it
/// doesn't provide a value exchange functionality).
pub trait TExecutorView<K, T, L, V>:
TResourceView<Key = K, Layout = L>
BlockSynchronizationKillSwitch
+ TResourceView<Key = K, Layout = L>
+ TModuleView<Key = K>
+ TAggregatorV1View<Identifier = K>
+ TDelayedFieldView<Identifier = DelayedFieldID, ResourceKey = K, ResourceGroupTag = T>
Expand All @@ -213,7 +221,8 @@ pub trait TExecutorView<K, T, L, V>:
}

impl<A, K, T, L, V> TExecutorView<K, T, L, V> for A where
A: TResourceView<Key = K, Layout = L>
A: BlockSynchronizationKillSwitch
+ TResourceView<Key = K, Layout = L>
+ TModuleView<Key = K>
+ TAggregatorV1View<Identifier = K>
+ TDelayedFieldView<Identifier = DelayedFieldID, ResourceKey = K, ResourceGroupTag = T>
Expand Down Expand Up @@ -293,6 +302,15 @@ where
}
}

impl<S> BlockSynchronizationKillSwitch for S
where
S: StateView,
{
fn interrupt_requested(&self) -> bool {
false
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ResourceGroupSize {
Concrete(u64),
Expand Down
27 changes: 19 additions & 8 deletions aptos-move/aptos-vm/src/aptos_vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ use aptos_vm_types::{
},
module_write_set::ModuleWriteSet,
output::VMOutput,
resolver::{ExecutorView, ResourceGroupView},
resolver::{BlockSynchronizationKillSwitch, ExecutorView, ResourceGroupView},
storage::{change_set_configs::ChangeSetConfigs, StorageGasParameters},
};
use ark_bn254::Bn254;
Expand Down Expand Up @@ -2038,17 +2038,24 @@ impl AptosVM {

/// Main entrypoint for executing a user transaction that also allows the customization of the
/// gas meter to be used.
pub fn execute_user_transaction_with_custom_gas_meter<G, F>(
pub fn execute_user_transaction_with_custom_gas_meter<'a, G, F>(
&self,
resolver: &impl AptosMoveResolver,
resolver: &'a impl AptosMoveResolver,
code_storage: &impl AptosCodeStorage,
txn: &SignedTransaction,
log_context: &AdapterLogSchema,
make_gas_meter: F,
) -> Result<(VMStatus, VMOutput, G), VMStatus>
where
G: AptosGasMeter,
F: FnOnce(u64, VMGasParameters, StorageGasParameters, bool, Gas) -> G,
F: FnOnce(
u64,
VMGasParameters,
StorageGasParameters,
bool,
Gas,
Option<&'a dyn BlockSynchronizationKillSwitch>,
) -> G,
{
let txn_metadata = TransactionMetadata::new(txn);

Expand All @@ -2061,6 +2068,7 @@ impl AptosVM {
self.storage_gas_params(log_context)?.clone(),
is_approved_gov_script,
balance,
Some(resolver.as_block_synchronization_kill_switch()),
);
let (status, output) = self.execute_user_transaction_impl(
resolver,
Expand All @@ -2080,16 +2088,16 @@ impl AptosVM {
///
/// This can be useful for off-chain applications that wants to perform additional
/// measurements or analysis while preserving the production gas behavior.
pub fn execute_user_transaction_with_modified_gas_meter<G, F>(
pub fn execute_user_transaction_with_modified_gas_meter<'a, G, F>(
&self,
resolver: &impl AptosMoveResolver,
resolver: &'a impl AptosMoveResolver,
code_storage: &impl AptosCodeStorage,
txn: &SignedTransaction,
log_context: &AdapterLogSchema,
modify_gas_meter: F,
) -> Result<(VMStatus, VMOutput, G), VMStatus>
where
F: FnOnce(ProdGasMeter) -> G,
F: FnOnce(ProdGasMeter<'a>) -> G,
G: AptosGasMeter,
{
self.execute_user_transaction_with_custom_gas_meter(
Expand All @@ -2101,13 +2109,15 @@ impl AptosVM {
vm_gas_params,
storage_gas_params,
is_approved_gov_script,
meter_balance| {
meter_balance,
_maybe_block_synchronization_kill_switch| {
modify_gas_meter(make_prod_gas_meter(
gas_feature_version,
vm_gas_params,
storage_gas_params,
is_approved_gov_script,
meter_balance,
None, // No block synchronization kill switch
))
},
)
Expand Down Expand Up @@ -2478,6 +2488,7 @@ impl AptosVM {
storage_gas_params,
/* is_approved_gov_script */ false,
max_gas_amount.into(),
None, // No block synchronization kill switch
);

let resolver = state_view.as_move_resolver();
Expand Down
7 changes: 6 additions & 1 deletion aptos-move/aptos-vm/src/data_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ use aptos_vm_environment::{
};
use aptos_vm_types::{
resolver::{
ExecutorView, ResourceGroupSize, ResourceGroupView, StateStorageView, TResourceGroupView,
BlockSynchronizationKillSwitch, ExecutorView, ResourceGroupSize, ResourceGroupView,
StateStorageView, TResourceGroupView,
},
resource_group_adapter::ResourceGroupAdapter,
};
Expand Down Expand Up @@ -332,6 +333,10 @@ impl<'e, E: ExecutorView> AsExecutorView for StorageAdapter<'e, E> {
fn as_executor_view(&self) -> &dyn ExecutorView {
self.executor_view
}

fn as_block_synchronization_kill_switch(&self) -> &dyn BlockSynchronizationKillSwitch {
self.executor_view
}
}

// Allows to extract the view from `StorageAdapter`.
Expand Down
9 changes: 7 additions & 2 deletions aptos-move/aptos-vm/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ use aptos_logger::{enabled, Level};
use aptos_memory_usage_tracker::MemoryTrackedGasMeter;
use aptos_types::on_chain_config::Features;
use aptos_vm_logging::{log_schema::AdapterLogSchema, speculative_log, speculative_warn};
use aptos_vm_types::storage::{space_pricing::DiskSpacePricing, StorageGasParameters};
use aptos_vm_types::{
resolver::BlockSynchronizationKillSwitch,
storage::{space_pricing::DiskSpacePricing, StorageGasParameters},
};
use move_core_types::vm_status::{StatusCode, VMStatus};
use move_vm_runtime::ModuleStorage;

/// This is used until gas version 18, which introduces a configurable entry for this.
const MAXIMUM_APPROVED_TRANSACTION_SIZE_LEGACY: u64 = 1024 * 1024;

/// Gas meter used in the production (validator) setup.
pub type ProdGasMeter = MemoryTrackedGasMeter<StandardGasMeter<StandardGasAlgebra>>;
pub type ProdGasMeter<'a> = MemoryTrackedGasMeter<StandardGasMeter<StandardGasAlgebra<'a>>>;

/// Creates a gas meter intended for executing transactions in the production.
///
Expand All @@ -31,13 +34,15 @@ pub fn make_prod_gas_meter(
storage_gas_params: StorageGasParameters,
is_approved_gov_script: bool,
meter_balance: Gas,
maybe_block_synchronization_kill_switch: Option<&dyn BlockSynchronizationKillSwitch>,
) -> ProdGasMeter {
MemoryTrackedGasMeter::new(StandardGasMeter::new(StandardGasAlgebra::new(
gas_feature_version,
vm_gas_params,
storage_gas_params,
is_approved_gov_script,
meter_balance,
maybe_block_synchronization_kill_switch,
)))
}

Expand Down
6 changes: 5 additions & 1 deletion aptos-move/aptos-vm/src/move_vm_ext/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use aptos_aggregator::resolver::{AggregatorV1Resolver, DelayedFieldResolver};
use aptos_table_natives::TableResolver;
use aptos_types::{on_chain_config::ConfigStorage, state_store::state_key::StateKey};
use aptos_vm_types::resolver::{
ExecutorView, ResourceGroupSize, ResourceGroupView, StateStorageView,
BlockSynchronizationKillSwitch, ExecutorView, ResourceGroupSize, ResourceGroupView,
StateStorageView,
};
use bytes::Bytes;
use move_binary_format::errors::PartialVMResult;
Expand Down Expand Up @@ -51,6 +52,9 @@ pub trait ResourceGroupResolver {

pub trait AsExecutorView {
fn as_executor_view(&self) -> &dyn ExecutorView;

// TODO: remove once trait upcasting coercion is stabilized (rust issue #65991).
fn as_block_synchronization_kill_switch(&self) -> &dyn BlockSynchronizationKillSwitch;
}

pub trait AsResourceGroupView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use aptos_vm_types::{
abstract_write_op::{AbstractResourceWriteOp, WriteWithDelayedFieldsOp},
change_set::{randomly_check_layout_matches, VMChangeSet},
resolver::{
ExecutorView, ResourceGroupSize, ResourceGroupView, StateStorageView, TModuleView,
TResourceGroupView, TResourceView,
BlockSynchronizationKillSwitch, ExecutorView, ResourceGroupSize, ResourceGroupView,
StateStorageView, TModuleView, TResourceGroupView, TResourceView,
},
};
use bytes::Bytes;
Expand Down Expand Up @@ -176,6 +176,12 @@ impl<'r> TDelayedFieldView for ExecutorViewWithChangeSet<'r> {
}
}

impl<'r> BlockSynchronizationKillSwitch for ExecutorViewWithChangeSet<'r> {
fn interrupt_requested(&self) -> bool {
self.base_executor_view.interrupt_requested()
}
}

impl<'r> TResourceView for ExecutorViewWithChangeSet<'r> {
type Key = StateKey;
type Layout = MoveTypeLayout;
Expand Down
1 change: 1 addition & 0 deletions aptos-move/aptos-vm/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ impl AptosVM {
storage_gas_params,
false,
gas_meter_balance.into(),
None,
);

let change_set_configs = &self
Expand Down
1 change: 1 addition & 0 deletions aptos-move/block-executor/src/proptest_types/baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ impl<K: Debug + Hash + Clone + Eq> BaselineOutput<K> {
},
}
},
MockTransaction::InterruptRequested => unreachable!("Not tested with outputs"),
}
}

Expand Down
8 changes: 8 additions & 0 deletions aptos-move/block-executor/src/proptest_types/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ impl<K, E> MockIncarnation<K, E> {
/// value determines the index for choosing the read & write sets of the particular execution.
#[derive(Clone, Debug)]
pub(crate) enum MockTransaction<K, E> {
InterruptRequested,
Write {
/// Incarnation counter, increased during each mock (re-)execution. Allows tracking the final
/// incarnation for each mock transaction, whose behavior should be reproduced for baseline.
Expand Down Expand Up @@ -430,6 +431,9 @@ impl<K, E> MockTransaction<K, E> {
} => incarnation_behaviors,
Self::SkipRest(_) => unreachable!("SkipRest does not contain incarnation behaviors"),
Self::Abort => unreachable!("Abort does not contain incarnation behaviors"),
Self::InterruptRequested => {
unreachable!("InterruptRequested does not contain incarnation behaviors")
},
}
}
}
Expand Down Expand Up @@ -1038,6 +1042,10 @@ where
ExecutionStatus::SkipRest(mock_output)
},
MockTransaction::Abort => ExecutionStatus::Abort(txn_idx as usize),
MockTransaction::InterruptRequested => {
while !view.interrupt_requested() {}
ExecutionStatus::SkipRest(MockOutput::skip_output())
},
}
}

Expand Down
4 changes: 4 additions & 0 deletions aptos-move/block-executor/src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,10 @@ impl Scheduler {

!self.has_halted.swap(true, Ordering::SeqCst)
}

pub(crate) fn has_halted(&self) -> bool {
self.has_halted.load(Ordering::Relaxed)
}
}

impl TWaitForDependency for Scheduler {
Expand Down
Loading

0 comments on commit 10c8281

Please sign in to comment.