From 15a6cbd73f39804284c89ce4a75192bbc0a98435 Mon Sep 17 00:00:00 2001 From: muXxer Date: Thu, 31 Oct 2024 11:46:45 +0100 Subject: [PATCH] chore(execution): sync comments between `latest` and `v0` --- iota-execution/v0/iota-adapter/src/adapter.rs | 13 +++ .../v0/iota-adapter/src/execution_engine.rs | 90 +++++++++++++++++++ .../src/programmable_transactions/context.rs | 40 +++++++++ .../programmable_transactions/execution.rs | 58 ++++++++++++ .../programmable_transactions/linkage_view.rs | 21 +++++ 5 files changed, 222 insertions(+) diff --git a/iota-execution/v0/iota-adapter/src/adapter.rs b/iota-execution/v0/iota-adapter/src/adapter.rs index 1d29399cd18..295facc2e8f 100644 --- a/iota-execution/v0/iota-adapter/src/adapter.rs +++ b/iota-execution/v0/iota-adapter/src/adapter.rs @@ -36,6 +36,12 @@ mod checked { }; use tracing::instrument; + /// Creates a new instance of `MoveVM` with the specified native functions + /// and protocol configuration. The VM is configured using a `VMConfig` + /// that sets limits for vector length, value depth, and other + /// runtime options based on the provided `ProtocolConfig`. If gas profiling + /// is enabled, the function configures the profiler with the provided + /// path. pub fn new_move_vm( natives: NativeFunctionTable, protocol_config: &ProtocolConfig, @@ -71,6 +77,12 @@ mod checked { .map_err(|_| IotaError::ExecutionInvariantViolation) } + /// Creates a new set of `NativeContextExtensions` for the Move VM, + /// configuring extensions such as `ObjectRuntime` and + /// `NativesCostTable`. These extensions manage object resolution, input + /// objects, metering, protocol configuration, and metrics tracking. + /// They are available and mainly used in native function implementations + /// via `NativeContext` instance. pub fn new_native_extensions<'r>( child_resolver: &'r dyn ChildObjectResolver, input_objects: BTreeMap, @@ -127,6 +139,7 @@ mod checked { Ok(()) } + /// Returns an error message for a missing unwrapped object. pub fn missing_unwrapped_msg(id: &ObjectID) -> String { format!( "Unable to unwrap object {}. Was unable to retrieve last known version in the parent sync", diff --git a/iota-execution/v0/iota-adapter/src/execution_engine.rs b/iota-execution/v0/iota-adapter/src/execution_engine.rs index c4361c81a06..26353e36d0a 100644 --- a/iota-execution/v0/iota-adapter/src/execution_engine.rs +++ b/iota-execution/v0/iota-adapter/src/execution_engine.rs @@ -74,6 +74,17 @@ mod checked { type_layout_resolver::TypeLayoutResolver, }; + /// The main entry point to the adapter's transaction execution. It + /// prepares a transaction for execution, then executes it through an + /// inner execution method and finally produces an instance of + /// transaction effects. It also returns the inner temporary store, which + /// contains the objects resulting from the transction execution, the gas + /// status instance, which tracks the gas usage, and the execution result. + /// The function handles transaction execution based on the provided + /// `TransactionKind`. It checks for any expensive operations, manages + /// shared object references, and ensures transaction dependencies are + /// met. The returned objects are not committed to the store until the + /// resulting effects are applied by the caller. #[instrument(name = "tx_execute_to_effects", level = "debug", skip_all)] pub fn execute_transaction_to_effects( store: &dyn BackingStore, @@ -231,6 +242,12 @@ mod checked { ) } + /// Function dedicated to the execution of a GenesisTransaction. + /// The function creates an `InnerTemporaryStore`, processes the input + /// objects, and executes the transaction in unmetered mode using the + /// `Genesis` execution mode. It returns an inner temporary store that + /// contains the objects found into the input `GenesisTransaction` by + /// adding the data for `previous_transaction` and `storage_rebate` fields. pub fn execute_genesis_state_update( store: &dyn BackingStore, protocol_config: &ProtocolConfig, @@ -263,6 +280,14 @@ mod checked { Ok(temporary_store.into_inner()) } + /// Executes a transaction by processing the specified `TransactionKind`, + /// applying the necessary gas charges and running the main execution logic. + /// The function handles certain error conditions such as denied + /// certificate, deleted input objects, exceeded execution meter limits, + /// failed conservation checks. It also accounts for unmetered storage + /// rebates and adjusts for special cases like epoch change + /// transactions. Gas costs are managed through the `GasCharger` + /// argument; gas is also charged in case of errors. #[instrument(name = "tx_execute", level = "debug", skip_all)] fn execute_transaction( temporary_store: &mut TemporaryStore<'_>, @@ -387,6 +412,14 @@ mod checked { (cost_summary, result) } + /// Performs IOTA conservation checks during transaction execution, ensuring + /// that the transaction does not create or destroy IOTA. If + /// conservation is violated, the function attempts to recover + /// by resetting the gas charger, recharging gas, and rechecking + /// conservation. If recovery fails, it panics to avoid IOTA creation or + /// destruction. These checks include both simple and expensive + /// checks based on the configuration and are skipped for genesis or epoch + /// change transactions. #[instrument(name = "run_conservation_checks", level = "debug", skip_all)] fn run_conservation_checks( temporary_store: &mut TemporaryStore<'_>, @@ -465,6 +498,10 @@ mod checked { result } + /// Checks if the estimated size of transaction effects exceeds predefined + /// limits based on the protocol configuration. For metered + /// transactions, it enforces hard limits, while for system transactions, it + /// allows soft limits with warnings. #[instrument(name = "check_meter_limit", level = "debug", skip_all)] fn check_meter_limit( temporary_store: &mut TemporaryStore<'_>, @@ -504,6 +541,10 @@ mod checked { } } + /// Checks if the total size of written objects in the transaction exceeds + /// the limits defined in the protocol configuration. For metered + /// transactions, it enforces a hard limit, while for system transactions, + /// it allows a soft limit with warnings. #[instrument(name = "check_written_objects_limit", level = "debug", skip_all)] fn check_written_objects_limit( temporary_store: &mut TemporaryStore<'_>, @@ -547,6 +588,12 @@ mod checked { Ok(()) } + /// Executes the given transaction based on its `TransactionKind` by + /// processing it through corresponding handlers such as epoch changes, + /// genesis transactions, consensus commit prologues, and programmable + /// transactions. For each type of transaction, the corresponding logic is + /// invoked, such as advancing the epoch, setting up consensus commits, or + /// executing a programmable transaction. #[instrument(level = "debug", skip_all)] fn execution_loop( temporary_store: &mut TemporaryStore<'_>, @@ -684,6 +731,14 @@ mod checked { Ok(result) } + /// Mints epoch rewards by creating both storage and computation rewards + /// using a `ProgrammableTransactionBuilder`. The function takes in the + /// `AdvanceEpochParams`, serializes the storage and computation + /// charges, and invokes the reward creation function within the Iota + /// Prepares invocations for creating both storage and computation rewards + /// with a `ProgrammableTransactionBuilder` using the `AdvanceEpochParams`. + /// The corresponding functions from the Iota framework can be invoked later + /// during execution of the programmable transaction. fn mint_epoch_rewards_in_pt( builder: &mut ProgrammableTransactionBuilder, params: &AdvanceEpochParams, @@ -718,6 +773,13 @@ mod checked { (storage_charges, computation_rewards) } + /// Constructs a `ProgrammableTransaction` to advance the epoch. It creates + /// storage charges and computation rewards by invoking + /// `mint_epoch_rewards_in_pt`, advances the epoch by setting up the + /// necessary arguments, such as epoch number, protocol version, storage + /// rebate, and slashing rate, and executing the `advance_epoch` function + /// within the Iota system. Then, it destroys the storage rebates to + /// complete the transaction. pub fn construct_advance_epoch_pt( mut builder: ProgrammableTransactionBuilder, params: &AdvanceEpochParams, @@ -774,6 +836,13 @@ mod checked { Ok(builder.finish()) } + /// Advances the epoch by constructing a `ProgrammableTransaction` with + /// `construct_advance_epoch_pt` and executing it. + /// If the transaction fails, it switches to safe mode and retries the + /// epoch advancement in a more controlled environment. The function also + /// handles the publication and upgrade of system packages for the new + /// epoch. If any system package is added or upgraded, it ensures the + /// proper execution and storage of the changes. fn advance_epoch( builder: ProgrammableTransactionBuilder, change_epoch: ChangeEpoch, @@ -949,6 +1018,9 @@ mod checked { ) } + /// This function adds a Move call to the Iota framework's + /// `authenticator_state_create` function, preparing the transaction for + /// execution. fn setup_authenticator_state_create( mut builder: ProgrammableTransactionBuilder, ) -> ProgrammableTransactionBuilder { @@ -964,6 +1036,7 @@ mod checked { builder } + /// Configures a `ProgrammableTransactionBuilder` to create a bridge. fn setup_bridge_create( mut builder: ProgrammableTransactionBuilder, chain_id: ChainIdentifier, @@ -994,6 +1067,8 @@ mod checked { builder } + /// Configures a `ProgrammableTransactionBuilder` to update the bridge + /// committee. fn setup_bridge_committee_update( mut builder: ProgrammableTransactionBuilder, bridge_shared_version: SequenceNumber, @@ -1035,6 +1110,12 @@ mod checked { builder } + /// Sets up and executes a `ProgrammableTransaction` to update the + /// authenticator state. This function constructs a transaction that + /// invokes the `authenticator_state_update` function from the Iota + /// framework, passing the authenticator state object and new active JWKS as + /// arguments. It then executes the transaction using the system + /// execution mode. fn setup_authenticator_state_update( update: AuthenticatorStateUpdateV1, temporary_store: &mut TemporaryStore<'_>, @@ -1077,6 +1158,10 @@ mod checked { ) } + /// Configures a `ProgrammableTransactionBuilder` to expire authenticator + /// state by invoking the `authenticator_state_expire_jwks` function + /// from the Iota framework. The function adds the necessary Move call + /// with the authenticator state object and the minimum epoch as arguments. fn setup_authenticator_state_expire( mut builder: ProgrammableTransactionBuilder, expire: AuthenticatorStateExpire, @@ -1100,6 +1185,11 @@ mod checked { builder } + /// The function constructs a transaction that invokes + /// the `randomness_state_update` function from the Iota framework, + /// passing the randomness state object, the `randomness_round`, + /// and the `random_bytes` as arguments. It then executes the transaction + /// using the system execution mode. fn setup_randomness_state_update( update: RandomnessStateUpdate, temporary_store: &mut TemporaryStore<'_>, diff --git a/iota-execution/v0/iota-adapter/src/programmable_transactions/context.rs b/iota-execution/v0/iota-adapter/src/programmable_transactions/context.rs index f5c630c28ec..3881633441a 100644 --- a/iota-execution/v0/iota-adapter/src/programmable_transactions/context.rs +++ b/iota-execution/v0/iota-adapter/src/programmable_transactions/context.rs @@ -118,6 +118,12 @@ mod checked { } impl<'vm, 'state, 'a> ExecutionContext<'vm, 'state, 'a> { + /// Creates a new instance of the transaction execution context, + /// initializing the necessary components such as protocol + /// configuration, Move VM, gas management, inputs, and native + /// extensions. This function processes the input arguments, sets up gas + /// handling for the transaction, and prepares the state for + /// executing Move programs. #[instrument(name = "ExecutionContext::new", level = "trace", skip_all)] pub fn new( protocol_config: &'a ProtocolConfig, @@ -381,6 +387,7 @@ mod checked { ) { return Err(CommandArgumentError::InvalidObjectByValue); } + // Any input object taken by value must be mutable if matches!( input_metadata_opt, @@ -940,6 +947,10 @@ mod checked { Ok((metadata, &mut result_value.value)) } + /// Executes a Move function bypassing visibility checks, allowing the + /// execution of private or protected functions. This method + /// sets up the necessary gas status and data store, and then + /// delegates the execution to the Move VM runtime. pub(crate) fn execute_function_bypass_visibility( &mut self, module: &ModuleId, @@ -960,6 +971,10 @@ mod checked { ) } + /// Loads a Move function from the specified module with the given type + /// arguments without executing it. This function initializes + /// the data store and delegates the loading process to the Move + /// VM runtime. pub(crate) fn load_function( &mut self, module_id: &ModuleId, @@ -975,6 +990,10 @@ mod checked { ) } + /// Constructs an `ObjectValue` based on the provided Move object type, + /// transferability, usage context, and byte contents. This + /// function utilizes the protocol configuration, Move VM, and + /// linkage view to properly interpret and instantiate the object. pub(crate) fn make_object_value( &mut self, type_: MoveObjectType, @@ -991,6 +1010,10 @@ mod checked { ) } + /// Publishes a bundle of Move modules to the blockchain under the + /// specified sender's account address. The function initializes + /// a data store and delegates the publishing operation to the Move VM + /// runtime. pub fn publish_module_bundle( &mut self, modules: Vec>, @@ -1009,6 +1032,8 @@ mod checked { } impl<'vm, 'state, 'a> TypeTagResolver for ExecutionContext<'vm, 'state, 'a> { + /// Retrieves the `TypeTag` corresponding to the provided `Type` by + /// querying the Move VM runtime. fn get_type_tag(&self, type_: &Type) -> Result { self.vm .get_runtime() @@ -1040,6 +1065,11 @@ mod checked { } } + /// Loads a `Type` from the given `StructTag`, retrieving the corresponding + /// struct from the package in storage. The function sets up the linkage + /// context to resolve the struct's module and verifies + /// any type parameter constraints. If the struct has type parameters, they + /// are recursively loaded and verified. pub fn load_type_from_struct( vm: &MoveVM, linkage_view: &mut LinkageView, @@ -1135,6 +1165,12 @@ mod checked { }) } + /// Constructs an `ObjectValue` based on the provided `MoveObjectType`, + /// contents, and additional flags such as transferability and usage + /// context. If the object is a coin, it deserializes the contents into + /// a `Coin` type; otherwise, it treats the contents as raw data. The + /// function then loads the corresponding struct type from the Move + /// package and verifies its abilities if needed. pub(crate) fn make_object_value( vm: &MoveVM, linkage_view: &mut LinkageView, @@ -1168,6 +1204,10 @@ mod checked { }) } + /// Converts a provided `Object` into an `ObjectValue`, extracting and + /// validating the `MoveObjectType` and contents. This function assumes + /// the object contains Move-specific data and passes the extracted data + /// through `make_object_value` to create the corresponding `ObjectValue`. pub(crate) fn value_from_object( vm: &MoveVM, linkage_view: &mut LinkageView, diff --git a/iota-execution/v0/iota-adapter/src/programmable_transactions/execution.rs b/iota-execution/v0/iota-adapter/src/programmable_transactions/execution.rs index cccc62f4eed..cc70099dc59 100644 --- a/iota-execution/v0/iota-adapter/src/programmable_transactions/execution.rs +++ b/iota-execution/v0/iota-adapter/src/programmable_transactions/execution.rs @@ -71,6 +71,13 @@ mod checked { programmable_transactions::context::*, }; + /// Executes a `ProgrammableTransaction` in the specified `ExecutionMode`, + /// applying a series of commands to the execution context. The + /// function initializes the execution context, processes each command + /// in sequence, and handles errors by recording any loaded runtime objects + /// before exiting. After successful command execution, it applies the + /// resulting changes, saving the loaded runtime objects and wrapped + /// object containers for later use. pub fn execute( protocol_config: &ProtocolConfig, metrics: Arc, @@ -408,6 +415,11 @@ mod checked { res } + /// Writes back the results of an execution, updating mutable references and + /// processing return values. This function iterates through mutable + /// reference values and their corresponding kinds, restoring them to + /// the execution context. It also processes return values for non-entry + /// Move calls by converting them into `Value` types. fn write_back_results( context: &mut ExecutionContext<'_, '_, '_>, argument_updates: &mut Mode::ArgumentUpdates, @@ -438,6 +450,12 @@ mod checked { .collect() } + /// Constructs a `Value` from the given `ValueKind` and byte data. Depending + /// on the kind, it either creates an `Object` or `Raw` value. For + /// `Object` types, it uses the execution context to generate an + /// `ObjectValue`, considering whether the object was used in a non-entry + /// Move call. For `Raw` types, it wraps the raw bytes with type and ability + /// information. fn make_value( context: &mut ExecutionContext<'_, '_, '_>, value_info: ValueKind, @@ -635,6 +653,11 @@ mod checked { )]) } + /// Checks the compatibility between an existing Move package and the new + /// upgrading modules based on the specified upgrade policy. The + /// function first validates the upgrade policy, then normalizes the + /// existing and new modules to compare them. For each module, it verifies + /// compatibility according to the policy. fn check_compatibility<'a>( context: &ExecutionContext, existing_package: &MovePackage, @@ -672,6 +695,11 @@ mod checked { Ok(()) } + /// Verifies the compatibility of two normalized Move modules based on the + /// specified upgrade policy. Depending on the policy, it checks if the + /// new module is a subset, equal, or compatible with the + /// current module. The compatibility check may include aspects like struct + /// layout, public function linking, and struct type parameters. fn check_module_compatibility( policy: &UpgradePolicy, cur_module: &normalized::Module, @@ -705,6 +733,10 @@ mod checked { }) } + /// Retrieves a `PackageObject` from the storage based on the provided + /// `package_id`. It ensures that exactly one package is fetched, + /// returning an invariant violation if the number of fetched packages + /// does not match the expected count. fn fetch_package( context: &ExecutionContext<'_, '_, '_>, package_id: &ObjectID, @@ -722,6 +754,9 @@ mod checked { } } + /// Fetches a list of `PackageObject` instances based on the provided + /// package IDs from the execution context. It collects the package IDs + /// and attempts to retrieve the corresponding packages from the state view. fn fetch_packages<'ctx, 'vm, 'state, 'a>( context: &'ctx ExecutionContext<'vm, 'state, 'a>, package_ids: impl IntoIterator, @@ -755,6 +790,11 @@ mod checked { /// ************************************************************************ /// **** ******************* + /// Executes a Move function within the given module by invoking the Move + /// VM, passing the specified type arguments and serialized arguments. + /// Depending on the `TxContextKind`, the transaction context + /// is appended to the arguments. The function handles mutable updates to + /// the transaction context when objects are created during execution. fn vm_move_call( context: &mut ExecutionContext<'_, '_, '_>, module_id: &ModuleId, @@ -800,6 +840,10 @@ mod checked { Ok(result) } + /// Deserializes a list of binary-encoded Move modules into `CompiledModule` + /// instances using the protocol's binary configuration. The function + /// ensures that the module list is not empty and converts any + /// deserialization errors into an `ExecutionError`. #[allow(clippy::extra_unused_type_parameters)] fn deserialize_modules( context: &mut ExecutionContext<'_, '_, '_>, @@ -823,6 +867,11 @@ mod checked { Ok(modules) } + /// Publishes a set of `CompiledModule` instances to the blockchain under + /// the specified package ID and verifies them using the Iota bytecode + /// verifier. The modules are serialized and published via the VM, + /// and the Iota verifier runs additional checks after the Move bytecode + /// verifier has passed. fn publish_and_verify_modules( context: &mut ExecutionContext<'_, '_, '_>, package_id: ObjectID, @@ -857,6 +906,11 @@ mod checked { Ok(()) } + /// Initializes the provided `CompiledModule` instances by searching for and + /// executing any functions named `INIT_FN_NAME`. For each module + /// containing an initialization function, the function is invoked + /// without arguments, and the result is checked to ensure no return values + /// are present. fn init_modules( context: &mut ExecutionContext<'_, '_, '_>, argument_updates: &mut Mode::ArgumentUpdates, @@ -1126,6 +1180,10 @@ mod checked { .collect() } + /// Verifies that certain private functions in the Iota framework are not + /// directly invoked. This function checks if the module and function + /// being called belong to restricted areas, such as the `iota::event` + /// or `iota::transfer` modules. fn check_private_generics( _context: &mut ExecutionContext, module_id: &ModuleId, diff --git a/iota-execution/v0/iota-adapter/src/programmable_transactions/linkage_view.rs b/iota-execution/v0/iota-adapter/src/programmable_transactions/linkage_view.rs index fe0bcc57d57..40a0270c3fe 100644 --- a/iota-execution/v0/iota-adapter/src/programmable_transactions/linkage_view.rs +++ b/iota-execution/v0/iota-adapter/src/programmable_transactions/linkage_view.rs @@ -58,6 +58,10 @@ pub struct LinkageInfo { pub struct SavedLinkage(LinkageInfo); impl<'state> LinkageView<'state> { + /// Creates a new `LinkageView` instance with the provided `IotaResolver`. + /// This instance is responsible for resolving and linking types across + /// different contexts. It initializes internal caches for type origins + /// and past contexts. pub fn new(resolver: Box) -> Self { Self { resolver, @@ -67,6 +71,7 @@ impl<'state> LinkageView<'state> { } } + /// Reset the `LinkageInfo`. pub fn reset_linkage(&mut self) { self.linkage_info = None; } @@ -151,10 +156,16 @@ impl<'state> LinkageView<'state> { Ok(runtime_id) } + /// Retrieves the original package ID (as an `AccountAddress`) from the + /// linkage information, if available. pub fn original_package_id(&self) -> Option { Some(self.linkage_info.as_ref()?.runtime_id) } + /// Retrieves the cached type origin for the given `ModuleId` and struct + /// identifier (`IdentStr`). This method uses the internal + /// `type_origin_cache` to provide fast lookups for previously resolved + /// types. fn get_cached_type_origin( &self, runtime_id: &ModuleId, @@ -167,6 +178,8 @@ impl<'state> LinkageView<'state> { .cloned() } + /// Adds a type origin to the cache, associating the given `ModuleId` and + /// struct identifier (`Identifier`) with the provided defining `ObjectID`. fn add_type_origin( &self, runtime_id: ModuleId, @@ -197,12 +210,14 @@ impl<'state> LinkageView<'state> { Ok(()) } + /// Retrieves the current link context's storage ID as an `AccountAddress`. pub(crate) fn link_context(&self) -> AccountAddress { self.linkage_info .as_ref() .map_or(AccountAddress::ZERO, |l| l.storage_id) } + /// Relocates a given `ModuleId` based on the current linkage context. pub(crate) fn relocate(&self, module_id: &ModuleId) -> Result { let Some(linkage) = &self.linkage_info else { invariant_violation!("No linkage context set while relocating {module_id}.") @@ -233,6 +248,12 @@ impl<'state> LinkageView<'state> { )) } + /// Determines the defining module for a given struct within a `ModuleId`. + /// The function first checks the cached type origin and returns the + /// corresponding `ModuleId` if found. If not, it relocates the + /// module and queries the type origin table from the associated package. If + /// the defining module is found, it caches the result and returns the + /// `ModuleId`. pub(crate) fn defining_module( &self, runtime_id: &ModuleId,