Skip to content

Commit

Permalink
chore(ethereum): Release 1.0.1 (#140)
Browse files Browse the repository at this point in the history
* chore(ethereum): Release 1.0.1

* fix: add execution payload proof verification

* fix: remove non-necessary mut

* docs: update snark bench

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Thomas Chataigner <[email protected]>
  • Loading branch information
3 people authored Aug 1, 2024
1 parent 37f76f3 commit af8ff82
Show file tree
Hide file tree
Showing 20 changed files with 237 additions and 86 deletions.
6 changes: 3 additions & 3 deletions ethereum/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ethereum/core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ethereum-lc-core"
version = "1.0.0"
version = "1.0.1"
edition = { workspace = true }
repository = { workspace = true }
license = { workspace = true }
Expand Down
128 changes: 124 additions & 4 deletions ethereum/core/src/merkle/update_proofs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ use crate::merkle::error::MerkleError;
use crate::merkle::utils::get_subtree_index;
use crate::merkle::Merkleized;
use crate::types::block::consensus::BeaconBlockHeader;
use crate::types::block::execution::{
ExecutionBlockHeader, ExecutionBranch, EXECUTION_BRANCH_NBR_SIBLINGS,
EXECUTION_PAYLOAD_GENERALIZED_INDEX,
};
use crate::types::committee::{
SyncCommittee, SyncCommitteeBranch, CURRENT_SYNC_COMMITTEE_GENERALIZED_INDEX,
NEXT_SYNC_COMMITTEE_GENERALIZED_INDEX, SYNC_COMMITTEE_BRANCH_NBR_SIBLINGS,
Expand All @@ -28,7 +32,7 @@ use crate::types::{
/// A `bool` indicating whether the finality proof is valid.
pub fn is_finality_proof_valid(
state_root: &Bytes32,
finality_header: &mut BeaconBlockHeader,
finality_header: &BeaconBlockHeader,
finality_branch: &FinalizedRootBranch,
) -> Result<bool, MerkleError> {
is_proof_valid(
Expand All @@ -53,7 +57,7 @@ pub fn is_finality_proof_valid(
/// A `bool` indicating whether the sync committee proof is valid.
pub fn is_next_committee_proof_valid(
state_root: &Bytes32,
next_committee: &mut SyncCommittee,
next_committee: &SyncCommittee,
next_committee_branch: &SyncCommitteeBranch,
) -> Result<bool, MerkleError> {
is_proof_valid(
Expand All @@ -78,7 +82,7 @@ pub fn is_next_committee_proof_valid(
/// A `bool` indicating whether the current committee proof is valid.
pub fn is_current_committee_proof_valid(
state_root: &Bytes32,
current_committee: &mut SyncCommittee,
current_committee: &SyncCommittee,
current_committee_branch: &SyncCommitteeBranch,
) -> Result<bool, MerkleError> {
is_proof_valid(
Expand All @@ -90,6 +94,31 @@ pub fn is_current_committee_proof_valid(
)
}

/// Verifies the validity of an execution payload proof received in an [`crate::types::update::Update`] message.
///
/// # Arguments
///
/// * `state_root` - The state root of the Beacon block that the proof is attesting to.
/// * `execution_block_header` - The header of the block that the update is attesting to be executed.
/// * `execution_payload_branch` - The branch of the Merkle tree that proves the execution payload of the block.
///
/// # Returns
///
/// A `bool` indicating whether the execution payload proof is valid.
pub fn is_execution_payload_proof_valid(
state_root: &Bytes32,
execution_block_header: &ExecutionBlockHeader,
execution_payload_branch: &ExecutionBranch,
) -> Result<bool, MerkleError> {
is_proof_valid(
state_root,
execution_block_header,
execution_payload_branch,
EXECUTION_BRANCH_NBR_SIBLINGS,
EXECUTION_PAYLOAD_GENERALIZED_INDEX,
)
}

/// Generic function to verify the validity of a Merkle proof.
///
/// # Arguments
Expand All @@ -105,7 +134,7 @@ pub fn is_current_committee_proof_valid(
/// A `bool` indicating whether the proof is valid.
fn is_proof_valid<M: Merkleized>(
state_root: &Bytes32,
leaf_object: &mut M,
leaf_object: &M,
branch: &[Bytes32],
depth: usize,
generalized_index: usize,
Expand Down Expand Up @@ -176,3 +205,94 @@ fn accumulator_update(acc_hash: HashValue, (sibling_hash, bit): (&HashValue, boo
sha2_hash_concat(&acc_hash, sibling_hash).unwrap()
}
}

#[cfg(all(test, feature = "ethereum"))]
mod test {
use crate::merkle::update_proofs::{
is_current_committee_proof_valid, is_execution_payload_proof_valid,
is_finality_proof_valid, is_next_committee_proof_valid,
};
use crate::test_utils::{
generate_committee_change_test_assets, generate_inclusion_test_assets,
};
use crate::types::bootstrap::Bootstrap;
use std::env::current_dir;
use std::fs;

#[test]
fn test_is_execution_payload_proof_valid() {
let test_assets = generate_inclusion_test_assets();

let is_valid = is_execution_payload_proof_valid(
test_assets
.finality_update()
.finalized_header()
.beacon()
.body_root(),
test_assets.finality_update().finalized_header().execution(),
test_assets
.finality_update()
.finalized_header()
.execution_branch(),
)
.unwrap();

assert!(is_valid);
}

#[test]
fn test_is_finality_proof_valid() {
let test_assets = generate_inclusion_test_assets();

let is_valid = is_finality_proof_valid(
test_assets
.finality_update()
.attested_header()
.beacon()
.state_root(),
test_assets.finality_update().finalized_header().beacon(),
test_assets.finality_update().finality_branch(),
)
.unwrap();

assert!(is_valid);
}

#[test]
fn test_is_next_committee_proof_valid() {
let test_assets = generate_committee_change_test_assets();

let is_valid = is_next_committee_proof_valid(
test_assets
.update_new_period()
.attested_header()
.beacon()
.state_root(),
test_assets.update_new_period().next_sync_committee(),
test_assets.update_new_period().next_sync_committee_branch(),
)
.unwrap();

assert!(is_valid);
}

#[test]
fn test_is_current_committee_proof_valid() {
let test_asset_path = current_dir()
.unwrap()
.join("../test-assets/committee-change/LightClientBootstrapDeneb.ssz");

let test_bytes = fs::read(test_asset_path).unwrap();

let bootstrap = Bootstrap::from_ssz_bytes(&test_bytes).unwrap();

let is_valid = is_current_committee_proof_valid(
bootstrap.header().beacon().state_root(),
bootstrap.current_sync_committee(),
bootstrap.current_sync_committee_branch(),
)
.unwrap();

assert!(is_valid);
}
}
8 changes: 5 additions & 3 deletions ethereum/core/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const INCLUSION_CHECKPOINT: &str =
const COMMITTEE_CHANGE_CHECKPOINT: &str =
"0xefb4338d596b9d335b2da176dc85ee97469fc80c7e2d35b9b9c1558b4602077a";

#[derive(Getters)]
#[getset(get = "pub")]
pub struct CommitteeChangeTestAssets {
pub store: LightClientStore,
pub update: Update,
Expand Down Expand Up @@ -73,9 +75,9 @@ pub fn generate_committee_change_test_assets() -> CommitteeChangeTestAssets {
#[derive(Getters)]
#[getset(get = "pub")]
pub struct InclusionTestAssets {
pub store: LightClientStore,
pub finality_update: FinalityUpdate,
pub eip1186_proof: EIP1186Proof,
store: LightClientStore,
finality_update: FinalityUpdate,
eip1186_proof: EIP1186Proof,
}

pub fn generate_inclusion_test_assets() -> InclusionTestAssets {
Expand Down
2 changes: 1 addition & 1 deletion ethereum/core/src/types/block/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub struct BeaconBlockHeader {
proposer_index: u64,
parent_root: Bytes32,
state_root: Bytes32,
body_root: Bytes32,
pub(crate) body_root: Bytes32,
}

impl BeaconBlockHeader {
Expand Down
8 changes: 7 additions & 1 deletion ethereum/core/src/types/block/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ use getset::Getters;
/// From [the Capella specifications](https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/capella/light-client/sync-protocol.md#custom-types).
pub const EXECUTION_BRANCH_NBR_SIBLINGS: usize = 4;

/// The [generalized Merkle tree index](https://github.com/ethereum/consensus-specs/blob/81f3ea8322aff6b9fb15132d050f8f98b16bdba4/ssz/merkle-proofs.md#generalized-merkle-tree-index)
/// for the execution payload.
///
/// From [the Altair specifications](https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/capella/light-client/sync-protocol.md#constants)
pub const EXECUTION_PAYLOAD_GENERALIZED_INDEX: usize = 25;

/// Path in the tree to the execution payload in the beacon block body.
pub type ExecutionBranch = [Bytes32; EXECUTION_BRANCH_NBR_SIBLINGS];

Expand All @@ -45,7 +51,7 @@ pub const MAX_EXTRA_DATA_BYTES_LEN: usize = BYTES_32_LEN;

/// `ExecutionBlockHeader` represents the header of an execution block.
///
/// From [the Capella specifications](https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/capella/beacon-chain.md#executionpayloadheader).
/// From [the Deneb specifications](https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#executionpayloadheader).
#[derive(Debug, Clone, Eq, PartialEq, Getters)]
#[getset(get = "pub")]
pub struct ExecutionBlockHeader {
Expand Down
4 changes: 2 additions & 2 deletions ethereum/core/src/types/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ pub const LIGHT_CLIENT_HEADER_BASE_BYTES_LEN: usize = BEACON_BLOCK_HEADER_BYTES_
#[getset(get = "pub")]
pub struct LightClientHeader {
pub(crate) beacon: BeaconBlockHeader,
execution: ExecutionBlockHeader,
execution_branch: ExecutionBranch,
pub(crate) execution: ExecutionBlockHeader,
pub(crate) execution_branch: ExecutionBranch,
}

impl Merkleized for LightClientHeader {
Expand Down
12 changes: 7 additions & 5 deletions ethereum/core/src/types/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub const FINALIZED_HEADER_OFFSET: usize = OFFSET_BYTE_LENGTH

/// The `LightClientStore` represents the fill state for our Light Client. It includes the necessary
/// data to be maintained to verify the consensus rules in future updates.
///
/// From [the Altaïr specification](https://github.com/ethereum/consensus-specs/blob/9c39645761e9526ff4b272ff9101ede9bd54b7a5/specs/altair/light-client/sync-protocol.md#lightclientstore).
#[derive(Debug, Clone, Eq, PartialEq, Getters)]
#[getset(get = "pub")]
pub struct LightClientStore {
Expand Down Expand Up @@ -110,7 +112,7 @@ impl LightClientStore {
// Confirm that the given sync committee was committed in the block
let is_valid = is_current_committee_proof_valid(
bootstrap.header().beacon().state_root(),
&mut bootstrap.current_sync_committee().clone(),
bootstrap.current_sync_committee(),
bootstrap.current_sync_committee_branch(),
)
.map_err(|err| StoreError::InvalidCurrentCommitteeProof { source: err.into() })?;
Expand Down Expand Up @@ -257,7 +259,7 @@ impl LightClientStore {
// Ensure that the received finality proof is valid
let is_valid = is_finality_proof_valid(
update.attested_header().beacon().state_root(),
&mut update.finalized_header().beacon().clone(),
update.finalized_header().beacon(),
update.finality_branch(),
)
.map_err(|err| ConsensusError::MerkleError { source: err.into() })?;
Expand All @@ -274,7 +276,7 @@ impl LightClientStore {
} else {
let is_valid = is_next_committee_proof_valid(
update.attested_header().beacon().state_root(),
&mut update.next_sync_committee().clone(),
update.next_sync_committee(),
update.next_sync_committee_branch(),
)
.map_err(|err| ConsensusError::MerkleError { source: err.into() })?;
Expand Down Expand Up @@ -606,7 +608,7 @@ impl CompactStore {

// Assert that the received data make sense chronologically
let valid_time = update.signature_slot() > update.attested_beacon_header().slot()
&& update.attested_beacon_header().slot() >= update.finalized_beacon_header().slot();
&& update.attested_beacon_header().slot() >= update.finalized_header().beacon().slot();

if !valid_time {
return Err(ConsensusError::InvalidTimestamp);
Expand All @@ -621,7 +623,7 @@ impl CompactStore {
// Ensure that the received finality proof is valid
let is_valid = is_finality_proof_valid(
update.attested_beacon_header().state_root(),
&mut update.finalized_beacon_header().clone(),
update.finalized_header().beacon(),
update.finality_branch(),
)
.map_err(|err| ConsensusError::MerkleError { source: err.into() })?;
Expand Down
Loading

0 comments on commit af8ff82

Please sign in to comment.