diff --git a/Cargo.lock b/Cargo.lock index 0f59cde091..3209d8390b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12162,6 +12162,7 @@ dependencies = [ "move-resource-viewer", "move-table-extension", "move-transactional-test-runner", + "move-vm-types", "once_cell", "serde", "serde_json", @@ -12355,6 +12356,7 @@ dependencies = [ "serde_bytes", "starcoin-config", "starcoin-crypto", + "starcoin-framework 0.1.0", "starcoin-frameworks", "starcoin-gas-algebra", "starcoin-gas-meter", diff --git a/executor/tests/readonly_function_call_test.rs b/executor/tests/readonly_function_call_test.rs index 3e72355ede..076699c557 100644 --- a/executor/tests/readonly_function_call_test.rs +++ b/executor/tests/readonly_function_call_test.rs @@ -134,7 +134,7 @@ fn test_readonly_function_call() -> Result<()> { .map_err(|err| { assert_eq!( err.downcast::().unwrap(), - VMStatus::Error(StatusCode::REJECTED_WRITE_SET) + VMStatus::error(StatusCode::REJECTED_WRITE_SET, None) ); }); diff --git a/vm/starcoin-transactional-test-harness/Cargo.toml b/vm/starcoin-transactional-test-harness/Cargo.toml index fef9a2591d..63dcdf341b 100644 --- a/vm/starcoin-transactional-test-harness/Cargo.toml +++ b/vm/starcoin-transactional-test-harness/Cargo.toml @@ -27,6 +27,7 @@ move-binary-format = { workspace = true } move-command-line-common = { workspace = true } move-compiler = { workspace = true } move-core-types = { workspace = true } +move-vm-types = { workspace = true } move-transactional-test-runner = { workspace = true } move-table-extension = { workspace = true } once_cell = { workspace = true } diff --git a/vm/starcoin-transactional-test-harness/src/remote_state.rs b/vm/starcoin-transactional-test-harness/src/remote_state.rs index dca6b555f1..eb2ebbe008 100644 --- a/vm/starcoin-transactional-test-harness/src/remote_state.rs +++ b/vm/starcoin-transactional-test-harness/src/remote_state.rs @@ -4,7 +4,7 @@ use anyhow::{anyhow, Result}; use jsonrpc_client_transports::RpcChannel; use move_binary_format::errors::VMError; -use move_core_types::resolver::{ModuleResolver, ResourceResolver}; +use move_vm_types::resolver::{ModuleResolver, ResourceResolver}; use starcoin_crypto::HashValue; use move_table_extension::{TableHandle, TableResolver}; @@ -163,8 +163,6 @@ where A: ModuleResolver, B: ModuleResolver, { - type Error = A::Error; - fn get_module(&self, module_id: &ModuleId) -> Result>, Self::Error> { match self.a.get_module(module_id)? { Some(d) => Ok(Some(d)), diff --git a/vm/vm-runtime/Cargo.toml b/vm/vm-runtime/Cargo.toml index b60e582ae4..203fa384cd 100644 --- a/vm/vm-runtime/Cargo.toml +++ b/vm/vm-runtime/Cargo.toml @@ -23,6 +23,7 @@ rand = { workspace = true } rand_core = { default-features = false, workspace = true } starcoin-logger = { workspace = true } starcoin-frameworks = { workspace = true } +starcoin-framework = { workspace = true } starcoin-types = { workspace = true } starcoin-vm-types = { workspace = true } move-stdlib = { workspace = true } @@ -41,10 +42,9 @@ serde_bytes = { workspace = true } rayon = { workspace = true } num_cpus = { workspace = true } hex = "0.4.3" -bytes = { workspace = true } +bytes = { workspace = true } move-bytecode-verifier = { workspace = true } - [dev-dependencies] stdlib = { workspace = true } diff --git a/vm/vm-runtime/src/data_cache.rs b/vm/vm-runtime/src/data_cache.rs index 3a09a7551c..a8b33a841a 100644 --- a/vm/vm-runtime/src/data_cache.rs +++ b/vm/vm-runtime/src/data_cache.rs @@ -3,7 +3,6 @@ //! Scratchpad for on chain values during the execution. use crate::create_access_path; -use anyhow::Error; use bytes::Bytes; use move_binary_format::deserializer::DeserializerConfig; use move_binary_format::CompiledModule; @@ -13,19 +12,24 @@ use move_core_types::value::MoveTypeLayout; use move_table_extension::{TableHandle, TableResolver}; use starcoin_logger::prelude::*; use starcoin_types::account_address::AccountAddress; -use starcoin_vm_types::state_store::state_key::StateKey; -use starcoin_vm_types::state_store::state_value::StateValue; -use starcoin_vm_types::state_store::TStateView; +use starcoin_vm_runtime_types::resource_group_adapter::ResourceGroupAdapter; +use starcoin_vm_types::state_store::{ + errors::StateviewError, state_key::StateKey, state_storage_usage::StateStorageUsage, + state_value::StateValue, StateView, TStateView, +}; use starcoin_vm_types::{ access_path::AccessPath, errors::*, language_storage::{ModuleId, StructTag}, - state_view::StateView, vm_status::StatusCode, write_set::{WriteOp, WriteSet}, }; -use std::collections::btree_map::BTreeMap; -use std::ops::{Deref, DerefMut}; +use std::{ + cell::RefCell, + collections::btree_map::BTreeMap, + collections::HashSet, + ops::{Deref, DerefMut}, +}; pub(crate) fn get_resource_group_from_metadata( struct_tag: &StructTag, @@ -101,7 +105,7 @@ impl<'block, S: TStateView> TStateView for StateViewCache<'block, S> { type Key = StateKey; // Get some data either through the cache or the `StateView` on a cache miss. - fn get_state_value(&self, state_key: &StateKey) -> anyhow::Result> { + fn get_state_value(&self, state_key: &StateKey) -> Result, StateviewError> { match self.data_map.get(state_key) { Some(opt_data) => Ok(opt_data.clone().map(|v| StateValue::from(v))), None => match self.data_view.get_state_value(state_key) { @@ -115,8 +119,8 @@ impl<'block, S: TStateView> TStateView for StateViewCache<'block, S> { } } - fn is_genesis(&self) -> bool { - self.data_view.is_genesis() + fn get_usage(&self) -> Result { + todo!() } } @@ -127,7 +131,7 @@ impl<'block, S: StateView> ModuleResolver for StateViewCache<'block, S> { RemoteStorage::new(self).get_module_metadata(module_id) } - fn get_module(&self, module_id: &ModuleId) -> VMResult>> { + fn get_module(&self, module_id: &ModuleId) -> Result, Self::Error> { RemoteStorage::new(self).get_module(module_id) } } @@ -140,7 +144,7 @@ impl<'block, S: StateView> ResourceResolver for StateViewCache<'block, S> { struct_tag: &StructTag, metadata: &[Metadata], layout: Option<&MoveTypeLayout>, - ) -> Result<(Option, usize), Self::Error> { + ) -> Result<(Option, usize), Self::Error> { RemoteStorage::new(self) .get_resource_bytes_with_metadata_and_layout(address, struct_tag, metadata, layout) } @@ -178,14 +182,15 @@ impl<'a, S: StateView> ModuleResolver for RemoteStorage<'a, S> { compiled_module.metadata } - fn get_module(&self, module_id: &ModuleId) -> VMResult> { + fn get_module(&self, module_id: &ModuleId) -> Result, Self::Error> { // REVIEW: cache this? let ap = AccessPath::from(module_id); - self.get(&ap).map_err(|e| e.finish(Location::Undefined)) + self.get(&ap).map(|r| r.map(Bytes::from)) } } impl<'a, S: StateView> ResourceResolver for RemoteStorage<'a, S> { type Error = VMError; + // TODO(simon): don't ignore metadata and layout fn get_resource_bytes_with_metadata_and_layout( &self, @@ -193,7 +198,7 @@ impl<'a, S: StateView> ResourceResolver for RemoteStorage<'a, S> { struct_tag: &StructTag, _metadata: &[Metadata], _layout: Option<&MoveTypeLayout>, - ) -> PartialVMResult<(Option, usize)> { + ) -> Result<(Option, usize), Self::Error> { let ap = create_access_path(*address, struct_tag.clone()); let buf = self.get(&ap)?.map(Bytes::from); let size = resource_size(&buf); @@ -268,7 +273,7 @@ impl ModuleResolver for RemoteStorageOwned { self.as_move_resolver().get_module_metadata(module_id) } - fn get_module(&self, module_id: &ModuleId) -> Result>, Self::Error> { + fn get_module(&self, module_id: &ModuleId) -> Result, Self::Error> { self.as_move_resolver().get_module(module_id) } } @@ -282,8 +287,9 @@ impl ResourceResolver for RemoteStorageOwned { struct_tag: &StructTag, metadata: &[Metadata], layout: Option<&MoveTypeLayout>, - ) -> Result<(Option, usize), Self::Error> { - todo!() + ) -> Result<(Option, usize), Self::Error> { + self.as_move_resolver() + .get_resource_bytes_with_metadata_and_layout(address, struct_tag, metadata, layout) } } @@ -293,7 +299,7 @@ impl TableResolver for RemoteStorageOwned { handle: &TableHandle, key: &[u8], maybe_layout: Option<&MoveTypeLayout>, - ) -> Result, PartialVMError> { + ) -> Result, PartialVMError> { self.as_move_resolver() .resolve_table_entry_bytes_with_layout(handle, key, maybe_layout) } diff --git a/vm/vm-runtime/src/errors.rs b/vm/vm-runtime/src/errors.rs index 154012590c..0ada3d9051 100644 --- a/vm/vm-runtime/src/errors.rs +++ b/vm/vm-runtime/src/errors.rs @@ -103,11 +103,11 @@ pub fn convert_prologue_runtime_error(error: VMError) -> Result<(), VMStatus> { StatusCode::UNEXPECTED_ERROR_FROM_KNOWN_MOVE_FUNCTION } }; - VMStatus::Error(new_major_status) + VMStatus::error(new_major_status, None) } - status @ VMStatus::ExecutionFailure { .. } | status @ VMStatus::Error(_) => { + status @ VMStatus::ExecutionFailure { .. } | status @ VMStatus::Error { .. } => { error!("[starcoin_vm] Unexpected prologue error: {:?}", status); - VMStatus::Error(StatusCode::UNEXPECTED_ERROR_FROM_KNOWN_MOVE_FUNCTION) + VMStatus::error(StatusCode::UNEXPECTED_ERROR_FROM_KNOWN_MOVE_FUNCTION, None) } }) } @@ -127,7 +127,7 @@ pub fn convert_normal_success_epilogue_error(error: VMError) -> Result<(), VMSta "[starcoin_vm] Unexpected success epilogue Move abort: {:?}::{:?} (Category: {:?} Reason: {:?})", location, code, category, reason, ); - VMStatus::Error(StatusCode::UNEXPECTED_ERROR_FROM_KNOWN_MOVE_FUNCTION) + VMStatus::error(StatusCode::UNEXPECTED_ERROR_FROM_KNOWN_MOVE_FUNCTION, None) } } } @@ -139,7 +139,7 @@ pub fn convert_normal_success_epilogue_error(error: VMError) -> Result<(), VMSta "[starcoin_vm] Unexpected success epilogue error: {:?}", status ); - VMStatus::Error(StatusCode::UNEXPECTED_ERROR_FROM_KNOWN_MOVE_FUNCTION) + VMStatus::error(StatusCode::UNEXPECTED_ERROR_FROM_KNOWN_MOVE_FUNCTION, None) } }) } diff --git a/vm/vm-runtime/src/lib.rs b/vm/vm-runtime/src/lib.rs index f946650998..ea33c90279 100644 --- a/vm/vm-runtime/src/lib.rs +++ b/vm/vm-runtime/src/lib.rs @@ -26,7 +26,7 @@ use starcoin_vm_types::{ access_path::AccessPath, account_address::AccountAddress, language_storage::StructTag, - state_view::StateView, + state_store::StateView, transaction::{Transaction, TransactionOutput}, }; diff --git a/vm/vm-runtime/src/move_vm_ext/resolver.rs b/vm/vm-runtime/src/move_vm_ext/resolver.rs index db3939a278..7a5218f2bd 100644 --- a/vm/vm-runtime/src/move_vm_ext/resolver.rs +++ b/vm/vm-runtime/src/move_vm_ext/resolver.rs @@ -4,8 +4,8 @@ use move_binary_format::errors::PartialVMError; use move_core_types::resolver::MoveResolver; use move_table_extension::TableResolver; +use starcoin_vm_runtime_types::resolver::ExecutorView; use starcoin_vm_types::on_chain_config::ConfigStorage; -use std::fmt::Debug; /// A general resolver used by StarcoinVM. Allows to implement custom hooks on /// top of storage, e.g. get resources from resource groups, etc. diff --git a/vm/vm-runtime/src/move_vm_ext/session.rs b/vm/vm-runtime/src/move_vm_ext/session.rs index 47308f2a2c..735f4bb22a 100644 --- a/vm/vm-runtime/src/move_vm_ext/session.rs +++ b/vm/vm-runtime/src/move_vm_ext/session.rs @@ -1,11 +1,6 @@ -use crate::access_path_cache::AccessPathCache; use crate::move_vm_ext::StarcoinMoveResolver; use move_binary_format::errors::VMResult; use move_core_types::account_address::AccountAddress; -use move_core_types::effects::{ChangeSet as MoveChangeSet, Op as MoveStorageOp}; -use move_core_types::language_storage::ModuleId; -use move_core_types::vm_status::{StatusCode, VMStatus}; -use move_table_extension::TableChangeSet; use move_vm_runtime::session::Session; use serde::{Deserialize, Serialize}; use starcoin_crypto::hash::{CryptoHash, CryptoHasher, PlainCryptoHash}; @@ -14,16 +9,9 @@ use starcoin_vm_runtime_types::{ change_set::VMChangeSet, storage::change_set_configs::ChangeSetConfigs, }; use starcoin_vm_types::block_metadata::BlockMetadata; -use starcoin_vm_types::contract_event::ContractEvent; -use starcoin_vm_types::event::EventKey; use starcoin_vm_types::on_chain_config::Features; -use starcoin_vm_types::state_store::state_key::StateKey; -use starcoin_vm_types::state_store::table::{TableHandle, TableInfo}; use starcoin_vm_types::transaction::SignatureCheckedTransaction; use starcoin_vm_types::transaction_metadata::TransactionMetadata; -use starcoin_vm_types::write_set::{WriteOp, WriteSet, WriteSetMut}; -use std::collections::BTreeMap; -use std::convert::TryFrom; use std::ops::{Deref, DerefMut}; use std::sync::Arc; diff --git a/vm/vm-runtime/src/natives.rs b/vm/vm-runtime/src/natives.rs index 4f5a6f17f1..5c443fda96 100644 --- a/vm/vm-runtime/src/natives.rs +++ b/vm/vm-runtime/src/natives.rs @@ -154,7 +154,7 @@ pub fn starcoin_natives_with_builder(builder: &mut SafeNativeBuilder) -> NativeF CORE_CODE_ADDRESS, builder, )) - .chain(aptos_table_natives::table_natives( + .chain(starcoin_table_natives::table_natives( CORE_CODE_ADDRESS, builder, )) @@ -163,7 +163,7 @@ pub fn starcoin_natives_with_builder(builder: &mut SafeNativeBuilder) -> NativeF pub fn assert_no_test_natives(err_msg: &str) { assert!( - aptos_natives( + starcoin_natives( LATEST_GAS_FEATURE_VERSION, NativeGasParameters::zeros(), MiscGasParameters::zeros(), @@ -200,7 +200,7 @@ pub fn configure_for_unit_test() { #[cfg(feature = "testing")] fn unit_test_extensions_hook(exts: &mut NativeContextExtensions) { - use starcoin_table_natives::NativeTableContext; + //use starcoin_table_natives::NativeTableContext; exts.add(NativeTableContext::new([0u8; 32], &*DUMMY_RESOLVER)); exts.add(NativeCodeContext::default()); diff --git a/vm/vm-runtime/src/parallel_executor/mod.rs b/vm/vm-runtime/src/parallel_executor/mod.rs index 15005c0844..708e9fa45e 100644 --- a/vm/vm-runtime/src/parallel_executor/mod.rs +++ b/vm/vm-runtime/src/parallel_executor/mod.rs @@ -19,7 +19,7 @@ use starcoin_parallel_executor::{ }; use starcoin_vm_types::{ state_store::state_key::StateKey, - state_view::StateView, + state_store::StateView, transaction::{Transaction, TransactionOutput, TransactionStatus}, write_set::{WriteOp, WriteSet}, }; @@ -103,8 +103,9 @@ impl ParallelStarcoinVM { Some(err), )) } - Err(Error::InvariantViolation) => Err(VMStatus::Error( + Err(Error::InvariantViolation) => Err(VMStatus::error( StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR, + None, )), Err(Error::UserError(err)) => Err(err), } diff --git a/vm/vm-runtime/src/parallel_executor/storage_wrapper.rs b/vm/vm-runtime/src/parallel_executor/storage_wrapper.rs index a76db536f7..0facae98e6 100644 --- a/vm/vm-runtime/src/parallel_executor/storage_wrapper.rs +++ b/vm/vm-runtime/src/parallel_executor/storage_wrapper.rs @@ -3,11 +3,11 @@ use crate::data_cache::{IntoMoveResolver, RemoteStorageOwned}; use starcoin_parallel_executor::executor::MVHashMapView; -use starcoin_vm_types::state_store::state_value::StateValue; -use starcoin_vm_types::state_store::TStateView; -use starcoin_vm_types::{ - state_store::state_key::StateKey, state_view::StateView, write_set::WriteOp, +use starcoin_vm_types::state_store::{ + errors::StateviewError, state_key::StateKey, state_storage_usage::StateStorageUsage, + state_value::StateValue, StateView, TStateView, }; +use starcoin_vm_types::write_set::WriteOp; pub(crate) struct VersionedView<'a, S: StateView> { base_view: &'a S, @@ -31,7 +31,7 @@ impl<'a, S: TStateView> TStateView for VersionedView<'a, S> { type Key = StateKey; // Get some data either through the cache or the `StateView` on a cache miss. - fn get_state_value(&self, state_key: &StateKey) -> anyhow::Result> { + fn get_state_value(&self, state_key: &StateKey) -> Result, StateviewError> { match self.hashmap_view.read(state_key) { Some(v) => Ok(match v.as_ref() { WriteOp::Value(w) => Some(w.clone().map(|v| StateValue::from(v))), @@ -41,7 +41,7 @@ impl<'a, S: TStateView> TStateView for VersionedView<'a, S> { } } - fn is_genesis(&self) -> bool { - self.base_view.is_genesis() + fn get_usage(&self) -> Result { + todo!() } } diff --git a/vm/vm-runtime/src/starcoin_vm.rs b/vm/vm-runtime/src/starcoin_vm.rs index de5c16b4ce..ac82febd33 100644 --- a/vm/vm-runtime/src/starcoin_vm.rs +++ b/vm/vm-runtime/src/starcoin_vm.rs @@ -15,7 +15,8 @@ use anyhow::{bail, format_err, Error, Result}; use move_core_types::gas_algebra::{InternalGasPerByte, NumBytes}; use move_core_types::vm_status::StatusCode::VALUE_SERIALIZATION_ERROR; use move_table_extension::NativeTableContext; -use move_vm_runtime::session::{SerializedReturnValues, Session}; +use move_vm_runtime::module_traversal::{TraversalContext, TraversalStorage}; +use move_vm_runtime::session::Session; use move_vm_types::gas::GasMeter; use num_cpus; use once_cell::sync::OnceCell; @@ -41,35 +42,27 @@ use starcoin_types::{ }; use starcoin_vm_types::access::{ModuleAccess, ScriptAccess}; use starcoin_vm_types::account_address::AccountAddress; -use starcoin_vm_types::account_config::upgrade::UpgradeEvent; use starcoin_vm_types::account_config::{ - core_code_address, genesis_address, ModuleUpgradeStrategy, TwoPhaseUpgradeV2Resource, - G_EPILOGUE_NAME, G_EPILOGUE_V2_NAME, G_PROLOGUE_NAME, + core_code_address, genesis_address, upgrade::UpgradeEvent, ModuleUpgradeStrategy, + TwoPhaseUpgradeV2Resource, G_EPILOGUE_NAME, G_EPILOGUE_V2_NAME, G_PROLOGUE_NAME, }; -use starcoin_vm_types::errors::VMResult; +use starcoin_vm_types::errors::{Location, VMResult}; use starcoin_vm_types::file_format::{CompiledModule, CompiledScript}; use starcoin_vm_types::gas_schedule::G_LATEST_GAS_COST_TABLE; use starcoin_vm_types::genesis_config::StdlibVersion; use starcoin_vm_types::identifier::IdentStr; -use starcoin_vm_types::language_storage::ModuleId; +use starcoin_vm_types::language_storage::{ModuleId, TypeTag}; use starcoin_vm_types::on_chain_config::{ - FlexiDagConfig, GasSchedule, MoveLanguageVersion, G_GAS_CONSTANTS_IDENTIFIER, - G_INSTRUCTION_SCHEDULE_IDENTIFIER, G_NATIVE_SCHEDULE_IDENTIFIER, G_VM_CONFIG_IDENTIFIER, + FlexiDagConfig, GasSchedule, MoveLanguageVersion, OnChainConfig, VMConfig, Version, + G_GAS_CONSTANTS_IDENTIFIER, G_INSTRUCTION_SCHEDULE_IDENTIFIER, G_NATIVE_SCHEDULE_IDENTIFIER, + G_VM_CONFIG_IDENTIFIER, }; -use starcoin_vm_types::state_store::state_key::StateKey; +use starcoin_vm_types::state_store::{state_key::StateKey, StateView}; use starcoin_vm_types::state_view::StateReaderExt; use starcoin_vm_types::transaction::{DryRunTransaction, Package, TransactionPayloadType}; -use starcoin_vm_types::transaction_metadata::TransactionPayloadMetadata; +use starcoin_vm_types::transaction_metadata::{TransactionMetadata, TransactionPayloadMetadata}; use starcoin_vm_types::value::{serialize_values, MoveValue}; -use starcoin_vm_types::vm_status::KeptVMStatus; -use starcoin_vm_types::{ - errors::Location, - language_storage::TypeTag, - on_chain_config::{OnChainConfig, VMConfig, Version}, - state_view::StateView, - transaction_metadata::TransactionMetadata, - vm_status::{StatusCode, VMStatus}, -}; +use starcoin_vm_types::vm_status::{KeptVMStatus, StatusCode, VMStatus}; use std::borrow::Borrow; use std::cmp::min; use std::sync::Arc; @@ -160,18 +153,18 @@ impl StarcoinVM { let gas_params = StarcoinGasParameters::from_on_chain_gas_schedule(&gs.clone().to_btree_map()); if let Some(ref params) = gas_params { - if params.natives != self.native_params { - debug!("update native_params"); - match Arc::get_mut(&mut self.move_vm) { - None => { - bail!("failed to get move vm when load config"); - } - Some(mv) => { - mv.update_native_functions(params.clone().natives)?; - } + // TODO(simon): do double check + // if params.natives != self.native_params { + debug!("update native_params"); + match Arc::get_mut(&mut self.move_vm) { + None => { + bail!("failed to get move vm when load config"); + } + Some(mv) => { + mv.update_native_functions(params.clone().natives)?; } - self.native_params = params.natives.clone(); } + self.native_params = params.natives.clone(); self.gas_params = gas_params; } } @@ -300,13 +293,13 @@ impl StarcoinVM { self.vm_config .as_ref() .map(|config| &config.gas_schedule) - .ok_or(VMStatus::Error(StatusCode::VM_STARTUP_FAILURE)) + .ok_or(VMStatus::error(StatusCode::VM_STARTUP_FAILURE, None)) } pub fn get_version(&self) -> Result { self.version .clone() - .ok_or(VMStatus::Error(StatusCode::VM_STARTUP_FAILURE)) + .ok_or(VMStatus::error(StatusCode::VM_STARTUP_FAILURE, None)) } pub fn get_move_version(&self) -> Option { self.move_version @@ -318,7 +311,7 @@ impl StarcoinVM { if package_or_script_bytecode_version > supported_move_version.major { // TODO: currently, if the bytecode version of a package or script is higher than onchain config, // return `FEATURE_UNDER_GATING` error, and the txn will not be included in blocks. - return Err(VMStatus::Error(StatusCode::FEATURE_UNDER_GATING)); + return Err(VMStatus::error(StatusCode::FEATURE_UNDER_GATING, None)); } } Ok(()) @@ -333,7 +326,10 @@ impl StarcoinVM { "[VM] Transaction size too big {} (max {})", raw_bytes_len, txn_gas_params.max_transaction_size_in_bytes ); - return Err(VMStatus::Error(StatusCode::EXCEEDED_MAX_TRANSACTION_SIZE)); + return Err(VMStatus::error( + StatusCode::EXCEEDED_MAX_TRANSACTION_SIZE, + None, + )); } // The submitted max gas units that the transaction can consume is greater than the @@ -346,8 +342,9 @@ impl StarcoinVM { txn_data.max_gas_amount(), txn_gas_params.gas_unit_scaling_factor ); - return Err(VMStatus::Error( + return Err(VMStatus::error( StatusCode::MAX_GAS_UNITS_EXCEEDS_MAX_GAS_UNITS_BOUND, + None, )); } @@ -364,8 +361,9 @@ impl StarcoinVM { txn_data.max_gas_amount(), txn_gas_params.gas_unit_scaling_factor ); - return Err(VMStatus::Error( + return Err(VMStatus::error( StatusCode::MAX_GAS_UNITS_BELOW_MIN_TRANSACTION_GAS_UNITS, + None, )); } @@ -380,7 +378,10 @@ impl StarcoinVM { txn_gas_params.min_price_per_gas_unit, txn_data.gas_unit_price() ); - return Err(VMStatus::Error(StatusCode::GAS_UNIT_PRICE_BELOW_MIN_BOUND)); + return Err(VMStatus::error( + StatusCode::GAS_UNIT_PRICE_BELOW_MIN_BOUND, + None, + )); } // The submitted gas price is greater than the maximum gas unit price set by the VM. @@ -390,7 +391,10 @@ impl StarcoinVM { txn_gas_params.max_price_per_gas_unit, txn_data.gas_unit_price() ); - return Err(VMStatus::Error(StatusCode::GAS_UNIT_PRICE_ABOVE_MAX_BOUND)); + return Err(VMStatus::error( + StatusCode::GAS_UNIT_PRICE_ABOVE_MAX_BOUND, + None, + )); } Ok(()) } @@ -402,7 +406,7 @@ impl StarcoinVM { ) -> Result<(), VMStatus> { let txn_data = TransactionMetadata::new(transaction)?; let data_cache = remote_cache.as_move_resolver(); - let mut session: SessionAdapter<_> = self + let mut session: SessionAdapter = self .move_vm .new_session(&data_cache, SessionId::txn(transaction)) .into(); @@ -426,8 +430,9 @@ impl StarcoinVM { match Self::only_new_module_strategy(remote_cache, package.package_address()) { Err(e) => { warn!("[VM]Update module strategy deserialize err : {:?}", e); - return Err(VMStatus::Error( + return Err(VMStatus::error( StatusCode::FAILED_TO_DESERIALIZE_RESOURCE, + None, )); } Ok(only_new_module) => only_new_module, @@ -491,11 +496,11 @@ impl StarcoinVM { let data_cache = StateViewCache::new(state_view); let signature_verified_txn = match txn.check_signature() { Ok(t) => t, - Err(_) => return Some(VMStatus::Error(StatusCode::INVALID_SIGNATURE)), + Err(_) => return Some(VMStatus::error(StatusCode::INVALID_SIGNATURE, None)), }; if let Err(err) = self.load_configs(state_view) { warn!("Load config error at verify_transaction: {}", err); - return Some(VMStatus::Error(StatusCode::VM_STARTUP_FAILURE)); + return Some(VMStatus::error(StatusCode::VM_STARTUP_FAILURE, None)); } match self.verify_transaction_impl(&signature_verified_txn, &data_cache) { Ok(_) => None, @@ -556,7 +561,7 @@ impl StarcoinVM { fn execute_package( &self, - mut session: SessionAdapter, + mut session: SessionAdapter, gas_meter: &mut StarcoinGasMeter, txn_data: &TransactionMetadata, package: &Package, @@ -599,7 +604,10 @@ impl StarcoinVM { { Err(e) => { warn!("[VM]Update module strategy deserialize err : {:?}", e); - return Err(VMStatus::Error(StatusCode::FAILED_TO_DESERIALIZE_RESOURCE)); + return Err(VMStatus::error( + StatusCode::FAILED_TO_DESERIALIZE_RESOURCE, + None, + )); } Ok(only_new_module) => only_new_module, }; @@ -612,7 +620,7 @@ impl StarcoinVM { .map(|m| m.code().to_vec()) .collect(), package.package_address(), // be careful with the sender. - gas_meter, + gas_meter, PublishModuleBundleOption { force_publish: enforced, only_new_module, @@ -662,9 +670,9 @@ impl StarcoinVM { } } - fn execute_script_or_script_function( + fn execute_script_or_script_function( &self, - mut session: SessionAdapter, + mut session: SessionAdapter, gas_meter: &mut StarcoinGasMeter, txn_data: &TransactionMetadata, payload: &TransactionPayload, @@ -712,33 +720,32 @@ impl StarcoinVM { ) } TransactionPayload::Package(_) => { - return Err(VMStatus::Error(StatusCode::UNREACHABLE)); + return Err(VMStatus::error(StatusCode::UNREACHABLE, None)); } } - .map_err(|e| - { - warn!("[VM] execute_script_function error, status_type: {:?}, status_code:{:?}, message:{:?}, location:{:?}", e.status_type(), e.major_status(), e.message(), e.location()); - e.into_vm_status() - })?; + .map_err(|e| + { + warn!("[VM] execute_script_function error, status_type: {:?}, status_code:{:?}, message:{:?}, location:{:?}", e.status_type(), e.major_status(), e.message(), e.location()); + e.into_vm_status() + })?; charge_global_write_gas_usage(gas_meter, &session, &txn_data.sender())?; self.success_transaction_cleanup(session, gas_meter, txn_data) } } - fn validate_execute_entry_function( - session: &mut SessionAdapter, + fn validate_execute_entry_function( + session: &mut SessionAdapter, module: &ModuleId, function_name: &IdentStr, ty_args: Vec, args: Vec>, gas_meter: &mut impl GasMeter, sender: AccountAddress, - ) -> VMResult { - let (_, func, loaded_func) = - session - .inner - .load_function(module, function_name, &ty_args)?; + ) -> VMResult<()> { + let loaded_func = session + .inner + .load_function(module, function_name, &ty_args)?; verifier::transaction_arg_validation::validate_combine_singer_and_args( session, @@ -747,27 +754,32 @@ impl StarcoinVM { &loaded_func, )?; - let final_args = SessionAdapter::::check_and_rearrange_args_by_signer_position( - func, - args.into_iter().map(|b| b.borrow().to_vec()).collect(), + let _final_args = SessionAdapter::check_and_rearrange_args_by_signer_position( + loaded_func.borrow(), + args.iter().map(|b| b.borrow().to_vec()).collect(), sender, )?; - session - .inner - .execute_entry_function(module, function_name, ty_args, final_args, gas_meter) + + let tranversal_storage = TraversalStorage::new(); + session.inner.execute_entry_function( + loaded_func, + args, + gas_meter, + &mut TraversalContext::new(&tranversal_storage), + ) } - fn validate_execute_script( - session: &mut SessionAdapter, + fn validate_execute_script( + session: &mut SessionAdapter, script: impl Borrow<[u8]>, ty_args: Vec, args: Vec>, gas_meter: &mut impl GasMeter, sender: AccountAddress, - ) -> VMResult { - let (main, loaded_func) = session + ) -> VMResult<()> { + let loaded_func = session .inner - .load_script(script.borrow(), ty_args.clone())?; + .load_script(script.borrow(), ty_args.as_ref())?; verifier::transaction_arg_validation::validate_combine_singer_and_args( session, @@ -776,28 +788,34 @@ impl StarcoinVM { &loaded_func, )?; - let final_args = SessionAdapter::::check_and_rearrange_args_by_signer_position( - main, - args.into_iter().map(|b| b.borrow().to_vec()).collect(), + let _final_args = SessionAdapter::check_and_rearrange_args_by_signer_position( + loaded_func.borrow(), + args.iter().map(|b| b.borrow().to_vec()).collect(), sender, )?; - session - .inner - .execute_script(script, ty_args, final_args, gas_meter) + + let traversal_storage = TraversalStorage::new(); + session.inner.execute_script( + script, + ty_args, + args, + gas_meter, + &mut TraversalContext::new(&traversal_storage), + ) } /// Run the prologue of a transaction by calling into `PROLOGUE_NAME` function stored /// in the `ACCOUNT_MODULE` on chain. - fn run_prologue( + fn run_prologue( &self, - session: &mut SessionAdapter, + session: &mut SessionAdapter, gas_meter: &mut StarcoinGasMeter, txn_data: &TransactionMetadata, ) -> Result<(), VMStatus> { let genesis_address = genesis_address(); let gas_token_ty = TypeTag::Struct(Box::new(txn_data.gas_token_code().try_into().map_err( - |_e| VMStatus::Error(StatusCode::BAD_TRANSACTION_FEE_CURRENCY), + |_e| VMStatus::error(StatusCode::BAD_TRANSACTION_FEE_CURRENCY, None), )?)); let txn_sequence_number = txn_data.sequence_number(); let authentication_key_preimage = txn_data.authentication_key_preimage().to_vec(); @@ -819,6 +837,7 @@ impl StarcoinVM { ), }; + let traversal_storage = TraversalStorage::new(); // Run prologue by genesis account session .as_mut() @@ -840,6 +859,7 @@ impl StarcoinVM { MoveValue::Address(package_address), ]), gas_meter, + &mut TraversalContext::new(&traversal_storage), ) .map(|_return_vals| ()) .or_else(convert_prologue_runtime_error) @@ -847,9 +867,9 @@ impl StarcoinVM { /// Run the epilogue of a transaction by calling into `EPILOGUE_NAME` function stored /// in the `ACCOUNT_MODULE` on chain. - fn run_epilogue( + fn run_epilogue( &self, - session: &mut SessionAdapter, + session: &mut SessionAdapter, gas_meter: &mut StarcoinGasMeter, txn_data: &TransactionMetadata, success: bool, @@ -857,7 +877,7 @@ impl StarcoinVM { let genesis_address = genesis_address(); let gas_token_ty = TypeTag::Struct(Box::new(txn_data.gas_token_code().try_into().map_err( - |_e| VMStatus::Error(StatusCode::BAD_TRANSACTION_FEE_CURRENCY), + |_e| VMStatus::error(StatusCode::BAD_TRANSACTION_FEE_CURRENCY, None), )?)); let txn_sequence_number = txn_data.sequence_number(); let txn_authentication_key_preimage = txn_data.authentication_key_preimage().to_vec(); @@ -914,6 +934,7 @@ impl StarcoinVM { ]), ) }; + let traversal_storage = TraversalStorage::new(); session .as_mut() .execute_function_bypass_visibility( @@ -922,6 +943,7 @@ impl StarcoinVM { vec![gas_token_ty], args, gas_meter, + &mut TraversalContext::new(&traversal_storage), ) .map(|_return_vals| ()) .or_else(convert_normal_success_epilogue_error) @@ -973,13 +995,14 @@ impl StarcoinVM { if version >= StdlibVersion::Version(FLEXI_DAG_UPGRADE_VERSION_MARK) { args_vec.push(MoveValue::vector_u8( bcs_ext::to_bytes(&parents_hash.unwrap_or_default()) - .or(Err(VMStatus::Error(VALUE_SERIALIZATION_ERROR)))?, + .or(Err(VMStatus::error(VALUE_SERIALIZATION_ERROR, None)))?, )); function_name = &account_config::G_BLOCK_PROLOGUE_V2_NAME; } } let args = serialize_values(&args_vec); - let mut session: SessionAdapter<_> = self.move_vm.new_session(storage, session_id).into(); + let mut session: SessionAdapter = self.move_vm.new_session(storage, session_id).into(); + let traverse_storage = TraversalStorage::new(); session .as_mut() .execute_function_bypass_visibility( @@ -988,6 +1011,7 @@ impl StarcoinVM { vec![], args, &mut gas_meter, + &mut TraversalContext::new(&traverse_storage), ) .map(|_return_vals| ()) .or_else(convert_prologue_runtime_error)?; @@ -1024,7 +1048,7 @@ impl StarcoinVM { } }; - let session: SessionAdapter<_> = self + let session: SessionAdapter = self .move_vm .new_session(storage, SessionId::txn_meta(&txn_data)) .into(); @@ -1033,7 +1057,7 @@ impl StarcoinVM { // check signature let signature_checked_txn = match txn.check_signature() { Ok(t) => Ok(t), - Err(_) => Err(VMStatus::Error(StatusCode::INVALID_SIGNATURE)), + Err(_) => Err(VMStatus::error(StatusCode::INVALID_SIGNATURE, None)), }; match signature_checked_txn { @@ -1158,7 +1182,7 @@ impl StarcoinVM { // TODO load config by config change event self.load_configs(&data_cache) - .map_err(|_err| VMStatus::Error(StatusCode::STORAGE_ERROR))?; + .map_err(|_err| VMStatus::error(StatusCode::STORAGE_ERROR, None))?; let mut gas_left = block_gas_limit.unwrap_or(u64::MAX); let blocks = chunk_block_transactions(transactions); @@ -1201,7 +1225,7 @@ impl StarcoinVM { } // TODO load config by config change event self.check_reconfigure(&data_cache, &output) - .map_err(|_err| VMStatus::Error(StatusCode::STORAGE_ERROR))?; + .map_err(|_err| VMStatus::error(StatusCode::STORAGE_ERROR, None))?; #[cfg(feature = "metrics")] if let Some(timer) = timer { @@ -1314,7 +1338,7 @@ impl StarcoinVM { "Load config error at execute_readonly_function_internal: {}", err ); - return Err(VMStatus::Error(StatusCode::VM_STARTUP_FAILURE)); + return Err(VMStatus::error(StatusCode::VM_STARTUP_FAILURE, None)); } let gas_params = self.get_gas_parameters()?; let mut gas_meter = StarcoinGasMeter::new( @@ -1330,6 +1354,8 @@ impl StarcoinVM { gas_meter.set_metering(false); gas_meter }; + + let traversal_storage = TraversalStorage::new(); let mut session = self.move_vm.new_session(&data_cache, SessionId::void()); let result = session .execute_function_bypass_visibility( @@ -1338,6 +1364,7 @@ impl StarcoinVM { type_params, args, &mut gas_meter, + &mut TraversalContext::new(&traversal_storage), ) .map_err(|e| e.into_vm_status())? .return_values @@ -1345,7 +1372,7 @@ impl StarcoinVM { .map(|(a, _)| a) .collect(); - let (change_set, events, mut extensions) = session + let (change_set, mut extensions) = session .finish_with_extensions() .map_err(|e| e.into_vm_status())?; let table_context: NativeTableContext = extensions.remove(); @@ -1356,20 +1383,19 @@ impl StarcoinVM { // No table infos should be produced in readonly function. let (_table_infos, write_set, _events) = SessionOutput { change_set, - events, table_change_set, } .into_change_set(&mut ())?; if !write_set.is_empty() { warn!("Readonly function {} changes state", function_name); - return Err(VMStatus::Error(StatusCode::REJECTED_WRITE_SET)); + return Err(VMStatus::error(StatusCode::REJECTED_WRITE_SET, None)); } Ok(result) } - fn success_transaction_cleanup( + fn success_transaction_cleanup( &self, - mut session: SessionAdapter, + mut session: SessionAdapter, gas_meter: &mut StarcoinGasMeter, txn_data: &TransactionMetadata, ) -> Result<(VMStatus, TransactionOutput), VMStatus> { @@ -1396,7 +1422,7 @@ impl StarcoinVM { storage: &S, ) -> (VMStatus, TransactionOutput) { gas_meter.set_metering(false); - let mut session: SessionAdapter<_> = self + let mut session: SessionAdapter = self .move_vm .new_session(storage, SessionId::txn_meta(txn_data)) .into(); @@ -1422,7 +1448,7 @@ impl StarcoinVM { (error_code, txn_output) } TransactionStatus::Discard(status) => { - (VMStatus::Error(status), discard_error_output(status)) + (VMStatus::error(status, None), discard_error_output(status)) } TransactionStatus::Retry => unreachable!(), } @@ -1431,7 +1457,7 @@ impl StarcoinVM { pub fn get_gas_parameters(&self) -> Result<&StarcoinGasParameters, VMStatus> { self.gas_params.as_ref().ok_or_else(|| { debug!("VM Startup Failed. Gas Parameters Not Found"); - VMStatus::Error(StatusCode::VM_STARTUP_FAILURE) + VMStatus::error(StatusCode::VM_STARTUP_FAILURE, None) }) } @@ -1512,9 +1538,9 @@ pub fn chunk_block_transactions(txns: Vec) -> Vec blocks } -pub(crate) fn charge_global_write_gas_usage( +pub(crate) fn charge_global_write_gas_usage( gas_meter: &mut StarcoinGasMeter, - session: &SessionAdapter, + session: &SessionAdapter, sender: &AccountAddress, ) -> Result<(), VMStatus> { let write_set_gas = u64::from(gas_meter.cal_write_set_gas()); @@ -1531,9 +1557,9 @@ pub(crate) fn charge_global_write_gas_usage( .map_err(|p_err| p_err.finish(Location::Undefined).into_vm_status()) } -pub(crate) fn get_transaction_output( +pub(crate) fn get_transaction_output( ap_cache: &mut A, - session: SessionAdapter, + session: SessionAdapter, gas_left: Gas, max_gas_amount: Gas, status: KeptVMStatus, @@ -1542,15 +1568,13 @@ pub(crate) fn get_transaction_output( let gas_used = max_gas_amount .checked_sub(gas_left) .expect("Balance should always be less than or equal to max gas amount"); - let (change_set, events, mut extensions) = - Into::>::into(session).finish_with_extensions()?; + let (change_set, mut extensions) = Into::::into(session).finish_with_extensions()?; let table_context: NativeTableContext = extensions.remove(); let table_change_set = table_context .into_change_set() .map_err(|e| e.finish(Location::Undefined))?; let (table_infos, write_set, events) = SessionOutput { change_set, - events, table_change_set, } .into_change_set(ap_cache)?; diff --git a/vm/vm-runtime/src/verifier/transaction_arg_validation.rs b/vm/vm-runtime/src/verifier/transaction_arg_validation.rs index c8ec49f473..180923441b 100644 --- a/vm/vm-runtime/src/verifier/transaction_arg_validation.rs +++ b/vm/vm-runtime/src/verifier/transaction_arg_validation.rs @@ -12,6 +12,8 @@ use move_core_types::vm_status::StatusCode; use move_core_types::{ account_address::AccountAddress, ident_str, identifier::Identifier, language_storage::ModuleId, }; +use move_vm_runtime::module_traversal::{TraversalContext, TraversalStorage}; +use move_vm_runtime::LoadedFunction; use move_vm_types::gas::{GasMeter, UnmeteredGasMeter}; use move_vm_types::loaded_data::runtime_types::Type; use once_cell::sync::Lazy; @@ -83,17 +85,17 @@ fn get_allowed_structs() -> &'static ConstructorMap { /// 2. number of signers is same as the number of senders /// 3. check arg types are allowed after signers /// -pub(crate) fn validate_combine_singer_and_args( - session: &mut SessionAdapter, +pub(crate) fn validate_combine_singer_and_args( + session: &mut SessionAdapter, senders: Vec, args: &[impl Borrow<[u8]>], - func: &LoadedFunctionInstantiation, + func: &LoadedFunction, ) -> VMResult<()> { - SessionAdapter::::check_script_return(func.return_.clone())?; + SessionAdapter::check_script_return(func.return_tys())?; let mut signer_param_cnt = 0; // find all signer params at the beginning - for ty in func.parameters.iter() { + for ty in func.param_tys() { match ty { Type::Signer => signer_param_cnt += 1, Type::Reference(inner_type) => { @@ -106,13 +108,13 @@ pub(crate) fn validate_combine_singer_and_args( } let allowed_structs = get_allowed_structs(); + let ty_builder = session.inner.get_ty_builder(); + // Need to keep this here to ensure we return the historic correct error code for replay - for ty in func.parameters[signer_param_cnt..].iter() { - let valid = is_valid_txn_arg( - session, - &ty.subst(&func.type_arguments).unwrap(), - allowed_structs, - ); + for ty in func.param_tys()[signer_param_cnt..].iter() { + let subst_res = ty_builder.create_ty_with_subst(ty, func.ty_args()); + let typ = subst_res.map_err(|e| e.finish(Location::Undefined))?; + let valid = is_valid_txn_arg(session, &typ, allowed_structs); if !valid { return Err( PartialVMError::new(StatusCode::INVALID_MAIN_FUNCTION_SIGNATURE) @@ -124,13 +126,13 @@ pub(crate) fn validate_combine_singer_and_args( } } - if (signer_param_cnt + args.len()) != func.parameters.len() { + if (signer_param_cnt + args.len()) != func.param_tys().len() { return Err( PartialVMError::new(StatusCode::NUMBER_OF_ARGUMENTS_MISMATCH) .with_message(format!( "signer params {signer_param_cnt}, args {}, func parameters {}", args.len(), - func.parameters.len() + func.param_tys().len() )) .finish(Location::Script), ); @@ -152,9 +154,9 @@ pub(crate) fn validate_combine_singer_and_args( // FAILED_TO_DESERIALIZE_ARGUMENT error. let _ = construct_args( session, - &func.parameters[signer_param_cnt..], + &func.param_tys()[signer_param_cnt..], args, - &func.type_arguments, + &func.ty_args(), allowed_structs, false, )?; @@ -163,8 +165,8 @@ pub(crate) fn validate_combine_singer_and_args( } // Return whether the argument is valid/allowed and whether it needs construction. -pub(crate) fn is_valid_txn_arg( - session: &SessionAdapter, +pub(crate) fn is_valid_txn_arg( + session: &SessionAdapter, typ: &Type, allowed_structs: &ConstructorMap, ) -> bool { @@ -173,7 +175,7 @@ pub(crate) fn is_valid_txn_arg( match typ { Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address => true, Vector(inner) => is_valid_txn_arg(session, inner, allowed_structs), - Struct(idx) | StructInstantiation(idx, _) => session + Struct { idx, .. } | StructInstantiation { idx, .. } => session .inner .get_struct_type(*idx) .map(|st| { @@ -188,8 +190,8 @@ pub(crate) fn is_valid_txn_arg( // Construct arguments. Walk through the arguments and according to the signature // construct arguments that require so. // TODO: This needs a more solid story and a tighter integration with the VM. -pub(crate) fn construct_args( - session: &mut SessionAdapter, +pub(crate) fn construct_args( + session: &mut SessionAdapter, types: &[Type], args: &[impl Borrow<[u8]>], ty_args: &[Type], @@ -202,10 +204,13 @@ pub(crate) fn construct_args( if types.len() != args.len() { return Err(invalid_signature()); } + let ty_builder = session.inner.get_ty_builder(); for (ty, arg) in types.iter().zip(args) { + let subst_res = ty_builder.create_ty_with_subst(ty, ty_args); + let ty = subst_res.map_err(|e| e.finish(Location::Undefined))?; let arg = construct_arg( session, - &ty.subst(ty_args).unwrap(), + &ty, allowed_structs, arg.borrow().to_vec(), &mut gas_meter, @@ -220,8 +225,8 @@ fn invalid_signature() -> VMError { PartialVMError::new(StatusCode::INVALID_MAIN_FUNCTION_SIGNATURE).finish(Location::Script) } -fn construct_arg( - session: &mut SessionAdapter, +fn construct_arg( + session: &mut SessionAdapter, ty: &Type, allowed_structs: &ConstructorMap, arg: Vec, @@ -273,8 +278,8 @@ fn construct_arg( // A Cursor is used to recursively walk the serialized arg manually and correctly. In effect we // are parsing the BCS serialized implicit constructor invocation tree, while serializing the // constructed types into the output parameter arg. -pub(crate) fn recursively_construct_arg( - session: &mut SessionAdapter, +pub(crate) fn recursively_construct_arg( + session: &mut SessionAdapter, ty: &Type, allowed_structs: &ConstructorMap, cursor: &mut Cursor<&[u8]>, @@ -304,7 +309,7 @@ pub(crate) fn recursively_construct_arg( len -= 1; } } - Struct(idx) | StructInstantiation(idx, _) => { + Struct { idx, .. } | StructInstantiation { idx, .. } => { let st = session .inner .get_struct_type(*idx) @@ -343,8 +348,8 @@ pub(crate) fn recursively_construct_arg( // constructed value. This is the correct data to pass as the argument to a function taking // said struct as a parameter. In this function we execute the constructor constructing the // value and returning the BCS serialized representation. -fn validate_and_construct( - session: &mut SessionAdapter, +fn validate_and_construct( + session: &mut SessionAdapter, expected_type: &Type, constructor: &FunctionId, allowed_structs: &ConstructorMap, @@ -407,17 +412,22 @@ fn validate_and_construct( *max_invocations -= 1; } - let (module, function, instantiation) = session.inner.load_function_with_type_arg_inference( + let function = session.inner.load_function_with_type_arg_inference( &constructor.module, constructor.function.as_ref(), expected_type, )?; let mut args = vec![]; - for param_type in &instantiation.parameters { + let ty_builder = session.inner.get_ty_builder(); + for param_ty in function.param_tys() { let mut arg = vec![]; + let arg_ty = ty_builder + .create_ty_with_subst(param_ty, function.ty_args()) + .unwrap(); + recursively_construct_arg( session, - ¶m_type.subst(&instantiation.type_arguments).unwrap(), + &arg_ty, allowed_structs, cursor, initial_cursor_len, @@ -427,12 +437,12 @@ fn validate_and_construct( )?; args.push(arg); } - let serialized_result = session.inner.execute_instantiated_function( - module, + let storage = TraversalStorage::new(); + let serialized_result = session.inner.execute_loaded_function( function, - instantiation, args, gas_meter, + &mut TraversalContext::new(&storage), )?; let mut ret_vals = serialized_result.return_values; // We know ret_vals.len() == 1 diff --git a/vm/vm-runtime/src/vm_adapter/adapter.rs b/vm/vm-runtime/src/vm_adapter/adapter.rs index 7a564e2ec0..63927b61e0 100644 --- a/vm/vm-runtime/src/vm_adapter/adapter.rs +++ b/vm/vm-runtime/src/vm_adapter/adapter.rs @@ -2,9 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 use move_binary_format::errors::*; -use move_binary_format::normalized::Function; use move_binary_format::{ - access::ModuleAccess, compatibility::Compatibility, normalized, CompiledModule, IndexKind, + access::ModuleAccess, compatibility::Compatibility, CompiledModule, IndexKind, }; use move_core_types::value::MoveValue; use move_core_types::vm_status::StatusCode; @@ -12,14 +11,12 @@ use move_core_types::{ account_address::AccountAddress, identifier::IdentStr, language_storage::{ModuleId, TypeTag}, - resolver::*, }; -use move_vm_runtime::session::Session; +use move_vm_runtime::{session::Session, LoadedFunction}; use move_vm_types::gas::GasMeter; use move_vm_types::loaded_data::runtime_types::Type; use std::borrow::Borrow; use std::collections::BTreeSet; -use std::sync::Arc; use tracing::warn; /// Publish module bundle options @@ -102,12 +99,12 @@ impl<'r, 'l> SessionAdapter<'r, 'l> { //} pub(crate) fn check_and_rearrange_args_by_signer_position( - func: Arc, + func: &LoadedFunction, args: Vec>, sender: AccountAddress, ) -> VMResult>> { let has_signer = func - .parameter_types() + .param_tys() .iter() .position(|i| matches!(i, &Type::Signer)) .map(|pos| { @@ -229,11 +226,10 @@ impl<'r, 'l> SessionAdapter<'r, 'l> { } let old_module_ref = self.inner.load_module(&module_id)?; - let old_module = old_module_ref.module(); - let old_m = normalized::Module::new(old_module); - let new_m = normalized::Module::new(module); - if Compatibility::new(true, true, false) - .check(&old_m, &new_m) + let old_module = CompiledModule::deserialize(old_module_ref.as_ref()) + .map_err(|e| e.finish(Location::Undefined))?; + if Compatibility::new(true, false) + .check(&old_module, module) .is_err() && !option.force_publish { @@ -263,18 +259,13 @@ impl<'r, 'l> SessionAdapter<'r, 'l> { sender: AccountAddress, ) -> VMResult<()> { //load the script, perform verification - let ( - main, - LoadedFunctionInstantiation { - type_arguments: _, - parameters, - return_, - }, - ) = self.inner.load_script(script.borrow(), ty_args)?; + let function = self + .inner + .load_script(script.borrow(), ty_args.as_slice())?; - Self::check_script_return(return_)?; + Self::check_script_return(ty_args.as_slice())?; - self.check_script_signer_and_build_args(main, parameters, args, sender)?; + self.check_script_signer_and_build_args(&function, ty_args, args, sender)?; Ok(()) } @@ -287,25 +278,18 @@ impl<'r, 'l> SessionAdapter<'r, 'l> { args: Vec>, sender: AccountAddress, ) -> VMResult<()> { - let ( - _module, - func, - LoadedFunctionInstantiation { - type_arguments: _, - parameters, - return_, - }, - ) = self.inner.load_function(module, function_name, &ty_args)?; + let func = self.inner.load_function(module, function_name, &ty_args)?; - Self::check_script_return(return_)?; + Self::check_script_return(func.ty_args())?; - self.check_script_signer_and_build_args(func, parameters, args, sender)?; + self.check_script_signer_and_build_args(&func, ty_args, args, sender)?; Ok(()) } + // TODO(simon): what's the difference between Type and TypeTag? //ensure the script function not return value - pub(crate) fn check_script_return(return_: Vec) -> VMResult<()> { + pub(crate) fn check_script_return(return_: &[T]) -> VMResult<()> { if !return_.is_empty() { Err(PartialVMError::new(StatusCode::RET_TYPE_MISMATCH_ERROR) .with_message(format!( @@ -319,22 +303,32 @@ impl<'r, 'l> SessionAdapter<'r, 'l> { } fn check_script_signer_and_build_args( - &self, - func: Arc, - arg_tys: Vec, + &mut self, + func: &LoadedFunction, + arg_tys: Vec, args: Vec>, sender: AccountAddress, ) -> VMResult<()> { let final_args = Self::check_and_rearrange_args_by_signer_position(func, args, sender)?; - let (_, _) = self.inner.deserialize_args(arg_tys, final_args)?; + let arg_tys = arg_tys + .into_iter() + .map(|tt| self.inner.load_type(&tt)) + .try_fold(vec![], |mut acc, ty| { + acc.push(ty?); + Ok(acc) + })?; + let (_, _) = self + .inner + .deserialize_args(arg_tys, final_args) + .map_err(|e| e.finish(Location::Undefined))?; Ok(()) } /// Clear vm runtimer loader's cache to reload new modules from state cache fn empty_loader_cache(&self) -> VMResult<()> { - self.inner.mark_loader_cache_as_invaliddated(); - self.inner.flush_loader_cache_if_invalidated(); + self.inner.get_move_vm().mark_loader_cache_as_invalid(); + self.inner.get_move_vm().flush_loader_cache_if_invalidated(); Ok(()) } } diff --git a/vm/vm-runtime/src/vm_adapter/adapter_common.rs b/vm/vm-runtime/src/vm_adapter/adapter_common.rs index df33c74e98..a8f0e9192f 100644 --- a/vm/vm-runtime/src/vm_adapter/adapter_common.rs +++ b/vm/vm-runtime/src/vm_adapter/adapter_common.rs @@ -3,9 +3,9 @@ use anyhow::Result; use move_core_types::vm_status::{StatusCode, VMStatus}; -use starcoin_vm_types::state_view::StateView; use starcoin_vm_types::{ block_metadata::BlockMetadata, + state_store::StateView, transaction::{SignedUserTransaction, Transaction, TransactionOutput, TransactionStatus}, write_set::WriteSet, };