diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 255950d219..dc8603ab9b 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -36,10 +36,13 @@ use starcoin_types::{ transaction::{SignedUserTransaction, Transaction}, U256, }; -use starcoin_vm_types::access_path::AccessPath; -use starcoin_vm_types::account_config::genesis_address; -use starcoin_vm_types::genesis_config::ConsensusStrategy; -use starcoin_vm_types::on_chain_resource::Epoch; +use starcoin_vm_types::{ + access_path::AccessPath, + account_config::genesis_address, + genesis_config::{ChainId, ConsensusStrategy}, + on_chain_resource::Epoch, + write_set::WriteSet, +}; use std::cmp::min; use std::iter::Extend; use std::option::Option::{None, Some}; @@ -49,6 +52,8 @@ use std::{ sync::Arc, }; +pub const MAIN_FORCE_UPGRADE_BLOCK_NUMBER: BlockNumber = 17000000; + static MAIN_DIRECT_SAVE_BLOCK_HASH_MAP: Lazy> = Lazy::new(|| { let mut maps = BTreeMap::new(); @@ -573,6 +578,13 @@ static MAIN_DIRECT_SAVE_BLOCK_HASH_MAP: Lazy> = Lazy::new(|| { + let mut maps = BTreeMap::new(); + maps.insert(MAIN_FORCE_UPGRADE_BLOCK_NUMBER, WriteSet::default()); + maps +}); + static OUTPUT_BLOCK: AtomicBool = AtomicBool::new(false); pub struct ChainStatusWithBlock { @@ -672,6 +684,7 @@ impl BlockChain { storage.get_accumulator_store(AccumulatorStoreType::Block), ); let statedb = ChainStateDB::new(storage.clone().into_super_arc(), None); + let chain_id = genesis_block.header().chain_id(); let executed_block = Self::execute_block_and_save( storage.as_ref(), statedb, @@ -681,6 +694,7 @@ impl BlockChain { None, genesis_block, None, + chain_id, )?; Self::new(time_service, executed_block.block.id(), storage, None) } @@ -897,6 +911,7 @@ impl BlockChain { parent_status: Option, block: Block, vm_metrics: Option, + chain_id: ChainId, ) -> Result { let header = block.header(); debug_assert!(header.is_genesis() || parent_status.is_some()); @@ -920,13 +935,19 @@ impl BlockChain { ); t }; - watch(CHAIN_WATCH_NAME, "n21"); + let mut extra_set = WriteSet::default(); + if chain_id.is_main() { + if let Some(write_set) = MAIN_FORCE_UPGRADE_BLOCK_MAP.get(&block.header().number()) { + extra_set = write_set.clone(); + } + } let executed_data = starcoin_executor::block_execute( &statedb, transactions.clone(), epoch.block_gas_limit(), vm_metrics, + extra_set, )?; watch(CHAIN_WATCH_NAME, "n22"); let state_root = executed_data.state_root; @@ -1203,6 +1224,7 @@ impl BlockChain { OUTPUT_BLOCK.store(true, Ordering::Relaxed); } + // XXX FIXME YSG REFACTOR fn execute_block_without_save( statedb: ChainStateDB, txn_accumulator: MerkleAccumulator, @@ -1211,6 +1233,7 @@ impl BlockChain { parent_status: Option, block: Block, vm_metrics: Option, + chain_id: ChainId, ) -> Result { let header = block.header(); debug_assert!(header.is_genesis() || parent_status.is_some()); @@ -1236,11 +1259,21 @@ impl BlockChain { }; watch(CHAIN_WATCH_NAME, "n21"); + + // XXX FIXME YSG REFACTOR + let mut extra_set = WriteSet::default(); + if chain_id.is_main() { + if let Some(write_set) = MAIN_FORCE_UPGRADE_BLOCK_MAP.get(&block.header().number()) { + extra_set = write_set.clone(); + } + } + let executed_data = starcoin_executor::block_execute( &statedb, transactions.clone(), epoch.block_gas_limit(), vm_metrics, + extra_set, )?; watch(CHAIN_WATCH_NAME, "n22"); let state_root = executed_data.state_root; @@ -1581,6 +1614,7 @@ impl ChainReader for BlockChain { Some(self.status.status.clone()), verified_block.0, self.vm_metrics.clone(), + self.info().chain_id(), ) } } @@ -1594,6 +1628,7 @@ impl ChainReader for BlockChain { Some(self.status.status.clone()), verified_block.0, self.vm_metrics.clone(), + self.info().chain_id(), ) } diff --git a/chain/tests/block_test_utils.rs b/chain/tests/block_test_utils.rs index f6d7016c26..cf0f3f2f1c 100644 --- a/chain/tests/block_test_utils.rs +++ b/chain/tests/block_test_utils.rs @@ -21,6 +21,7 @@ use starcoin_types::{ block_metadata::BlockMetadata, U256, }; +use starcoin_vm_types::write_set::WriteSet; use std::convert::TryFrom; use std::sync::Arc; @@ -222,7 +223,13 @@ fn gen_root_hashes( //state_db let chain_state = ChainStateDB::new(storage.clone(), Some(pre_state_root)); - match block_execute(&chain_state, block_txns, block_gat_limit, None) { + match block_execute( + &chain_state, + block_txns, + block_gat_limit, + None, + WriteSet::default(), + ) { Ok(executed_data) => { let txn_accumulator = MerkleAccumulator::new( pre_accumulator_root, @@ -276,7 +283,7 @@ proptest! { let chain_state = ChainStateDB::new(Arc::new(storage), None); let mut account = AccountInfoUniverse::default(); let txns = txn_transfer(&mut account, gens); - let result = block_execute(&chain_state, txns, 0, None); + let result = block_execute(&chain_state, txns, 0, None,WriteSet::default()); info!("execute result: {:?}", result); } } diff --git a/executor/benchmark/src/lib.rs b/executor/benchmark/src/lib.rs index 3706971393..0f6b23e059 100644 --- a/executor/benchmark/src/lib.rs +++ b/executor/benchmark/src/lib.rs @@ -24,10 +24,10 @@ use starcoin_types::{ block_metadata::BlockMetadata, transaction::{Transaction, TransactionPayload}, }; -use starcoin_vm_types::genesis_config::StdlibVersion; -use starcoin_vm_types::token::stc; -use starcoin_vm_types::transaction::authenticator::AuthenticationKey; -use starcoin_vm_types::transaction::ScriptFunction; +use starcoin_vm_types::{ + genesis_config::StdlibVersion, token::stc, transaction::authenticator::AuthenticationKey, + transaction::ScriptFunction, write_set::WriteSet, +}; use std::sync::mpsc; use std::sync::Arc; @@ -222,9 +222,14 @@ impl<'test, S: ChainStateReader + ChainStateWriter> TxnExecutor<'test, S> { let num_txns = transactions.len(); version += num_txns as u64; - let _ = - starcoin_executor::block_execute(self.chain_state, transactions, u64::MAX, None) - .expect("Execute transactions fail."); + let _ = starcoin_executor::block_execute( + self.chain_state, + transactions, + u64::MAX, + None, + WriteSet::default(), + ) + .expect("Execute transactions fail."); self.chain_state.flush().expect("flush state should be ok"); let execute_time = std::time::Instant::now().duration_since(execute_start); diff --git a/executor/src/block_executor.rs b/executor/src/block_executor.rs index e7b46165d4..aef8341faa 100644 --- a/executor/src/block_executor.rs +++ b/executor/src/block_executor.rs @@ -40,6 +40,7 @@ pub fn block_execute( txns: Vec, block_gas_limit: u64, vm_metrics: Option, + extra_set: WriteSet, ) -> ExecutorResult { let txn_outputs = crate::execute_block_transactions(chain_state, txns.clone(), block_gas_limit, vm_metrics) @@ -85,6 +86,14 @@ pub fn block_execute( }; } + if !extra_set.is_empty() { + chain_state + .apply_write_set(extra_set) + .map_err(BlockExecutorError::BlockChainStateErr)?; + chain_state + .commit() + .map_err(BlockExecutorError::BlockChainStateErr)?; + } executed_data.state_root = chain_state.state_root(); Ok(executed_data) } diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs index 9b057d9b24..6067c961a7 100644 --- a/executor/tests/executor_test.rs +++ b/executor/tests/executor_test.rs @@ -43,6 +43,7 @@ use starcoin_types::account_config::G_STC_TOKEN_CODE; use starcoin_vm_runtime::starcoin_vm::{chunk_block_transactions, StarcoinVM}; use starcoin_vm_types::account_config::core_code_address; use starcoin_vm_types::state_store::state_key::StateKey; +use starcoin_vm_types::write_set::WriteSet; use test_helper::txn::create_account_txn_sent_as_association; #[derive(Default)] @@ -403,8 +404,13 @@ fn test_block_execute_gas_limit() -> Result<()> { assert_eq!(max_include_txn_num, txns.len() as u64); txns.insert(0, Transaction::BlockMetadata(block_meta)); - let executed_data = - starcoin_executor::block_execute(&chain_state, txns, block_gas_limit, None)?; + let executed_data = starcoin_executor::block_execute( + &chain_state, + txns, + block_gas_limit, + None, + WriteSet::default(), + )?; let txn_infos = executed_data.txn_infos; // all user txns can be included @@ -450,9 +456,14 @@ fn test_block_execute_gas_limit() -> Result<()> { }) .collect(); txns.insert(0, Transaction::BlockMetadata(block_meta2)); - let txn_infos = - starcoin_executor::block_execute(&chain_state, txns, max_block_gas_limit, None)? - .txn_infos; + let txn_infos = starcoin_executor::block_execute( + &chain_state, + txns, + max_block_gas_limit, + None, + WriteSet::default(), + )? + .txn_infos; // not all user txns can be included assert_eq!(txn_infos.len() as u64, max_txn_num + 1); diff --git a/txpool/src/test.rs b/txpool/src/test.rs index e205b388e6..6db7f4dcaf 100644 --- a/txpool/src/test.rs +++ b/txpool/src/test.rs @@ -18,6 +18,7 @@ use starcoin_state_api::ChainStateWriter; use starcoin_statedb::ChainStateDB; use starcoin_storage::BlockStore; use starcoin_txpool_api::{TxPoolSyncService, TxnStatusFullEvent}; +use starcoin_types::write_set::WriteSet; use starcoin_types::{ account_address::{self, AccountAddress}, account_config, @@ -259,7 +260,14 @@ async fn test_rollback() -> Result<()> { 0, Transaction::BlockMetadata(enacted_block.to_metadata(parent_block_header.gas_used())), ); - let root = starcoin_executor::block_execute(&chain_state, txns, u64::MAX, None)?.state_root; + let root = starcoin_executor::block_execute( + &chain_state, + txns, + u64::MAX, + None, + WriteSet::default(), + )? + .state_root; assert_eq!(root, enacted_block.header().state_root()); chain_state.flush()?;