diff --git a/crates/consensus/Cargo.toml b/crates/consensus/Cargo.toml index a6767d4..52469af 100644 --- a/crates/consensus/Cargo.toml +++ b/crates/consensus/Cargo.toml @@ -12,12 +12,14 @@ hex = { version = "0.4.3", default-features = false, features = ["alloc", "serde milagro_bls = { git = "https://github.com/datachainlab/milagro_bls", rev = "bc2b5b5e8d48b7e2e1bfaa56dc2d93e13cb32095", default-features = false } ssz-rs = { git = "https://github.com/bluele/ssz_rs", branch = "serde-no-std", default-features = false, features = ["serde"] } ssz-rs-derive = { git = "https://github.com/bluele/ssz_rs", branch = "serde-no-std", default-features = false } -rs_merkle = { version = "1.2.0", default-features = false } +rs_merkle = { version = "1.2.0", default-features = false, optional = true} primitive-types = { version = "0.12.1", default-features = false } [dev-dependencies] serde_json = "1.0.91" +rs_merkle = { version = "1.2.0", default-features = false } [features] default = ["std"] std = [] +prover = ["rs_merkle"] diff --git a/crates/consensus/src/fork/bellatrix.rs b/crates/consensus/src/fork/bellatrix.rs index 1c0436a..e39b756 100644 --- a/crates/consensus/src/fork/bellatrix.rs +++ b/crates/consensus/src/fork/bellatrix.rs @@ -6,9 +6,7 @@ use crate::{ }, bls::Signature, compute::hash_tree_root, - errors::Error, internal_prelude::*, - merkle::MerkleTree, sync_protocol::{SyncAggregate, SyncCommittee}, types::{Address, ByteList, ByteVector, Bytes32, H256, U256, U64}, }; @@ -259,49 +257,56 @@ pub struct LightClientUpdate { pub signature_slot: Slot, } -pub fn gen_execution_payload_field_proof< - const BYTES_PER_LOGS_BLOOM: usize, - const MAX_EXTRA_DATA_BYTES: usize, ->( - payload: &ExecutionPayloadHeader, - subtree_index: usize, -) -> Result<(Root, Vec), Error> { - let tree = MerkleTree::from_leaves( - ([ - payload.parent_hash.0, - hash_tree_root(payload.fee_recipient.clone()).unwrap().0, - payload.state_root.0, - payload.receipts_root.0, - hash_tree_root(payload.logs_bloom.clone()).unwrap().0, - payload.prev_randao.0, - hash_tree_root(payload.block_number).unwrap().0, - hash_tree_root(payload.gas_limit).unwrap().0, - hash_tree_root(payload.gas_used).unwrap().0, - hash_tree_root(payload.timestamp).unwrap().0, - hash_tree_root(payload.extra_data.clone()).unwrap().0, - hash_tree_root(payload.base_fee_per_gas.clone()).unwrap().0, - payload.block_hash.0, - payload.transactions_root.0, - Default::default(), - Default::default(), - ] as [_; 16]) - .as_ref(), - ); - Ok(( - H256(tree.root().unwrap()), - tree.proof(&[subtree_index]) - .proof_hashes() - .iter() - .map(|h| H256::from_slice(h)) - .collect::>(), - )) +#[cfg(any(feature = "prover", test))] +pub mod prover { + use super::*; + use crate::{errors::Error, merkle::MerkleTree}; + + pub fn gen_execution_payload_field_proof< + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + >( + payload: &ExecutionPayloadHeader, + subtree_index: usize, + ) -> Result<(Root, Vec), Error> { + let tree = MerkleTree::from_leaves( + ([ + payload.parent_hash.0, + hash_tree_root(payload.fee_recipient.clone()).unwrap().0, + payload.state_root.0, + payload.receipts_root.0, + hash_tree_root(payload.logs_bloom.clone()).unwrap().0, + payload.prev_randao.0, + hash_tree_root(payload.block_number).unwrap().0, + hash_tree_root(payload.gas_limit).unwrap().0, + hash_tree_root(payload.gas_used).unwrap().0, + hash_tree_root(payload.timestamp).unwrap().0, + hash_tree_root(payload.extra_data.clone()).unwrap().0, + hash_tree_root(payload.base_fee_per_gas.clone()).unwrap().0, + payload.block_hash.0, + payload.transactions_root.0, + Default::default(), + Default::default(), + ] as [_; 16]) + .as_ref(), + ); + Ok(( + H256(tree.root().unwrap()), + tree.proof(&[subtree_index]) + .proof_hashes() + .iter() + .map(|h| H256::from_slice(h)) + .collect::>(), + )) + } } #[cfg(test)] mod tests { use super::*; + use crate::errors::Error; use crate::fork::bellatrix::{LightClientUpdate, BELLATRIX_FORK_SPEC}; - use crate::merkle::{get_subtree_index, is_valid_normalized_merkle_branch}; + use crate::merkle::{get_subtree_index, is_valid_normalized_merkle_branch, MerkleTree}; use crate::sync_protocol::SyncCommittee; use crate::{ beacon::DOMAIN_SYNC_COMMITTEE, @@ -354,7 +359,7 @@ mod tests { .is_ok()); { - let (root, proof) = gen_execution_payload_field_proof( + let (root, proof) = prover::gen_execution_payload_field_proof( &payload_header, get_subtree_index(BELLATRIX_FORK_SPEC.execution_payload_state_root_gindex) as usize, ) @@ -369,7 +374,7 @@ mod tests { .is_ok()); } { - let (root, proof) = gen_execution_payload_field_proof( + let (root, proof) = prover::gen_execution_payload_field_proof( &payload_header, get_subtree_index(BELLATRIX_FORK_SPEC.execution_payload_block_number_gindex) as usize, diff --git a/crates/consensus/src/fork/capella.rs b/crates/consensus/src/fork/capella.rs index 9c2e971..a58cf8c 100644 --- a/crates/consensus/src/fork/capella.rs +++ b/crates/consensus/src/fork/capella.rs @@ -7,9 +7,7 @@ use crate::{ }, bls::Signature, compute::hash_tree_root, - errors::Error, internal_prelude::*, - merkle::MerkleTree, sync_protocol::{SyncAggregate, SyncCommittee}, types::{Address, ByteList, ByteVector, Bytes32, H256, U256, U64}, }; @@ -293,49 +291,56 @@ pub struct LightClientHeader, } -pub fn gen_execution_payload_field_proof< - const BYTES_PER_LOGS_BLOOM: usize, - const MAX_EXTRA_DATA_BYTES: usize, ->( - payload: &ExecutionPayloadHeader, - leaf_index: usize, -) -> Result<(Root, Vec), Error> { - let tree = MerkleTree::from_leaves( - ([ - payload.parent_hash.0, - hash_tree_root(payload.fee_recipient.clone()).unwrap().0, - payload.state_root.0, - payload.receipts_root.0, - hash_tree_root(payload.logs_bloom.clone()).unwrap().0, - payload.prev_randao.0, - hash_tree_root(payload.block_number).unwrap().0, - hash_tree_root(payload.gas_limit).unwrap().0, - hash_tree_root(payload.gas_used).unwrap().0, - hash_tree_root(payload.timestamp).unwrap().0, - hash_tree_root(payload.extra_data.clone()).unwrap().0, - hash_tree_root(payload.base_fee_per_gas.clone()).unwrap().0, - payload.block_hash.0, - payload.transactions_root.0, - payload.withdrawals_root.0, - Default::default(), - ] as [_; 16]) - .as_ref(), - ); - Ok(( - H256(tree.root().unwrap()), - tree.proof(&[leaf_index]) - .proof_hashes() - .iter() - .map(|h| H256::from_slice(h)) - .collect::>(), - )) +#[cfg(any(feature = "prover", test))] +pub mod prover { + use super::*; + use crate::{errors::Error, merkle::MerkleTree}; + + pub fn gen_execution_payload_field_proof< + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + >( + payload: &ExecutionPayloadHeader, + leaf_index: usize, + ) -> Result<(Root, Vec), Error> { + let tree = MerkleTree::from_leaves( + ([ + payload.parent_hash.0, + hash_tree_root(payload.fee_recipient.clone()).unwrap().0, + payload.state_root.0, + payload.receipts_root.0, + hash_tree_root(payload.logs_bloom.clone()).unwrap().0, + payload.prev_randao.0, + hash_tree_root(payload.block_number).unwrap().0, + hash_tree_root(payload.gas_limit).unwrap().0, + hash_tree_root(payload.gas_used).unwrap().0, + hash_tree_root(payload.timestamp).unwrap().0, + hash_tree_root(payload.extra_data.clone()).unwrap().0, + hash_tree_root(payload.base_fee_per_gas.clone()).unwrap().0, + payload.block_hash.0, + payload.transactions_root.0, + payload.withdrawals_root.0, + Default::default(), + ] as [_; 16]) + .as_ref(), + ); + Ok(( + H256(tree.root().unwrap()), + tree.proof(&[leaf_index]) + .proof_hashes() + .iter() + .map(|h| H256::from_slice(h)) + .collect::>(), + )) + } } #[cfg(test)] mod tests { use super::*; - use crate::merkle::{get_subtree_index, is_valid_normalized_merkle_branch}; + use crate::merkle::{get_subtree_index, is_valid_normalized_merkle_branch, MerkleTree}; use crate::{compute::hash_tree_root, types::H256}; + use rs_merkle::Error; use ssz_rs::Merkleized; use std::fs; @@ -375,7 +380,7 @@ mod tests { .is_ok()); { - let (root, proof) = gen_execution_payload_field_proof( + let (root, proof) = prover::gen_execution_payload_field_proof( &payload_header, get_subtree_index(CAPELLA_FORK_SPEC.execution_payload_state_root_gindex) as usize, ) @@ -390,7 +395,7 @@ mod tests { .is_ok()); } { - let (root, proof) = gen_execution_payload_field_proof( + let (root, proof) = prover::gen_execution_payload_field_proof( &payload_header, get_subtree_index(CAPELLA_FORK_SPEC.execution_payload_block_number_gindex) as usize, ) diff --git a/crates/consensus/src/fork/deneb.rs b/crates/consensus/src/fork/deneb.rs index 985dd6d..032cbed 100644 --- a/crates/consensus/src/fork/deneb.rs +++ b/crates/consensus/src/fork/deneb.rs @@ -7,9 +7,7 @@ use crate::{ }, bls::Signature, compute::hash_tree_root, - errors::Error, internal_prelude::*, - merkle::{get_subtree_index, MerkleTree}, sync_protocol::{SyncAggregate, SyncCommittee}, types::{Address, ByteList, ByteVector, Bytes32, H256, U256, U64}, }; @@ -311,62 +309,65 @@ pub struct LightClientHeader, } -pub fn gen_execution_payload_field_proof< - const BYTES_PER_LOGS_BLOOM: usize, - const MAX_EXTRA_DATA_BYTES: usize, ->( - payload: &ExecutionPayloadHeader, - leaf_index: usize, -) -> Result<(Root, Vec), Error> { - let tree = MerkleTree::from_leaves( - ([ - payload.parent_hash.0, - hash_tree_root(payload.fee_recipient.clone()).unwrap().0, - payload.state_root.0, - payload.receipts_root.0, - hash_tree_root(payload.logs_bloom.clone()).unwrap().0, - payload.prev_randao.0, - hash_tree_root(payload.block_number).unwrap().0, - hash_tree_root(payload.gas_limit).unwrap().0, - hash_tree_root(payload.gas_used).unwrap().0, - hash_tree_root(payload.timestamp).unwrap().0, - hash_tree_root(payload.extra_data.clone()).unwrap().0, - hash_tree_root(payload.base_fee_per_gas.clone()).unwrap().0, - payload.block_hash.0, - payload.transactions_root.0, - payload.withdrawals_root.0, - hash_tree_root(payload.blob_gas_used).unwrap().0, - hash_tree_root(payload.excess_blob_gas).unwrap().0, - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ] as [_; 32]) - .as_ref(), - ); - Ok(( - H256(tree.root().unwrap()), - tree.proof(&[leaf_index]) - .proof_hashes() - .iter() - .map(|h| H256::from_slice(h)) - .collect::>(), - )) -} - -pub mod test_utils { +#[cfg(any(feature = "prover", test))] +pub mod prover { use super::*; + use crate::errors::Error; + use crate::merkle::{get_subtree_index, MerkleTree}; + + pub fn gen_execution_payload_field_proof< + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + >( + payload: &ExecutionPayloadHeader, + leaf_index: usize, + ) -> Result<(Root, Vec), Error> { + let tree = MerkleTree::from_leaves( + ([ + payload.parent_hash.0, + hash_tree_root(payload.fee_recipient.clone()).unwrap().0, + payload.state_root.0, + payload.receipts_root.0, + hash_tree_root(payload.logs_bloom.clone()).unwrap().0, + payload.prev_randao.0, + hash_tree_root(payload.block_number).unwrap().0, + hash_tree_root(payload.gas_limit).unwrap().0, + hash_tree_root(payload.gas_used).unwrap().0, + hash_tree_root(payload.timestamp).unwrap().0, + hash_tree_root(payload.extra_data.clone()).unwrap().0, + hash_tree_root(payload.base_fee_per_gas.clone()).unwrap().0, + payload.block_hash.0, + payload.transactions_root.0, + payload.withdrawals_root.0, + hash_tree_root(payload.blob_gas_used).unwrap().0, + hash_tree_root(payload.excess_blob_gas).unwrap().0, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ] as [_; 32]) + .as_ref(), + ); + Ok(( + H256(tree.root().unwrap()), + tree.proof(&[leaf_index]) + .proof_hashes() + .iter() + .map(|h| H256::from_slice(h)) + .collect::>(), + )) + } pub fn gen_execution_payload_proof< const MAX_PROPOSER_SLASHINGS: usize, @@ -463,8 +464,7 @@ mod tests { block.hash_tree_root().unwrap() ); - let (block_root, payload_proof) = - test_utils::gen_execution_payload_proof(&block.body).unwrap(); + let (block_root, payload_proof) = prover::gen_execution_payload_proof(&block.body).unwrap(); assert_eq!( block_root.as_bytes(), block.body.hash_tree_root().unwrap().as_bytes() @@ -482,7 +482,7 @@ mod tests { .is_ok()); { - let (root, proof) = gen_execution_payload_field_proof( + let (root, proof) = prover::gen_execution_payload_field_proof( &payload_header, get_subtree_index(DENEB_FORK_SPEC.execution_payload_state_root_gindex) as usize, ) @@ -497,7 +497,7 @@ mod tests { .is_ok()); } { - let (root, proof) = gen_execution_payload_field_proof( + let (root, proof) = prover::gen_execution_payload_field_proof( &payload_header, get_subtree_index(DENEB_FORK_SPEC.execution_payload_block_number_gindex) as usize, ) diff --git a/crates/consensus/src/merkle.rs b/crates/consensus/src/merkle.rs index 49ff6d3..2b68b6f 100644 --- a/crates/consensus/src/merkle.rs +++ b/crates/consensus/src/merkle.rs @@ -2,6 +2,7 @@ use crate::{beacon::Root, errors::MerkleError, internal_prelude::*, types::H256} use sha2::{Digest, Sha256}; /// MerkleTree is a merkle tree implementation using sha256 as a hashing algorithm. +#[cfg(any(feature = "prover", test))] pub type MerkleTree = rs_merkle::MerkleTree; pub fn is_valid_normalized_merkle_branch( diff --git a/crates/light-client-cli/Cargo.toml b/crates/light-client-cli/Cargo.toml index f7562dc..369a8ff 100644 --- a/crates/light-client-cli/Cargo.toml +++ b/crates/light-client-cli/Cargo.toml @@ -18,6 +18,6 @@ dirs = "4.0" env_logger = { version = "0.10.0" } tokio = { version = "1.24.1", default-features = false, features = ["rt-multi-thread", "macros"] } -ethereum-consensus = { path = "../consensus" } +ethereum-consensus = { path = "../consensus", features = ["prover"]} ethereum-light-client-verifier = { path = "../light-client-verifier" } lodestar-rpc = { path = "../lodestar-rpc" } diff --git a/crates/light-client-cli/src/client.rs b/crates/light-client-cli/src/client.rs index ffb0358..e7aaae0 100644 --- a/crates/light-client-cli/src/client.rs +++ b/crates/light-client-cli/src/client.rs @@ -224,11 +224,11 @@ impl< let execution_update = { let execution_payload_header = update.finalized_header.execution.clone(); - let (_, state_root_branch) = deneb::gen_execution_payload_field_proof( + let (_, state_root_branch) = deneb::prover::gen_execution_payload_field_proof( &execution_payload_header, EXECUTION_PAYLOAD_STATE_ROOT_SUBTREE_INDEX, )?; - let (_, block_number_branch) = deneb::gen_execution_payload_field_proof( + let (_, block_number_branch) = deneb::prover::gen_execution_payload_field_proof( &execution_payload_header, EXECUTION_PAYLOAD_BLOCK_NUMBER_SUBTREE_INDEX, )?; diff --git a/crates/light-client-verifier/Cargo.toml b/crates/light-client-verifier/Cargo.toml index 0424c3c..ce679df 100644 --- a/crates/light-client-verifier/Cargo.toml +++ b/crates/light-client-verifier/Cargo.toml @@ -27,4 +27,4 @@ std = [ "patricia-merkle-trie/std" ] mock = [] -test-utils = ["std", "mock", "rand"] +test-utils = ["std", "mock", "rand", "ethereum-consensus/prover"] diff --git a/crates/light-client-verifier/src/consensus.rs b/crates/light-client-verifier/src/consensus.rs index 4ecbd07..8025400 100644 --- a/crates/light-client-verifier/src/consensus.rs +++ b/crates/light-client-verifier/src/consensus.rs @@ -544,7 +544,7 @@ pub mod test_utils { ); let (_, finalized_execution_branch) = - ethereum_consensus::fork::deneb::test_utils::gen_execution_payload_proof( + ethereum_consensus::fork::deneb::prover::gen_execution_payload_proof( &finalized_block.body, ) .unwrap();