diff --git a/abi/resolver/src/lib.rs b/abi/resolver/src/lib.rs index cc45c6369d..3bd56bbec0 100644 --- a/abi/resolver/src/lib.rs +++ b/abi/resolver/src/lib.rs @@ -405,6 +405,10 @@ mod tests { fn is_genesis(&self) -> bool { todo!() } + + fn get_block_number(&self) -> Option { + None + } } #[test] diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 2e8c62a47e..7f21108fd9 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -453,12 +453,13 @@ impl BlockChain { parents_hash: Option>, ) -> Result { let header = block.header(); - // Todo: add debug_assert for height_of_statedb let height_of_state = statedb.get_block_number(); debug_assert!(header.is_genesis() || parent_status.is_some()); debug_assert!(!header.is_genesis() || parent_status.is_none()); let block_id = header.id(); let block_num = header.number(); + debug_assert!(header.is_genesis() && height_of_state.is_none()); + debug_assert!(!header.is_genesis() && height_of_state.is_some()); let transactions = { // genesis block do not generate BlockMetadata transaction. let mut t = match &parent_status { @@ -1066,7 +1067,7 @@ impl ChainReader for BlockChain { let state_proof = if let Some(access_path) = access_path { let statedb = self .statedb - .fork_at(transaction_info.txn_info().state_root_hash()); + .fork_at(transaction_info.txn_info().state_root_hash(), None); Some(statedb.get_with_proof(&access_path)?) } else { None diff --git a/contrib-contracts/src/starcoin_merkle_test.rs b/contrib-contracts/src/starcoin_merkle_test.rs index dbc6f8f581..96f40a4d47 100644 --- a/contrib-contracts/src/starcoin_merkle_test.rs +++ b/contrib-contracts/src/starcoin_merkle_test.rs @@ -7,6 +7,7 @@ use starcoin_types::identifier::Identifier; use starcoin_types::language_storage::ModuleId; use starcoin_vm_types::access_path::AccessPath; use starcoin_vm_types::account_config::association_address; +use starcoin_vm_types::state_view::StateView; use starcoin_vm_types::transaction::{Package, ScriptFunction, TransactionPayload}; use starcoin_vm_types::value::MoveValue; use test_helper::executor::{ @@ -38,6 +39,7 @@ fn test_starcoin_merkle() -> Result<()> { } let state_root = chain_state.state_root(); + let block_number = chain_state.get_block_number(); { let script_function = ScriptFunction::new( @@ -62,7 +64,7 @@ fn test_starcoin_merkle() -> Result<()> { { // change to previous state root. - let old_chain_state = chain_state.fork_at(state_root); + let old_chain_state = chain_state.fork_at(state_root, block_number); // let state_root = chain_state.state_root(); let _expected_root = MoveValue::vector_u8(state_root.to_vec()); diff --git a/executor/tests/executor_test.rs b/executor/tests/executor_test.rs index 9b057d9b24..92c7aa28ac 100644 --- a/executor/tests/executor_test.rs +++ b/executor/tests/executor_test.rs @@ -56,6 +56,10 @@ impl StateView for NullStateView { fn is_genesis(&self) -> bool { false } + + fn get_block_number(&self) -> Option { + None + } } #[stest::test] diff --git a/network-rpc/api/src/remote_chain_state.rs b/network-rpc/api/src/remote_chain_state.rs index 3f625043b9..7e8fe7cbff 100644 --- a/network-rpc/api/src/remote_chain_state.rs +++ b/network-rpc/api/src/remote_chain_state.rs @@ -154,4 +154,8 @@ impl StateView for RemoteChainStateReader { fn is_genesis(&self) -> bool { false } + + fn get_block_number(&self) -> Option { + None + } } diff --git a/rpc/client/src/remote_state_reader.rs b/rpc/client/src/remote_state_reader.rs index 796d71cd9e..7efe7aaf1e 100644 --- a/rpc/client/src/remote_state_reader.rs +++ b/rpc/client/src/remote_state_reader.rs @@ -140,4 +140,8 @@ impl<'a> StateView for RemoteStateReader<'a> { fn is_genesis(&self) -> bool { false } + + fn get_block_number(&self) -> Option { + None + } } diff --git a/rpc/server/src/module/contract_rpc.rs b/rpc/server/src/module/contract_rpc.rs index efa902d109..d74480bbbb 100644 --- a/rpc/server/src/module/contract_rpc.rs +++ b/rpc/server/src/module/contract_rpc.rs @@ -128,9 +128,11 @@ where args, } = call; let f = async move { - let state_root = service.state_root().await?; + let state_root = service.clone().state_root().await?; + let block_number = service.get_block_number().await?; let output = playground.call_contract( state_root, + block_number, function_id.0.module, function_id.0.function, type_args.into_iter().map(|v| v.0).collect(), @@ -231,7 +233,9 @@ where let service = self.chain_state.clone(); let storage = self.storage.clone(); let fut = async move { - let state = ChainStateDB::new(storage, Some(service.state_root().await?)); + let state_root = service.clone().state_root().await?; + let block_number = service.get_block_number().await?; + let state = ChainStateDB::new_with_root(storage, Some(state_root), block_number); ABIResolver::new(&state) .resolve_function(&function_id.0.module, function_id.0.function.as_ident_str()) } diff --git a/state/service/src/service.rs b/state/service/src/service.rs index 90abfdee2f..4c6ec30e0c 100644 --- a/state/service/src/service.rs +++ b/state/service/src/service.rs @@ -140,8 +140,12 @@ impl EventHandler for ChainStateService { let NewHeadBlock(block, _dag_parents) = msg; let state_root = block.header().state_root(); - debug!("ChainStateActor change StateRoot to : {:?}", state_root); - self.service.change_root(state_root); + let block_number = block.header().number(); + debug!( + "ChainStateActor change StateRoot to : {:?} {block_number}", + state_root + ); + self.service.change_root(state_root, block_number); } } @@ -171,7 +175,7 @@ impl Inner { ) -> Result> { match state_root { Some(root) => { - let reader = self.state_db.fork_at(root); + let reader = self.state_db.fork_at(root, None); reader.get_account_state_set(&address) } None => self.get_account_state_set(&address), @@ -183,7 +187,7 @@ impl Inner { access_path: AccessPath, state_root: HashValue, ) -> Result { - let reader = self.state_db.fork_at(state_root); + let reader = self.state_db.fork_at(state_root, None); reader.get_with_proof(&access_path) } @@ -193,7 +197,7 @@ impl Inner { key: Vec, state_root: HashValue, ) -> Result { - let reader = self.state_db.fork_at(state_root); + let reader = self.state_db.fork_at(state_root, None); reader.get_with_table_item_proof(&handle, &key) } @@ -202,12 +206,12 @@ impl Inner { account: AccountAddress, state_root: HashValue, ) -> Result> { - let reader = self.state_db.fork_at(state_root); + let reader = self.state_db.fork_at(state_root, None); reader.get_account_state(&account) } - pub(crate) fn change_root(&mut self, state_root: HashValue) { - self.state_db = self.state_db.fork_at(state_root); + pub(crate) fn change_root(&mut self, state_root: HashValue, block_number: BlockNumber) { + self.state_db = self.state_db.fork_at(state_root, Some(block_number)); self.adjust_time(); } diff --git a/state/statedb/src/lib.rs b/state/statedb/src/lib.rs index 83594e41bd..02882e29e7 100644 --- a/state/statedb/src/lib.rs +++ b/state/statedb/src/lib.rs @@ -291,8 +291,8 @@ impl ChainStateDB { } /// Fork a new statedb at `root_hash` - pub fn fork_at(&self, state_root: HashValue) -> Self { - Self::new_with_root(self.store.clone(), Some(state_root), None) + pub fn fork_at(&self, state_root: HashValue, block_number: Option) -> Self { + Self::new_with_root(self.store.clone(), Some(state_root), block_number) } fn new_state_tree(&self, root_hash: HashValue) -> StateTree { diff --git a/test-helper/src/starcoin_dao.rs b/test-helper/src/starcoin_dao.rs index 7be7ba0ae5..b28b2109b8 100644 --- a/test-helper/src/starcoin_dao.rs +++ b/test-helper/src/starcoin_dao.rs @@ -66,7 +66,7 @@ fn get_with_proof_by_root( access_path: AccessPath, state_root: HashValue, ) -> Result { - let reader = state_db.fork_at(state_root); + let reader = state_db.fork_at(state_root, None); reader.get_with_proof(&access_path) } diff --git a/vm/dev/src/playground.rs b/vm/dev/src/playground.rs index 4996298c5e..72f41a9cf5 100644 --- a/vm/dev/src/playground.rs +++ b/vm/dev/src/playground.rs @@ -43,21 +43,25 @@ impl PlaygroudService { pub fn dry_run( &self, state_root: HashValue, + block_number: Option, txn: DryRunTransaction, ) -> Result<(VMStatus, TransactionOutput)> { - let state_view = ChainStateDB::new(self.state.clone(), Some(state_root)); + let state_view = + ChainStateDB::new_with_root(self.state.clone(), Some(state_root), block_number); dry_run(&state_view, txn, self.metrics.clone()) } pub fn call_contract( &self, state_root: HashValue, + block_number: Option, module_id: ModuleId, func: Identifier, type_args: Vec, args: Vec, ) -> Result> { - let state_view = ChainStateDB::new(self.state.clone(), Some(state_root)); + let state_view = + ChainStateDB::new_with_root(self.state.clone(), Some(state_root), block_number); let rets = call_contract( &state_view, module_id, diff --git a/vm/e2e-tests/src/data_store.rs b/vm/e2e-tests/src/data_store.rs index bf9c595b7f..1dfb5bed9a 100644 --- a/vm/e2e-tests/src/data_store.rs +++ b/vm/e2e-tests/src/data_store.rs @@ -105,6 +105,10 @@ impl StateView for FakeDataStore { fn is_genesis(&self) -> bool { self.inner().is_empty() } + + fn get_block_number(&self) -> Option { + None + } } impl ChainStateWriter for FakeDataStore { diff --git a/vm/resource-viewer/src/lib.rs b/vm/resource-viewer/src/lib.rs index cc9c044620..ed80ff9d6e 100644 --- a/vm/resource-viewer/src/lib.rs +++ b/vm/resource-viewer/src/lib.rs @@ -324,4 +324,8 @@ impl StateView for NullStateView { fn is_genesis(&self) -> bool { false } + + fn get_block_number(&self) -> Option { + None + } } diff --git a/vm/starcoin-transactional-test-harness/src/fork_state.rs b/vm/starcoin-transactional-test-harness/src/fork_state.rs index 10da079cef..aa6dafcdf8 100644 --- a/vm/starcoin-transactional-test-harness/src/fork_state.rs +++ b/vm/starcoin-transactional-test-harness/src/fork_state.rs @@ -117,7 +117,7 @@ impl ChainStateAsyncService for MockChainStateAsyncService { ) -> Result> { match state_root { Some(root) => { - let reader = self.state_db().fork_at(root); + let reader = self.state_db().fork_at(root, None); reader.get_account_state_set(&address) } None => self.state_db().get_account_state_set(&address), @@ -132,7 +132,7 @@ impl ChainStateAsyncService for MockChainStateAsyncService { access_path: AccessPath, state_root: HashValue, ) -> Result { - let reader = self.state_db().fork_at(state_root); + let reader = self.state_db().fork_at(state_root, None); reader.get_with_proof(&access_path) } @@ -141,7 +141,7 @@ impl ChainStateAsyncService for MockChainStateAsyncService { account_address: AccountAddress, state_root: HashValue, ) -> Result> { - let reader = self.state_db().fork_at(state_root); + let reader = self.state_db().fork_at(state_root, None); reader.get_account_state(&account_address) } @@ -160,7 +160,7 @@ impl ChainStateAsyncService for MockChainStateAsyncService { key: Vec, state_root: HashValue, ) -> Result { - let reader = self.state_db().fork_at(state_root); + let reader = self.state_db().fork_at(state_root, None); reader.get_with_table_item_proof(&handle, &key) } diff --git a/vm/starcoin-transactional-test-harness/src/remote_state.rs b/vm/starcoin-transactional-test-harness/src/remote_state.rs index 8066300b06..b77ffbe5c6 100644 --- a/vm/starcoin-transactional-test-harness/src/remote_state.rs +++ b/vm/starcoin-transactional-test-harness/src/remote_state.rs @@ -78,6 +78,10 @@ where fn is_genesis(&self) -> bool { false } + + fn get_block_number(&self) -> Option { + None + } } impl ChainStateWriter for SelectableStateView where @@ -184,6 +188,10 @@ where fn is_genesis(&self) -> bool { false } + + fn get_block_number(&self) -> Option { + None + } } //TODO migrate this to rpc client crate. @@ -405,4 +413,8 @@ impl StateView for RemoteViewer { fn is_genesis(&self) -> bool { false } + + fn get_block_number(&self) -> Option { + None + } } diff --git a/vm/types/src/state_view.rs b/vm/types/src/state_view.rs index b74a80963e..92163554a5 100644 --- a/vm/types/src/state_view.rs +++ b/vm/types/src/state_view.rs @@ -43,9 +43,7 @@ pub trait StateView: Sync { /// Currently TransactionPayload::WriteSet is only valid for genesis state creation. fn is_genesis(&self) -> bool; - fn get_block_number(&self) -> Option { - panic!("Never call me and implement this function yourself"); - } + fn get_block_number(&self) -> Option; } impl StateView for R @@ -60,6 +58,10 @@ where fn is_genesis(&self) -> bool { self.deref().is_genesis() } + + fn get_block_number(&self) -> Option { + self.deref().get_block_number() + } } impl StateReaderExt for T where T: StateView {} diff --git a/vm/vm-runtime/src/data_cache.rs b/vm/vm-runtime/src/data_cache.rs index 6775f05ec4..1b49981d1f 100644 --- a/vm/vm-runtime/src/data_cache.rs +++ b/vm/vm-runtime/src/data_cache.rs @@ -89,6 +89,10 @@ impl<'block, S: StateView> StateView for StateViewCache<'block, S> { fn is_genesis(&self) -> bool { self.data_view.is_genesis() } + + fn get_block_number(&self) -> Option { + self.data_view.get_block_number() + } } impl<'block, S: StateView> ModuleResolver for StateViewCache<'block, S> { diff --git a/vm/vm-runtime/src/parallel_executor/storage_wrapper.rs b/vm/vm-runtime/src/parallel_executor/storage_wrapper.rs index 0a316ac2cc..824f74688f 100644 --- a/vm/vm-runtime/src/parallel_executor/storage_wrapper.rs +++ b/vm/vm-runtime/src/parallel_executor/storage_wrapper.rs @@ -40,4 +40,8 @@ impl<'a, S: StateView> StateView for VersionedView<'a, S> { fn is_genesis(&self) -> bool { self.base_view.is_genesis() } + + fn get_block_number(&self) -> Option { + self.base_view.get_block_number() + } } diff --git a/vm/vm-runtime/src/starcoin_vm.rs b/vm/vm-runtime/src/starcoin_vm.rs index 1bd7150b38..6ea5b607f8 100644 --- a/vm/vm-runtime/src/starcoin_vm.rs +++ b/vm/vm-runtime/src/starcoin_vm.rs @@ -280,7 +280,7 @@ impl StarcoinVM { if height_of_state >= FLEXI_DAG_FORK_HEIGHT && stdlib_version >= StdlibVersion::Version(FLEXIDAG_UPGRADE_VERSION_MARK) { - todo!() + debug!("flexidag stdlib"); } (gas_schedule, "gas schedule from GasSchedule")