From d5dacc6da4d646c8f37636ff9dfa8709b5e76602 Mon Sep 17 00:00:00 2001 From: Eason Date: Mon, 24 Jul 2023 12:59:30 +0800 Subject: [PATCH] refactor: remove global variable --- core/api/src/adapter.rs | 54 ++++++- core/api/src/jsonrpc/impl/ckb_light_client.rs | 36 +++-- core/api/src/jsonrpc/impl/web3.rs | 144 +++++++++--------- core/api/src/jsonrpc/mod.rs | 2 +- core/consensus/src/adapter.rs | 43 ++++-- core/consensus/src/engine.rs | 6 +- core/consensus/src/synchronization.rs | 3 +- core/executor/src/lib.rs | 36 ++--- core/executor/src/precompiles/call_ckb_vm.rs | 3 +- core/executor/src/precompiles/get_cell.rs | 5 +- core/executor/src/precompiles/get_header.rs | 5 +- core/executor/src/precompiles/metadata.rs | 7 +- .../src/precompiles/verify_by_ckb_vm.rs | 3 +- .../system_contract/ckb_light_client/mod.rs | 21 +-- .../src/system_contract/image_cell/mod.rs | 15 +- .../src/system_contract/metadata/handle.rs | 30 ++-- .../src/system_contract/metadata/mod.rs | 9 +- core/executor/src/system_contract/mod.rs | 49 +++--- .../src/system_contract/native_token.rs | 4 +- .../tests/system_script/ckb_light_client.rs | 31 ++-- .../src/tests/system_script/image_cell.rs | 26 +--- core/mempool/src/adapter/mod.rs | 54 ++++--- core/run/src/lib.rs | 29 +--- protocol/src/lazy.rs | 4 +- protocol/src/traits/api.rs | 6 +- 25 files changed, 339 insertions(+), 286 deletions(-) diff --git a/core/api/src/adapter.rs b/core/api/src/adapter.rs index f0f012b7f..db2015dcb 100644 --- a/core/api/src/adapter.rs +++ b/core/api/src/adapter.rs @@ -3,11 +3,14 @@ use std::sync::Arc; use core_executor::{ system_contract::metadata::MetadataHandle, AxonExecutor, AxonExecutorAdapter, MPTTrie, }; +use core_executor::{ + HEADER_CELL_ROOT_KEY, IMAGE_CELL_CONTRACT_ADDRESS, METADATA_CONTRACT_ADDRESS, METADATA_ROOT_KEY, +}; use protocol::traits::{APIAdapter, Context, Executor, ExecutorAdapter, MemPool, Network, Storage}; use protocol::types::{ Account, BigEndianHash, Block, BlockNumber, Bytes, CkbRelatedInfo, ExecutorContext, Hash, - Header, Metadata, Proposal, Receipt, SignedTransaction, TxResp, H160, MAX_BLOCK_GAS_LIMIT, - NIL_DATA, RLP_NULL, U256, + Header, Metadata, Proposal, Receipt, SignedTransaction, TxResp, H160, H256, + MAX_BLOCK_GAS_LIMIT, NIL_DATA, RLP_NULL, U256, }; use protocol::{async_trait, codec::ProtocolCodec, trie, ProtocolResult}; @@ -237,14 +240,51 @@ where block_number: Option, ) -> ProtocolResult { if let Some(num) = block_number { - return MetadataHandle::default().get_metadata_by_block_number(num); + return MetadataHandle::new(self.get_metadata_root(ctx).await?) + .get_metadata_by_block_number(num); } - let num = self.storage.get_latest_block_header(ctx).await?.number; - MetadataHandle::default().get_metadata_by_block_number(num) + let num = self + .storage + .get_latest_block_header(ctx.clone()) + .await? + .number; + MetadataHandle::new(self.get_metadata_root(ctx).await?).get_metadata_by_block_number(num) + } + + async fn get_ckb_related_info(&self, ctx: Context) -> ProtocolResult { + MetadataHandle::new(self.get_metadata_root(ctx).await?).get_ckb_related_info() } - async fn get_ckb_related_info(&self, _ctx: Context) -> ProtocolResult { - MetadataHandle::default().get_ckb_related_info() + async fn get_image_cell_root(&self, ctx: Context) -> ProtocolResult { + let state_root = self.storage.get_latest_block(ctx).await?.header.state_root; + let state_mpt_tree = MPTTrie::from_root(state_root, Arc::clone(&self.trie_db))?; + let raw_account = state_mpt_tree + .get(IMAGE_CELL_CONTRACT_ADDRESS.as_bytes())? + .ok_or_else(|| APIError::Adapter("Can't find this address".to_string()))?; + + let account = Account::decode(raw_account).unwrap(); + let storage_mpt_tree = MPTTrie::from_root(account.storage_root, Arc::clone(&self.trie_db))?; + + Ok(storage_mpt_tree + .get(HEADER_CELL_ROOT_KEY.as_bytes())? + .map(|r| H256::from_slice(&r)) + .unwrap_or_default()) + } + + async fn get_metadata_root(&self, ctx: Context) -> ProtocolResult { + let state_root = self.storage.get_latest_block(ctx).await?.header.state_root; + let state_mpt_tree = MPTTrie::from_root(state_root, Arc::clone(&self.trie_db))?; + let raw_account = state_mpt_tree + .get(METADATA_CONTRACT_ADDRESS.as_bytes())? + .ok_or_else(|| APIError::Adapter("Can't find this address".to_string()))?; + + let account = Account::decode(raw_account).unwrap(); + let storage_mpt_tree = MPTTrie::from_root(account.storage_root, Arc::clone(&self.trie_db))?; + + Ok(storage_mpt_tree + .get(METADATA_ROOT_KEY.as_bytes())? + .map(|r| H256::from_slice(&r)) + .unwrap_or_default()) } } diff --git a/core/api/src/jsonrpc/impl/ckb_light_client.rs b/core/api/src/jsonrpc/impl/ckb_light_client.rs index 920facf79..8236dea32 100644 --- a/core/api/src/jsonrpc/impl/ckb_light_client.rs +++ b/core/api/src/jsonrpc/impl/ckb_light_client.rs @@ -1,24 +1,31 @@ +use std::sync::Arc; + use ckb_jsonrpc_types::{CellData, CellInfo, HeaderView as CkbHeaderView, JsonBytes, OutPoint}; use ckb_traits::HeaderProvider; use ckb_types::core::cell::{CellProvider, CellStatus}; use ckb_types::{packed, prelude::Pack}; -use core_executor::system_contract::DataProvider; - +use core_executor::DataProvider; +use jsonrpsee::core::Error; +use protocol::traits::{APIAdapter, Context}; use protocol::{async_trait, ckb_blake2b_256, types::H256}; use crate::jsonrpc::{CkbLightClientRpcServer, RpcResult}; -#[derive(Default, Clone, Debug)] -pub struct CkbLightClientRpcImpl { - data_provider: DataProvider, +#[derive(Clone, Debug)] +pub struct CkbLightClientRpcImpl { + adapter: Arc, } #[async_trait] -impl CkbLightClientRpcServer for CkbLightClientRpcImpl { +impl CkbLightClientRpcServer for CkbLightClientRpcImpl { async fn get_block_header_by_hash(&self, hash: H256) -> RpcResult> { - Ok(self - .data_provider + let root = self + .adapter + .get_image_cell_root(Context::new()) + .await + .map_err(|e| Error::Custom(e.to_string()))?; + Ok(DataProvider::new(root) .get_header(&(hash.0.pack())) .map(Into::into)) } @@ -29,8 +36,13 @@ impl CkbLightClientRpcServer for CkbLightClientRpcImpl { with_data: bool, ) -> RpcResult> { let out_point: packed::OutPoint = out_point.into(); + let root = self + .adapter + .get_image_cell_root(Context::new()) + .await + .map_err(|e| Error::Custom(e.to_string()))?; - match self.data_provider.cell(&out_point, false) { + match DataProvider::new(root).cell(&out_point, false) { CellStatus::Live(c) => { let data = with_data.then_some(c.mem_cell_data).flatten(); Ok(Some(CellInfo { @@ -45,3 +57,9 @@ impl CkbLightClientRpcServer for CkbLightClientRpcImpl { } } } + +impl CkbLightClientRpcImpl { + pub fn new(adapter: Arc) -> Self { + Self { adapter } + } +} diff --git a/core/api/src/jsonrpc/impl/web3.rs b/core/api/src/jsonrpc/impl/web3.rs index 50df9af0d..9b4170405 100644 --- a/core/api/src/jsonrpc/impl/web3.rs +++ b/core/api/src/jsonrpc/impl/web3.rs @@ -190,6 +190,80 @@ impl Web3RpcImpl { reward, )) } + + async fn extract_interoperation_tx_sender( + &self, + utx: &UnverifiedTransaction, + signature: &SignatureComponents, + ) -> RpcResult { + // Call CKB-VM mode + if signature.r[0] == 0 { + let r = rlp::decode::(&signature.r[1..]) + .map_err(|e| Error::Custom(e.to_string()))?; + + return Ok(Hasher::digest(&r.pub_key).into()); + } + + // Verify by CKB-VM mode + let r = SignatureR::decode(&signature.r).map_err(|e| Error::Custom(e.to_string()))?; + let s = SignatureS::decode(&signature.s).map_err(|e| Error::Custom(e.to_string()))?; + let address_source = r.address_source(); + + let ckb_tx_view = + InteroperationImpl::dummy_transaction(r.clone(), s, Some(utx.signature_hash(true).0)); + let dummy_input = r.dummy_input(); + + let input = ckb_tx_view + .inputs() + .get(address_source.index as usize) + .ok_or(Error::Custom("Invalid address source".to_string()))?; + + log::debug!("[mempool]: verify interoperation tx sender \ntx view \n{:?}\ndummy input\n {:?}\naddress source\n{:?}\n", ckb_tx_view, dummy_input, address_source); + + // Dummy input mode + if is_dummy_out_point(&input.previous_output()) { + log::debug!("[mempool]: verify interoperation tx dummy input mode."); + + if let Some(cell) = dummy_input { + if address_source.type_ == 1 && cell.type_script.is_none() { + return Err(Error::Custom( + "Invalid address source in dummy input mode".to_string(), + )); + } + + let script_hash = if address_source.type_ == 0 { + cell.lock_script_hash() + } else { + cell.type_script_hash().unwrap() + }; + + return Ok(Hasher::digest(script_hash).into()); + } + + return Err(Error::Custom("No dummy input cell".to_string())); + } + + // Reality input mode + let root = self + .adapter + .get_image_cell_root(Context::new()) + .await + .map_err(|e| Error::Custom(e.to_string()))?; + match DataProvider::new(root).cell(&input.previous_output(), true) { + CellStatus::Live(cell) => { + let script_hash = if address_source.type_ == 0 { + ckb_blake2b_256(cell.cell_output.lock().as_slice()) + } else if let Some(type_script) = cell.cell_output.type_().to_opt() { + ckb_blake2b_256(type_script.as_slice()) + } else { + return Err(Error::Custom("Invalid address source".to_string())); + }; + + Ok(Hasher::digest(script_hash).into()) + } + _ => Err(Error::Custom("Cannot find input cell in ICSC".to_string())), + } + } } #[async_trait] @@ -231,7 +305,7 @@ impl Web3RpcServer for Web3RpcImpl { if sig.is_eth_sig() { None } else { - Some(extract_interoperation_tx_sender(&utx, sig)?) + Some(self.extract_interoperation_tx_sender(&utx, sig).await?) } } else { return Err(Error::Custom("The transaction is not signed".to_string())); @@ -1161,71 +1235,3 @@ pub fn from_receipt_to_web3_log( } } } - -fn extract_interoperation_tx_sender( - utx: &UnverifiedTransaction, - signature: &SignatureComponents, -) -> RpcResult { - // Call CKB-VM mode - if signature.r[0] == 0 { - let r = rlp::decode::(&signature.r[1..]) - .map_err(|e| Error::Custom(e.to_string()))?; - - return Ok(Hasher::digest(&r.pub_key).into()); - } - - // Verify by CKB-VM mode - let r = SignatureR::decode(&signature.r).map_err(|e| Error::Custom(e.to_string()))?; - let s = SignatureS::decode(&signature.s).map_err(|e| Error::Custom(e.to_string()))?; - let address_source = r.address_source(); - - let ckb_tx_view = - InteroperationImpl::dummy_transaction(r.clone(), s, Some(utx.signature_hash(true).0)); - let dummy_input = r.dummy_input(); - - let input = ckb_tx_view - .inputs() - .get(address_source.index as usize) - .ok_or(Error::Custom("Invalid address source".to_string()))?; - - log::debug!("[mempool]: verify interoperation tx sender \ntx view \n{:?}\ndummy input\n {:?}\naddress source\n{:?}\n", ckb_tx_view, dummy_input, address_source); - - // Dummy input mode - if is_dummy_out_point(&input.previous_output()) { - log::debug!("[mempool]: verify interoperation tx dummy input mode."); - - if let Some(cell) = dummy_input { - if address_source.type_ == 1 && cell.type_script.is_none() { - return Err(Error::Custom( - "Invalid address source in dummy input mode".to_string(), - )); - } - - let script_hash = if address_source.type_ == 0 { - cell.lock_script_hash() - } else { - cell.type_script_hash().unwrap() - }; - - return Ok(Hasher::digest(script_hash).into()); - } - - return Err(Error::Custom("No dummy input cell".to_string())); - } - - // Reality input mode - match DataProvider.cell(&input.previous_output(), true) { - CellStatus::Live(cell) => { - let script_hash = if address_source.type_ == 0 { - ckb_blake2b_256(cell.cell_output.lock().as_slice()) - } else if let Some(type_script) = cell.cell_output.type_().to_opt() { - ckb_blake2b_256(type_script.as_slice()) - } else { - return Err(Error::Custom("Invalid address source".to_string())); - }; - - Ok(Hasher::digest(script_hash).into()) - } - _ => Err(Error::Custom("Cannot find input cell in ICSC".to_string())), - } -} diff --git a/core/api/src/jsonrpc/mod.rs b/core/api/src/jsonrpc/mod.rs index 10994c05e..06e1003b8 100644 --- a/core/api/src/jsonrpc/mod.rs +++ b/core/api/src/jsonrpc/mod.rs @@ -259,7 +259,7 @@ pub async fn run_jsonrpc_server( let filter = r#impl::filter_module(Arc::clone(&adapter), config.web3.log_filter_max_block_range) .into_rpc(); - let ckb_light_client_rpc = r#impl::CkbLightClientRpcImpl::default().into_rpc(); + let ckb_light_client_rpc = r#impl::CkbLightClientRpcImpl::new(Arc::clone(&adapter)).into_rpc(); rpc.merge(node_rpc).unwrap(); rpc.merge(axon_rpc).unwrap(); diff --git a/core/consensus/src/adapter.rs b/core/consensus/src/adapter.rs index 2241c812d..4abec1205 100644 --- a/core/consensus/src/adapter.rs +++ b/core/consensus/src/adapter.rs @@ -8,11 +8,13 @@ use parking_lot::RwLock; use common_apm::Instant; use common_apm_derive::trace_span; use core_executor::system_contract::metadata::MetadataHandle; -use core_executor::{AxonExecutor, AxonExecutorAdapter}; +use core_executor::{ + AxonExecutor, AxonExecutorAdapter, METADATA_CONTRACT_ADDRESS, METADATA_ROOT_KEY, +}; use core_network::{PeerId, PeerIdExt}; use protocol::traits::{ - CommonConsensusAdapter, ConsensusAdapter, Context, Executor, Gossip, MemPool, MessageTarget, - Network, PeerTrust, Priority, Rpc, Storage, SynchronizationAdapter, + Backend, CommonConsensusAdapter, ConsensusAdapter, Context, Executor, Gossip, MemPool, + MessageTarget, Network, PeerTrust, Priority, Rpc, Storage, SynchronizationAdapter, }; use protocol::types::{ BatchSignedTxs, Block, BlockNumber, Bytes, ExecResp, Hash, Header, Hex, MerkleRoot, Metadata, @@ -41,7 +43,6 @@ pub struct OverlordConsensusAdapter< storage: Arc, trie_db: Arc, - metadata: Arc, overlord_handler: RwLock>>, crypto: Arc, } @@ -339,9 +340,10 @@ where Arc::clone(&self.storage), proposal.clone().into(), )?; + let root = backend.storage(METADATA_CONTRACT_ADDRESS, *METADATA_ROOT_KEY); + let metadata_handle = MetadataHandle::new(root); - let verifier_list = self - .metadata + let verifier_list = metadata_handle .get_metadata_by_block_number(proposal.number)? .verifier_list; @@ -357,15 +359,21 @@ where } async fn is_last_block_in_current_epoch(&self, block_number: u64) -> ProtocolResult { - self.metadata.is_last_block_in_current_epoch(block_number) + self.get_metadata_handle(Context::new()) + .await? + .is_last_block_in_current_epoch(block_number) } async fn get_metadata_by_block_number(&self, block_number: u64) -> ProtocolResult { - self.metadata.get_metadata_by_block_number(block_number) + self.get_metadata_handle(Context::new()) + .await? + .get_metadata_by_block_number(block_number) } async fn get_metadata_by_epoch(&self, epoch: u64) -> ProtocolResult { - self.metadata.get_metadata_by_epoch(epoch) + self.get_metadata_handle(Context::new()) + .await? + .get_metadata_by_epoch(epoch) } #[trace_span(kind = "consensus.adapter")] @@ -460,7 +468,8 @@ where // the auth_list for the target should comes from previous number let metadata = self - .metadata + .get_metadata_handle(ctx.clone()) + .await? .get_metadata_by_block_number(block.header.number)?; if !metadata.version.contains(block.header.number) { @@ -620,14 +629,12 @@ where mempool: Arc, storage: Arc, trie_db: Arc, - metadata: Arc, crypto: Arc, ) -> ProtocolResult { Ok(OverlordConsensusAdapter { network, mempool, storage, - metadata, trie_db, overlord_handler: RwLock::new(None), crypto, @@ -637,4 +644,16 @@ where pub fn set_overlord_handler(&self, handler: OverlordHandler) { *self.overlord_handler.write() = Some(handler) } + + async fn get_metadata_handle(&self, ctx: Context) -> ProtocolResult { + let current_state_root = self.storage.get_latest_block_header(ctx).await?.state_root; + let backend = AxonExecutorAdapter::from_root( + current_state_root, + Arc::clone(&self.trie_db), + Arc::clone(&self.storage), + Default::default(), + )?; + let root = backend.storage(METADATA_CONTRACT_ADDRESS, *METADATA_ROOT_KEY); + Ok(MetadataHandle::new(root)) + } } diff --git a/core/consensus/src/engine.rs b/core/consensus/src/engine.rs index b3a82fc3b..53a479527 100644 --- a/core/consensus/src/engine.rs +++ b/core/consensus/src/engine.rs @@ -21,10 +21,7 @@ use protocol::types::{ Block, Bytes, ExecResp, Hash, Hasher, Hex, Log, MerkleRoot, Metadata, Proof, Proposal, Receipt, SignedTransaction, ValidatorExtend, BASE_FEE_PER_GAS, MAX_BLOCK_GAS_LIMIT, RLP_NULL, U256, }; -use protocol::{ - async_trait, lazy::CURRENT_STATE_ROOT, tokio::sync::Mutex as AsyncMutex, ProtocolError, - ProtocolResult, -}; +use protocol::{async_trait, tokio::sync::Mutex as AsyncMutex, ProtocolError, ProtocolResult}; use core_executor::logs_bloom; @@ -639,7 +636,6 @@ impl ConsensusEngine { proof: proof.clone(), }; - CURRENT_STATE_ROOT.swap(Arc::new(resp.state_root)); self.status.swap(new_status); // update timeout_gap of mempool diff --git a/core/consensus/src/synchronization.rs b/core/consensus/src/synchronization.rs index d589d1cda..cad1374f6 100644 --- a/core/consensus/src/synchronization.rs +++ b/core/consensus/src/synchronization.rs @@ -8,7 +8,7 @@ use common_apm_derive::trace_span; use protocol::tokio::{sync::Mutex, time::sleep}; use protocol::traits::{Context, Synchronization, SynchronizationAdapter}; use protocol::types::{Block, Proof, Proposal, Receipt, SignedTransaction, U256}; -use protocol::{async_trait, lazy::CURRENT_STATE_ROOT, ProtocolResult}; +use protocol::{async_trait, ProtocolResult}; use crate::status::{CurrentStatus, StatusAgent}; use crate::util::digest_signed_transactions; @@ -375,7 +375,6 @@ impl OverlordSynchronization { ) .await?; - CURRENT_STATE_ROOT.swap(Arc::new(resp.state_root)); status_agent.swap(new_status); // If there are transactions in the transaction pool that have been on chain diff --git a/core/executor/src/lib.rs b/core/executor/src/lib.rs index de6aed197..85579b96d 100644 --- a/core/executor/src/lib.rs +++ b/core/executor/src/lib.rs @@ -10,7 +10,10 @@ mod tests; mod utils; pub use crate::adapter::{AxonExecutorAdapter, MPTTrie, RocksTrieDB}; - +pub use crate::system_contract::{ + metadata::MetadataHandle, DataProvider, HEADER_CELL_ROOT_KEY, IMAGE_CELL_CONTRACT_ADDRESS, + METADATA_CONTRACT_ADDRESS, METADATA_ROOT_KEY, +}; pub use crate::utils::{ code_address, decode_revert_msg, logs_bloom, DefaultFeeAllocator, FeeInlet, }; @@ -18,7 +21,6 @@ pub use crate::utils::{ use std::cell::RefCell; use std::collections::BTreeMap; use std::iter::FromIterator; -use std::sync::Arc; use arc_swap::ArcSwap; use evm::executor::stack::{MemoryStackState, PrecompileFn, StackExecutor, StackSubstateMetadata}; @@ -35,10 +37,8 @@ use protocol::types::{ use crate::precompiles::build_precompile_set; use crate::system_contract::{ - after_block_hook, before_block_hook, ckb_light_client::BLOCK_PERIOD_UPDATED_HEADER_CELL_ROOT, - metadata::handle::BLOCK_PERIOD_METADATA_ROOT, system_contract_dispatch, CkbLightClientContract, - ImageCellContract, MetadataContract, NativeTokenContract, SystemContract, HEADER_CELL_ROOT_KEY, - METADATA_ROOT_KEY, + after_block_hook, before_block_hook, system_contract_dispatch, CkbLightClientContract, + ImageCellContract, MetadataContract, NativeTokenContract, SystemContract, }; lazy_static::lazy_static! { @@ -46,8 +46,8 @@ lazy_static::lazy_static! { } thread_local! { - pub static CURRENT_HEADER_CELL_ROOT: RefCell = RefCell::new(H256::default()); - pub static CURRENT_METADATA_ROOT: RefCell = RefCell::new(H256::default()); + pub(crate) static CURRENT_HEADER_CELL_ROOT: RefCell = RefCell::new(H256::default()); + pub(crate) static CURRENT_METADATA_ROOT: RefCell = RefCell::new(H256::default()); } pub trait FeeAllocate: Sync + Send { @@ -185,7 +185,7 @@ impl Executor for AxonExecutor { // commit changes by all txs included in this block only once let new_state_root = adapter.commit(); - self.update_system_contract_roots_for_external_module(); + // self.update_system_contract_roots_for_external_module(); ExecResp { state_root: new_state_root, @@ -322,16 +322,16 @@ impl AxonExecutor { }); } - /// The system contract roots are updated at the end of execute transactions - /// of a block. - fn update_system_contract_roots_for_external_module(&self) { - BLOCK_PERIOD_UPDATED_HEADER_CELL_ROOT.store(Arc::new( - CURRENT_HEADER_CELL_ROOT.with(|root| *root.borrow()), - )); + // /// The system contract roots are updated at the end of execute transactions + // /// of a block. + // fn update_system_contract_roots_for_external_module(&self) { + // BLOCK_PERIOD_UPDATED_HEADER_CELL_ROOT.store(Arc::new( + // CURRENT_HEADER_CELL_ROOT.with(|root| *root.borrow()), + // )); - BLOCK_PERIOD_METADATA_ROOT - .store(Arc::new(CURRENT_METADATA_ROOT.with(|root| *root.borrow()))); - } + // BLOCK_PERIOD_METADATA_ROOT + // .store(Arc::new(CURRENT_METADATA_ROOT.with(|root| *root.borrow()))); + // } #[cfg(test)] fn test_exec( diff --git a/core/executor/src/precompiles/call_ckb_vm.rs b/core/executor/src/precompiles/call_ckb_vm.rs index feadc6b3e..64495255f 100644 --- a/core/executor/src/precompiles/call_ckb_vm.rs +++ b/core/executor/src/precompiles/call_ckb_vm.rs @@ -8,6 +8,7 @@ use protocol::types::{CellDep, H160, H256}; use core_interoperation::{cycle_to_gas, gas_to_cycle, InteroperationImpl}; use crate::precompiles::{axon_precompile_address, PrecompileContract}; +use crate::CURRENT_HEADER_CELL_ROOT; use crate::{err, system_contract::DataProvider}; macro_rules! try_rlp { @@ -33,7 +34,7 @@ impl PrecompileContract for CkbVM { let rlp = Rlp::new(input); let res = ::call_ckb_vm( Default::default(), - &DataProvider::default(), + &DataProvider::new(CURRENT_HEADER_CELL_ROOT.with(|r| *r.borrow())), get_cell_dep(&rlp)?, &try_rlp!(rlp, list_at, 3), gas_to_cycle(gas), diff --git a/core/executor/src/precompiles/get_cell.rs b/core/executor/src/precompiles/get_cell.rs index e85b48b90..403886423 100644 --- a/core/executor/src/precompiles/get_cell.rs +++ b/core/executor/src/precompiles/get_cell.rs @@ -9,7 +9,7 @@ use protocol::types::{H160, H256}; use crate::precompiles::{axon_precompile_address, PrecompileContract}; use crate::system_contract::image_cell::{image_cell_abi, CellKey}; -use crate::{err, system_contract::image_cell::ImageCellContract}; +use crate::{err, system_contract::image_cell::ImageCellContract, CURRENT_HEADER_CELL_ROOT}; #[derive(Default, Clone)] pub struct GetCell; @@ -33,8 +33,9 @@ impl PrecompileContract for GetCell { let (tx_hash, index) = parse_input(input)?; + let root = CURRENT_HEADER_CELL_ROOT.with(|r| *r.borrow()); let cell = ImageCellContract::default() - .get_cell(&CellKey { tx_hash, index }) + .get_cell(root, &CellKey { tx_hash, index }) .map_err(|_| err!(_, "get cell"))? .map(|c| Cell { cell_output: packed::CellOutput::new_unchecked(c.cell_output).into(), diff --git a/core/executor/src/precompiles/get_header.rs b/core/executor/src/precompiles/get_header.rs index 1ec2697bb..1efa20611 100644 --- a/core/executor/src/precompiles/get_header.rs +++ b/core/executor/src/precompiles/get_header.rs @@ -5,7 +5,7 @@ use evm::{Context, ExitError, ExitSucceed}; use protocol::types::{H160, H256}; use crate::precompiles::{axon_precompile_address, PrecompileContract}; -use crate::{err, system_contract::CkbLightClientContract}; +use crate::{err, system_contract::CkbLightClientContract, CURRENT_HEADER_CELL_ROOT}; #[derive(Default, Clone)] pub struct GetHeader; @@ -30,8 +30,9 @@ impl PrecompileContract for GetHeader { let block_hash = H256(<[u8; 32] as AbiDecode>::decode(input).map_err(|_| err!(_, "decode input"))?); + let root = CURRENT_HEADER_CELL_ROOT.with(|r| *r.borrow()); let raw = CkbLightClientContract::default() - .get_raw(&block_hash.0) + .get_raw(root, &block_hash.0) .map_err(|_| err!(_, "get header"))?; Ok(( diff --git a/core/executor/src/precompiles/metadata.rs b/core/executor/src/precompiles/metadata.rs index 99cb01ae8..95d46b53a 100644 --- a/core/executor/src/precompiles/metadata.rs +++ b/core/executor/src/precompiles/metadata.rs @@ -4,7 +4,7 @@ use evm::{Context, ExitError, ExitSucceed}; use protocol::types::H160; use crate::precompiles::{axon_precompile_address, PrecompileContract}; -use crate::{err, system_contract::metadata::MetadataHandle}; +use crate::{err, system_contract::metadata::MetadataHandle, CURRENT_METADATA_ROOT}; const INPUT_LEN: usize = 1 + 8; @@ -34,12 +34,13 @@ impl PrecompileContract for Metadata { } let (ty, number) = parse_input(input)?; + let root = CURRENT_METADATA_ROOT.with(|r| *r.borrow()); let metadata = match ty { - 0u8 => MetadataHandle::default() + 0u8 => MetadataHandle::new(root) .get_metadata_by_block_number(number) .map_err(|e| err!(_, e.to_string()))?, - 1u8 => MetadataHandle::default() + 1u8 => MetadataHandle::new(root) .get_metadata_by_epoch(number) .map_err(|e| err!(_, e.to_string()))?, _ => return err!("Invalid call type"), diff --git a/core/executor/src/precompiles/verify_by_ckb_vm.rs b/core/executor/src/precompiles/verify_by_ckb_vm.rs index bef764a40..07fb3bb59 100644 --- a/core/executor/src/precompiles/verify_by_ckb_vm.rs +++ b/core/executor/src/precompiles/verify_by_ckb_vm.rs @@ -8,6 +8,7 @@ use protocol::types::{CellDep, OutPoint, SignatureR, SignatureS, Witness, H160, use core_interoperation::{cycle_to_gas, gas_to_cycle, InteroperationImpl}; use crate::precompiles::{axon_precompile_address, PrecompileContract}; +use crate::CURRENT_HEADER_CELL_ROOT; use crate::{err, system_contract::DataProvider}; macro_rules! try_rlp { @@ -38,7 +39,7 @@ impl PrecompileContract for CkbVM { if let Some(gas) = gas_limit { let res = InteroperationImpl::verify_by_ckb_vm( Default::default(), - &DataProvider::default(), + &DataProvider::new(CURRENT_HEADER_CELL_ROOT.with(|r| *r.borrow())), &InteroperationImpl::dummy_transaction( SignatureR::new_by_ref(cell_deps, header_deps, inputs, Default::default()), SignatureS::new(witnesses), diff --git a/core/executor/src/system_contract/ckb_light_client/mod.rs b/core/executor/src/system_contract/ckb_light_client/mod.rs index 1a21e55ab..004b035a1 100644 --- a/core/executor/src/system_contract/ckb_light_client/mod.rs +++ b/core/executor/src/system_contract/ckb_light_client/mod.rs @@ -2,7 +2,6 @@ mod abi; mod store; pub use abi::ckb_light_client_abi; -use arc_swap::ArcSwap; use std::sync::atomic::{AtomicBool, Ordering}; @@ -16,18 +15,14 @@ use crate::system_contract::utils::{succeed_resp, update_states}; use crate::system_contract::{system_contract_address, SystemContract}; use crate::{exec_try, CURRENT_HEADER_CELL_ROOT}; +pub const CKB_LIGHT_CLIENT_CONTRACT_ADDRESS: H160 = system_contract_address(0x2); static ALLOW_READ: AtomicBool = AtomicBool::new(false); -lazy_static::lazy_static! { - pub(crate) static ref BLOCK_PERIOD_UPDATED_HEADER_CELL_ROOT: ArcSwap - = ArcSwap::from_pointee(H256::default()); -} - #[derive(Default)] pub struct CkbLightClientContract; impl SystemContract for CkbLightClientContract { - const ADDRESS: H160 = system_contract_address(0x2); + const ADDRESS: H160 = CKB_LIGHT_CLIENT_CONTRACT_ADDRESS; fn exec_( &self, @@ -79,21 +74,17 @@ impl SystemContract for CkbLightClientContract { /// These methods are provide for interoperation module to get CKB headers. impl CkbLightClientContract { - // Use the block period update root to avoid some mistake. - pub(crate) fn get_root(&self) -> H256 { - **BLOCK_PERIOD_UPDATED_HEADER_CELL_ROOT.load() - } - pub fn get_header_by_block_hash( &self, + root: H256, block_hash: &H256, ) -> ProtocolResult> { - let store = CkbLightClientStore::new(self.get_root())?; + let store = CkbLightClientStore::new(root)?; store.get_header(&block_hash.0) } - pub fn get_raw(&self, key: &[u8]) -> ProtocolResult>> { - let store = CkbLightClientStore::new(self.get_root())?; + pub fn get_raw(&self, root: H256, key: &[u8]) -> ProtocolResult>> { + let store = CkbLightClientStore::new(root)?; let ret = store.trie.get(key)?.map(Into::into); Ok(ret) } diff --git a/core/executor/src/system_contract/image_cell/mod.rs b/core/executor/src/system_contract/image_cell/mod.rs index f668d72a3..49f2ec478 100644 --- a/core/executor/src/system_contract/image_cell/mod.rs +++ b/core/executor/src/system_contract/image_cell/mod.rs @@ -13,19 +13,19 @@ use protocol::traits::ExecutorAdapter; use protocol::types::{SignedTransaction, TxResp, H160, H256}; use protocol::ProtocolResult; -use crate::system_contract::ckb_light_client::BLOCK_PERIOD_UPDATED_HEADER_CELL_ROOT; use crate::system_contract::image_cell::store::ImageCellStore; use crate::system_contract::utils::{succeed_resp, update_states}; use crate::system_contract::{system_contract_address, SystemContract}; use crate::{exec_try, MPTTrie, CURRENT_HEADER_CELL_ROOT}; +pub const IMAGE_CELL_CONTRACT_ADDRESS: H160 = system_contract_address(0x3); static ALLOW_READ: AtomicBool = AtomicBool::new(false); #[derive(Default)] pub struct ImageCellContract; impl SystemContract for ImageCellContract { - const ADDRESS: H160 = system_contract_address(0x3); + const ADDRESS: H160 = IMAGE_CELL_CONTRACT_ADDRESS; fn exec_( &self, @@ -73,12 +73,8 @@ impl SystemContract for ImageCellContract { /// These methods are provide for interoperation module to get CKB cells. impl ImageCellContract { - pub(crate) fn get_root(&self) -> H256 { - **BLOCK_PERIOD_UPDATED_HEADER_CELL_ROOT.load() - } - - pub fn get_cell(&self, key: &CellKey) -> ProtocolResult> { - ImageCellStore::new(self.get_root())?.get_cell(key) + pub fn get_cell(&self, root: H256, key: &CellKey) -> ProtocolResult> { + ImageCellStore::new(root)?.get_cell(key) } pub fn allow_read(&self) -> bool { @@ -91,9 +87,10 @@ impl ImageCellContract { /// deployed cell. pub(super) fn save_cells( &self, + root: H256, cells: Vec, created_number: u64, ) -> ProtocolResult<()> { - ImageCellStore::new(self.get_root())?.save_cells(cells, created_number) + ImageCellStore::new(root)?.save_cells(cells, created_number) } } diff --git a/core/executor/src/system_contract/metadata/handle.rs b/core/executor/src/system_contract/metadata/handle.rs index 7e6c69bcc..c32e2cd01 100644 --- a/core/executor/src/system_contract/metadata/handle.rs +++ b/core/executor/src/system_contract/metadata/handle.rs @@ -1,23 +1,22 @@ -use arc_swap::ArcSwap; - use protocol::types::{CkbRelatedInfo, Metadata, H160, H256}; use protocol::ProtocolResult; use crate::system_contract::metadata::MetadataStore; -lazy_static::lazy_static! { - pub(crate) static ref BLOCK_PERIOD_METADATA_ROOT: ArcSwap - = ArcSwap::from_pointee(H256::default()); -} - /// The MetadataHandle is used to expose apis that can be accessed from outside /// of the system contract. -#[derive(Default)] -pub struct MetadataHandle; +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MetadataHandle { + root: H256, +} impl MetadataHandle { + pub fn new(root: H256) -> Self { + MetadataHandle { root } + } + pub fn get_metadata_by_block_number(&self, block_number: u64) -> ProtocolResult { - let store = MetadataStore::new(self.get_metadata_root())?; + let store = MetadataStore::new(self.root)?; // Should retrieve the first metadata for the genesis block if block_number == 0 { @@ -30,11 +29,11 @@ impl MetadataHandle { } pub fn get_metadata_by_epoch(&self, epoch: u64) -> ProtocolResult { - MetadataStore::new(self.get_metadata_root())?.get_metadata(epoch) + MetadataStore::new(self.root)?.get_metadata(epoch) } pub fn is_last_block_in_current_epoch(&self, block_number: u64) -> ProtocolResult { - let store = MetadataStore::new(self.get_metadata_root())?; + let store = MetadataStore::new(self.root)?; let segment = store.get_epoch_segment()?; let is_last_block = segment.is_last_block_in_epoch(block_number); Ok(is_last_block) @@ -46,11 +45,6 @@ impl MetadataHandle { } pub fn get_ckb_related_info(&self) -> ProtocolResult { - MetadataStore::new(self.get_metadata_root())?.get_ckb_related_info() - } - - // Get the metadata root from block period update variable. - fn get_metadata_root(&self) -> H256 { - **BLOCK_PERIOD_METADATA_ROOT.load() + MetadataStore::new(self.root)?.get_ckb_related_info() } } diff --git a/core/executor/src/system_contract/metadata/mod.rs b/core/executor/src/system_contract/metadata/mod.rs index 24096c097..c85ac43a0 100644 --- a/core/executor/src/system_contract/metadata/mod.rs +++ b/core/executor/src/system_contract/metadata/mod.rs @@ -24,6 +24,7 @@ use crate::{exec_try, CURRENT_METADATA_ROOT}; type Epoch = u64; +pub const METADATA_CONTRACT_ADDRESS: H160 = system_contract_address(0x1); const METADATA_CACHE_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(10) }; lazy_static::lazy_static! { @@ -36,7 +37,7 @@ lazy_static::lazy_static! { pub struct MetadataContract; impl SystemContract for MetadataContract { - const ADDRESS: H160 = system_contract_address(0x1); + const ADDRESS: H160 = METADATA_CONTRACT_ADDRESS; fn exec_( &self, @@ -57,7 +58,7 @@ impl SystemContract for MetadataContract { ); if block_number != 0 { - let handle = MetadataHandle::default(); + let handle = MetadataHandle::new(CURRENT_METADATA_ROOT.with(|r| *r.borrow())); if !exec_try!( handle.is_validator(block_number, sender), @@ -124,6 +125,6 @@ impl SystemContract for MetadataContract { } } -pub fn check_ckb_related_info_exist() -> bool { - MetadataHandle::default().get_ckb_related_info().is_ok() +pub fn check_ckb_related_info_exist(root: H256) -> bool { + MetadataHandle::new(root).get_ckb_related_info().is_ok() } diff --git a/core/executor/src/system_contract/mod.rs b/core/executor/src/system_contract/mod.rs index ab3e3b3c6..20ada6c11 100644 --- a/core/executor/src/system_contract/mod.rs +++ b/core/executor/src/system_contract/mod.rs @@ -2,15 +2,20 @@ mod error; mod native_token; mod utils; -pub mod ckb_light_client; -pub mod image_cell; +pub(crate) mod ckb_light_client; +pub(crate) mod image_cell; pub mod metadata; -pub use crate::system_contract::ckb_light_client::CkbLightClientContract; -pub use crate::system_contract::image_cell::ImageCellContract; -use crate::system_contract::metadata::handle::BLOCK_PERIOD_METADATA_ROOT; -pub use crate::system_contract::metadata::{check_ckb_related_info_exist, MetadataContract}; -pub use crate::system_contract::native_token::NativeTokenContract; +pub use crate::system_contract::ckb_light_client::{ + CkbLightClientContract, CKB_LIGHT_CLIENT_CONTRACT_ADDRESS, +}; +pub use crate::system_contract::image_cell::{ImageCellContract, IMAGE_CELL_CONTRACT_ADDRESS}; +pub use crate::system_contract::metadata::{ + check_ckb_related_info_exist, MetadataContract, METADATA_CONTRACT_ADDRESS, +}; +pub use crate::system_contract::native_token::{ + NativeTokenContract, NATIVE_TOKEN_CONTRACT_ADDRESS, +}; use std::path::Path; use std::sync::Arc; @@ -26,7 +31,6 @@ use protocol::types::{Bytes, Hasher, SignedTransaction, TxResp, H160, H256}; use protocol::{ckb_blake2b_256, traits::ExecutorAdapter}; use crate::adapter::RocksTrieDB; -use crate::system_contract::ckb_light_client::BLOCK_PERIOD_UPDATED_HEADER_CELL_ROOT; use crate::system_contract::image_cell::utils::always_success_script_deploy_cell; use crate::system_contract::utils::generate_mpt_root_changes; @@ -80,10 +84,8 @@ pub fn init, Adapter: ExecutorAdapter>( path: P, config: ConfigRocksDB, adapter: &mut Adapter, -) { - // Init metadata root for consensus and mempool module. +) -> (H256, H256) { let current_metadata_root = adapter.storage(MetadataContract::ADDRESS, *METADATA_ROOT_KEY); - BLOCK_PERIOD_METADATA_ROOT.store(Arc::new(current_metadata_root)); // Init metadata db. let metadata_db_path = path.as_ref().join("metadata"); @@ -112,14 +114,13 @@ pub fn init, Adapter: ExecutorAdapter>( if current_cell_root.is_zero() { // todo need refactoring ImageCellContract::default() - .save_cells(vec![always_success_script_deploy_cell()], 0) + .save_cells(H256::zero(), vec![always_success_script_deploy_cell()], 0) .unwrap(); let changes = generate_mpt_root_changes(adapter, ImageCellContract::ADDRESS); - return adapter.apply(changes, vec![], false); + adapter.apply(changes, vec![], false); } - // Init CKB header and cell root for interoperation module. - BLOCK_PERIOD_UPDATED_HEADER_CELL_ROOT.store(Arc::new(current_cell_root)); + (current_metadata_root, current_cell_root) } pub fn before_block_hook(adapter: &mut Adapter) { @@ -156,13 +157,15 @@ pub fn system_contract_dispatch( None } -#[derive(Default, Clone, Debug)] -pub struct DataProvider; +#[derive(Clone, Debug)] +pub struct DataProvider { + root: H256, +} impl CellProvider for DataProvider { fn cell(&self, out_point: &packed::OutPoint, _eager_load: bool) -> CellStatus { if let Some(c) = ImageCellContract::default() - .get_cell(&(out_point).into()) + .get_cell(self.root, &(out_point).into()) .ok() .flatten() { @@ -176,7 +179,7 @@ impl CellProvider for DataProvider { impl CellDataProvider for DataProvider { fn get_cell_data(&self, out_point: &packed::OutPoint) -> Option { ImageCellContract::default() - .get_cell(&(out_point.into())) + .get_cell(self.root, &(out_point.into())) .ok() .flatten() .map(|info| info.cell_data) @@ -197,7 +200,7 @@ impl HeaderProvider for DataProvider { fn get_header(&self, hash: &packed::Byte32) -> Option { let block_hash = hash.unpack(); CkbLightClientContract::default() - .get_header_by_block_hash(&H256(block_hash.0)) + .get_header_by_block_hash(self.root, &H256(block_hash.0)) .ok() .flatten() .map(|h| { @@ -217,3 +220,9 @@ impl HeaderProvider for DataProvider { }) } } + +impl DataProvider { + pub fn new(root: H256) -> Self { + DataProvider { root } + } +} diff --git a/core/executor/src/system_contract/native_token.rs b/core/executor/src/system_contract/native_token.rs index c5207d698..77a333dcc 100644 --- a/core/executor/src/system_contract/native_token.rs +++ b/core/executor/src/system_contract/native_token.rs @@ -4,11 +4,13 @@ use protocol::types::{Apply, Basic, SignedTransaction, TxResp, H160, U256}; use crate::system_contract::utils::{revert_resp, succeed_resp}; use crate::system_contract::{system_contract_address, SystemContract}; +pub const NATIVE_TOKEN_CONTRACT_ADDRESS: H160 = system_contract_address(0x0); + #[derive(Default)] pub struct NativeTokenContract; impl SystemContract for NativeTokenContract { - const ADDRESS: H160 = system_contract_address(0x0); + const ADDRESS: H160 = NATIVE_TOKEN_CONTRACT_ADDRESS; fn exec_(&self, backend: &mut B, tx: &SignedTransaction) -> TxResp { let tx = &tx.transaction.unsigned; diff --git a/core/executor/src/tests/system_script/ckb_light_client.rs b/core/executor/src/tests/system_script/ckb_light_client.rs index bfbc529f9..59d2c8256 100644 --- a/core/executor/src/tests/system_script/ckb_light_client.rs +++ b/core/executor/src/tests/system_script/ckb_light_client.rs @@ -60,11 +60,11 @@ fn test_update_first(backend: &mut MemoryBackend, executor: &CkbLightClientContr let r = exec(backend, executor, data.encode()); assert!(r.exit_reason.is_succeed()); - check_root(backend, executor); check_nonce(backend, 1); + let root = backend.storage(CkbLightClientContract::ADDRESS, *HEADER_CELL_ROOT_KEY); let queried_header = executor - .get_header_by_block_hash(&H256::default()) + .get_header_by_block_hash(root, &H256::default()) .unwrap() .unwrap(); @@ -80,11 +80,11 @@ fn test_update_second(backend: &mut MemoryBackend, executor: &CkbLightClientCont let r = exec(backend, executor, data.encode()); assert!(r.exit_reason.is_succeed()); - check_root(backend, executor); check_nonce(backend, 2); + let root = backend.storage(CkbLightClientContract::ADDRESS, *HEADER_CELL_ROOT_KEY); let queried_header = executor - .get_header_by_block_hash(&H256::from_slice(&header.block_hash)) + .get_header_by_block_hash(root, &H256::from_slice(&header.block_hash)) .unwrap() .unwrap(); @@ -99,10 +99,9 @@ fn test_roll_back_first(backend: &mut MemoryBackend, executor: &CkbLightClientCo let r = exec(backend, executor, data.encode()); assert!(r.exit_reason.is_succeed()); - check_root(backend, executor); - + let root = backend.storage(CkbLightClientContract::ADDRESS, *HEADER_CELL_ROOT_KEY); let queried_header = executor - .get_header_by_block_hash(&H256::default()) + .get_header_by_block_hash(root, &H256::default()) .unwrap() .unwrap(); @@ -117,9 +116,10 @@ fn test_roll_back_second(backend: &mut MemoryBackend, executor: &CkbLightClientC let r = exec(backend, executor, data.encode()); assert!(r.exit_reason.is_succeed()); - check_root(backend, executor); - - let queried_header = executor.get_header_by_block_hash(&H256::default()).unwrap(); + let root = backend.storage(CkbLightClientContract::ADDRESS, *HEADER_CELL_ROOT_KEY); + let queried_header = executor + .get_header_by_block_hash(root, &H256::default()) + .unwrap(); assert!(queried_header.is_none()); } @@ -140,17 +140,6 @@ fn exec(backend: &mut MemoryBackend, executor: &CkbLightClientContract, data: Ve executor.exec_(backend, &tx) } -fn check_root(backend: &MemoryBackend, executor: &CkbLightClientContract) { - let account = backend - .state() - .get(&CkbLightClientContract::ADDRESS) - .unwrap(); - assert_eq!( - &executor.get_root(), - account.storage.get(&HEADER_CELL_ROOT_KEY).unwrap(), - ); -} - fn check_nonce(backend: &mut MemoryBackend, nonce: u64) { assert_eq!( backend.basic(CkbLightClientContract::ADDRESS).nonce, diff --git a/core/executor/src/tests/system_script/image_cell.rs b/core/executor/src/tests/system_script/image_cell.rs index e0dbf4536..f65ac6547 100644 --- a/core/executor/src/tests/system_script/image_cell.rs +++ b/core/executor/src/tests/system_script/image_cell.rs @@ -41,11 +41,11 @@ fn test_update_first(backend: &mut MemoryBackend, executor: &ImageCellContract) let r = exec(backend, executor, data.encode()); assert!(r.exit_reason.is_succeed()); - check_root(backend, executor); check_nonce(backend, 1); + let root = backend.storage(CkbLightClientContract::ADDRESS, *HEADER_CELL_ROOT_KEY); let cell_key = CellKey::new([7u8; 32], 0x0); - let get_cell = executor.get_cell(&cell_key).unwrap().unwrap(); + let get_cell = executor.get_cell(root, &cell_key).unwrap().unwrap(); check_cell(&get_cell, 0x1, None); } @@ -64,11 +64,11 @@ fn test_update_second(backend: &mut MemoryBackend, executor: &ImageCellContract) let r = exec(backend, executor, data.encode()); assert!(r.exit_reason.is_succeed()); - check_root(backend, executor); check_nonce(backend, 2); + let root = backend.storage(CkbLightClientContract::ADDRESS, *HEADER_CELL_ROOT_KEY); let cell_key = CellKey::new([7u8; 32], 0x0); - let get_cell = executor.get_cell(&cell_key).unwrap().unwrap(); + let get_cell = executor.get_cell(root, &cell_key).unwrap().unwrap(); check_cell(&get_cell, 0x1, Some(0x2)); } @@ -86,10 +86,9 @@ fn test_rollback_first(backend: &mut MemoryBackend, executor: &ImageCellContract let r = exec(backend, executor, data.encode()); assert!(r.exit_reason.is_succeed()); - check_root(backend, executor); - + let root = backend.storage(CkbLightClientContract::ADDRESS, *HEADER_CELL_ROOT_KEY); let cell_key = CellKey::new([7u8; 32], 0x0); - let get_cell = executor.get_cell(&cell_key).unwrap().unwrap(); + let get_cell = executor.get_cell(root, &cell_key).unwrap().unwrap(); check_cell(&get_cell, 0x1, None); } @@ -107,10 +106,9 @@ fn test_rollback_second(backend: &mut MemoryBackend, executor: &ImageCellContrac let r = exec(backend, executor, data.encode()); assert!(r.exit_reason.is_succeed()); - check_root(backend, executor); - + let root = backend.storage(CkbLightClientContract::ADDRESS, *HEADER_CELL_ROOT_KEY); let cell_key = CellKey::new([7u8; 32], 0x0); - let get_cell = executor.get_cell(&cell_key).unwrap(); + let get_cell = executor.get_cell(root, &cell_key).unwrap(); assert!(get_cell.is_none()); } @@ -131,14 +129,6 @@ fn exec(backend: &mut MemoryBackend, executor: &ImageCellContract, data: Vec executor.exec_(backend, &tx) } -fn check_root(backend: &MemoryBackend, executor: &ImageCellContract) { - let account = backend.state().get(&ImageCellContract::ADDRESS).unwrap(); - assert_eq!( - &executor.get_root(), - account.storage.get(&HEADER_CELL_ROOT_KEY).unwrap(), - ); -} - fn check_cell(get_cell: &CellInfo, created_number: u64, consumed_number: Option) { let cell = &prepare_outputs()[0]; diff --git a/core/mempool/src/adapter/mod.rs b/core/mempool/src/adapter/mod.rs index d2be579f5..c323a9390 100644 --- a/core/mempool/src/adapter/mod.rs +++ b/core/mempool/src/adapter/mod.rs @@ -20,14 +20,16 @@ use protocol::types::{ SignatureR, SignatureS, SignedTransaction, H160, U256, }; use protocol::{ - async_trait, codec::ProtocolCodec, lazy::CURRENT_STATE_ROOT, tokio, trie, Display, - ProtocolError, ProtocolErrorKind, ProtocolResult, + async_trait, codec::ProtocolCodec, tokio, trie, Display, ProtocolError, ProtocolErrorKind, + ProtocolResult, }; use common_apm_derive::trace_span; use common_crypto::{Crypto, Secp256k1Recoverable}; -use core_executor::system_contract::{metadata::MetadataHandle, DataProvider}; -use core_executor::{is_call_system_script, AxonExecutorAdapter}; +use core_executor::{ + is_call_system_script, AxonExecutorAdapter, DataProvider, MetadataHandle, HEADER_CELL_ROOT_KEY, + IMAGE_CELL_CONTRACT_ADDRESS, METADATA_CONTRACT_ADDRESS, METADATA_ROOT_KEY, +}; use core_interoperation::InteroperationImpl; use crate::adapter::message::{MsgPullTxs, END_GOSSIP_NEW_TXS, RPC_PULL_TXS}; @@ -115,10 +117,9 @@ impl IntervalTxsBroadcaster { } pub struct DefaultMemPoolAdapter { - network: N, - storage: Arc, - trie_db: Arc, - metadata: Arc, + network: N, + storage: Arc, + trie_db: Arc, addr_nonce: DashMap, gas_limit: AtomicU64, @@ -144,7 +145,6 @@ where network: N, storage: Arc, trie_db: Arc, - metadata: Arc, chain_id: u64, gas_limit: u64, max_tx_size: usize, @@ -166,7 +166,6 @@ where network, storage, trie_db, - metadata, addr_nonce: DashMap::new(), gas_limit: AtomicU64::new(gas_limit), @@ -188,8 +187,10 @@ where ) -> ProtocolResult { let addr = &stx.sender; let block = self.storage.get_latest_block(ctx.clone()).await?; + let backend = self.executor_backend(ctx).await?; + let root = backend.storage(METADATA_CONTRACT_ADDRESS, *METADATA_ROOT_KEY); - if self.metadata.is_validator(block.header.number + 1, *addr)? { + if MetadataHandle::new(root).is_validator(block.header.number + 1, *addr)? { return Ok(U256::zero()); } @@ -274,7 +275,7 @@ where Ok(()) } - fn verify_signature(&self, stx: &SignedTransaction) -> ProtocolResult<()> { + async fn verify_signature(&self, ctx: Context, stx: &SignedTransaction) -> ProtocolResult<()> { let signature = stx.transaction.signature.clone().unwrap(); if signature.is_eth_sig() { // Verify secp256k1 signature @@ -288,6 +289,9 @@ where return Ok(()); } + let backend = self.executor_backend(ctx).await?; + let root = backend.storage(IMAGE_CELL_CONTRACT_ADDRESS, *HEADER_CELL_ROOT_KEY); + // Verify interoperation signature match signature.r[0] { 0u8 => { @@ -297,7 +301,7 @@ where InteroperationImpl::call_ckb_vm( Default::default(), - &DataProvider::default(), + &DataProvider::new(root), r.cell_dep, &[r.pub_key, signature.s], u64::MAX, @@ -318,7 +322,7 @@ where InteroperationImpl::verify_by_ckb_vm( Default::default(), - &DataProvider::default(), + &DataProvider::new(root), &InteroperationImpl::dummy_transaction( r.clone(), s, @@ -332,6 +336,16 @@ where } Ok(()) } + + async fn executor_backend(&self, ctx: Context) -> ProtocolResult> { + let current_state_root = self.storage.get_latest_block_header(ctx).await?.state_root; + AxonExecutorAdapter::from_root( + current_state_root, + Arc::clone(&self.trie_db), + Arc::clone(&self.storage), + Default::default(), + ) + } } #[async_trait] @@ -413,13 +427,7 @@ where } } - let backend = AxonExecutorAdapter::from_root( - **CURRENT_STATE_ROOT.load(), - Arc::clone(&self.trie_db), - Arc::clone(&self.storage), - Default::default(), - )?; - + let backend = self.executor_backend(ctx).await?; let account = backend.basic(*addr); self.addr_nonce .insert(*addr, (account.nonce, account.balance)); @@ -456,8 +464,8 @@ where self.verify_chain_id(ctx.clone(), stx)?; self.verify_tx_size(ctx.clone(), stx)?; self.verify_gas_price(stx)?; - self.verify_gas_limit(ctx, stx)?; - self.verify_signature(stx)?; + self.verify_gas_limit(ctx.clone(), stx)?; + self.verify_signature(ctx, stx).await?; Ok(()) } diff --git a/core/run/src/lib.rs b/core/run/src/lib.rs index 826dcfccd..c0793f23f 100644 --- a/core/run/src/lib.rs +++ b/core/run/src/lib.rs @@ -22,7 +22,7 @@ use common_crypto::{ }; use protocol::codec::{hex_decode, ProtocolCodec}; -use protocol::lazy::{CHAIN_ID, CURRENT_STATE_ROOT}; +use protocol::lazy::CHAIN_ID; #[cfg(unix)] use protocol::tokio::signal::unix as os_impl; use protocol::tokio::{ @@ -266,30 +266,21 @@ impl Axon { .to_string(); let txs_wal = Arc::new(SignedTxsWAL::new(txs_wal_path)); - // Init system contract when the chain is not first initiated - if current_block.header.state_root != H256::default() { + // Init system contract + let (metadata_root, _header_cell_root) = self.init_system_contract(&trie_db, ¤t_block, &storage); - } - - // Init metadata handle which will be used in mempool - let metadata_handle = Arc::new(MetadataHandle::default()); // Init mempool and recover signed transactions with the current block number let current_stxs = txs_wal.load_by_number(current_block.header.number + 1); log::info!("Recover {} txs from wal", current_stxs.len()); let mempool = self - .init_mempool( - &trie_db, - &network_service.handle(), - &storage, - &metadata_handle, - ¤t_stxs, - ) + .init_mempool(&trie_db, &network_service.handle(), &storage, ¤t_stxs) .await; // Get the validator list from current metadata for consensus initialization - let metadata = metadata_handle.get_metadata_by_block_number(current_block.header.number)?; + let metadata = MetadataHandle::new(metadata_root) + .get_metadata_by_block_number(current_block.header.number)?; let validators: Vec = metadata .verifier_list .iter() @@ -316,7 +307,6 @@ impl Axon { Arc::clone(&mempool), Arc::clone(&storage), Arc::clone(&trie_db), - Arc::clone(&metadata_handle), Arc::clone(&crypto), )?; let consensus_adapter = Arc::new(consensus_adapter); @@ -441,7 +431,6 @@ impl Axon { trie_db: &Arc, network_service: &N, storage: &Arc, - metadata_handle: &Arc, signed_txs: &[SignedTransaction], ) -> Arc>> where @@ -453,7 +442,6 @@ impl Axon { network_service.clone(), Arc::clone(storage), Arc::clone(trie_db), - Arc::clone(metadata_handle), self.genesis.block.header.chain_id, self.genesis.block.header.gas_limit.as_u64(), self.config.mempool.pool_size as usize, @@ -489,7 +477,7 @@ impl Axon { trie_db: &Arc, current_block: &Block, storage: &Arc>, - ) { + ) -> (H256, H256) { let path_system_contract = self.config.data_path_for_system_contract(); let mut backend = AxonExecutorAdapter::from_root( current_block.header.state_root, @@ -502,7 +490,7 @@ impl Axon { path_system_contract, self.config.rocksdb.clone(), &mut backend, - ); + ) } fn get_my_pubkey(&self, hex_privkey: Vec) -> Secp256k1PublicKey { @@ -568,7 +556,6 @@ impl Axon { }, }; - CURRENT_STATE_ROOT.swap(Arc::new(current_consensus_status.last_state_root)); CHAIN_ID.swap(Arc::new(header.chain_id)); StatusAgent::new(current_consensus_status) diff --git a/protocol/src/lazy.rs b/protocol/src/lazy.rs index d89cd0c2f..c19a31e34 100644 --- a/protocol/src/lazy.rs +++ b/protocol/src/lazy.rs @@ -2,11 +2,9 @@ use arc_swap::ArcSwap; use ckb_always_success_script::ALWAYS_SUCCESS; use ckb_types::{core::ScriptHashType, packed, prelude::*}; -use crate::ckb_blake2b_256; -use crate::types::{Hex, MerkleRoot}; +use crate::{ckb_blake2b_256, types::Hex}; lazy_static::lazy_static! { - pub static ref CURRENT_STATE_ROOT: ArcSwap = ArcSwap::from_pointee(Default::default()); pub static ref CHAIN_ID: ArcSwap = ArcSwap::from_pointee(Default::default()); pub static ref PROTOCOL_VERSION: ArcSwap = ArcSwap::from_pointee(Default::default()); diff --git a/protocol/src/traits/api.rs b/protocol/src/traits/api.rs index 8092b36d4..e7ea0e58b 100644 --- a/protocol/src/traits/api.rs +++ b/protocol/src/traits/api.rs @@ -1,6 +1,6 @@ use crate::types::{ Account, Block, BlockNumber, Bytes, CkbRelatedInfo, Hash, Header, Metadata, Proposal, Receipt, - SignedTransaction, TxResp, H160, U256, + SignedTransaction, TxResp, H160, H256, U256, }; use crate::{async_trait, traits::Context, ProtocolResult}; @@ -99,4 +99,8 @@ pub trait APIAdapter: Send + Sync { ) -> ProtocolResult; async fn get_ckb_related_info(&self, ctx: Context) -> ProtocolResult; + + async fn get_image_cell_root(&self, ctx: Context) -> ProtocolResult; + + async fn get_metadata_root(&self, ctx: Context) -> ProtocolResult; }