From ed3ffa9753272422a6ea26b9ee4d2cd88fa89b33 Mon Sep 17 00:00:00 2001 From: Ivan Kalinin Date: Mon, 10 Feb 2025 17:43:43 +0100 Subject: [PATCH] feat(collator): use `tycho-executor` --- Cargo.lock | 37 ++- Cargo.toml | 7 +- cli/src/cmd/tools/gen_account.rs | 2 - cli/src/cmd/tools/gen_zerostate.rs | 5 - cli/src/util/jrpc_client.rs | 5 - cli/src/util/mod.rs | 3 - collator/Cargo.toml | 4 +- .../collator/do_collate/execution_wrapper.rs | 38 +-- collator/src/collator/do_collate/finalize.rs | 4 +- collator/src/collator/do_collate/prepare.rs | 37 +-- collator/src/collator/execution_manager.rs | 268 +++++++++--------- collator/src/collator/types.rs | 41 ++- rpc/src/models.rs | 3 - 13 files changed, 216 insertions(+), 238 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d517bf4bd..aa9c3dae4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -947,7 +947,7 @@ dependencies = [ [[package]] name = "everscale-types" version = "0.1.2" -source = "git+https://github.com/broxus/everscale-types.git?rev=adada6e6539abd798dbbc5a7fc1d17cc31fa7eff#adada6e6539abd798dbbc5a7fc1d17cc31fa7eff" +source = "git+https://github.com/broxus/everscale-types.git?rev=f0d46607c19c9657b90360b4bc5c229a56540ffa#f0d46607c19c9657b90360b4bc5c229a56540ffa" dependencies = [ "ahash", "anyhow", @@ -976,7 +976,7 @@ dependencies = [ [[package]] name = "everscale-types-proc" version = "0.1.5" -source = "git+https://github.com/broxus/everscale-types.git?rev=adada6e6539abd798dbbc5a7fc1d17cc31fa7eff#adada6e6539abd798dbbc5a7fc1d17cc31fa7eff" +source = "git+https://github.com/broxus/everscale-types.git?rev=f0d46607c19c9657b90360b4bc5c229a56540ffa#f0d46607c19c9657b90360b4bc5c229a56540ffa" dependencies = [ "proc-macro2", "quote", @@ -3250,20 +3250,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "ton_executor" -version = "2.0.0" -source = "git+https://github.com/broxus/ton-labs-executor.git?rev=de566312176aa524d4afc26a04c931f97079b77f#de566312176aa524d4afc26a04c931f97079b77f" -dependencies = [ - "ahash", - "anyhow", - "everscale-types", - "num-bigint", - "thiserror 2.0.11", - "tracing", - "tycho-vm", -] - [[package]] name = "tower" version = "0.5.1" @@ -3554,7 +3540,6 @@ dependencies = [ "tl-proto", "tokio", "tokio-util", - "ton_executor", "tracing", "tracing-subscriber", "trait-variant", @@ -3562,6 +3547,7 @@ dependencies = [ "tycho-collator", "tycho-consensus", "tycho-core", + "tycho-executor", "tycho-network", "tycho-storage", "tycho-util", @@ -3661,6 +3647,19 @@ dependencies = [ "tycho-util", ] +[[package]] +name = "tycho-executor" +version = "0.1.0" +source = "git+https://github.com/broxus/tycho-vm.git?rev=40d3962ccc5892da6ced5aef360bf705dda5171f#40d3962ccc5892da6ced5aef360bf705dda5171f" +dependencies = [ + "ahash", + "anyhow", + "everscale-types", + "num-bigint", + "thiserror 2.0.11", + "tycho-vm", +] + [[package]] name = "tycho-gen-protos" version = "0.2.3" @@ -3857,7 +3856,7 @@ dependencies = [ [[package]] name = "tycho-vm" version = "0.1.0" -source = "git+https://github.com/broxus/tycho-vm.git#9bd83c7e990ea0c3f28fd1979a35256983338346" +source = "git+https://github.com/broxus/tycho-vm.git?rev=40d3962ccc5892da6ced5aef360bf705dda5171f#40d3962ccc5892da6ced5aef360bf705dda5171f" dependencies = [ "ahash", "anyhow", @@ -3878,7 +3877,7 @@ dependencies = [ [[package]] name = "tycho-vm-proc" version = "0.1.0" -source = "git+https://github.com/broxus/tycho-vm.git#9bd83c7e990ea0c3f28fd1979a35256983338346" +source = "git+https://github.com/broxus/tycho-vm.git?rev=40d3962ccc5892da6ced5aef360bf705dda5171f#40d3962ccc5892da6ced5aef360bf705dda5171f" dependencies = [ "darling", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index f66a95c5f..d1f239c0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,9 +117,8 @@ weedb = "0.4.1" zstd-safe = "7.2" zstd-sys = "2.0" -# TODO: RIIR -ton_executor = { git = "https://github.com/broxus/ton-labs-executor.git", rev = "de566312176aa524d4afc26a04c931f97079b77f" } -tycho-vm = { git = "https://github.com/broxus/tycho-vm.git" } +tycho-executor = { git = "https://github.com/broxus/tycho-vm.git", rev = "40d3962ccc5892da6ced5aef360bf705dda5171f" } +tycho-vm = { git = "https://github.com/broxus/tycho-vm.git", rev = "40d3962ccc5892da6ced5aef360bf705dda5171f" } # local deps tycho-block-util = { path = "./block-util", version = "0.2.3" } @@ -133,7 +132,7 @@ tycho-storage = { path = "./storage", version = "0.2.3" } tycho-util = { path = "./util", version = "0.2.3" } [patch.crates-io] -everscale-types = { git = "https://github.com/broxus/everscale-types.git", rev = "adada6e6539abd798dbbc5a7fc1d17cc31fa7eff" } +everscale-types = { git = "https://github.com/broxus/everscale-types.git", rev = "f0d46607c19c9657b90360b4bc5c229a56540ffa" } [workspace.lints.rust] future_incompatible = "warn" diff --git a/cli/src/cmd/tools/gen_account.rs b/cli/src/cmd/tools/gen_account.rs index da8595b0c..5864b845b 100644 --- a/cli/src/cmd/tools/gen_account.rs +++ b/cli/src/cmd/tools/gen_account.rs @@ -179,7 +179,6 @@ impl WalletBuilder { last_trans_lt: 0, balance: self.balance.into(), state: AccountState::Active(state_init), - init_code_hash: None, }; account.storage_stat.used = compute_storage_used(&account)?; @@ -332,7 +331,6 @@ impl MultisigBuilder { last_trans_lt: 0, balance: self.balance.into(), state: AccountState::Active(state_init), - init_code_hash: None, }; account.storage_stat.used = compute_storage_used(&account)?; diff --git a/cli/src/cmd/tools/gen_zerostate.rs b/cli/src/cmd/tools/gen_zerostate.rs index f7065f67e..4d1609e85 100644 --- a/cli/src/cmd/tools/gen_zerostate.rs +++ b/cli/src/cmd/tools/gen_zerostate.rs @@ -410,8 +410,6 @@ impl ZerostateConfig { split_merge_at: None, fees_collected: CurrencyCollection::ZERO, funds_created: CurrencyCollection::ZERO, - copyleft_rewards: Dict::new(), - proof_chain: None, })); } @@ -446,7 +444,6 @@ impl ZerostateConfig { last_key_block: None, block_create_stats: None, global_balance: state.total_balance.clone(), - copyleft_rewards: Dict::new(), })?); Ok(state) @@ -852,7 +849,6 @@ fn build_config_account( data: Some(data), libraries: Dict::new(), }), - init_code_hash: None, }; account.storage_stat.used = compute_storage_used(&account)?; @@ -887,7 +883,6 @@ fn build_elector_code(address: &HashBytes, balance: Tokens) -> Result { data: Some(data), libraries: Dict::new(), }), - init_code_hash: None, }; account.storage_stat.used = compute_storage_used(&account)?; diff --git a/cli/src/util/jrpc_client.rs b/cli/src/util/jrpc_client.rs index 49bc4a4f6..f2c394ecf 100644 --- a/cli/src/util/jrpc_client.rs +++ b/cli/src/util/jrpc_client.rs @@ -123,11 +123,6 @@ where last_trans_lt: <_>::load_from(s)?, balance: <_>::load_from(s)?, state: <_>::load_from(s)?, - init_code_hash: if s.is_data_empty() { - None - } else { - Some(<_>::load_from(s)?) - }, })) } diff --git a/cli/src/util/mod.rs b/cli/src/util/mod.rs index 9508657bd..9a8e8cef1 100644 --- a/cli/src/util/mod.rs +++ b/cli/src/util/mod.rs @@ -41,9 +41,6 @@ pub fn compute_storage_used(account: &Account) -> Result { storage.store_u64(account.last_trans_lt)?; account.balance.store_into(&mut storage, cx)?; account.state.store_into(&mut storage, cx)?; - if account.init_code_hash.is_some() { - account.init_code_hash.store_into(&mut storage, cx)?; - } storage.build_ext(cx)? }; diff --git a/collator/Cargo.toml b/collator/Cargo.toml index 1295ecaea..402b94765 100644 --- a/collator/Cargo.toml +++ b/collator/Cargo.toml @@ -36,7 +36,6 @@ thiserror = { workspace = true } tl-proto = { workspace = true } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] } tokio-util = { workspace = true } -ton_executor = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } trait-variant = { workspace = true } @@ -45,9 +44,10 @@ trait-variant = { workspace = true } tycho-block-util = { workspace = true } tycho-consensus = { workspace = true } tycho-core = { workspace = true } +tycho-executor = { workspace = true } tycho-network = { workspace = true } tycho-storage = { workspace = true } -tycho-util = { workspace = true } +tycho-util = { workspace = true, features = ["bc"] } tycho-vm = { workspace = true } [dev-dependencies] diff --git a/collator/src/collator/do_collate/execution_wrapper.rs b/collator/src/collator/do_collate/execution_wrapper.rs index 145202889..b8ee697e4 100644 --- a/collator/src/collator/do_collate/execution_wrapper.rs +++ b/collator/src/collator/do_collate/execution_wrapper.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use anyhow::{bail, Result}; +use anyhow::{bail, Context, Result}; use everscale_types::cell::{CellBuilder, CellSlice, HashBytes}; use everscale_types::models::{ BaseMessage, BlockchainConfig, CurrencyCollection, ImportFees, InMsg, InMsgExternal, @@ -8,12 +8,12 @@ use everscale_types::models::{ OutMsgDequeueImmediate, OutMsgExternal, OutMsgImmediate, OutMsgNew, ShardIdent, TickTock, Transaction, }; -use ton_executor::ExecutedTransaction; use tycho_block_util::queue::QueueKey; use crate::collator::execution_manager::MessagesExecutor; use crate::collator::types::{ - BlockCollationData, ParsedMessage, PreparedInMsg, PreparedOutMsg, SpecialOrigin, + BlockCollationData, ExecutedTransaction, ParsedMessage, PreparedInMsg, PreparedOutMsg, + SpecialOrigin, }; use crate::internal_queue::types::EnqueuedMessage; use crate::tracing_targets; @@ -159,7 +159,9 @@ impl ExecutorWrapper { .executor .execute_ordinary_transaction(account_stuff, in_message)?; - let executor_output = executed.result?; + let executor_output = executed + .result + .context("special transactions can't be skipped")?; self.process_transaction(executor_output, Some(executed.in_message), collation_data) } @@ -196,29 +198,32 @@ impl ExecutorWrapper { fn create_ticktock_transaction( &mut self, account_id: &HashBytes, - tick_tock: TickTock, + kind: TickTock, collation_data: &mut BlockCollationData, ) -> Result>> { tracing::trace!( target: tracing_targets::COLLATOR, account_addr = %account_id, - kind = ?tick_tock, + ?kind, "create_ticktock_transaction", ); let Some(account_stuff) = self.executor - .take_account_stuff_if(account_id, |stuff| match tick_tock { + .take_account_stuff_if(account_id, |stuff| match kind { TickTock::Tick => stuff.special.tick, TickTock::Tock => stuff.special.tock, })? else { - return Ok(vec![]); + return Ok(Vec::new()); }; - let executor_output = self + let Some(executor_output) = self .executor - .execute_ticktock_transaction(account_stuff, tick_tock)?; + .execute_ticktock_transaction(account_stuff, kind)? + else { + return Ok(Vec::new()); + }; self.process_transaction(executor_output, None, collation_data) } @@ -250,10 +255,9 @@ fn new_transaction( let mut out_messages = vec![]; - for out_msg_cell in executed.out_msgs.values() { - let out_msg_cell = out_msg_cell?; - let out_msg_hash = *out_msg_cell.repr_hash(); - let out_msg_info = out_msg_cell.parse::()?; + for out_msg_cell in executed.out_msgs { + let out_msg_hash = *out_msg_cell.inner().repr_hash(); + let out_msg_info = out_msg_cell.inner().parse::()?; tracing::trace!( target: tracing_targets::COLLATOR, @@ -279,7 +283,7 @@ fn new_transaction( IntermediateAddr::FULL_SRC_SAME_WORKCHAIN }, fwd_fee_remaining: *fwd_fee, - message: Lazy::from_raw(out_msg_cell.clone()), + message: out_msg_cell.clone(), })?, transaction: executed.transaction.clone(), }); @@ -295,7 +299,7 @@ fn new_transaction( out_messages.push(Box::new(ParsedMessage { info: out_msg_info, dst_in_current_shard, - cell: out_msg_cell, + cell: out_msg_cell.into_inner(), special_origin: None, block_seqno: Some(collation_data.block_id_short.seqno), from_same_shard: Some(true), @@ -303,7 +307,7 @@ fn new_transaction( } MsgInfo::ExtOut(_) => { let out_msg = OutMsg::External(OutMsgExternal { - out_msg: Lazy::from_raw(out_msg_cell), + out_msg: out_msg_cell, transaction: executed.transaction.clone(), }); diff --git a/collator/src/collator/do_collate/finalize.rs b/collator/src/collator/do_collate/finalize.rs index 9bc59fb92..fee13123e 100644 --- a/collator/src/collator/do_collate/finalize.rs +++ b/collator/src/collator/do_collate/finalize.rs @@ -228,7 +228,7 @@ impl Phase { let executor = self.extra.executor; // update shard accounts tree and prepare accounts blocks - let mut global_libraries = executor.executor_params().state_libs.clone(); + let mut global_libraries = executor.executor_params().libraries.clone(); let is_masterchain = shard.is_masterchain(); let config_address = &self.state.mc_data.config.address; @@ -537,7 +537,6 @@ impl Phase { .as_ref() .map(Lazy::new) .transpose()?, - copyleft_msgs: Default::default(), config: if mc_state_extra.after_key_block { Some(mc_state_extra.config.clone()) } else { @@ -990,7 +989,6 @@ impl Phase { last_key_block, block_create_stats, global_balance, - copyleft_rewards: Default::default(), }; Ok((mc_state_extra, min_ref_mc_seqno)) diff --git a/collator/src/collator/do_collate/prepare.rs b/collator/src/collator/do_collate/prepare.rs index 54c9631dc..e37116d7b 100644 --- a/collator/src/collator/do_collate/prepare.rs +++ b/collator/src/collator/do_collate/prepare.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use anyhow::Result; use everscale_types::models::GlobalCapability; -use ton_executor::{ExecuteParams, PreloadedBlockchainConfig}; +use tycho_executor::{ExecutorParams, ParsedConfig}; use super::execute::ExecuteState; use super::execution_wrapper::ExecutorWrapper; @@ -48,38 +48,31 @@ impl Phase { ); // init executor - let preloaded_bc_config = Arc::new(PreloadedBlockchainConfig::with_config( - self.state.mc_data.config.clone(), - self.state.mc_data.global_id, + let preloaded_bc_config = Arc::new(ParsedConfig::parse( + self.state.mc_data.config.params.clone(), + self.state.collation_data.gen_utime, )?); - let block_version = preloaded_bc_config.global_version().version; - let signature_with_id = if preloaded_bc_config - .global_version() - .capabilities - .contains(GlobalCapability::CapSignatureWithId) - { - Some(self.state.mc_data.global_id) - } else { - None - }; + let capabilities = preloaded_bc_config.global.capabilities; let executor = MessagesExecutor::new( self.state.shard_id, self.state.collation_data.next_lt, preloaded_bc_config, - Arc::new(ExecuteParams { - state_libs: self.state.mc_data.libraries.clone(), + Arc::new(ExecutorParams { + libraries: self.state.mc_data.libraries.clone(), // generated unix time block_unixtime: self.state.collation_data.gen_utime, // block's start logical time block_lt: self.state.collation_data.start_lt, // block random seed - seed_block: self.state.collation_data.rand_seed, - block_version, - behavior_modifiers: Some(tycho_vm::BehaviourModifiers { - signature_with_id, + rand_seed: self.state.collation_data.rand_seed, + allow_delete_frozen_accounts: false, + full_body_in_bounce: capabilities.contains(GlobalCapability::CapFullBodyInBounced), + vm_modifiers: tycho_vm::BehaviourModifiers { + signature_with_id: capabilities + .contains(GlobalCapability::CapSignatureWithId) + .then_some(self.state.mc_data.global_id), ..Default::default() - }), - debug: false, + }, }), self.state.prev_shard_data.observable_accounts().clone(), self.state diff --git a/collator/src/collator/execution_manager.rs b/collator/src/collator/execution_manager.rs index d3caef393..cf31ecb5a 100644 --- a/collator/src/collator/execution_manager.rs +++ b/collator/src/collator/execution_manager.rs @@ -8,16 +8,12 @@ use everscale_types::cell::HashBytes; use everscale_types::models::*; use humantime::format_duration; use rayon::prelude::*; -use ton_executor::{ - ExecuteParams, ExecutedTransaction, ExecutorOutput, OrdinaryTransactionExecutor, - PreloadedBlockchainConfig, TickTockTransactionExecutor, TransactionExecutor, -}; +use tycho_executor::{Executor, ExecutorParams, ParsedConfig, TxError}; use tycho_util::metrics::HistogramGuard; use tycho_util::FastHashMap; -use tycho_vm::{SafeRc, SmcInfoTonV6, Tuple}; use super::messages_buffer::MessageGroup; -use super::types::{AccountId, ParsedMessage, ShardAccountStuff}; +use super::types::{AccountId, ExecutedTransaction, ParsedMessage, ShardAccountStuff}; use crate::tracing_targets; pub(super) struct MessagesExecutor { @@ -25,9 +21,9 @@ pub(super) struct MessagesExecutor { // this time is used if account's lt is smaller min_next_lt: u64, /// blockchain config - config: Arc, + config: Arc, /// vm execution params related to current block - params: Arc, + params: Arc, /// shard accounts accounts_cache: AccountsCache, /// Params to calculate messages execution work in work units @@ -38,8 +34,8 @@ impl MessagesExecutor { pub fn new( shard_id: ShardIdent, min_next_lt: u64, - config: Arc, - params: Arc, + config: Arc, + params: Arc, shard_accounts: ShardAccounts, wu_params_execute: WorkUnitsParamsExecute, ) -> Self { @@ -49,6 +45,8 @@ impl MessagesExecutor { config, params, accounts_cache: AccountsCache { + // TODO: Better handle workchains out of range. + workchain_id: shard_id.workchain().try_into().unwrap(), shard_accounts, items: Default::default(), }, @@ -60,7 +58,7 @@ impl MessagesExecutor { self.min_next_lt } - pub fn executor_params(&self) -> &Arc { + pub fn executor_params(&self) -> &Arc { &self.params } @@ -73,6 +71,7 @@ impl MessagesExecutor { let AccountsCache { shard_accounts, items, + .. } = self.accounts_cache; (items.into_values(), shard_accounts) } @@ -118,34 +117,16 @@ impl MessagesExecutor { let accounts_cache = Arc::new(&self.accounts_cache); let result = msg_group .into_par_iter() - .map_init( - move || { - // TEMP: There will be a per-thread executor state. - let unpacked = SmcInfoTonV6::unpack_config( - &config.raw_config().params, - params.block_unixtime, - ) - .ok(); - - ( - config.clone(), - params.clone(), - accounts_cache.clone(), - unpacked, - ) - }, - |(config, params, accounts_cache, unpacked), (account_id, msgs)| { - Self::execute_subgroup( - account_id, - msgs, - accounts_cache, - min_next_lt, - config, - unpacked.clone().unwrap_or_default(), - params, - ) - }, - ) + .map(|(account_id, msgs)| { + Self::execute_subgroup( + account_id, + msgs, + &accounts_cache, + min_next_lt, + &config, + ¶ms, + ) + }) .collect_vec_list(); for result in result { @@ -219,19 +200,11 @@ impl MessagesExecutor { msgs: Vec>, accounts_cache: &AccountsCache, min_next_lt: u64, - config: &Arc, - unpacked_config: SafeRc, - params: &Arc, + config: &ParsedConfig, + params: &ExecutorParams, ) -> Result { let shard_account_stuff = accounts_cache.get_account_stuff(&account_id)?; - Self::execute_messages( - shard_account_stuff, - msgs, - min_next_lt, - config, - unpacked_config, - params, - ) + Self::execute_messages(shard_account_stuff, msgs, min_next_lt, config, params) } #[allow(clippy::too_many_arguments)] @@ -255,20 +228,16 @@ impl MessagesExecutor { *group_max_vert_size = cmp::max(*group_max_vert_size, executed.transactions.len()); for tx in executed.transactions { - if matches!(&tx.in_message.info, MsgInfo::ExtIn(_)) { - if let Err(e) = &tx.result { - tracing::warn!( - target: tracing_targets::EXEC_MANAGER, - account_addr = %executed.account_state.account_addr, - message_hash = %tx.in_message.cell.repr_hash(), - "failed to execute external message: {e:?}", - ); - *ext_msgs_error_count += 1; - continue; - } - } - - let executed = tx.result?; + let Some(executed) = tx.result else { + tracing::warn!( + target: tracing_targets::EXEC_MANAGER, + account_addr = %executed.account_state.account_addr, + message_hash = %tx.in_message.cell.repr_hash(), + "skipped external message", + ); + *ext_msgs_error_count += 1; + continue; + }; self.min_next_lt = cmp::max(self.min_next_lt, executed.next_lt); @@ -300,9 +269,8 @@ impl MessagesExecutor { mut account_state: Box, msgs: Vec>, min_next_lt: u64, - config: &Arc, - unpacked_config: SafeRc, - params: &Arc, + config: &ParsedConfig, + params: &ExecutorParams, ) -> Result { let mut ext_msgs_skipped = 0; let timer = std::time::Instant::now(); @@ -320,7 +288,6 @@ impl MessagesExecutor { msg, min_next_lt, config, - unpacked_config.clone(), params, )?); } @@ -343,21 +310,16 @@ impl MessagesExecutor { let config = self.config.clone(); let params = self.params.clone(); - // TEMP: There will be a per-thread cached state for a new executor. - let unpacked_config = - SmcInfoTonV6::unpack_config(&config.raw_config().params, params.block_unixtime)?; - let (account_stuff, executed) = execute_ordinary_transaction_impl( &mut account_stuff, in_message, min_next_lt, &config, - unpacked_config, ¶ms, ) .map(|executed| (account_stuff, executed))?; - if let Ok(tx) = &executed.result { + if let Some(tx) = &executed.result { self.min_next_lt = cmp::max(min_next_lt, tx.next_lt); } self.accounts_cache.add_account_stuff(account_stuff); @@ -369,32 +331,30 @@ impl MessagesExecutor { &mut self, mut account_stuff: Box, tick_tock: TickTock, - ) -> Result { + ) -> Result> { let min_next_lt = self.min_next_lt; let config = self.config.clone(); let params = self.params.clone(); - // TEMP: There will be a per-thread cached state for a new executor. - let unpacked_config = - SmcInfoTonV6::unpack_config(&config.raw_config().params, params.block_unixtime)?; - - let (account_stuff, executed) = execute_ticktock_transaction( + let Some(executed) = execute_ticktock_transaction( &mut account_stuff, tick_tock, min_next_lt, &config, - unpacked_config, ¶ms, - ) - .map(|executed| (account_stuff, executed))?; + )? + else { + return Ok(None); + }; self.min_next_lt = cmp::max(min_next_lt, executed.next_lt); self.accounts_cache.add_account_stuff(account_stuff); - Ok(executed) + Ok(Some(executed)) } } struct AccountsCache { + workchain_id: i8, shard_accounts: ShardAccounts, items: FastHashMap>, } @@ -416,7 +376,9 @@ impl AccountsCache { } Entry::Vacant(entry) => { if let Some((_, state)) = self.shard_accounts.get(account_id)? { - let account_stuff = ShardAccountStuff::new(account_id, state).map(Box::new)?; + let account_stuff = + ShardAccountStuff::new(self.workchain_id, account_id, state) + .map(Box::new)?; if f(&account_stuff) { return Ok(Some(account_stuff)); } @@ -434,9 +396,12 @@ impl AccountsCache { if let Some(account) = self.items.get(account_id) { Ok(account.clone()) } else if let Some((_depth, shard_account)) = self.shard_accounts.get(account_id)? { - ShardAccountStuff::new(account_id, shard_account).map(Box::new) + ShardAccountStuff::new(self.workchain_id, account_id, shard_account).map(Box::new) } else { - Ok(Box::new(ShardAccountStuff::new_empty(account_id))) + Ok(Box::new(ShardAccountStuff::new_empty( + self.workchain_id, + account_id, + ))) } } @@ -471,7 +436,7 @@ pub struct ExecutedTransactions { } pub struct ExecutedOrdinaryTransaction { - pub result: Result, + pub result: Option, pub in_message: Box, } @@ -479,9 +444,8 @@ fn execute_ordinary_transaction_impl( account_stuff: &mut ShardAccountStuff, in_message: Box, min_lt: u64, - config: &PreloadedBlockchainConfig, - unpacked_config: SafeRc, - params: &ExecuteParams, + config: &ParsedConfig, + params: &ExecutorParams, ) -> Result { tracing::trace!( target: tracing_targets::EXEC_MANAGER, @@ -493,71 +457,93 @@ fn execute_ordinary_transaction_impl( let _histogram = HistogramGuard::begin("tycho_collator_execute_ordinary_time"); - let shard_account = &mut account_stuff.shard_account; - let result = OrdinaryTransactionExecutor::new().execute_with_libs_and_params( - Some(&in_message.cell), - shard_account, - min_lt, - params, - config, - unpacked_config, - ); + let is_external = matches!(in_message.info, MsgInfo::ExtIn(_)); - let result = match result { - Ok(( - total_fees, - ExecutorOutput { - account, - transaction, - }, - )) => { - let tx_lt = shard_account.last_trans_lt; - account_stuff.apply_transaction(tx_lt, total_fees, account, &transaction); - Ok(transaction) + let uncommited = Executor::new(params, config) + .with_min_lt(min_lt) + .begin_ordinary( + &account_stuff.make_std_addr(), + matches!(in_message.info, MsgInfo::ExtIn(_)), + in_message.cell.clone(), + &account_stuff.shard_account, + ); + + let output = match uncommited { + Ok(uncommited) => uncommited.commit()?, + Err(TxError::Skipped) if is_external => { + return Ok(ExecutedOrdinaryTransaction { + result: None, + in_message, + }) } - Err(e) => Err(e), + Err(e) => return Err(e.into()), }; - Ok(ExecutedOrdinaryTransaction { result, in_message }) + let tx_lt = output.new_state.last_trans_lt; + + account_stuff.shard_account = output.new_state; + account_stuff.apply_transaction( + tx_lt, + output.transaction_meta.total_fees, + output.new_state_meta, + output.transaction.clone(), + ); + + Ok(ExecutedOrdinaryTransaction { + result: Some(ExecutedTransaction { + transaction: output.transaction, + out_msgs: output.transaction_meta.out_msgs, + gas_used: output.transaction_meta.gas_used, + next_lt: output.transaction_meta.next_lt, + }), + in_message, + }) } fn execute_ticktock_transaction( account_stuff: &mut ShardAccountStuff, - tick_tock: TickTock, + kind: TickTock, min_lt: u64, - config: &PreloadedBlockchainConfig, - unpacked_config: SafeRc, - params: &ExecuteParams, -) -> Result { + config: &ParsedConfig, + params: &ExecutorParams, +) -> Result> { tracing::trace!( target: tracing_targets::EXEC_MANAGER, account_addr = %account_stuff.account_addr, - kind = ?tick_tock, + ?kind, "executing ticktock", ); let _histogram = HistogramGuard::begin("tycho_collator_execute_ticktock_time"); - let shard_account = &mut account_stuff.shard_account; - - // NOTE: Failed (without tx) ticktock execution is considered as a fatal error - let ( - total_fees, - ExecutorOutput { - account, - transaction, - }, - ) = TickTockTransactionExecutor::new(tick_tock).execute_with_libs_and_params( - None, - shard_account, - min_lt, - params, - config, - unpacked_config, - )?; - - let tx_lt = shard_account.last_trans_lt; - account_stuff.apply_transaction(tx_lt, total_fees, account, &transaction); - - Ok(transaction) + let uncommited = Executor::new(params, config) + .with_min_lt(min_lt) + .begin_tick_tock( + &account_stuff.make_std_addr(), + kind, + &account_stuff.shard_account, + ); + + let output = match uncommited { + Ok(uncommited) => uncommited.commit()?, + Err(TxError::Skipped) => return Ok(None), + Err(TxError::Fatal(e)) => return Err(e), + }; + + let tx_lt = output.new_state.last_trans_lt; + + account_stuff.shard_account = output.new_state; + account_stuff.apply_transaction( + tx_lt, + output.transaction_meta.total_fees, + output.new_state_meta, + output.transaction.clone(), + ); + + Ok(Some(ExecutedTransaction { + transaction: output.transaction, + out_msgs: output.transaction_meta.out_msgs, + gas_used: output.transaction_meta.gas_used, + next_lt: output.transaction_meta.next_lt, + })) } diff --git a/collator/src/collator/types.rs b/collator/src/collator/types.rs index 44022fc6c..ac7f9e3a2 100644 --- a/collator/src/collator/types.rs +++ b/collator/src/collator/types.rs @@ -8,15 +8,16 @@ use everscale_types::dict::Dict; use everscale_types::models::{ AccountState, BlockId, BlockIdShort, BlockInfo, BlockLimits, BlockParamLimits, BlockRef, CollationConfig, CurrencyCollection, HashUpdate, ImportFees, InMsg, Lazy, LibDescr, MsgInfo, - MsgsExecutionParams, OptionalAccount, OutMsg, PrevBlockRef, ShardAccount, ShardAccounts, - ShardDescription, ShardFeeCreated, ShardFees, ShardIdent, ShardIdentFull, ShardStateUnsplit, - SimpleLib, SpecialFlags, StateInit, Transaction, ValueFlow, + MsgsExecutionParams, OptionalAccount, OutMsg, OwnedMessage, PrevBlockRef, ShardAccount, + ShardAccounts, ShardDescription, ShardFeeCreated, ShardFees, ShardIdent, ShardIdentFull, + ShardStateUnsplit, SimpleLib, SpecialFlags, StateInit, StdAddr, Transaction, ValueFlow, }; +use everscale_types::num::Tokens; use tl_proto::TlWrite; -use ton_executor::{AccountMeta, ExecutedTransaction}; use tycho_block_util::queue::{QueuePartitionIdx, SerializedQueueDiff}; use tycho_block_util::state::{RefMcStateHandle, ShardStateStuff}; use tycho_core::global_config::MempoolGlobalConfig; +use tycho_executor::AccountMeta; use tycho_network::PeerId; use tycho_util::FastHashMap; @@ -554,6 +555,7 @@ pub(super) type AccountId = HashBytes; #[derive(Clone)] pub(super) struct ShardAccountStuff { + pub workchain_id: i8, pub account_addr: AccountId, pub shard_account: ShardAccount, pub special: SpecialFlags, @@ -566,7 +568,11 @@ pub(super) struct ShardAccountStuff { } impl ShardAccountStuff { - pub fn new(account_addr: &AccountId, shard_account: ShardAccount) -> Result { + pub fn new( + workchain_id: i8, + account_addr: &AccountId, + shard_account: ShardAccount, + ) -> Result { let initial_state_hash = *shard_account.account.inner().repr_hash(); let mut libraries = Dict::new(); @@ -592,6 +598,7 @@ impl ShardAccountStuff { } Ok(Self { + workchain_id, account_addr: *account_addr, shard_account, special, @@ -604,7 +611,7 @@ impl ShardAccountStuff { }) } - pub fn new_empty(account_addr: &AccountId) -> Self { + pub fn new_empty(workchain_id: i8, account_addr: &AccountId) -> Self { static EMPTY_SHARD_ACCOUNT: OnceLock = OnceLock::new(); let shard_account = EMPTY_SHARD_ACCOUNT @@ -618,6 +625,7 @@ impl ShardAccountStuff { let initial_state_hash = *shard_account.account.inner().repr_hash(); Self { + workchain_id, account_addr: *account_addr, shard_account, special: Default::default(), @@ -634,6 +642,10 @@ impl ShardAccountStuff { Ok(self.shard_account.load_account()?.is_none()) } + pub fn make_std_addr(&self) -> StdAddr { + StdAddr::new(self.workchain_id, self.account_addr) + } + pub fn build_hash_update(&self) -> Lazy { Lazy::new(&HashUpdate { old: self.initial_state_hash, @@ -645,12 +657,11 @@ impl ShardAccountStuff { pub fn apply_transaction( &mut self, lt: u64, - total_fees: CurrencyCollection, + total_fees: Tokens, account_meta: AccountMeta, - tx: &ExecutedTransaction, + tx: Lazy, ) { - self.transactions - .insert(lt, (total_fees, tx.transaction.clone())); + self.transactions.insert(lt, (total_fees.into(), tx)); self.balance = account_meta.balance; self.libraries = account_meta.libraries; self.exists = account_meta.exists; @@ -818,12 +829,18 @@ impl ShardDescriptionExt for ShardDescription { split_merge_at: None, // TODO: check if we really should not use it here fees_collected: value_flow.fees_collected.clone(), funds_created: value_flow.created.clone(), - copyleft_rewards: Default::default(), - proof_chain: None, } } } +#[derive(Clone, Debug)] +pub struct ExecutedTransaction { + pub transaction: Lazy, + pub out_msgs: Vec>, + pub gas_used: u64, + pub next_lt: u64, +} + pub struct ParsedMessage { pub info: MsgInfo, pub dst_in_current_shard: bool, diff --git a/rpc/src/models.rs b/rpc/src/models.rs index 0a7209fe9..68b35f8ad 100644 --- a/rpc/src/models.rs +++ b/rpc/src/models.rs @@ -59,8 +59,5 @@ pub fn serialize_account(account: &Account) -> Result