Skip to content

Commit

Permalink
test: add axon-tools unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
wenyuanhust committed Nov 2, 2023
1 parent 1c0f31f commit 82519ca
Show file tree
Hide file tree
Showing 9 changed files with 818 additions and 1 deletion.
464 changes: 463 additions & 1 deletion Cargo.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions devtools/axon-tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ Some axon related utilities.
"""

[dev-dependencies]
eth_light_client_in_ckb-prover = { version = "0.3.0-alpha", git = "https://github.com/synapseweb3/eth-light-client-in-ckb" }
ethereum = "0.14"
ethers-core = "2.0.10"
hex = "0.4"
rand = "0.8"

[dependencies]
Expand Down
3 changes: 3 additions & 0 deletions devtools/axon-tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ pub use proof::{verify_proof, verify_trie_proof};
pub use hash::keccak_256;

pub mod consts;

#[cfg(test)]
mod tests;
30 changes: 30 additions & 0 deletions devtools/axon-tools/src/tests/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"header": {
"version": "V0",
"prev_hash": "0xa5643d9a0983004a662c154d6b2ae2a9aa10566b21333467400c5dcb6558bb38",
"proposer": "0x8af204ac5d7cb8815a6c53a50b72d01e729d3b22",
"state_root": "0x3e7e13a5fdd338fc7254d52745136dde2bbeb82718713415be596dc635274bbe",
"transactions_root": "0x93ac653e9457b39685218933d81145df1b4fd06a9b2e6be0217cad4a608ad6fb",
"signed_txs_hash": "0x2077d36822b7bd8f570d99355c62c8c04d4bf8bcfcb3bfdd5c90be783b713983",
"receipts_root": "0x08c61b0c680f18a1f33a8bce9b09d0fffee3a595cd5c95519fa21e80894d87e9",
"log_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000",
"timestamp": "0x6538e7e0",
"number": "0xe7c3",
"gas_used": "0x2a3d5",
"gas_limit": "0x1c9c380",
"extra_data": [],
"base_fee_per_gas": "0x539",
"proof": {
"number": "0xe7c2",
"round": "0x0",
"block_hash": "0x734f6e28a7caf9df326c21d8c57b89034ed02f782a11d04d18284b7aa4de43f0",
"signature": "0x933be0cd674477473bd68a55a53511a652fbcecfa4cafaa244d0b55ca3f6a7f296d50a2744337365fd6407d737cc389f054b70b3c82ee27a1669a43cc344ba7ad42a7cc663faa63190a739dc1c6a1a5d80d45f5903f42d118fc5e4d695cc4815",
"bitmap": "0xb0"
},
"call_system_script_count": "0x0",
"chain_id": "0x41786f6e"
},
"tx_hashes": [
"0x6917d8ef5fbac4fab865a872cd4ed2ca9fd0c514491d7b148530392fa9d656c8"
]
}
54 changes: 54 additions & 0 deletions devtools/axon-tools/src/tests/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"version": {
"start": "0x0",
"end": "0x3b9aca00"
},
"epoch": "0x0",
"verifier_list": [
{
"bls_pub_key": "0x98eef09a3927acb225191101a1d9aa85775fdcdc87b9ba36898f6c132b485d66aef91c0f51cda331be4f985c3be6761c",
"pub_key": "0x0232c489c23b1207107e9a24648c1e4754a8c1c0b38db96df57a526201035058cb",
"address": "0xf4cc1652dcec2e5de9ce6fb1b6f9fa9456e957f1",
"propose_weight": "0x1",
"vote_weight": "0x1"
},
{
"bls_pub_key": "0xa26e3fe1cf51bd4822072c61bdc315ac32e3d3c2e2484bb92942666399e863b4bf56cf2926383cc706ffc15dfebc85c6",
"pub_key": "0x031ddc35212b7fc7ff6685b17d91f77c972535aee5c7ae5684d3e72b986f08834b",
"address": "0x8ab0cf264df99d83525e9e11c7e4db01558ae1b1",
"propose_weight": "0x1",
"vote_weight": "0x1"
},
{
"bls_pub_key": "0x80310fa9df724b5603d283b472ed3bf85254a8a4ceda8a274b421f6cf2be1d9184267cdfe9a199d36ff14e57668a55d0",
"pub_key": "0x02b77c74eb68af3d4d6cc7884ed6709f1a2a1af0f713382a4438ec2ea3a70d4d7f",
"address": "0xf386573563c3a75dbbd269fce9782620826ddac2",
"propose_weight": "0x1",
"vote_weight": "0x1"
},
{
"bls_pub_key": "0x897721e9016864141a8b982a48217f66ef318ce598aa31842cddaaebe3cd7feab17050022afa6c2123aba39938fe4142",
"pub_key": "0x027ffd6a6a231561f2afe5878b1c743323b34263d16787130b1815fe35649b0bf5",
"address": "0x8af204ac5d7cb8815a6c53a50b72d01e729d3b22",
"propose_weight": "0x1",
"vote_weight": "0x1"
}
],
"propose_counter": [
{
"address": "0x0000000000000000000000000000000000000000",
"count": "0x0"
}
],
"consensus_config": {
"gas_limit": "0xffffffff",
"gas_price": "0x1",
"interval": "0xbb8",
"propose_ratio": "0xf",
"prevote_ratio": "0xa",
"precommit_ratio": "0xa",
"brake_ratio": "0xa",
"tx_num_limit": "0x4e20",
"max_tx_size": "0x400"
}
}
2 changes: 2 additions & 0 deletions devtools/axon-tools/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod verify_proof;
mod verify_trie_proof;
7 changes: 7 additions & 0 deletions devtools/axon-tools/src/tests/proof.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"number": "0xe7c3",
"round": "0x0",
"block_hash": "0x6e48fa2d2002453abd9b51e4ac0342abb1f027b8272d6e27ce79a630b3f26673",
"signature": "0xb3e8e27db04baec18c04bc0b8ffe7fdbf2b5f7d6ef243c8be02bfd75defee32f1c0ff73a9fa67fee24630d2da5aa70f111ba41c0212be5d91b95f3bb84e5c0406b4742cca8c8f8362c07024fd8081d16875b01f43c6aa11c60b196af8c671a9b",
"bitmap": "0x70"
}
80 changes: 80 additions & 0 deletions devtools/axon-tools/src/tests/verify_proof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#[cfg(test)]
mod tests {
use crate::hash::keccak_256;
use crate::types::{AxonBlock, BlockVersion, Metadata, Proof, Proposal, ValidatorExtend};
use bytes::Bytes;
use ethereum_types::{H160, H256, U256};
use rlp::Encodable;
use serde::de::DeserializeOwned;

fn read_json<T: DeserializeOwned>(path: &str) -> T {
let json = std::fs::read_to_string(path).unwrap();
serde_json::from_str(&json).unwrap()
}

#[test]
fn test_proposal() {
let proposal = Proposal {
version: BlockVersion::V0,
prev_hash: H256::from([1u8; 32]),
proposer: H160::from([2u8; 20]),
prev_state_root: H256::from([3u8; 32]),
transactions_root: H256::from([4u8; 32]),
signed_txs_hash: H256::from([5u8; 32]),
timestamp: 0,
number: 100,
gas_limit: U256::from(6),
extra_data: Vec::new(),
base_fee_per_gas: U256::from(7),
proof: Proof {
number: 0,
round: 1,
block_hash: H256::from([1u8; 32]),
signature: Bytes::from("1234"),
bitmap: Bytes::from("abcd"),
},
chain_id: 1000 as u64,
call_system_script_count: 1,
tx_hashes: vec![],
};

let rlp_bytes = proposal.rlp_bytes();
let hash = keccak_256(&rlp_bytes);
let ref_hash = [
95u8, 14, 98, 221, 57, 150, 113, 31, 144, 120, 33, 170, 102, 71, 19, 108, 141, 247, 85,
17, 193, 76, 201, 242, 128, 231, 44, 231, 204, 189, 67, 230,
];
assert_eq!(hash, ref_hash);
}

#[test]
fn test_verify_proof() {
let block: AxonBlock = read_json("src/tests/block.json");
let proof: Proof = read_json("src/tests/proof.json");
let metadata: Metadata = read_json("src/tests/metadata.json");
let mut validators = metadata
.verifier_list
.iter()
.map(|v| ValidatorExtend {
bls_pub_key: v.bls_pub_key.clone(),
pub_key: v.pub_key.clone(),
address: v.address,
propose_weight: v.propose_weight,
vote_weight: v.vote_weight,
})
.collect::<Vec<_>>();

let previous_state_root =
hex::decode("9fc948be2cfb0127e979dc9c7e6d2f4a2890b54e0e81fd69c687303e6b25ddde")
.unwrap();

let result = crate::verify_proof(
block,
H256::from_slice(&previous_state_root),
&mut validators,
proof,
);

assert!(result.is_ok());
}
}
176 changes: 176 additions & 0 deletions devtools/axon-tools/src/tests/verify_trie_proof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
#[cfg(test)]
mod tests {
use crate::verify_trie_proof;
use eth_light_client_in_ckb_prover::{encode_receipt, Receipts};
use ethereum_types::{Bloom, H256, U256};
use ethers_core::{
types::{Log, TransactionReceipt, U64},
utils::{keccak256, rlp},
};

#[test]
fn test_receipt() {
let mut tx_receipts = Vec::<TransactionReceipt>::new();

{
let mut receipt = TransactionReceipt::default();
receipt.transaction_hash = H256::from([0u8; 32]);
receipt.transaction_index = 0.into();
receipt.cumulative_gas_used = U256::from(10);
receipt.transaction_type = Some(U64::from(2));
receipt.status = Some(U64::from(1));
let logs = vec![Log::default()];
receipt.logs_bloom = logs_bloom(logs.iter());
receipt.logs = logs;

let receipt_encode = encode_receipt(&receipt);
let reference_encode: Vec<u8> = [
2u8, 249, 1, 30, 1, 10, 185, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 215, 148, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 128,
]
.to_vec();

assert_eq!(receipt_encode, reference_encode);
tx_receipts.push(receipt);
}

let receipts: Receipts = tx_receipts.into();
let ref_root = [
197u8, 180, 204, 76, 181, 157, 142, 152, 246, 237, 148, 126, 24, 207, 94, 119, 119,
205, 11, 16, 193, 17, 102, 157, 61, 7, 166, 133, 173, 208, 124, 6,
];
assert_eq!(receipts.root().0, ref_root);
}

#[test]
fn test_verify_trie_proof() {
let mut tx_receipts = Vec::<TransactionReceipt>::new();

{
let mut receipt = TransactionReceipt::default();
receipt.transaction_hash = H256::from([0u8; 32]);
receipt.transaction_index = 0.into();
receipt.gas_used = Some(U256::from(100));
receipt.transaction_type = Some(U64::from(0));
receipt.status = Some(U64::from(1));
tx_receipts.push(receipt);
}

{
let mut receipt = TransactionReceipt::default();
receipt.transaction_hash = H256::from([1u8; 32]);
receipt.transaction_index = 1.into();
receipt.gas_used = Some(U256::from(100));
receipt.transaction_type = Some(U64::from(1));
receipt.status = Some(U64::from(1));
tx_receipts.push(receipt);
}

let receipts: Receipts = tx_receipts.into();

{
println!("proof of index 0");
let proof_index = 0 as u64;
let receipt_proof = receipts.generate_proof(proof_index as usize);

{
println!("test key 0");
let key = rlp::encode(&proof_index);
let result = verify_trie_proof(receipts.root(), &key, receipt_proof.clone());
assert!(result.unwrap().is_some());
}

{
println!("test key 1");
let key = rlp::encode(&(1 as u64));
let result = verify_trie_proof(receipts.root(), &key, receipt_proof.clone());
assert!(result.unwrap().is_none());
}

{
println!("test key 2");
let key = rlp::encode(&(2 as u64));
let result = verify_trie_proof(receipts.root(), &key, receipt_proof.clone());
assert!(result.unwrap().is_none());
}

{
println!("test illegal trie root");
let key = rlp::encode(&(200 as u64));
let result = verify_trie_proof(H256::from([4u8; 32]), &key, receipt_proof.clone());
assert!(result.is_err());
}
}

{
println!("proof of index 1, wrong");
let proof_index = 1 as u64;
let receipt_proof = receipts.generate_proof(proof_index as usize);

{
println!("test key 0");
let key = rlp::encode(&(0 as u64));
let result = verify_trie_proof(receipts.root(), &key, receipt_proof.clone());
assert!(result.unwrap().is_none());
}

{
println!("test key 1");
let key = rlp::encode(&(1 as u64));
let result = verify_trie_proof(receipts.root(), &key, receipt_proof.clone());
assert!(result.unwrap().is_some());
}
}
}

pub fn logs_bloom<'a, I>(logs: I) -> Bloom
where
I: Iterator<Item = &'a Log>,
{
let mut bloom = Bloom::zero();

for log in logs {
m3_2048(&mut bloom, log.address.as_bytes());
for topic in log.topics.iter() {
m3_2048(&mut bloom, topic.as_bytes());
}
}
bloom
}

pub struct Hasher;

impl Hasher {
pub fn digest<B: AsRef<[u8]>>(bytes: B) -> H256 {
if bytes.as_ref().is_empty() {
return NIL_DATA;
}

H256(keccak256(bytes))
}
}

pub const NIL_DATA: H256 = H256([
0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03,
0xc0, 0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85,
0xa4, 0x70,
]);
const BLOOM_BYTE_LENGTH: usize = 256;

fn m3_2048(bloom: &mut Bloom, x: &[u8]) {
let hash = Hasher::digest(x).0;
for i in [0, 2, 4] {
let bit = (hash[i + 1] as usize + ((hash[i] as usize) << 8)) & 0x7FF;
bloom.0[BLOOM_BYTE_LENGTH - 1 - bit / 8] |= 1 << (bit % 8);
}
}
}

0 comments on commit 82519ca

Please sign in to comment.