Skip to content

Commit

Permalink
test: check genesis data of dev chain in unit tests to lock the conse…
Browse files Browse the repository at this point in the history
…nsus (#1304)
  • Loading branch information
yangby-cryptape authored Aug 4, 2023
1 parent 8f3eded commit 2995849
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 37 deletions.
58 changes: 21 additions & 37 deletions core/run/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ pub struct Axon {
state_root: MerkleRoot,
}

#[cfg(test)]
mod tests;

impl Axon {
pub fn new(config: Config, genesis: RichBlock) -> Axon {
Axon {
Expand Down Expand Up @@ -143,20 +146,21 @@ impl Axon {
storage: &Arc<ImplStorage<RocksAdapter>>,
) -> ProtocolResult<()> {
let trie_db = self.init_trie_db(false).await?;
let mut mpt = MPTTrie::new(Arc::clone(&trie_db));

insert_accounts(&mut mpt, &self.config.accounts).await?;
let state_root = {
let mut mpt = MPTTrie::new(Arc::clone(&trie_db));
insert_accounts(&mut mpt, &self.config.accounts).expect("insert accounts");
mpt.commit()?
};

let path_metadata = self.config.data_path_for_system_contract();
let resp = execute_transactions(
&self.genesis,
&mut mpt,
state_root,
&trie_db,
storage,
path_metadata,
&self.config.rocksdb.clone(),
)
.await?;
)?;

log::info!(
"Execute the genesis distribute success, genesis state root {:?}, response {:?}",
Expand Down Expand Up @@ -197,20 +201,21 @@ impl Axon {
)?;
Arc::new(trie_db)
};
let mut mpt = MPTTrie::new(Arc::clone(&trie_db));

insert_accounts(&mut mpt, &self.config.accounts).await?;
let state_root = {
let mut mpt = MPTTrie::new(Arc::clone(&trie_db));
insert_accounts(&mut mpt, &self.config.accounts).expect("insert accounts");
mpt.commit()?
};

let path_metadata = tmp_dir.path().join("metadata");
let resp = execute_transactions(
&self.genesis,
&mut mpt,
state_root,
&trie_db,
&storage,
path_metadata,
&self.config.rocksdb.clone(),
)
.await?;
)?;

self.apply_genesis_data(resp.state_root, resp.receipt_root)?;

Expand Down Expand Up @@ -995,7 +1000,7 @@ where
}
}

async fn insert_accounts(
fn insert_accounts(
mpt: &mut MPTTrie<RocksTrieDB>,
accounts: &[InitialAccount],
) -> ProtocolResult<()> {
Expand All @@ -1012,9 +1017,9 @@ async fn insert_accounts(
Ok(())
}

async fn execute_transactions<S, DB>(
fn execute_transactions<S, DB>(
rich: &RichBlock,
mpt: &mut MPTTrie<RocksTrieDB>,
state_root: H256,
trie_db: &Arc<DB>,
storage: &Arc<S>,
path_metadata: PathBuf,
Expand All @@ -1026,7 +1031,7 @@ where
{
let executor = AxonExecutor::default();
let mut backend = AxonExecutorAdapter::from_root(
mpt.commit()?,
state_root,
Arc::clone(trie_db),
Arc::clone(storage),
Proposal::new_without_state_root(&rich.block.header).into(),
Expand Down Expand Up @@ -1064,24 +1069,3 @@ where

Ok(())
}

#[cfg(test)]
mod tests {
use protocol::codec::hex_decode;
use protocol::types::RichBlock;
use std::fs;

#[test]
fn decode_genesis() {
let raw = fs::read("../../devtools/chain/genesis_single_node.json").unwrap();
let genesis: RichBlock = serde_json::from_slice(&raw).unwrap();
println!("{:?}", genesis);
}

#[test]
fn decode_type_id() {
let type_id =
hex_decode("c0810210210c06ba233273e94d7fc89b00a705a07fdc0ae4c78e4036582ff336").unwrap();
println!("{:?}", type_id);
}
}
138 changes: 138 additions & 0 deletions core/run/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
use std::{
convert::AsRef,
env::set_current_dir,
fs, io,
path::{Path, PathBuf},
str::FromStr,
sync::Arc,
};

use common_config_parser::{parse_file, types::Config};
use core_executor::{MPTTrie, RocksTrieDB};
use core_storage::{adapter::rocks::RocksAdapter, ImplStorage};
use protocol::{
codec::hex_decode,
tokio,
types::{RichBlock, H256},
};

use crate::{execute_transactions, insert_accounts};

const DEV_CONFIG_DIR: &str = "../../devtools/chain";

const GENESIS_FILE: &str = "genesis_single_node.json";
const CONFIG_FILE: &str = "config.toml";

const GENESIS_HASH: &str = "0x69eca8420bb4b072d732db96260a656f0e10201c6841b215a8ed107681e17d1c";
const GENESIS_STATE_ROOT: &str =
"0x65f57a6a666e656de33ed68957e04b35b3fe1b35a90f6eafb6f283c907dc3d77";
const GENESIS_RECEIPTS_ROOT: &str =
"0x0abcdb8fd7acc8c71f28a16c3095fdafca0171f371076650152b1c356a1bccad";

#[test]
fn decode_genesis() {
let raw = fs::read("../../devtools/chain/genesis_single_node.json").unwrap();
assert!(serde_json::from_slice::<RichBlock>(&raw).is_ok());
}

#[test]
fn decode_type_id() {
let type_id_str = "c0810210210c06ba233273e94d7fc89b00a705a07fdc0ae4c78e4036582ff336";
assert!(hex_decode(type_id_str).is_ok());
}

#[tokio::test(flavor = "multi_thread")]
async fn genesis_hash_for_dev_chain() {
let dev_config_dir = PathBuf::from_str(DEV_CONFIG_DIR).expect("read dev config dir");
let tmp_dir = tempfile::tempdir().unwrap_or_else(|err| {
panic!("failed to create temporary directory since {err:?}");
});
let tmp_dir_path = tmp_dir.path();

copy_dir(dev_config_dir, tmp_dir_path).expect("configs copied");
set_current_dir(tmp_dir_path).expect("change work directory");

let config: Config = {
let config_path = tmp_dir_path.join(CONFIG_FILE);
parse_file(config_path, false).expect("parse config file")
};
let genesis: RichBlock = {
let genesis_path = tmp_dir_path.join(GENESIS_FILE);
parse_file(genesis_path, true).expect("parse genesis file")
};

let expected_genesis_hash = H256::from_str(GENESIS_HASH).expect("expected genesis hash");
check_hashes(
"genesis hash",
expected_genesis_hash,
genesis.block.header.hash(),
);

let storage = {
let path_block = tmp_dir.path().join("block");
let rocks_adapter = Arc::new(
RocksAdapter::new(path_block, config.rocksdb.clone()).expect("temporary block storage"),
);
let impl_storage = ImplStorage::new(rocks_adapter, config.rocksdb.cache_size);
Arc::new(impl_storage)
};

let trie_db = {
let path_state = tmp_dir.path().join("state");
let trie_db = RocksTrieDB::new(
path_state,
config.rocksdb.clone(),
config.executor.triedb_cache_size,
)
.expect("temporary trie db");
Arc::new(trie_db)
};

let state_root = {
let mut mpt = MPTTrie::new(Arc::clone(&trie_db));
insert_accounts(&mut mpt, &config.accounts).expect("insert accounts");
mpt.commit().expect("mpt commit")
};

let path_metadata = tmp_dir_path.join("metadata");
let resp = execute_transactions(
&genesis,
state_root,
&trie_db,
&storage,
path_metadata,
&config.rocksdb,
)
.expect("execute transactions");

let expected_state_root = H256::from_str(GENESIS_STATE_ROOT).expect("expected genesis hash");
check_hashes("genesis state root", expected_state_root, resp.state_root);
let expected_receipts_root =
H256::from_str(GENESIS_RECEIPTS_ROOT).expect("expected genesis hash");
check_hashes(
"genesis receipts root",
expected_receipts_root,
resp.receipt_root,
);
}

fn check_hashes(name: &str, expected: H256, actual: H256) {
assert_eq!(
expected, actual,
"{name} of dev chain is changed, expect {expected:#x}, but got {actual:#x}",
);
}

fn copy_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
fs::create_dir_all(&dst)?;
for entry in fs::read_dir(src)? {
let entry = entry?;
let ty = entry.file_type()?;
if ty.is_dir() {
copy_dir(entry.path(), dst.as_ref().join(entry.file_name()))?;
} else {
std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
}
}
Ok(())
}

0 comments on commit 2995849

Please sign in to comment.