diff --git a/Cargo.lock b/Cargo.lock index 492da2105b..d47a8b7130 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5217,7 +5217,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash 0.8.11", - "clap 4.5.13", + "clap 4.5.17", "crossbeam-channel", "crossbeam-utils", "dashmap 5.5.3", @@ -7029,7 +7029,7 @@ dependencies = [ [[package]] name = "moveos-gas-profiling" -version = "0.7.0" +version = "0.7.2" dependencies = [ "anyhow", "handlebars", @@ -9608,6 +9608,7 @@ dependencies = [ "async-trait", "coerce", "function_name", + "hex", "log", "metrics", "move-core-types", diff --git a/crates/rooch-executor/Cargo.toml b/crates/rooch-executor/Cargo.toml index 33d1a84186..e41dfdd3be 100644 --- a/crates/rooch-executor/Cargo.toml +++ b/crates/rooch-executor/Cargo.toml @@ -35,3 +35,4 @@ rooch-types = { workspace = true } rooch-genesis = { workspace = true } rooch-event = { workspace = true } rooch-store = { workspace = true } +hex = "0.4.3" diff --git a/crates/rooch-executor/src/actor/messages.rs b/crates/rooch-executor/src/actor/messages.rs index 2e85ac7ec9..7a44e506d6 100644 --- a/crates/rooch-executor/src/actor/messages.rs +++ b/crates/rooch-executor/src/actor/messages.rs @@ -99,6 +99,7 @@ impl Message for ExecuteViewFunctionMessage { #[derive(Debug, Serialize, Deserialize)] pub struct StatesMessage { + pub state_root: Option, pub access_path: AccessPath, } diff --git a/crates/rooch-executor/src/actor/reader_executor.rs b/crates/rooch-executor/src/actor/reader_executor.rs index fc67b2bc5c..68a81d1566 100644 --- a/crates/rooch-executor/src/actor/reader_executor.rs +++ b/crates/rooch-executor/src/actor/reader_executor.rs @@ -21,6 +21,7 @@ use moveos_store::transaction_store::TransactionStore; use moveos_store::MoveOSStore; use moveos_types::function_return_value::AnnotatedFunctionResult; use moveos_types::function_return_value::AnnotatedFunctionReturnValue; +use moveos_types::h256::H256; use moveos_types::moveos_std::event::EventHandle; use moveos_types::moveos_std::event::{AnnotatedEvent, Event}; use moveos_types::moveos_std::object::ObjectMeta; @@ -146,7 +147,14 @@ impl Handler for ReaderExecutorActor { msg: StatesMessage, _ctx: &mut ActorContext, ) -> Result>, anyhow::Error> { - let resolver = RootObjectResolver::new(self.root.clone(), &self.moveos_store); + let resolver = if let Some(state_root_str) = msg.state_root { + let hex_bytes = hex::decode(state_root_str).expect("decode root state failed"); + let state_root = H256::from_slice(hex_bytes.as_slice()); + let root_object_meta = ObjectMeta::root_metadata(state_root, 55); + RootObjectResolver::new(root_object_meta, &self.moveos_store) + } else { + RootObjectResolver::new(self.root.clone(), &self.moveos_store) + }; resolver.get_states(msg.access_path) } } diff --git a/crates/rooch-executor/src/proxy/mod.rs b/crates/rooch-executor/src/proxy/mod.rs index e88cd073b4..4a3f0c7e18 100644 --- a/crates/rooch-executor/src/proxy/mod.rs +++ b/crates/rooch-executor/src/proxy/mod.rs @@ -116,9 +116,16 @@ impl ExecutorProxy { .await? } - pub async fn get_states(&self, access_path: AccessPath) -> Result>> { + pub async fn get_states( + &self, + state_root: Option, + access_path: AccessPath, + ) -> Result>> { self.reader_actor - .send(StatesMessage { access_path }) + .send(StatesMessage { + state_root, + access_path, + }) .await? } @@ -261,7 +268,7 @@ impl ExecutorProxy { } pub async fn chain_id(&self) -> Result { - self.get_states(AccessPath::object(ChainID::chain_id_object_id())) + self.get_states(None, AccessPath::object(ChainID::chain_id_object_id())) .await? .into_iter() .next() @@ -271,7 +278,7 @@ impl ExecutorProxy { } pub async fn bitcoin_network(&self) -> Result { - self.get_states(AccessPath::object(BitcoinNetwork::object_id())) + self.get_states(None, AccessPath::object(BitcoinNetwork::object_id())) .await? .into_iter() .next() @@ -283,7 +290,10 @@ impl ExecutorProxy { //TODO provide a trait to abstract the async state reader, elemiate the duplicated code bwteen RpcService and Client pub async fn get_sequence_number(&self, address: AccountAddress) -> Result { Ok(self - .get_states(AccessPath::object(Account::account_object_id(address))) + .get_states( + None, + AccessPath::object(Account::account_object_id(address)), + ) .await? .pop() .flatten() diff --git a/crates/rooch-open-rpc-spec/schemas/openrpc.json b/crates/rooch-open-rpc-spec/schemas/openrpc.json index 79ce1698b3..9c3f8050d4 100644 --- a/crates/rooch-open-rpc-spec/schemas/openrpc.json +++ b/crates/rooch-open-rpc-spec/schemas/openrpc.json @@ -416,6 +416,12 @@ "name": "rooch_getStates", "description": "Get the states by access_path If the StateOptions.decode is true, the state is decoded and the decoded value is returned in the response.", "params": [ + { + "name": "state_root", + "schema": { + "type": "string" + } + }, { "name": "access_path", "required": true, diff --git a/crates/rooch-rpc-api/src/api/rooch_api.rs b/crates/rooch-rpc-api/src/api/rooch_api.rs index d2c24ab904..827254791f 100644 --- a/crates/rooch-rpc-api/src/api/rooch_api.rs +++ b/crates/rooch-rpc-api/src/api/rooch_api.rs @@ -57,6 +57,7 @@ pub trait RoochAPI { #[method(name = "getStates")] async fn get_states( &self, + state_root: Option, access_path: AccessPathView, state_option: Option, ) -> RpcResult>>; @@ -91,7 +92,7 @@ pub trait RoochAPI { let key_states = field_key.into_iter().map(FieldKey::from).collect(); let access_path_view = AccessPathView::from(AccessPath::fields(object_id.into(), key_states)); - self.get_states(access_path_view, state_option).await + self.get_states(None, access_path_view, state_option).await } /// List Object Fields via ObjectID. diff --git a/crates/rooch-rpc-client/src/lib.rs b/crates/rooch-rpc-client/src/lib.rs index 1771a16d78..780c3026fe 100644 --- a/crates/rooch-rpc-client/src/lib.rs +++ b/crates/rooch-rpc-client/src/lib.rs @@ -1,16 +1,21 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 -use anyhow::Result; +use anyhow::{ensure, Error, Result}; use jsonrpsee::core::client::ClientT; use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; -use move_core_types::language_storage::ModuleId; +use move_core_types::account_address::AccountAddress; +use move_core_types::language_storage::{ModuleId, StructTag}; use move_core_types::metadata::Metadata; -use move_core_types::resolver::ModuleResolver; +use move_core_types::resolver::{ModuleResolver, ResourceResolver}; use moveos_types::access_path::AccessPath; +use moveos_types::h256::H256; use moveos_types::move_std::string::MoveString; +use moveos_types::moveos_std::account::Account; use moveos_types::moveos_std::move_module::MoveModule; -use moveos_types::state::ObjectState; +use moveos_types::moveos_std::object::{ObjectID, ObjectMeta, RawField}; +use moveos_types::state::{FieldKey, MoveType, ObjectState}; +use moveos_types::state_resolver::{StateKV, StateResolver, StatelessResolver}; use moveos_types::{ function_return_value::FunctionResult, module_binding::MoveFunctionCaller, moveos_std::tx_context::TxContext, transaction::FunctionCall, @@ -109,7 +114,7 @@ impl ModuleResolver for &Client { fn get_module(&self, id: &ModuleId) -> Result>> { tokio::task::block_in_place(|| { Handle::current().block_on(async { - let mut states = self.rooch.get_states(AccessPath::module(id)).await?; + let mut states = self.rooch.get_states(None, AccessPath::module(id)).await?; states .pop() .flatten() @@ -123,3 +128,111 @@ impl ModuleResolver for &Client { }) } } + +#[derive(Clone)] +pub struct ClientResolver { + root: ObjectMeta, + client: Client, +} + +impl ClientResolver { + pub fn new(client: Client, root: ObjectMeta) -> Self { + Self { root, client } + } +} + +impl ResourceResolver for ClientResolver { + fn get_resource_with_metadata( + &self, + address: &AccountAddress, + resource_tag: &StructTag, + _metadata: &[Metadata], + ) -> std::result::Result<(Option>, usize), Error> { + let account_object_id = Account::account_object_id(*address); + + let key = FieldKey::derive_resource_key(resource_tag); + let result = self + .get_field(&account_object_id, &key)? + .map(|s| { + ensure!( + s.match_dynamic_field_type(MoveString::type_tag(), resource_tag.clone().into()), + "Resource type mismatch, expected field value type: {:?}, actual: {:?}", + resource_tag, + s.object_type() + ); + let field = RawField::parse_resource_field(&s.value, resource_tag.clone().into())?; + Ok(field.value) + }) + .transpose(); + + match result { + Ok(opt) => { + if let Some(data) = opt { + Ok((Some(data), 0)) + } else { + Ok((None, 0)) + } + } + Err(err) => Err(err), + } + } +} + +impl ModuleResolver for ClientResolver { + fn get_module_metadata(&self, _module_id: &ModuleId) -> Vec { + vec![] + } + + fn get_module(&self, id: &ModuleId) -> std::result::Result>, Error> { + (&self.client).get_module(id) + } +} + +impl StatelessResolver for ClientResolver { + fn get_field_at(&self, state_root: H256, key: &FieldKey) -> Result, Error> { + tokio::task::block_in_place(|| { + Handle::current().block_on(async { + let access_path = AccessPath::object(ObjectID::new(key.0)); + let mut object_state_view_list = self + .client + .rooch + .get_states(Some(hex::encode(state_root.0.as_slice())), access_path) + .await?; + Ok(object_state_view_list.pop().flatten().map(|state_view| { + let v: ObjectState = state_view.into(); + v + })) + }) + }) + } + + fn list_fields_at( + &self, + state_root: H256, + cursor: Option, + limit: usize, + ) -> Result> { + tokio::task::block_in_place(|| { + Handle::current().block_on(async { + let object_id = ObjectID::new(state_root.0); + let field_cursor = cursor.map(|field_key| field_key.to_hex_literal()); + let fields_states = self + .client + .rooch + .list_field_states(object_id.into(), field_cursor, Some(limit as u64), None) + .await?; + Ok(fields_states + .data + .iter() + .map(|item| StateKV::from((item.field_key.into(), item.state.clone().into()))) + .collect()) + }) + }) + } +} + +impl StateResolver for ClientResolver { + fn root(&self) -> &ObjectMeta { + &self.root + } +} diff --git a/crates/rooch-rpc-client/src/rooch_client.rs b/crates/rooch-rpc-client/src/rooch_client.rs index cdd57c3d46..4dfd97440e 100644 --- a/crates/rooch-rpc-client/src/rooch_client.rs +++ b/crates/rooch-rpc-client/src/rooch_client.rs @@ -91,18 +91,24 @@ impl RoochRpcClient { pub async fn get_states( &self, + state_root: Option, access_path: AccessPath, ) -> Result>> { - Ok(self.http.get_states(access_path.into(), None).await?) + Ok(self + .http + .get_states(state_root, access_path.into(), None) + .await?) } pub async fn get_decoded_states( &self, + state_root: Option, access_path: AccessPath, ) -> Result>> { Ok(self .http .get_states( + state_root, access_path.into(), Some(StateOptions::default().decode(true)), ) @@ -116,6 +122,7 @@ impl RoochRpcClient { Ok(self .http .get_states( + None, access_path.into(), Some(StateOptions::default().decode(true).show_display(true)), ) @@ -168,9 +175,10 @@ impl RoochRpcClient { pub async fn get_sequence_number(&self, sender: RoochAddress) -> Result { Ok(self - .get_states(AccessPath::object(Account::account_object_id( - sender.into(), - ))) + .get_states( + None, + AccessPath::object(Account::account_object_id(sender.into())), + ) .await? .pop() .flatten() @@ -375,7 +383,7 @@ impl RoochRpcClient { account: RoochAddress, ) -> Result> { let access_path = AccessPath::resource(account.into(), T::struct_tag()); - let mut states = self.get_states(access_path).await?; + let mut states = self.get_states(None, access_path).await?; let state = states.pop().flatten(); if let Some(state) = state { let state = ObjectState::from(state); diff --git a/crates/rooch-rpc-server/src/server/rooch_server.rs b/crates/rooch-rpc-server/src/server/rooch_server.rs index db24f57402..d0cc93dbb9 100644 --- a/crates/rooch-rpc-server/src/server/rooch_server.rs +++ b/crates/rooch-rpc-server/src/server/rooch_server.rs @@ -195,6 +195,7 @@ impl RoochAPIServer for RoochServer { async fn get_states( &self, + state_root: Option, access_path: AccessPathView, state_option: Option, ) -> RpcResult>> { @@ -212,7 +213,7 @@ impl RoochAPIServer for RoochServer { let valid_states = states.iter().filter_map(|s| s.as_ref()).collect::>(); let mut valid_display_field_views = self .rpc_service - .get_display_fields_and_render(valid_states.as_slice()) + .get_display_fields_and_render(state_root, valid_states.as_slice()) .await?; valid_display_field_views.reverse(); states @@ -236,7 +237,7 @@ impl RoochAPIServer for RoochServer { } } else { self.rpc_service - .get_states(access_path.into()) + .get_states(state_root, access_path.into()) .await? .into_iter() .map(|s| s.map(ObjectStateView::from)) @@ -275,7 +276,7 @@ impl RoochAPIServer for RoochServer { if show_display { let display_field_views = self .rpc_service - .get_display_fields_and_render(state_refs.as_slice()) + .get_display_fields_and_render(None, state_refs.as_slice()) .await?; key_states .into_iter() @@ -335,7 +336,7 @@ impl RoochAPIServer for RoochServer { let mut valid_display_field_views = if show_display { let valid_states = states.iter().filter_map(|s| s.as_ref()).collect::>(); self.rpc_service - .get_display_fields_and_render(valid_states.as_slice()) + .get_display_fields_and_render(None, valid_states.as_slice()) .await? } else { vec![] @@ -368,7 +369,7 @@ impl RoochAPIServer for RoochServer { } } else { self.rpc_service - .get_states(access_path) + .get_states(None, access_path) .await? .into_iter() .map(|s| s.map(Into::into)) @@ -621,7 +622,7 @@ impl RoochAPIServer for RoochServer { let access_path = AccessPath::module(&module_id); let module = self .rpc_service - .get_states(access_path) + .get_states(None, access_path) .await? .pop() .flatten(); diff --git a/crates/rooch-rpc-server/src/service/aggregate_service.rs b/crates/rooch-rpc-server/src/service/aggregate_service.rs index 7315bfcd5a..9bb3cf7098 100644 --- a/crates/rooch-rpc-server/src/service/aggregate_service.rs +++ b/crates/rooch-rpc-server/src/service/aggregate_service.rs @@ -45,7 +45,7 @@ impl AggregateService { .collect(), ); self.rpc_service - .get_states(access_path) + .get_states(None, access_path) .await? .into_iter() .zip(coin_types) @@ -72,7 +72,7 @@ impl AggregateService { ) -> Result>> { let access_path = AccessPath::objects(coin_store_ids); self.rpc_service - .get_states(access_path) + .get_states(None, access_path) .await? .into_iter() .map(|state_opt| state_opt.map(CoinStoreInfo::try_from).transpose()) diff --git a/crates/rooch-rpc-server/src/service/rpc_service.rs b/crates/rooch-rpc-server/src/service/rpc_service.rs index 57f3f9276e..7d25db328f 100644 --- a/crates/rooch-rpc-server/src/service/rpc_service.rs +++ b/crates/rooch-rpc-server/src/service/rpc_service.rs @@ -112,12 +112,18 @@ impl RpcService { Ok(resp) } - pub async fn get_states(&self, access_path: AccessPath) -> Result>> { - self.executor.get_states(access_path).await + pub async fn get_states( + &self, + state_root: Option, + access_path: AccessPath, + ) -> Result>> { + self.executor.get_states(state_root, access_path).await } pub async fn exists_module(&self, module_id: ModuleId) -> Result { - let mut resp = self.get_states(AccessPath::module(&module_id)).await?; + let mut resp = self + .get_states(None, AccessPath::module(&module_id)) + .await?; Ok(resp.pop().flatten().is_some()) } @@ -367,8 +373,9 @@ impl RpcService { .iter() .filter_map(|s| s.as_ref()) .collect::>(); - let valid_display_field_views = - self.get_display_fields_and_render(&valid_states).await?; + let valid_display_field_views = self + .get_display_fields_and_render(None, &valid_states) + .await?; valid_states .iter() .zip(valid_display_field_views) @@ -405,7 +412,7 @@ impl RpcService { } object_states } else { - let states = self.get_states(access_path).await?; + let states = self.get_states(None, access_path).await?; states .into_iter() .zip(indexer_ids) @@ -466,7 +473,7 @@ impl RpcService { let access_path = AccessPath::fields(mapping_object_id, owner_keys); let address_mapping = self - .get_states(access_path) + .get_states(None, access_path) .await? .into_iter() .zip(user_addresses) @@ -488,6 +495,7 @@ impl RpcService { pub async fn get_display_fields_and_render( &self, + state_root: Option, states: &[&AnnotatedState], ) -> Result>> { let mut display_ids = vec![]; @@ -504,7 +512,7 @@ impl RpcService { // get display fields let path = AccessPath::objects(display_ids); let mut display_fields = self - .get_states(path) + .get_states(state_root, path) .await? .into_iter() .map(|option_s| { @@ -596,7 +604,7 @@ impl RpcService { ) -> Result<()> { { let states = self - .get_states(AccessPath::objects(object_ids.clone())) + .get_states(None, AccessPath::objects(object_ids.clone())) .await?; let mut remove_object_ids = vec![]; diff --git a/crates/rooch/src/commands/resource.rs b/crates/rooch/src/commands/resource.rs index 8d913b9c5a..2aadca9617 100644 --- a/crates/rooch/src/commands/resource.rs +++ b/crates/rooch/src/commands/resource.rs @@ -49,7 +49,7 @@ impl CommandAction> for ResourceCommand { } else { client .rooch - .get_decoded_states(AccessPath::resource(address, resource)) + .get_decoded_states(None, AccessPath::resource(address, resource)) .await? .pop() .flatten() diff --git a/crates/rooch/src/commands/state.rs b/crates/rooch/src/commands/state.rs index 74e04a0b98..770eb55f1c 100644 --- a/crates/rooch/src/commands/state.rs +++ b/crates/rooch/src/commands/state.rs @@ -42,7 +42,7 @@ impl CommandAction>> for StateCommand { } else { client .rooch - .get_decoded_states(self.access_path) + .get_decoded_states(None, self.access_path) .await .map_err(RoochError::from)? }; diff --git a/crates/rooch/src/lib.rs b/crates/rooch/src/lib.rs index 5f8694c287..bbeaa0f7b2 100644 --- a/crates/rooch/src/lib.rs +++ b/crates/rooch/src/lib.rs @@ -23,6 +23,8 @@ pub mod cli_types; pub mod commands; pub mod utils; +pub mod tx_runner; + #[derive(clap::Parser)] #[clap(author, long_version = LONG_VERSION.as_str(), about, long_about = None, styles = Styles::styled() diff --git a/crates/rooch/src/tx_runner.rs b/crates/rooch/src/tx_runner.rs new file mode 100644 index 0000000000..351d38a75a --- /dev/null +++ b/crates/rooch/src/tx_runner.rs @@ -0,0 +1,127 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + +use move_core_types::vm_status::KeptVMStatus::Executed; +use moveos::gas::table::{get_gas_schedule_entries, initial_cost_schedule, MoveOSGasMeter}; +use moveos::moveos::MoveOSConfig; +use moveos::vm::moveos_vm::{MoveOSSession, MoveOSVM}; +use moveos_common::types::ClassifiedGasMeter; +use moveos_object_runtime::runtime::ObjectRuntime; +use moveos_types::h256::H256; +use moveos_types::move_std::option::MoveOption; +use moveos_types::moveos_std::object::ObjectMeta; +use moveos_types::moveos_std::tx_context::TxContext; +use moveos_types::transaction::{MoveAction, VerifiedMoveAction, VerifiedMoveOSTransaction}; +use parking_lot::RwLock; +use rooch_genesis::FrameworksGasParameters; +use rooch_rpc_client::{Client, ClientResolver}; +use rooch_types::address::{BitcoinAddress, MultiChainAddress}; +use rooch_types::framework::auth_validator::{BuiltinAuthValidator, TxValidateResult}; +use rooch_types::framework::system_pre_execute_functions; +use rooch_types::transaction::RoochTransactionData; +use std::rc::Rc; +use std::str::FromStr; + +pub fn execute_tx_locally(state_root_str: String, client: Client, tx: RoochTransactionData) { + let hex_bytes = hex::decode(state_root_str.as_bytes()).expect("decode root state failed"); + let state_root = H256::from_slice(hex_bytes.as_slice()); + let root_object_meta = ObjectMeta::root_metadata(state_root, 55); + let client_resolver = ClientResolver::new(client, root_object_meta.clone()); + + let gas_entries = get_gas_schedule_entries(&client_resolver).unwrap(); + let cost_table = initial_cost_schedule(gas_entries); + + let mut gas_meter = MoveOSGasMeter::new(cost_table, 1000000000); + gas_meter.charge_io_write(tx.tx_size()).unwrap(); + + let verified_tx = convert_to_verified_tx(root_object_meta.clone(), tx) + .expect("convert_to_verified_tx failed"); + + let VerifiedMoveOSTransaction { + root: _, + ctx, + action, + } = verified_tx; + + let gas_parameters = + FrameworksGasParameters::load_from_chain(&client_resolver).expect("load_from_chain failed"); + + let object_runtime = Rc::new(RwLock::new(ObjectRuntime::new( + ctx, + root_object_meta.clone(), + &client_resolver, + ))); + + let vm = MoveOSVM::new( + gas_parameters.all_natives(), + MoveOSConfig::default().vm_config, + ) + .expect("create MoveVM failed"); + + let mut moveos_session = MoveOSSession::new( + vm.inner(), + &client_resolver, + object_runtime, + gas_meter, + false, + ); + + let system_pre_execute_functions = system_pre_execute_functions(); + + moveos_session + .execute_function_call(system_pre_execute_functions, false) + .expect("system_pre_execute_functions execution failed"); + + moveos_session + .execute_move_action(action) + .expect("execute_move_action failed"); + + let _result = moveos_session.finish_with_extensions(Executed); +} + +fn convert_to_verified_tx( + root: ObjectMeta, + tx_data: RoochTransactionData, +) -> anyhow::Result { + let mut tx_ctx = TxContext::new( + tx_data.sender.into(), + tx_data.sequence_number, + tx_data.max_gas_amount, + tx_data.tx_hash(), + tx_data.tx_size(), + ); + + let mut bitcoin_address = BitcoinAddress::from_str("18cBEMRxXHqzWWCxZNtU91F5sbUNKhL5PX")?; + + let user_multi_chain_address: MultiChainAddress = tx_data.sender.into(); + if user_multi_chain_address.is_bitcoin_address() { + bitcoin_address = user_multi_chain_address.try_into()?; + } + + let dummy_result = TxValidateResult { + auth_validator_id: BuiltinAuthValidator::Bitcoin.flag().into(), + auth_validator: MoveOption::none(), + session_key: MoveOption::none(), + bitcoin_address, + }; + + tx_ctx.add(dummy_result)?; + + let verified_action = match tx_data.action { + MoveAction::Script(script_call) => VerifiedMoveAction::Script { call: script_call }, + MoveAction::Function(function_call) => VerifiedMoveAction::Function { + call: function_call, + bypass_visibility: false, + }, + MoveAction::ModuleBundle(module_bundle) => VerifiedMoveAction::ModuleBundle { + module_bundle, + init_function_modules: vec![], + }, + }; + + Ok(VerifiedMoveOSTransaction::new( + root, + tx_ctx, + verified_action, + )) +} diff --git a/moveos/moveos/src/vm/moveos_vm.rs b/moveos/moveos/src/vm/moveos_vm.rs index 06af6f60c3..483c50da32 100644 --- a/moveos/moveos/src/vm/moveos_vm.rs +++ b/moveos/moveos/src/vm/moveos_vm.rs @@ -125,6 +125,10 @@ impl MoveOSVM { pub fn mark_loader_cache_as_invalid(&self) { self.inner.mark_loader_cache_as_invalid() } + + pub fn inner(&self) -> &MoveVM { + &self.inner + } } /// MoveOSSession is a wrapper of MoveVM session with MoveOS specific features. @@ -299,7 +303,7 @@ where /// The caller should ensure call verify_move_action before execute. /// Once we start executing transactions, we must ensure that the transaction execution has a result, regardless of success or failure, /// and we need to save the result and deduct gas - pub(crate) fn execute_move_action(&mut self, action: VerifiedMoveAction) -> VMResult<()> { + pub fn execute_move_action(&mut self, action: VerifiedMoveAction) -> VMResult<()> { let action_result = match action { VerifiedMoveAction::Script { call } => { let loaded_function = self @@ -670,7 +674,7 @@ where )) } - pub(crate) fn execute_function_call( + pub fn execute_function_call( &mut self, functions: Vec, meter_gas: bool,