Skip to content

Commit

Permalink
refactor: insert metadata directly when init chain
Browse files Browse the repository at this point in the history
  • Loading branch information
KaoImin committed Oct 7, 2023
1 parent 6fe5777 commit 12df447
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 69 deletions.
50 changes: 45 additions & 5 deletions core/executor/src/system_contract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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};
use crate::system_contract::metadata::MetadataStore;
pub use crate::system_contract::metadata::{
check_ckb_related_info_exist, MetadataContract, METADATA_CONTRACT_ADDRESS,
};
Expand All @@ -27,9 +28,9 @@ use evm::backend::ApplyBackend;
use parking_lot::RwLock;
use rocksdb::DB;

use protocol::ckb_blake2b_256;
use protocol::traits::{CkbDataProvider, ExecutorAdapter};
use protocol::types::{Bytes, Hasher, SignedTransaction, TxResp, H160, H256};
use protocol::types::{Bytes, Hasher, Metadata, SignedTransaction, TxResp, H160, H256};
use protocol::{ckb_blake2b_256, ProtocolResult};

use crate::adapter::RocksTrieDB;
use crate::system_contract::{
Expand Down Expand Up @@ -105,9 +106,29 @@ pub fn swap_header_cell_db(new_db: Arc<RocksTrieDB>) -> Arc<RocksTrieDB> {
.unwrap_or_else(|| panic!("header cell db is not initialized"))
}

/// This method init the CKB light client and metadata DB and insert the first
/// two metadata, so the `metadata_list.len()` should be equal to 2. The Axon
/// run process contains two part: `init` and `start`. The `init` part
/// should initialize the DB and insert the first two metadata. The `start` part
/// only need to initialize the DB. This method should be used in the `init`
/// process.
pub fn init<Adapter: ExecutorAdapter + ApplyBackend>(
db: Arc<DB>,
adapter: &mut Adapter,
metadata_list: &[Metadata],
) -> ProtocolResult<(H256, H256)> {
let ret = init_system_contract_db(db, adapter);
init_metadata(adapter, ret.0, metadata_list)?;

Ok(ret)
}

/// This method only init the CKB light client and metadata DB and should be
/// used in run process. The return value`tuple[0]` is current metadata MPT
/// root, `tuple[1]` is current CKB light client MPT root.
pub fn init_system_contract_db<Adapter: ExecutorAdapter + ApplyBackend>(
db: Arc<DB>,
adapter: &mut Adapter,
) -> (H256, H256) {
let current_metadata_root = adapter.storage(METADATA_CONTRACT_ADDRESS, *METADATA_ROOT_KEY);

Expand All @@ -128,14 +149,33 @@ pub fn init<Adapter: ExecutorAdapter + ApplyBackend>(
)));
}

let current_cell_root =
let current_light_client_root =
adapter.storage(CKB_LIGHT_CLIENT_CONTRACT_ADDRESS, *HEADER_CELL_ROOT_KEY);

if current_cell_root.is_zero() {
if current_light_client_root.is_zero() {
let changes = generate_mpt_root_changes(adapter, IMAGE_CELL_CONTRACT_ADDRESS);
adapter.apply(changes, vec![], false);
}
(current_metadata_root, current_cell_root)
(current_metadata_root, current_light_client_root)
}

/// This method is used for insert the first two metadata, so the
/// `metadata_list.len()` should be equal to 2.
fn init_metadata<Adapter: ExecutorAdapter + ApplyBackend>(
adapter: &mut Adapter,
metadata_root: H256,
metadata_list: &[Metadata],
) -> ProtocolResult<()> {
debug_assert!(metadata_list.len() == 2);

let mut store = MetadataStore::new(metadata_root)?;
store.append_metadata(&metadata_list[0])?;
store.append_metadata(&metadata_list[1])?;

let changes = generate_mpt_root_changes(adapter, METADATA_CONTRACT_ADDRESS);
adapter.apply(changes, vec![], false);

Ok(())
}

pub fn before_block_hook<Adapter: ExecutorAdapter + ApplyBackend>(adapter: &mut Adapter) {
Expand Down
6 changes: 3 additions & 3 deletions core/executor/src/tests/system_script/ckb_light_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::system_contract::ckb_light_client::{
ckb_light_client_abi, CkbHeaderReader, CkbLightClientContract,
};
use crate::system_contract::{
init, SystemContract, CKB_LIGHT_CLIENT_CONTRACT_ADDRESS, HEADER_CELL_ROOT_KEY,
IMAGE_CELL_CONTRACT_ADDRESS,
init_system_contract_db, SystemContract, CKB_LIGHT_CLIENT_CONTRACT_ADDRESS,
HEADER_CELL_ROOT_KEY, IMAGE_CELL_CONTRACT_ADDRESS,
};
use crate::tests::{gen_tx, gen_vicinity};

Expand All @@ -25,7 +25,7 @@ pub fn test_write_functions() {
let inner_db = RocksAdapter::new(ROCKSDB_PATH, Default::default())
.unwrap()
.inner_db();
init(inner_db, &mut backend);
init_system_contract_db(inner_db, &mut backend);

// need to refactor to be OO
test_update_first(&mut backend, &executor);
Expand Down
6 changes: 3 additions & 3 deletions core/executor/src/tests/system_script/image_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use crate::system_contract::image_cell::{
image_cell_abi, CellInfo, CellKey, ImageCellContract, ImageCellReader,
};
use crate::system_contract::{
init, SystemContract, CKB_LIGHT_CLIENT_CONTRACT_ADDRESS, HEADER_CELL_ROOT_KEY,
IMAGE_CELL_CONTRACT_ADDRESS,
init_system_contract_db, SystemContract, CKB_LIGHT_CLIENT_CONTRACT_ADDRESS,
HEADER_CELL_ROOT_KEY, IMAGE_CELL_CONTRACT_ADDRESS,
};
use crate::tests::{gen_tx, gen_vicinity};
use crate::{CURRENT_HEADER_CELL_ROOT, CURRENT_METADATA_ROOT};
Expand All @@ -27,7 +27,7 @@ pub fn test_write_functions() {
let inner_db = RocksAdapter::new(ROCKSDB_PATH, Default::default())
.unwrap()
.inner_db();
let (m_root, h_root) = init(inner_db, &mut backend);
let (m_root, h_root) = init_system_contract_db(inner_db, &mut backend);

CURRENT_METADATA_ROOT.with(|r| *r.borrow_mut() = m_root);
CURRENT_HEADER_CELL_ROOT.with(|r| *r.borrow_mut() = h_root);
Expand Down
4 changes: 2 additions & 2 deletions core/executor/src/tests/system_script/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use protocol::types::{MemoryBackend, SignedTransaction, H160, U256};

use crate::{
system_contract::{
init,
init_system_contract_db,
metadata::{
metadata_abi::{self, ConsensusConfig, Metadata, MetadataVersion, ValidatorExtend},
MetadataContract, MetadataStore,
Expand All @@ -29,7 +29,7 @@ fn test_write_functions() {
let inner_db = RocksAdapter::new(ROCKSDB_PATH, Default::default())
.unwrap()
.inner_db();
init(inner_db, &mut backend);
init_system_contract_db(inner_db, &mut backend);

test_init(&mut backend, &executor);

Expand Down
2 changes: 1 addition & 1 deletion core/interoperation/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl TestHandle {
)
.unwrap();

core_executor::system_contract::init(inner_db, &mut backend);
core_executor::system_contract::init_system_contract_db(inner_db, &mut backend);

handle
}
Expand Down
49 changes: 8 additions & 41 deletions core/run/src/components/chain_spec.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
use ethers_core::abi::AbiEncode;

use common_config_parser::types::spec::ChainSpec;
use common_crypto::{PrivateKey as _, Secp256k1RecoverablePrivateKey, Signature};
use core_executor::system_contract::{
metadata::metadata_abi::{AppendMetadataCall, MetadataContractCalls},
METADATA_CONTRACT_ADDRESS,
};

use protocol::types::{
Block, Eip1559Transaction, Hasher, Metadata, RichBlock, SignedTransaction, TransactionAction,
Block, Eip1559Transaction, Hasher, RichBlock, SignedTransaction, TransactionAction,
UnsignedTransaction, UnverifiedTransaction, BASE_FEE_PER_GAS,
};

Expand All @@ -18,39 +12,18 @@ pub(crate) trait ChainSpecExt {
}

impl ChainSpecExt for ChainSpec {
fn generate_genesis_block(&self, genesis_key: Secp256k1RecoverablePrivateKey) -> RichBlock {
let metadata_0 = self.params.clone();
let metadata_1 = {
let mut tmp = metadata_0.clone();
tmp.epoch = metadata_0.epoch + 1;
tmp.version.start = metadata_0.version.end + 1;
tmp.version.end = tmp.version.start + metadata_0.version.end - 1;
tmp
fn generate_genesis_block(&self, _genesis_key: Secp256k1RecoverablePrivateKey) -> RichBlock {
let txs = vec![];
let block = Block {
header: self.genesis.build_header(),
tx_hashes: vec![],
};
let data_0 = encode_metadata(metadata_0);
let data_1 = encode_metadata(metadata_1);

let chain_id = self.genesis.chain_id;

let txs: Vec<_> = [data_0, data_1]
.into_iter()
.enumerate()
.map(|(index, data)| {
let nonce = index as u64;
let action = TransactionAction::Call(METADATA_CONTRACT_ADDRESS);
let utx = build_unverified_transaction(nonce, action, data);
build_transaction(&genesis_key, utx, chain_id)
})
.collect();

let header = self.genesis.build_header();
let tx_hashes = txs.iter().map(|tx| tx.transaction.hash).collect::<Vec<_>>();
let block = Block { header, tx_hashes };

RichBlock { block, txs }
}
}

#[allow(dead_code)]
fn build_unverified_transaction(
nonce: u64,
action: TransactionAction,
Expand All @@ -69,6 +42,7 @@ fn build_unverified_transaction(
UnsignedTransaction::Eip1559(tx)
}

#[allow(dead_code)]
fn build_transaction(
priv_key: &Secp256k1RecoverablePrivateKey,
tx: UnsignedTransaction,
Expand All @@ -90,10 +64,3 @@ fn build_transaction(

SignedTransaction::from_unverified(utx, None).unwrap()
}

fn encode_metadata(metadata: Metadata) -> Vec<u8> {
MetadataContractCalls::AppendMetadata(AppendMetadataCall {
metadata: metadata.into(),
})
.encode()
}
24 changes: 19 additions & 5 deletions core/run/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ async fn start<K: KeyProvider>(
Proposal::new_without_state_root(&current_block.header).into(),
)?;

system_contract::init(inner_db, &mut backend);
// The first two metadata has been inserted in the init process, only need to
// init the system contract DB here.
system_contract::init_system_contract_db(inner_db, &mut backend);

// Init mempool and recover signed transactions with the current block number
let current_stxs = txs_wal.load_by_number(current_block.header.number + 1);
Expand Down Expand Up @@ -445,7 +447,18 @@ async fn execute_genesis(
spec: &ChainSpec,
db_group: &DatabaseGroup,
) -> ProtocolResult<RichBlock> {
let resp = execute_transactions(&partial_genesis, db_group, &spec.accounts)?;
let metadata_0 = spec.params.clone();
let metadata_1 = {
let mut tmp = metadata_0.clone();
tmp.epoch = metadata_0.epoch + 1;
tmp.version.start = metadata_0.version.end + 1;
tmp.version.end = tmp.version.start + metadata_0.version.end - 1;
tmp
};

let resp = execute_transactions(&partial_genesis, db_group, &spec.accounts, &[
metadata_0, metadata_1,
])?;

partial_genesis.block.header.state_root = resp.state_root;
partial_genesis.block.header.receipts_root = resp.receipt_root;
Expand All @@ -465,6 +478,7 @@ fn execute_transactions(
rich: &RichBlock,
db_group: &DatabaseGroup,
accounts: &[InitialAccount],
metadata_list: &[Metadata],
) -> ProtocolResult<ExecResp> {
let state_root = MPTTrie::new(db_group.trie_db())
.insert_accounts(accounts)
Expand All @@ -477,7 +491,7 @@ fn execute_transactions(
Proposal::new_without_state_root(&rich.block.header).into(),
)?;

system_contract::init(db_group.inner_db(), &mut backend);
system_contract::init(db_group.inner_db(), &mut backend, metadata_list)?;

let resp = AxonExecutor.exec(&mut backend, &rich.txs, &[]);

Expand Down Expand Up @@ -527,15 +541,15 @@ pub fn set_hardfork_info(
let current_block = storage.get_latest_block(Context::new()).await?;
let current_state_root = current_block.header.state_root;

// Init system contract
// Init system contract DB
let mut backend = AxonExecutorApplyAdapter::from_root(
current_block.header.state_root,
Arc::clone(&trie_db),
Arc::clone(&storage),
Proposal::new_without_state_root(&current_block.header).into(),
)?;

system_contract::init(inner_db, &mut backend);
system_contract::init_system_contract_db(inner_db, &mut backend);

let metadata_root = AxonExecutorReadOnlyAdapter::from_root(
current_state_root,
Expand Down
33 changes: 24 additions & 9 deletions core/run/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,26 @@ const TESTCASES: &[TestCase] = &[
chain_spec_file: "specs/single_node/chain-spec.toml",
key_file: "debug.key",
input_genesis_hash: "0x4e06dc4a01178db42c029f7d65f65a5763702a21082cfcb626c6c41054a7a276",
genesis_state_root: "0xb6c51706f77a788606c8b932ad4f752c3f9a54008cd82e85f417d3a7e900d5c2",
genesis_receipts_root: "0x7e747618f612d08dfe54bcb67f58f13a49e8b1bafee9a8f19a3a0f7122f44d02",
genesis_state_root: "0x6d872daaeadbd0c57d9ca58b51e210ff1b440983b8ba2c8cdd208d090e7607f9",
genesis_receipts_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
},
TestCase {
chain_name: "multi_nodes",
config_file: "nodes/node_1.toml",
chain_spec_file: "specs/multi_nodes/chain-spec.toml",
key_file: "debug.key",
input_genesis_hash: "0xf16db25ca1a0cff5339d76e9802c75c43faac35ee4a9294a51234b167c69159f",
genesis_state_root: "0x9f76f02e823115e7b9887d07678f40b8ff50f82d4d09214fa481bdad68f5192a",
genesis_receipts_root: "0x7e747618f612d08dfe54bcb67f58f13a49e8b1bafee9a8f19a3a0f7122f44d02",
genesis_state_root: "0x019fd9142c6f68322427c71345ef96d2ed42b122c477e342bb97d3b2d34f6a8e",
genesis_receipts_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
},
TestCase {
chain_name: "multi_nodes_short_epoch_len",
config_file: "nodes/node_1.toml",
chain_spec_file: "specs/multi_nodes_short_epoch_len/chain-spec.toml",
key_file: "debug.key",
input_genesis_hash: "0x4e06dc4a01178db42c029f7d65f65a5763702a21082cfcb626c6c41054a7a276",
genesis_state_root: "0x9dddf9df077b2bb98f72686256dae92fb975d416fa3093956151056b913a065d",
genesis_receipts_root: "0x7e747618f612d08dfe54bcb67f58f13a49e8b1bafee9a8f19a3a0f7122f44d02",
genesis_state_root: "0xb7d27d3c2dc9c99aaf8a4a1420f802c317cb7b053d9268a14a78613949a192a1",
genesis_receipts_root: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
},
];

Expand All @@ -77,7 +77,8 @@ fn decode_type_id() {

#[tokio::test(flavor = "multi_thread")]
async fn genesis_data_for_dev_chain() {
for case in TESTCASES {
for case in TESTCASES.iter() {
println!("======Test case {:?}======", case.chain_name);
check_genesis_data(case).await;
}
}
Expand Down Expand Up @@ -115,6 +116,7 @@ async fn check_genesis_data<'a>(case: &TestCase<'a>) {
};
let genesis = chain_spec.generate_genesis_block(key);

println!("checking genesis hash");
check_hashes(
case.chain_name,
"input genesis hash",
Expand Down Expand Up @@ -149,15 +151,28 @@ async fn check_genesis_data<'a>(case: &TestCase<'a>) {
)
.expect("initialize databases");

let resp = execute_transactions(&genesis, &db_group, &chain_spec.accounts)
.expect("execute transactions");
let metadata_0 = chain_spec.params.clone();
let metadata_1 = {
let mut tmp = metadata_0.clone();
tmp.epoch = metadata_0.epoch + 1;
tmp.version.start = metadata_0.version.end + 1;
tmp.version.end = tmp.version.start + metadata_0.version.end - 1;
tmp
};
let resp = execute_transactions(&genesis, &db_group, &chain_spec.accounts, &[
metadata_0, metadata_1,
])
.expect("execute transactions");

println!("checking state root");
check_hashes(
case.chain_name,
"genesis state root",
case.genesis_state_root,
resp.state_root,
);

println!("checking receipts hash");
check_hashes(
case.chain_name,
"genesis receipts root",
Expand Down

0 comments on commit 12df447

Please sign in to comment.