From 0cef24a441961313336b136ce11ea98659035eb3 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 20 Mar 2024 20:34:47 +0000 Subject: [PATCH 01/30] update circuits and witnesses, still need to update tests --- lightclient-circuits/Cargo.toml | 8 +++-- .../src/committee_update_circuit.rs | 7 +++-- lightclient-circuits/src/sync_step_circuit.rs | 16 +++++----- .../src/witness/multiproof.rs | 21 ++++++++------ lightclient-circuits/src/witness/rotation.rs | 14 ++++----- lightclient-circuits/src/witness/step.rs | 29 ++++++++----------- 6 files changed, 49 insertions(+), 46 deletions(-) diff --git a/lightclient-circuits/Cargo.toml b/lightclient-circuits/Cargo.toml index fa18d72..3ce9f56 100644 --- a/lightclient-circuits/Cargo.toml +++ b/lightclient-circuits/Cargo.toml @@ -25,8 +25,9 @@ sha2.workspace = true pse-poseidon = { git = "https://github.com/axiom-crypto/pse-poseidon.git" } # ethereum -ssz_rs = { workspace = true, features = ["serde"] } -ethereum-consensus-types ={ workspace = true, features = ["serde"] } +ethereum-types = {workspace = true, default-features = false } +eth2.workspace = true +tree_hash.workspace = true # local eth-types.workspace = true @@ -47,6 +48,9 @@ lazy_static = "1.4" getset = "0.1.2" rand_chacha = "0.3.0" + + + [dev-dependencies] rstest = "0.18.2" test-utils = { workspace = true } diff --git a/lightclient-circuits/src/committee_update_circuit.rs b/lightclient-circuits/src/committee_update_circuit.rs index 31ed653..eeecf4b 100644 --- a/lightclient-circuits/src/committee_update_circuit.rs +++ b/lightclient-circuits/src/committee_update_circuit.rs @@ -29,8 +29,9 @@ use halo2_ecc::{ fields::FieldChip, }; use itertools::Itertools; -use ssz_rs::Merkleized; +// use ssz_rs::Merkleized; use std::{env::var, iter, marker::PhantomData, vec}; +use tree_hash::TreeHash; /// `CommitteeUpdateCircuit` maps next sync committee SSZ root in the finalized state root to the corresponding Poseidon commitment to the public keys. /// @@ -90,7 +91,7 @@ impl CommitteeUpdateCircuit { builder, &sha256_chip, [ - args.finalized_header.slot.into_witness(), + args.finalized_header.slot.as_u64().into_witness(), args.finalized_header.proposer_index.into_witness(), args.finalized_header.parent_root.as_ref().into_witness(), finalized_state_root.clone().into(), @@ -205,7 +206,7 @@ impl CommitteeUpdateCircuit { let poseidon_commitment = poseidon_committee_commitment_from_compressed(&args.pubkeys_compressed, limb_bits); - let finalized_header_root = args.finalized_header.clone().hash_tree_root().unwrap(); + let finalized_header_root = args.finalized_header.tree_hash_root(); let finalized_header_root_hilo = { let bytes = finalized_header_root.as_ref(); diff --git a/lightclient-circuits/src/sync_step_circuit.rs b/lightclient-circuits/src/sync_step_circuit.rs index f85d4ec..89a47f9 100644 --- a/lightclient-circuits/src/sync_step_circuit.rs +++ b/lightclient-circuits/src/sync_step_circuit.rs @@ -42,8 +42,8 @@ use halo2_ecc::{ use halo2curves::bls12_381::{G1Affine, G2Affine}; use itertools::Itertools; use num_bigint::BigUint; -use ssz_rs::Merkleized; use std::{env::var, marker::PhantomData, vec}; +use tree_hash::TreeHash; /// `StepCircuit` verifies that Beacon chain block header is attested by a lightclient sync committee via aggregated signature, /// and the execution (Eth1) payload via Merkle proof against the finalized block header. @@ -110,7 +110,8 @@ impl StepCircuit { )?; // Compute attested header root - let attested_slot_bytes: HashInputChunk<_> = args.attested_header.slot.into_witness(); + let attested_slot_bytes: HashInputChunk<_> = + args.attested_header.slot.as_u64().into_witness(); let attested_header_state_root = args .attested_header .state_root @@ -138,7 +139,8 @@ impl StepCircuit { .iter() .map(|&b| builder.main().load_witness(F::from(b as u64))) .collect_vec(); - let finalized_slot_bytes: HashInputChunk<_> = args.finalized_header.slot.into_witness(); + let finalized_slot_bytes: HashInputChunk<_> = + args.finalized_header.slot.as_u64().into_witness(); let finalized_header_root = ssz_merkleize_chunks( builder, &sha256_chip, @@ -230,11 +232,11 @@ impl StepCircuit { const INPUT_SIZE: usize = 8 * 3 + 32 * 2; let mut input = [0; INPUT_SIZE]; - let mut attested_slot_le = args.attested_header.slot.to_le_bytes().to_vec(); + let mut attested_slot_le = args.attested_header.slot.as_u64().to_le_bytes().to_vec(); attested_slot_le.resize(8, 0); input[..8].copy_from_slice(&attested_slot_le); - let mut finalized_slot_le = args.finalized_header.slot.to_le_bytes().to_vec(); + let mut finalized_slot_le = args.finalized_header.slot.as_u64().to_le_bytes().to_vec(); finalized_slot_le.resize(8, 0); input[8..16].copy_from_slice(&finalized_slot_le); @@ -250,9 +252,7 @@ impl StepCircuit { let finalized_header_root: [u8; 32] = args .finalized_header - .clone() - .hash_tree_root() - .unwrap() + .tree_hash_root() .as_ref() .try_into() .unwrap(); diff --git a/lightclient-circuits/src/witness/multiproof.rs b/lightclient-circuits/src/witness/multiproof.rs index 59ec59f..44ff695 100644 --- a/lightclient-circuits/src/witness/multiproof.rs +++ b/lightclient-circuits/src/witness/multiproof.rs @@ -1,8 +1,8 @@ // TODO: A lot if not all/most of this code is copy pasta from: https://github.com/ralexstokes/ssz-rs/pull/118 which is mostly implemented w.r.t. the spec // TODO: Remove this once the above PR lands in ssz-rs +use ethereum_types::Hash256; use sha2::{Digest, Sha256}; -use ssz_rs::Node; use std::collections::{HashMap, HashSet}; pub type GeneralizedIndex = usize; @@ -93,7 +93,7 @@ pub fn get_helper_indices(indices: &[GeneralizedIndex]) -> Vec all_branch_indices } -pub fn calculate_merkle_root(leaf: Node, proof: &[Node], index: GeneralizedIndex) -> Node { +pub fn calculate_merkle_root(leaf: Hash256, proof: &[Hash256], index: GeneralizedIndex) -> Hash256 { debug_assert_eq!(proof.len(), get_path_length(index)); let mut result = leaf; @@ -114,15 +114,15 @@ pub fn calculate_merkle_root(leaf: Node, proof: &[Node], index: GeneralizedIndex /// Calculate the Merkle root of a set of leaves and their corresponding proofs. /// Note: `indices` and `leaves` must be in the same order as they correspond to each other. pub fn calculate_multi_merkle_root( - leaves: &[Node], - proof: &[Node], + leaves: &[Hash256], + proof: &[Hash256], indices: &[GeneralizedIndex], -) -> Node { +) -> Hash256 { assert_eq!(leaves.len(), indices.len()); let helper_indices = get_helper_indices(indices); assert_eq!(proof.len(), helper_indices.len()); - let mut objects: HashMap = indices + let mut objects: HashMap = indices .iter() .chain(helper_indices.iter()) .copied() @@ -163,9 +163,9 @@ pub fn calculate_multi_merkle_root( /// Return an array representing the tree nodes by generalized index: /// [0, 1, 2, 3, 4, 5, 6, 7], where each layer is a power of 2. The 0 index is ignored. The 1 index is the root. /// The result will be twice the size as the padded bottom layer for the input leaves. -pub fn merkle_tree(leaves: &[Node]) -> Vec { +pub fn merkle_tree(leaves: &[Hash256]) -> Vec { let bottom_length = get_power_of_two_ceil(leaves.len()); - let mut o = vec![Node::default(); bottom_length * 2]; + let mut o = vec![Hash256::default(); bottom_length * 2]; o[bottom_length..bottom_length + leaves.len()].copy_from_slice(leaves); for i in (1..bottom_length).rev() { let left = o[i * 2].as_ref(); @@ -178,7 +178,10 @@ pub fn merkle_tree(leaves: &[Node]) -> Vec { o } -pub fn create_multiproof(merkle_tree: &[Node], indices_to_prove: &[GeneralizedIndex]) -> Vec { +pub fn create_multiproof( + merkle_tree: &[Hash256], + indices_to_prove: &[GeneralizedIndex], +) -> Vec { get_helper_indices(indices_to_prove) .into_iter() .map(|i| merkle_tree[i]) diff --git a/lightclient-circuits/src/witness/rotation.rs b/lightclient-circuits/src/witness/rotation.rs index 8539b46..de48faf 100644 --- a/lightclient-circuits/src/witness/rotation.rs +++ b/lightclient-circuits/src/witness/rotation.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: LGPL-3.0-only use eth_types::Spec; -use ethereum_consensus_types::BeaconBlockHeader; +use ethereum_types::BeaconBlockHeader; use itertools::Itertools; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; @@ -60,21 +60,21 @@ impl Default for CommitteeUpdateArgs { S::SYNC_COMMITTEE_PUBKEYS_ROOT_INDEX, ); + let mut finalized_header = BeaconBlockHeader::empty(); + finalized_header.state_root = state_root.try_into().unwrap(); + Self { pubkeys_compressed: iter::repeat(dummy_x_bytes) .take(S::SYNC_COMMITTEE_SIZE) .collect_vec(), sync_committee_branch, - finalized_header: BeaconBlockHeader { - state_root: state_root.as_slice().try_into().unwrap(), - ..Default::default() - }, + finalized_header, _spec: PhantomData, } } } -pub(crate) fn mock_root(leaf: Vec, branch: &[Vec], mut gindex: usize) -> Vec { +pub(crate) fn mock_root(leaf: Vec, branch: &[Vec], mut gindex: usize) -> [u8; 32] { let mut last_hash = leaf; for i in 0..branch.len() { @@ -90,7 +90,7 @@ pub(crate) fn mock_root(leaf: Vec, branch: &[Vec], mut gindex: usize) -> gindex /= 2; } - last_hash + last_hash.try_into().unwrap() } #[cfg(test)] diff --git a/lightclient-circuits/src/witness/step.rs b/lightclient-circuits/src/witness/step.rs index 865a836..805822a 100644 --- a/lightclient-circuits/src/witness/step.rs +++ b/lightclient-circuits/src/witness/step.rs @@ -3,8 +3,7 @@ // SPDX-License-Identifier: LGPL-3.0-only use eth_types::Spec; -use ethereum_consensus_types::signing::compute_signing_root; -use ethereum_consensus_types::BeaconBlockHeader; +use ethereum_types::{BeaconBlockHeader, SignedRoot}; use ff::Field; use halo2curves::bls12_381::hash_to_curve::ExpandMsgXmd; use halo2curves::bls12_381::{hash_to_curve, Fr, G1, G2}; @@ -12,9 +11,8 @@ use halo2curves::group::Curve; use itertools::Itertools; use rand::SeedableRng; use serde::{Deserialize, Serialize}; -use ssz_rs::{Merkleized, Node}; use std::marker::PhantomData; -use std::ops::Deref; +use tree_hash::TreeHash; use super::mock_root; @@ -64,28 +62,25 @@ impl Default for SyncStepArgs { S::EXECUTION_STATE_ROOT_INDEX, ); - let mut finalized_header = BeaconBlockHeader { - body_root: Node::try_from(beacon_block_body_root.as_slice()).unwrap(), - ..Default::default() - }; + let mut finalized_header = BeaconBlockHeader::empty(); + finalized_header.body_root = beacon_block_body_root.try_into().unwrap(); - let finality_header_root = finalized_header.hash_tree_root().unwrap(); + let finality_header_root = finalized_header.tree_hash_root(); let finality_branch = vec![vec![0; 32]; S::FINALIZED_HEADER_DEPTH]; let attested_state_root = mock_root( - finality_header_root.deref().to_vec(), + finality_header_root.0.to_vec(), &finality_branch, S::FINALIZED_HEADER_INDEX, ); - let mut attested_header = BeaconBlockHeader { - state_root: Node::try_from(attested_state_root.as_slice()).unwrap(), - ..Default::default() - }; + let mut attested_header = BeaconBlockHeader::empty(); + attested_header.state_root = attested_state_root.try_into().unwrap(); - let signing_root = - compute_signing_root(attested_header.hash_tree_root().unwrap(), DOMAIN).unwrap(); + let signing_root = attested_header + .tree_hash_root() + .signing_root(DOMAIN.try_into().unwrap()); let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0); @@ -93,7 +88,7 @@ impl Default for SyncStepArgs { .map(|_| Fr::random(&mut rng)) .collect_vec(); let msg = >>::hash_to_curve( - signing_root.deref(), + signing_root.0, S::DST, ) .to_affine(); From 8c0fe03bb327aaeccd6d912945ff3ac6adfb3284 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 20 Mar 2024 21:32:30 +0000 Subject: [PATCH 02/30] fix preprocessor --- Cargo.toml | 5 + preprocessor/Cargo.toml | 16 +- preprocessor/src/lib.rs | 285 +++++++++++++++-------------------- preprocessor/src/rotation.rs | 91 +++++------ preprocessor/src/step.rs | 245 +++++++++++++++++------------- rust-toolchain | 1 - 6 files changed, 326 insertions(+), 317 deletions(-) delete mode 100644 rust-toolchain diff --git a/Cargo.toml b/Cargo.toml index bdd14a0..8869447 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,6 +71,11 @@ ethereum-consensus-types = { git = "https://github.com/ChainSafe/ethereum-consen beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus.git", rev = "f3bff52e9c43866f231ec40c8ab0e34125a8957f" } ssz_rs = "0.9" + +ethereum-types = { package = "types", git = "https://github.com/eserilev/lighthouse/", branch = "capella_deneb_light_client_types", default-features = false} +tree_hash = { version = "0.5" } +eth2 = { package = "eth2", git = "https://github.com/eserilev/lighthouse/", branch = "capella_deneb_light_client_types" } + # crypto group = "0.13" num-bigint = { version = "0.4", features = ["rand"] } diff --git a/preprocessor/Cargo.toml b/preprocessor/Cargo.toml index aa7679a..91a38c6 100644 --- a/preprocessor/Cargo.toml +++ b/preprocessor/Cargo.toml @@ -14,29 +14,32 @@ required-features = ["test-gen"] [dependencies] -ssz_rs.workspace = true halo2curves.workspace = true group.workspace = true -beacon-api-client.workspace = true # misc eyre = "0.6" tokio = { version = "1", features = ["full"] } +url = "2.2.2" hex.workspace = true log.workspace = true itertools.workspace = true serde_json.workspace = true serde.workspace = true -ethereum-consensus-types.workspace = true + +ethereum-types = {workspace = true, default-features = false } +eth2.workspace = true +tree_hash.workspace = true + # local eth-types.workspace = true lightclient-circuits.workspace = true reqwest = "0.11.22" # for test gen binary -ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus.git", rev = "f3bff52e9c43866f231ec40c8ab0e34125a8957f", optional = true } -blst = { version = "0.3.11", default-features = false, features = [ "portable", "no-threads" ], optional = true } +# ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus.git", rev = "f3bff52e9c43866f231ec40c8ab0e34125a8957f", optional = true } +blst = { version = "0.3.11", default-features = false, features = [ "portable", "no-threads" ]} [dev-dependencies] halo2-base.workspace = true @@ -44,4 +47,5 @@ snark-verifier-sdk.workspace = true ark-std.workspace = true [features] -test-gen = ["ethereum-consensus", "blst"] \ No newline at end of file +# test-gen = ["ethereum-consensus", "blst"] +test-gen = [] \ No newline at end of file diff --git a/preprocessor/src/lib.rs b/preprocessor/src/lib.rs index cfe6302..aee78a4 100644 --- a/preprocessor/src/lib.rs +++ b/preprocessor/src/lib.rs @@ -7,135 +7,54 @@ mod rotation; mod step; - -use beacon_api_client::{BlockId, Client, ClientTypes, Value, VersionedValue}; +use eth2::mixin::RequestAccept as _; +use eth2::types::Accept; +use eth2::BeaconNodeHttpClient; use eth_types::Spec; -use ethereum_consensus_types::bls::BlsSignature; -use ethereum_consensus_types::{ - BeaconBlockHeader, BlsPublicKey, ByteVector, LightClientBootstrap, LightClientFinalityUpdate, - LightClientUpdateCapella, Root, +use ethereum_types::{ + EthSpec, FixedVector, LightClientFinalityUpdate, LightClientFinalityUpdateCapella, + LightClientFinalityUpdateDeneb, PublicKeyBytes, }; - -use itertools::Itertools; +use ethereum_types::{ForkVersionedResponse, LightClientUpdate}; use lightclient_circuits::witness::{CommitteeUpdateArgs, SyncStepArgs}; pub use rotation::*; -use serde::{Deserialize, Serialize}; -use ssz_rs::{Node, Vector}; pub use step::*; +use url::Url; -pub async fn get_light_client_update_at_period( - client: &Client, +pub async fn get_light_client_update_at_period( + client: &BeaconNodeHttpClient, period: u64, -) -> eyre::Result< - LightClientUpdateCapella< - { S::SYNC_COMMITTEE_SIZE }, - { S::SYNC_COMMITTEE_ROOT_INDEX }, - { S::SYNC_COMMITTEE_DEPTH }, - { S::FINALIZED_HEADER_INDEX }, - { S::FINALIZED_HEADER_DEPTH }, - { S::BYTES_PER_LOGS_BLOOM }, - { S::MAX_EXTRA_DATA_BYTES }, - >, -> -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::SYNC_COMMITTEE_ROOT_INDEX]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, - [(); S::FINALIZED_HEADER_INDEX]:, -{ - let route = "eth/v1/beacon/light_client/updates"; - let mut updates: Vec> = client - .http - .get(client.endpoint.join(route)?) - .query(&[("start_period", period), ("count", 1)]) - .send() - .await? - .json() - .await?; +) -> eyre::Result> { + let mut path = Url::parse(client.as_ref()).unwrap(); + + path.path_segments_mut() + .map_err(|()| eyre::eyre!("Invalid URL: {}", client.as_ref()))? + .push("eth") + .push("v1") + .push("beacon") + .push("light_client") + .push("updates"); + + path.query_pairs_mut() + .append_pair("start_period", &period.to_string()) + .append_pair("count", "1"); + println!("Path: {:?}", path); + let resp = client + .get_response(path, |b| b.accept(Accept::Json)) + .await + .map_err(|e| eyre::eyre!("Failed to get light client update: {:?}", e))?; + println!("resp: {:?}", resp); + + let mut updates: Vec>> = resp.json().await?; + println!("Updates: {:?}", updates); + assert!(updates.len() == 1, "should only get one update"); Ok(updates.pop().unwrap().data) } -pub async fn get_light_client_bootstrap( - client: &Client, - block_root: Node, -) -> eyre::Result< - LightClientBootstrap< - { S::SYNC_COMMITTEE_SIZE }, - { S::SYNC_COMMITTEE_DEPTH }, - { S::BYTES_PER_LOGS_BLOOM }, - { S::MAX_EXTRA_DATA_BYTES }, - >, -> -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, -{ - let route = format!("eth/v1/beacon/light_client/bootstrap/{block_root:?}"); - let bootstrap = client.get::>(&route).await?.data; - Ok(bootstrap) -} - -pub async fn get_light_client_finality_update( - client: &Client, -) -> eyre::Result< - LightClientFinalityUpdate< - { S::SYNC_COMMITTEE_SIZE }, - { S::FINALIZED_HEADER_DEPTH }, - { S::BYTES_PER_LOGS_BLOOM }, - { S::MAX_EXTRA_DATA_BYTES }, - >, -> -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::FINALIZED_HEADER_DEPTH]:, -{ - Ok(client - .get::>("eth/v1/beacon/light_client/finality_update") - .await? - .data) -} - -pub async fn get_block_header( - client: &Client, - id: BlockId, -) -> eyre::Result { - // TODO: Once the ethereum beacon_api_client is updated, we can avoid this struct definition - #[derive(Serialize, Deserialize)] - struct BeaconHeaderSummary { - pub root: Root, - pub canonical: bool, - pub header: SignedBeaconBlockHeader, - } - #[derive(Serialize, Deserialize)] - struct SignedBeaconBlockHeader { - pub message: BeaconBlockHeader, - pub signature: BlsSignature, - } - - let route = format!("eth/v1/beacon/headers/{id}"); - let block: BeaconHeaderSummary = client.get::>(&route).await?.data; - Ok(block.header.message) -} - -pub async fn light_client_update_to_args( - update: &LightClientUpdateCapella< - { S::SYNC_COMMITTEE_SIZE }, - { S::SYNC_COMMITTEE_ROOT_INDEX }, - { S::SYNC_COMMITTEE_DEPTH }, - { S::FINALIZED_HEADER_INDEX }, - { S::FINALIZED_HEADER_DEPTH }, - { S::BYTES_PER_LOGS_BLOOM }, - { S::MAX_EXTRA_DATA_BYTES }, - >, - pubkeys_compressed: Vector, +pub async fn light_client_update_to_args( + update: &LightClientUpdate, + pubkeys_compressed: &FixedVector, domain: [u8; 32], ) -> eyre::Result<(SyncStepArgs, CommitteeUpdateArgs)> where @@ -147,19 +66,27 @@ where [(); S::SYNC_COMMITTEE_DEPTH]:, [(); S::FINALIZED_HEADER_INDEX]:, { - let finality_update = LightClientFinalityUpdate { - attested_header: update.attested_header.clone(), - finalized_header: update.finalized_header.clone(), - finality_branch: Vector::try_from( - update - .finality_branch - .iter() - .map(|v| ByteVector(Vector::try_from(v.to_vec()).unwrap())) - .collect_vec(), - ) - .unwrap(), - sync_aggregate: update.sync_aggregate.clone(), - signature_slot: update.signature_slot, + let finality_update = match update { + LightClientUpdate::Altair(_) => unimplemented!(), + LightClientUpdate::Capella(update) => { + LightClientFinalityUpdate::Capella(LightClientFinalityUpdateCapella { + attested_header: update.attested_header.clone(), + finalized_header: update.finalized_header.clone(), + finality_branch: update.finality_branch.clone(), + sync_aggregate: update.sync_aggregate.clone(), + signature_slot: update.signature_slot, + }) + } + + LightClientUpdate::Deneb(update) => { + LightClientFinalityUpdate::Deneb(LightClientFinalityUpdateDeneb { + attested_header: update.attested_header.clone(), + finalized_header: update.finalized_header.clone(), + finality_branch: update.finality_branch.clone(), + sync_aggregate: update.sync_aggregate.clone(), + signature_slot: update.signature_slot, + }) + } }; let rotation_args = rotation::rotation_args_from_update(update).await?; @@ -172,10 +99,8 @@ where #[cfg(test)] mod tests { - use beacon_api_client::StateId; + use eth2::types::StateId; use eth_types::Testnet; - use ethereum_consensus_types::signing::{compute_domain, DomainType}; - use ethereum_consensus_types::ForkData; use halo2_base::halo2_proofs::halo2curves::bn256::Bn256; use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; use halo2_base::utils::fs::gen_srs; @@ -189,16 +114,32 @@ mod tests { use snark_verifier_sdk::CircuitExt; use super::*; - use beacon_api_client::mainnet::Client as MainnetClient; use reqwest::Url; + use eth2::BeaconNodeHttpClient; + use ethereum_types::Domain; + use ethereum_types::EthSpec; + use ethereum_types::ForkData; + use ethereum_types::MainnetEthSpec; + use std::time::Duration; + #[tokio::test] async fn test_both_circuit_sepolia() { const K: u32 = 21; - let client = - MainnetClient::new(Url::parse("https://lodestar-sepolia.chainsafe.io").unwrap()); + const URL: &str = "https://lodestar-sepolia.chainsafe.io"; + let client = BeaconNodeHttpClient::new( + SensitiveUrl::parse(URL).unwrap(), + Timeouts::set_all(Duration::from_secs(10)), + ); - let block = get_block_header(&client, BlockId::Finalized).await.unwrap(); + let block = client + .get_beacon_headers_block_id(BlockId::Finalized) + .await + .unwrap() + .unwrap() + .data + .header + .message; let slot = block.slot; let period = slot / (32 * 256); @@ -209,54 +150,68 @@ mod tests { // Fetch light client update and create circuit arguments let (s, mut c) = { - let update = get_light_client_update_at_period(&client, period) - .await - .unwrap(); + let update = get_light_client_update_at_period::( + &client, + period.into(), + ) + .await + .unwrap(); - let block_root = client - .get_beacon_block_root(BlockId::Slot(slot)) - .await - .unwrap(); + let block_root = block.canonical_root(); - let bootstrap = get_light_client_bootstrap(&client, block_root) + let bootstrap = client + .get_light_client_bootstrap::(block_root) .await - .unwrap(); + .unwrap() + .unwrap() + .data; - let pubkeys_compressed = bootstrap.current_sync_committee.pubkeys; + let pubkeys_compressed = &bootstrap.current_sync_committee.pubkeys; let fork_version = client - .get_fork(StateId::Head) + .get_beacon_states_fork(StateId::Head) .await .unwrap() + .unwrap() + .data .current_version; + let genesis_validators_root = client - .get_genesis_details() + .get_beacon_genesis() .await .unwrap() + .data .genesis_validators_root; - let fork_data = ForkData { - genesis_validators_root, + + let domain = MainnetEthSpec::default_spec().compute_domain( + Domain::SyncCommittee, fork_version, - }; - let domain = compute_domain(DomainType::SyncCommittee, &fork_data).unwrap(); - light_client_update_to_args::(&update, pubkeys_compressed, domain) - .await - .unwrap() + genesis_validators_root, + ); + + light_client_update_to_args::( + &update, + pubkeys_compressed, + domain.into(), + ) + .await + .unwrap() }; let mut finalized_sync_committee_branch = { - let block_root = client - .get_beacon_block_root(BlockId::Slot(s.finalized_header.slot)) - .await - .unwrap(); + let block_root = s.finalized_header.canonical_root(); - get_light_client_bootstrap::(&client, block_root) + let k = client + .get_light_client_bootstrap::(block_root) .await .unwrap() + .unwrap() + .data .current_sync_committee_branch - .iter() - .map(|n| n.to_vec()) - .collect_vec() + .into_iter() + .map(|n| n.0.to_vec()) + .collect_vec(); + k }; // Magic swap of sync committee branch diff --git a/preprocessor/src/rotation.rs b/preprocessor/src/rotation.rs index 8c1b146..f8b0df8 100644 --- a/preprocessor/src/rotation.rs +++ b/preprocessor/src/rotation.rs @@ -4,19 +4,19 @@ use std::marker::PhantomData; -use beacon_api_client::{BlockId, Client, ClientTypes}; use eth_types::Spec; -use ethereum_consensus_types::LightClientUpdateCapella; use itertools::Itertools; -use lightclient_circuits::witness::CommitteeUpdateArgs; use log::debug; -use ssz_rs::Merkleized; -use crate::{get_block_header, get_light_client_update_at_period}; +use crate::get_light_client_update_at_period; +use eth2::{types::BlockId, BeaconNodeHttpClient}; +use ethereum_types::{EthSpec, LightClientUpdate}; +use lightclient_circuits::witness::CommitteeUpdateArgs; +use tree_hash::TreeHash; /// Fetches LightClientUpdate from the beacon client and converts it to a [`CommitteeUpdateArgs`] witness -pub async fn fetch_rotation_args( - client: &Client, +pub async fn fetch_rotation_args( + client: &BeaconNodeHttpClient, ) -> eyre::Result> where [(); S::SYNC_COMMITTEE_SIZE]:, @@ -27,29 +27,29 @@ where [(); S::SYNC_COMMITTEE_DEPTH]:, [(); S::FINALIZED_HEADER_INDEX]:, { - let block = get_block_header(client, BlockId::Head).await?; - let slot = block.slot; + let block = client + .get_beacon_headers_block_id(BlockId::Head) + .await + .unwrap() + .unwrap() + .data + .header + .message; + + let slot = block.slot.as_u64(); let period = slot / (32 * 256); debug!( "Fetching light client update at current Slot: {} at Period: {}", slot, period ); - let update = get_light_client_update_at_period(client, period).await?; + let update = get_light_client_update_at_period::(client, period).await?; rotation_args_from_update(&update).await } /// Converts a [`LightClientUpdateCapella`] to a [`CommitteeUpdateArgs`] witness. -pub async fn rotation_args_from_update( - update: &LightClientUpdateCapella< - { S::SYNC_COMMITTEE_SIZE }, - { S::SYNC_COMMITTEE_ROOT_INDEX }, - { S::SYNC_COMMITTEE_DEPTH }, - { S::FINALIZED_HEADER_INDEX }, - { S::FINALIZED_HEADER_DEPTH }, - { S::BYTES_PER_LOGS_BLOOM }, - { S::MAX_EXTRA_DATA_BYTES }, - >, +pub async fn rotation_args_from_update( + update: &LightClientUpdate, ) -> eyre::Result> where [(); S::SYNC_COMMITTEE_SIZE]:, @@ -60,45 +60,50 @@ where [(); S::SYNC_COMMITTEE_DEPTH]:, [(); S::FINALIZED_HEADER_INDEX]:, { - let mut update = update.clone(); + let update = update.clone(); let pubkeys_compressed = update - .next_sync_committee + .next_sync_committee() .pubkeys .iter() - .map(|pk| pk.to_bytes().to_vec()) + .map(|pk| pk.serialize().to_vec()) .collect_vec(); - let mut sync_committee_branch = update.next_sync_committee_branch.as_ref().to_vec(); + let mut sync_committee_branch = update.next_sync_committee_branch().as_ref().to_vec(); sync_committee_branch.insert( 0, update - .next_sync_committee + .next_sync_committee() .aggregate_pubkey - .hash_tree_root() - .unwrap(), + .tree_hash_root(), ); - assert!( - ssz_rs::is_valid_merkle_branch( - update.next_sync_committee.pubkeys.hash_tree_root().unwrap(), - &sync_committee_branch - .iter() - .map(|n| n.as_ref()) - .collect_vec(), - S::SYNC_COMMITTEE_PUBKEYS_DEPTH, - S::SYNC_COMMITTEE_PUBKEYS_ROOT_INDEX, - update.attested_header.beacon.state_root, - ) - .is_ok(), - "Execution payload merkle proof verification failed" - ); + // assert!( + // ssz_rs::is_valid_merkle_branch( + // update.next_sync_committee.pubkeys.hash_tree_root().unwrap(), + // &sync_committee_branch + // .iter() + // .map(|n| n.as_ref()) + // .collect_vec(), + // S::SYNC_COMMITTEE_PUBKEYS_DEPTH, + // S::SYNC_COMMITTEE_PUBKEYS_ROOT_INDEX, + // update.attested_header.beacon.state_root, + // ) + // .is_ok(), + // "Execution payload merkle proof verification failed" + // ); + let finalized_header_beacon = match update { + LightClientUpdate::Altair(_) => unimplemented!(), + LightClientUpdate::Capella(update) => update.finalized_header.beacon, + + LightClientUpdate::Deneb(update) => update.finalized_header.beacon, + }; let args = CommitteeUpdateArgs:: { pubkeys_compressed, - finalized_header: update.finalized_header.beacon.clone(), + finalized_header: finalized_header_beacon, sync_committee_branch: sync_committee_branch .into_iter() - .map(|n| n.to_vec()) + .map(|n| n.0.to_vec()) .collect_vec(), _spec: PhantomData, }; diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index 62a8d9b..880785c 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -4,22 +4,20 @@ use std::marker::PhantomData; -use beacon_api_client::Client; -use beacon_api_client::{BlockId, ClientTypes, StateId}; use eth_types::Spec; -use ethereum_consensus_types::bls::BlsPublicKey; -use ethereum_consensus_types::signing::{compute_domain, DomainType}; -use ethereum_consensus_types::{ForkData, LightClientBootstrap, LightClientFinalityUpdate}; use itertools::Itertools; use lightclient_circuits::witness::SyncStepArgs; -use ssz_rs::Vector; -use ssz_rs::{Merkleized, Node}; -use crate::{get_light_client_bootstrap, get_light_client_finality_update}; +use blst::min_pk as bls; +use eth2::types::StateId; +use eth2::BeaconNodeHttpClient; +use ethereum_types::Domain; +use ethereum_types::{EthSpec, FixedVector, LightClientFinalityUpdate, PublicKeyBytes}; +use tree_hash::TreeHash; /// Fetches the latest `LightClientFinalityUpdate`` and the current sync committee (from LightClientBootstrap) and converts it to a [`SyncStepArgs`] witness. -pub async fn fetch_step_args( - client: &Client, +pub async fn fetch_step_args( + client: &BeaconNodeHttpClient, ) -> eyre::Result> where [(); S::SYNC_COMMITTEE_SIZE]:, @@ -28,130 +26,173 @@ where [(); S::BYTES_PER_LOGS_BLOOM]:, [(); S::MAX_EXTRA_DATA_BYTES]:, { - let finality_update = get_light_client_finality_update(client).await?; - let block_root = client - .get_beacon_block_root(BlockId::Slot(finality_update.finalized_header.beacon.slot)) + //TODO Should probably parameterise SyncStepArgs as + let finality_update = client + .get_beacon_light_client_finality_update::() .await - .unwrap(); - let bootstrap: LightClientBootstrap< - { S::SYNC_COMMITTEE_SIZE }, - { S::SYNC_COMMITTEE_DEPTH }, - { S::BYTES_PER_LOGS_BLOOM }, - { S::MAX_EXTRA_DATA_BYTES }, - > = get_light_client_bootstrap(client, block_root).await?; + .map_err(|e| eyre::eyre!("Failed to get finality update: {:?}", e))? + .ok_or(eyre::eyre!("Failed to get finality update: None"))? + .data; - let pubkeys_compressed = bootstrap.current_sync_committee.pubkeys; + let block_root = match &finality_update { + LightClientFinalityUpdate::Altair(_) => unimplemented!(), + LightClientFinalityUpdate::Capella(header) => { + header.finalized_header.beacon.canonical_root() + } + LightClientFinalityUpdate::Deneb(header) => header.finalized_header.beacon.canonical_root(), + }; - let attested_state_id = finality_update.attested_header.beacon.state_root; + let bootstrap = client + .get_light_client_bootstrap::(block_root) + .await + .map_err(|e| eyre::eyre!("Failed to get bootstrap: {:?}", e))? + .ok_or(eyre::eyre!("Failed to get bootstrap: None"))? + .data; + + let pubkeys_compressed = &bootstrap.current_sync_committee().pubkeys; + + let attested_state_id = match &finality_update { + LightClientFinalityUpdate::Altair(_) => unimplemented!(), + LightClientFinalityUpdate::Capella(header) => header.attested_header.beacon.state_root, + LightClientFinalityUpdate::Deneb(header) => header.attested_header.beacon.state_root, + }; let fork_version = client - .get_fork(StateId::Root(attested_state_id)) - .await? + .get_beacon_states_fork(StateId::Root(attested_state_id)) + .await + .unwrap() + .unwrap() + .data .current_version; - let genesis_validators_root = client.get_genesis_details().await?.genesis_validators_root; - let fork_data = ForkData { - genesis_validators_root, + + let genesis_validators_root = client + .get_beacon_genesis() + .await + .unwrap() + .data + .genesis_validators_root; + + let domain = T::default_spec().compute_domain( + Domain::SyncCommittee, fork_version, - }; - let domain = compute_domain(DomainType::SyncCommittee, &fork_data)?; + genesis_validators_root, + ); - step_args_from_finality_update(finality_update, pubkeys_compressed, domain).await + step_args_from_finality_update(finality_update, pubkeys_compressed, domain.into()).await } /// Converts a [`LightClientFinalityUpdate`] to a [`SyncStepArgs`] witness. -pub async fn step_args_from_finality_update( - finality_update: LightClientFinalityUpdate< - { S::SYNC_COMMITTEE_SIZE }, - { S::FINALIZED_HEADER_DEPTH }, - { S::BYTES_PER_LOGS_BLOOM }, - { S::MAX_EXTRA_DATA_BYTES }, - >, - pubkeys_compressed: Vector, +pub async fn step_args_from_finality_update( + finality_update: LightClientFinalityUpdate, + pubkeys_compressed: &FixedVector, domain: [u8; 32], ) -> eyre::Result> { let pubkeys_uncompressed = pubkeys_compressed .iter() - .map(|pk| pk.decompressed_bytes()) + .map(|pk| { + bls::PublicKey::uncompress(&pk.serialize()) + .unwrap() + .serialize() + .to_vec() + }) .collect_vec(); - let execution_payload_root = finality_update - .finalized_header - .execution - .clone() - .hash_tree_root()? - .to_vec(); - let execution_payload_branch = finality_update - .finalized_header - .execution_branch - .iter() - .map(|n| n.0.to_vec()) - .collect_vec(); + let (execution_payload_root, execution_payload_branch) = match &finality_update { + LightClientFinalityUpdate::Altair(_) => unimplemented!(), + LightClientFinalityUpdate::Capella(header) => { + let finalized_header = &header.finalized_header; - assert!( - ssz_rs::is_valid_merkle_branch( - Node::try_from(execution_payload_root.as_slice())?, - &execution_payload_branch, - S::EXECUTION_STATE_ROOT_DEPTH, - S::EXECUTION_STATE_ROOT_INDEX, - finality_update.finalized_header.beacon.body_root, - ) - .is_ok(), - "Execution payload merkle proof verification failed" - ); - assert!( - ssz_rs::is_valid_merkle_branch( - finality_update - .finalized_header - .beacon - .clone() - .hash_tree_root() - .unwrap(), - &finality_update - .finality_branch - .iter() - .map(|n| n.as_ref()) - .collect_vec(), - S::FINALIZED_HEADER_DEPTH, - S::FINALIZED_HEADER_INDEX, - finality_update.attested_header.beacon.state_root, - ) - .is_ok(), - "Finality merkle proof verification failed" - ); + ( + finalized_header.execution.tree_hash_root().0.to_vec(), + finalized_header + .execution_branch + .iter() + .map(|n| n.0.to_vec()) + .collect_vec(), + ) + } + LightClientFinalityUpdate::Deneb(header) => { + let finalized_header = &header.finalized_header; + + ( + finalized_header.execution.tree_hash_root().0.to_vec(), + finalized_header + .execution_branch + .iter() + .map(|n| n.0.to_vec()) + .collect_vec(), + ) + } + }; + + // assert!( + // ssz_rs::is_valid_merkle_branch( + // Node::try_from(execution_payload_root.as_slice())?, + // &execution_payload_branch, + // S::EXECUTION_STATE_ROOT_DEPTH, + // S::EXECUTION_STATE_ROOT_INDEX, + // finality_update.finalized_header.beacon.body_root, + // ) + // .is_ok(), + // "Execution payload merkle proof verification failed" + // ); + // assert!( + // ssz_rs::is_valid_merkle_branch( + // finality_update + // .finalized_header + // .beacon + // .clone() + // .hash_tree_root() + // .unwrap(), + // &finality_update + // .finality_branch + // .iter() + // .map(|n| n.as_ref()) + // .collect_vec(), + // S::FINALIZED_HEADER_DEPTH, + // S::FINALIZED_HEADER_INDEX, + // finality_update.attested_header.beacon.state_root, + // ) + // .is_ok(), + // "Finality merkle proof verification failed" + // ); + + let attested_header_beacon = match &finality_update { + LightClientFinalityUpdate::Altair(_) => unimplemented!(), + LightClientFinalityUpdate::Capella(update) => update.attested_header.beacon.clone(), + + LightClientFinalityUpdate::Deneb(update) => update.attested_header.beacon.clone(), + }; + + let finalized_header_beacon = match &finality_update { + LightClientFinalityUpdate::Altair(_) => unimplemented!(), + LightClientFinalityUpdate::Capella(update) => update.finalized_header.beacon.clone(), + + LightClientFinalityUpdate::Deneb(update) => update.finalized_header.beacon.clone(), + }; Ok(SyncStepArgs { signature_compressed: finality_update - .sync_aggregate + .sync_aggregate() .sync_committee_signature - .to_bytes() + .serialize() .to_vec(), pubkeys_uncompressed, pariticipation_bits: finality_update - .sync_aggregate + .sync_aggregate() .sync_committee_bits .iter() - .by_vals() + // .by_vals() .collect_vec(), - attested_header: finality_update.attested_header.beacon, - finalized_header: finality_update.finalized_header.beacon, + attested_header: attested_header_beacon, + finalized_header: finalized_header_beacon, finality_branch: finality_update - .finality_branch - .iter() - .map(|n| n.0.to_vec()) - .collect_vec(), - execution_payload_root: finality_update - .finalized_header - .execution - .clone() - .hash_tree_root() - .unwrap() - .to_vec(), - execution_payload_branch: finality_update - .finalized_header - .execution_branch + .finality_branch() .iter() .map(|n| n.0.to_vec()) .collect_vec(), + execution_payload_root, + execution_payload_branch, domain, _spec: PhantomData, }) diff --git a/rust-toolchain b/rust-toolchain deleted file mode 100644 index 9df1964..0000000 --- a/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly-2024-01-08 From 274ff5139f3d4e12c81bc0883a4deb468daa22db Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 20 Mar 2024 21:37:00 +0000 Subject: [PATCH 03/30] fixed tests --- preprocessor/src/lib.rs | 9 +++++---- preprocessor/src/rotation.rs | 28 ++++++++++++++++++++-------- preprocessor/src/step.rs | 28 ++++++++++++++++++++-------- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/preprocessor/src/lib.rs b/preprocessor/src/lib.rs index aee78a4..53d4bc2 100644 --- a/preprocessor/src/lib.rs +++ b/preprocessor/src/lib.rs @@ -99,11 +99,12 @@ where #[cfg(test)] mod tests { - use eth2::types::StateId; + use eth2::types::{BlockId, StateId}; use eth_types::Testnet; use halo2_base::halo2_proofs::halo2curves::bn256::Bn256; use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; use halo2_base::utils::fs::gen_srs; + use itertools::Itertools; use lightclient_circuits::committee_update_circuit::CommitteeUpdateCircuit; use lightclient_circuits::halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr}; use lightclient_circuits::util::{Eth2ConfigPinning, Halo2ConfigPinning}; @@ -116,7 +117,7 @@ mod tests { use super::*; use reqwest::Url; - use eth2::BeaconNodeHttpClient; + use eth2::{BeaconNodeHttpClient, SensitiveUrl, Timeouts}; use ethereum_types::Domain; use ethereum_types::EthSpec; use ethereum_types::ForkData; @@ -166,7 +167,7 @@ mod tests { .unwrap() .data; - let pubkeys_compressed = &bootstrap.current_sync_committee.pubkeys; + let pubkeys_compressed = &bootstrap.current_sync_committee().pubkeys; let fork_version = client .get_beacon_states_fork(StateId::Head) @@ -207,7 +208,7 @@ mod tests { .unwrap() .unwrap() .data - .current_sync_committee_branch + .current_sync_committee_branch() .into_iter() .map(|n| n.0.to_vec()) .collect_vec(); diff --git a/preprocessor/src/rotation.rs b/preprocessor/src/rotation.rs index f8b0df8..82aa21c 100644 --- a/preprocessor/src/rotation.rs +++ b/preprocessor/src/rotation.rs @@ -112,9 +112,12 @@ where #[cfg(test)] mod tests { + use std::time::Duration; + use super::*; - use beacon_api_client::mainnet::Client as MainnetClient; + use eth2::{SensitiveUrl, Timeouts}; use eth_types::Testnet; + use ethereum_types::MainnetEthSpec; use halo2_base::halo2_proofs::halo2curves::bn256::Bn256; use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; use halo2_base::utils::fs::gen_srs; @@ -124,16 +127,20 @@ mod tests { halo2_base::gates::circuit::CircuitBuilderStage, util::{AppCircuit, Eth2ConfigPinning, Halo2ConfigPinning}, }; - use reqwest::Url; use snark_verifier_sdk::CircuitExt; #[tokio::test] async fn test_rotation_circuit_sepolia() { const CONFIG_PATH: &str = "../lightclient-circuits/config/committee_update_testnet.json"; const K: u32 = 21; - let client = - MainnetClient::new(Url::parse("https://lodestar-sepolia.chainsafe.io").unwrap()); - let witness = fetch_rotation_args::(&client).await.unwrap(); + const URL: &str = "https://lodestar-sepolia.chainsafe.io"; + let client = BeaconNodeHttpClient::new( + SensitiveUrl::parse(URL).unwrap(), + Timeouts::set_all(Duration::from_secs(10)), + ); + let witness = fetch_rotation_args::(&client) + .await + .unwrap(); let pinning = Eth2ConfigPinning::from_path(CONFIG_PATH); let params: ParamsKZG = gen_srs(K); @@ -162,9 +169,14 @@ mod tests { &CommitteeUpdateArgs::::default(), None, ); - let client = - MainnetClient::new(Url::parse("https://lodestar-sepolia.chainsafe.io").unwrap()); - let witness = fetch_rotation_args::(&client).await.unwrap(); + const URL: &str = "https://lodestar-sepolia.chainsafe.io"; + let client = BeaconNodeHttpClient::new( + SensitiveUrl::parse(URL).unwrap(), + Timeouts::set_all(Duration::from_secs(10)), + ); + let witness = fetch_rotation_args::(&client) + .await + .unwrap(); CommitteeUpdateCircuit::::gen_snark_shplonk( ¶ms, diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index 880785c..e3cbe18 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -200,7 +200,11 @@ pub async fn step_args_from_finality_update( #[cfg(test)] mod tests { + use std::time::Duration; + + use eth2::{SensitiveUrl, Timeouts}; use eth_types::Testnet; + use ethereum_types::MainnetEthSpec; use halo2_base::halo2_proofs::halo2curves::bn256::Bn256; use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; use halo2_base::utils::fs::gen_srs; @@ -212,16 +216,19 @@ mod tests { use snark_verifier_sdk::CircuitExt; use super::*; - use beacon_api_client::mainnet::Client as MainnetClient; use reqwest::Url; #[tokio::test] async fn test_sync_circuit_sepolia() { const K: u32 = 21; - let client = - MainnetClient::new(Url::parse("https://lodestar-sepolia.chainsafe.io").unwrap()); - - let witness = fetch_step_args::(&client).await.unwrap(); + const URL: &str = "https://lodestar-sepolia.chainsafe.io"; + let client = BeaconNodeHttpClient::new( + SensitiveUrl::parse(URL).unwrap(), + Timeouts::set_all(Duration::from_secs(10)), + ); + let witness = fetch_step_args::(&client) + .await + .unwrap(); let params: ParamsKZG = gen_srs(K); let circuit = StepCircuit::::create_circuit( @@ -249,9 +256,14 @@ mod tests { &SyncStepArgs::::default(), None, ); - let client = - MainnetClient::new(Url::parse("https://lodestar-sepolia.chainsafe.io").unwrap()); - let witness = fetch_step_args::(&client).await.unwrap(); + const URL: &str = "https://lodestar-sepolia.chainsafe.io"; + let client = BeaconNodeHttpClient::new( + SensitiveUrl::parse(URL).unwrap(), + Timeouts::set_all(Duration::from_secs(10)), + ); + let witness = fetch_step_args::(&client) + .await + .unwrap(); StepCircuit::::gen_snark_shplonk( ¶ms, From 1ffd2e60f3c3f3bc432b5189420e589a586c7d40 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 20 Mar 2024 21:50:48 +0000 Subject: [PATCH 04/30] tests for preprocessor work --- preprocessor/Cargo.toml | 1 - preprocessor/src/lib.rs | 5 +---- preprocessor/src/step.rs | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/preprocessor/Cargo.toml b/preprocessor/Cargo.toml index 91a38c6..bdf4848 100644 --- a/preprocessor/Cargo.toml +++ b/preprocessor/Cargo.toml @@ -47,5 +47,4 @@ snark-verifier-sdk.workspace = true ark-std.workspace = true [features] -# test-gen = ["ethereum-consensus", "blst"] test-gen = [] \ No newline at end of file diff --git a/preprocessor/src/lib.rs b/preprocessor/src/lib.rs index 53d4bc2..a00b862 100644 --- a/preprocessor/src/lib.rs +++ b/preprocessor/src/lib.rs @@ -115,12 +115,9 @@ mod tests { use snark_verifier_sdk::CircuitExt; use super::*; - use reqwest::Url; - use eth2::{BeaconNodeHttpClient, SensitiveUrl, Timeouts}; + use eth2::{SensitiveUrl, Timeouts}; use ethereum_types::Domain; - use ethereum_types::EthSpec; - use ethereum_types::ForkData; use ethereum_types::MainnetEthSpec; use std::time::Duration; diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index e3cbe18..8a9b4e4 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -216,7 +216,6 @@ mod tests { use snark_verifier_sdk::CircuitExt; use super::*; - use reqwest::Url; #[tokio::test] async fn test_sync_circuit_sepolia() { From ef5b74039d4705cc5538c6a4312a74e7e63cc127 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 20 Mar 2024 22:28:06 +0000 Subject: [PATCH 05/30] in progress: tixing test-utils --- Cargo.toml | 1 + prover/Cargo.toml | 1 - test-utils/Cargo.toml | 11 ++- test-utils/src/lib.rs | 184 +++++++++++++++++++---------------- test-utils/src/test_types.rs | 7 -- 5 files changed, 108 insertions(+), 96 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8869447..cc3042e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,6 +75,7 @@ ssz_rs = "0.9" ethereum-types = { package = "types", git = "https://github.com/eserilev/lighthouse/", branch = "capella_deneb_light_client_types", default-features = false} tree_hash = { version = "0.5" } eth2 = { package = "eth2", git = "https://github.com/eserilev/lighthouse/", branch = "capella_deneb_light_client_types" } +ethereum_ssz = "0.5.3" # crypto group = "0.13" diff --git a/prover/Cargo.toml b/prover/Cargo.toml index da8a49b..0d8faa4 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -47,7 +47,6 @@ ethers = { version = "2.0.7", default_features = false, features = [ ] } primitive-types = "0.12.2" reqwest = "0.11.22" -beacon-api-client.workspace = true ethereum-consensus-types.workspace = true ssz_rs.workspace = true diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 0536fb8..58e9cc9 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -5,12 +5,17 @@ edition = "2021" [dependencies] lightclient-circuits = { workspace = true } -ethereum-consensus-types = { workspace = true } eth-types = { workspace = true } -ssz_rs = { workspace = true } halo2curves = { workspace = true } halo2-base = { workspace = true } + +ethereum-types = {workspace = true, default-features = false } +eth2.workspace = true +tree_hash.workspace = true +ethereum_ssz = { workspace = true, default-features = false } + + itertools = "0.11.0" hex = "0.4.3" serde = { version = "1.0.130", features = ["derive"] } @@ -18,6 +23,6 @@ anyhow = "1.0.75" ethers = "2.0.10" test-utils = { git = "https://github.com/ChainSafe/ethereum-consensus-types", branch = "capella" } - snap = "1.1.0" serde_yaml = "0.9.19" +blst = { version = "0.3.11", default-features = false, features = [ "portable", "no-threads" ]} \ No newline at end of file diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index cd3f810..f406405 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -5,26 +5,33 @@ #![allow(incomplete_features)] #![feature(generic_const_exprs)] -mod execution_payload_header; +// mod execution_payload_header; mod test_types; - -use crate::execution_payload_header::ExecutionPayloadHeader; -use crate::test_types::{ByteVector, TestMeta, TestStep}; +// use crate::execution_payload_header::ExecutionPayloadHeader; +use crate::test_types::{TestMeta, TestStep}; +use blst::min_pk as bls; use eth_types::{Minimal, LIMB_BITS}; -use ethereum_consensus_types::presets::minimal::{ - LightClientBootstrap, LightClientUpdateCapella, BYTES_PER_LOGS_BLOOM, MAX_EXTRA_DATA_BYTES, +// use ethereum_consensus_types::presets::minimal::{ +// LightClientBootstrap, LightClientUpdateCapella, BYTES_PER_LOGS_BLOOM, MAX_EXTRA_DATA_BYTES, +// }; + +use ethereum_types::{ + BeaconBlockHeader, EthSpec, FixedVector, ForkData, Hash256, LightClientBootstrap, + LightClientBootstrapCapella, LightClientFinalityUpdate, LightClientFinalityUpdateCapella, + LightClientFinalityUpdateDeneb, LightClientUpdateCapella, MinimalEthSpec, PublicKeyBytes, + SyncCommittee, }; -use ethereum_consensus_types::signing::{compute_domain, DomainType}; -use ethereum_consensus_types::{BeaconBlockHeader, SyncCommittee}; -use ethereum_consensus_types::{ForkData, Root}; use itertools::Itertools; use lightclient_circuits::poseidon::poseidon_committee_commitment_from_uncompressed; use lightclient_circuits::witness::{CommitteeUpdateArgs, SyncStepArgs}; -use ssz_rs::prelude::*; -use ssz_rs::Merkleized; -use std::ops::Deref; +use serde::Deserialize; +use tree_hash::TreeHash; + +use std::fs::File; +use std::io::Read; use std::path::Path; -use test_utils::{load_snappy_ssz, load_yaml}; +use std::sync::Arc; +// use test_utils::{load_snappy_ssz, load_yaml}; pub(crate) const U256_BYTE_COUNT: usize = 32; @@ -32,13 +39,18 @@ pub(crate) const U256_BYTE_COUNT: usize = 32; pub fn get_initial_sync_committee_poseidon( path: &Path, ) -> anyhow::Result<(usize, ethers::prelude::U256)> { - let bootstrap: LightClientBootstrap = + let bootstrap: LightClientBootstrapCapella = load_snappy_ssz(path.join("bootstrap.ssz_snappy").to_str().unwrap()).unwrap(); let pubkeys_uncompressed = bootstrap .current_sync_committee .pubkeys .iter() - .map(|pk| pk.decompressed_bytes()) + .map(|pk| { + bls::PublicKey::uncompress(&pk.serialize()) + .unwrap() + .serialize() + .to_vec() + }) .collect_vec(); let committee_poseidon = poseidon_committee_commitment_from_uncompressed(&pubkeys_uncompressed, LIMB_BITS); @@ -49,9 +61,9 @@ pub fn get_initial_sync_committee_poseidon Root { +pub fn validators_root_from_test_path(path: &Path) -> Hash256 { let meta: TestMeta = load_yaml(path.join("meta.yaml").to_str().unwrap()); - Root::try_from( + Hash256::try_from( hex::decode(meta.genesis_validators_root.trim_start_matches("0x")) .unwrap() .as_slice(), @@ -61,16 +73,14 @@ pub fn validators_root_from_test_path(path: &Path) -> Root { // Load the updates for a given test and only includes the first sequence of steps that Spectre can perform // e.g. the the steps are cut at the first `ForceUpdate` step -pub fn valid_updates_from_test_path( - path: &Path, -) -> Vec> { +pub fn valid_updates_from_test_path(path: &Path) -> Vec> { let steps: Vec = load_yaml(path.join("steps.yaml").to_str().unwrap()); let updates = steps .iter() .take_while(|step| matches!(step, TestStep::ProcessUpdate { .. })) .filter_map(|step| match step { TestStep::ProcessUpdate { update, .. } => { - let update: LightClientUpdateCapella = load_snappy_ssz( + let update: LightClientUpdateCapella = load_snappy_ssz( path.join(format!("{}.ssz_snappy", update)) .to_str() .unwrap(), @@ -84,10 +94,52 @@ pub fn valid_updates_from_test_path( updates } +pub fn load_yaml Deserialize<'de>>(path: &str) -> T { + let mut file = File::open(path).unwrap_or_else(|_| { + panic!( + "File {} does not exist from dir {:?}", + path, + std::env::current_dir().unwrap() + ) + }); + let deserializer = serde_yaml::Deserializer::from_reader(&mut file); + let test_case: Result = + serde_yaml::with::singleton_map_recursive::deserialize(deserializer); + match test_case { + Ok(test_case) => test_case, + Err(err) => { + let content = std::fs::read_to_string(path).unwrap(); + panic!("{err} from {content} at {path:?}") + } + } +} + +pub fn load_snappy_ssz_bytes(path: &Path) -> Vec { + let mut file = File::open(path).unwrap(); + let mut data = vec![]; + file.read_to_end(&mut data).unwrap(); + + let mut decoder = snap::raw::Decoder::new(); + decoder.decompress_vec(&data).unwrap() +} + +pub fn load_snappy_ssz(path: &str) -> Option { + let path = Path::new(path); + if !path.exists() { + // panic!("Path to snappy_ssz file does not exist: {:?} from dir {:?}", path, std::env::current_dir()); + return None; + } + let buffer = load_snappy_ssz_bytes(path); + + let result = ::from_ssz_bytes(&buffer).unwrap(); + + Some(result) +} + pub fn read_test_files_and_gen_witness( path: &Path, ) -> (SyncStepArgs, CommitteeUpdateArgs) { - let bootstrap: LightClientBootstrap = + let bootstrap: LightClientBootstrapCapella = load_snappy_ssz(path.join("bootstrap.ssz_snappy").to_str().unwrap()).unwrap(); let genesis_validators_root = validators_root_from_test_path(path); @@ -102,18 +154,17 @@ pub fn read_test_files_and_gen_witness( let mut sync_committee_branch = updates[0] .next_sync_committee_branch .iter() - .map(|n| n.deref().to_vec()) + .map(|n| n.0.to_vec()) .collect_vec(); - let agg_pubkeys_compressed = updates[0] + let agg_pk = updates[0] .next_sync_committee .aggregate_pubkey - .to_bytes() + .tree_hash_root() + .0 .to_vec(); - let mut agg_pk: ByteVector<48> = ByteVector(Vector::try_from(agg_pubkeys_compressed).unwrap()); - - sync_committee_branch.insert(0, agg_pk.hash_tree_root().unwrap().deref().to_vec()); + sync_committee_branch.insert(0, agg_pk); let rotation_wit = CommitteeUpdateArgs:: { pubkeys_compressed: updates[0] @@ -121,7 +172,7 @@ pub fn read_test_files_and_gen_witness( .pubkeys .iter() .cloned() - .map(|pk| pk.to_bytes().to_vec()) + .map(|pk| pk.serialize().to_vec()) .collect_vec(), finalized_header: sync_wit.attested_header.clone(), sync_committee_branch, @@ -131,15 +182,15 @@ pub fn read_test_files_and_gen_witness( } fn to_sync_ciruit_witness( - committee: SyncCommittee, - light_client_update: &LightClientUpdateCapella, - genesis_validators_root: Root, + committee: Arc>, + light_client_update: &LightClientUpdateCapella, + genesis_validators_root: Hash256, ) -> SyncStepArgs { let mut args = SyncStepArgs:: { signature_compressed: light_client_update .sync_aggregate .sync_committee_signature - .to_bytes() + .serialize() .to_vec(), ..Default::default() }; @@ -147,73 +198,36 @@ fn to_sync_ciruit_witness( let pubkeys_uncompressed = committee .pubkeys .iter() - .map(|pk| pk.decompressed_bytes()) + .map(|pk| { + bls::PublicKey::uncompress(&pk.serialize()) + .unwrap() + .serialize() + .to_vec() + }) .collect_vec(); args.pubkeys_uncompressed = pubkeys_uncompressed; args.pariticipation_bits = light_client_update .sync_aggregate .sync_committee_bits .iter() - .map(|b| *b) + .map(|b| b) .collect(); args.attested_header = BeaconBlockHeader { slot: light_client_update.attested_header.beacon.slot, proposer_index: light_client_update.attested_header.beacon.proposer_index, - parent_root: Node::try_from( - light_client_update - .attested_header - .beacon - .parent_root - .as_ref(), - ) - .unwrap(), - state_root: Node::try_from( - light_client_update - .attested_header - .beacon - .state_root - .as_ref(), - ) - .unwrap(), - body_root: Node::try_from( - light_client_update - .attested_header - .beacon - .body_root - .as_ref(), - ) - .unwrap(), + parent_root: light_client_update.attested_header.beacon.parent_root, + state_root: light_client_update.attested_header.beacon.state_root, + body_root: light_client_update.attested_header.beacon.body_root, }; args.finalized_header = BeaconBlockHeader { slot: light_client_update.finalized_header.beacon.slot, proposer_index: light_client_update.finalized_header.beacon.proposer_index, - parent_root: Node::try_from( - light_client_update - .finalized_header - .beacon - .parent_root - .as_ref(), - ) - .unwrap(), - state_root: Node::try_from( - light_client_update - .finalized_header - .beacon - .state_root - .as_ref(), - ) - .unwrap(), - body_root: Node::try_from( - light_client_update - .finalized_header - .beacon - .body_root - .as_ref(), - ) - .unwrap(), + parent_root: light_client_update.finalized_header.beacon.parent_root, + state_root: light_client_update.finalized_header.beacon.state_root, + body_root: light_client_update.finalized_header.beacon.body_root, }; let fork_data = ForkData { - fork_version: [3, 0, 0, 1], + current_version: [3, 0, 0, 1], genesis_validators_root, }; let signing_domain = compute_domain(DomainType::SyncCommittee, &fork_data).unwrap(); @@ -243,7 +257,7 @@ fn to_sync_ciruit_witness( args.finality_branch = light_client_update .finality_branch .iter() - .map(|b| b.deref().to_vec()) + .map(|b| b.0.to_vec()) .collect(); args } diff --git a/test-utils/src/test_types.rs b/test-utils/src/test_types.rs index 0fc3105..f0c8b3e 100644 --- a/test-utils/src/test_types.rs +++ b/test-utils/src/test_types.rs @@ -43,10 +43,3 @@ pub struct RootAtSlot { pub beacon_root: String, pub execution_root: String, } - -// TODO: remove this once we have a better way to handle the `ssz_rs` dependency -#[derive(Debug, Default, Clone, PartialEq, SimpleSerialize, Eq)] -pub struct ByteVector(pub Vector); -#[derive(Default, Debug, Clone, PartialEq, Eq, SimpleSerialize)] -pub struct ByteList(pub List); -pub type ExecutionAddress = ByteVector<20>; From e8ad315ed460645950e07bb4f35939bb90f10ed9 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 20 Mar 2024 22:39:55 +0000 Subject: [PATCH 06/30] fixed test-utils --- test-utils/Cargo.toml | 1 - test-utils/src/execution_payload_header.rs | 73 ---------------------- test-utils/src/lib.rs | 57 +++++++---------- test-utils/src/test_types.rs | 2 - 4 files changed, 23 insertions(+), 110 deletions(-) delete mode 100644 test-utils/src/execution_payload_header.rs diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 58e9cc9..47bbb1d 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -22,7 +22,6 @@ serde = { version = "1.0.130", features = ["derive"] } anyhow = "1.0.75" ethers = "2.0.10" -test-utils = { git = "https://github.com/ChainSafe/ethereum-consensus-types", branch = "capella" } snap = "1.1.0" serde_yaml = "0.9.19" blst = { version = "0.3.11", default-features = false, features = [ "portable", "no-threads" ]} \ No newline at end of file diff --git a/test-utils/src/execution_payload_header.rs b/test-utils/src/execution_payload_header.rs deleted file mode 100644 index aefdb50..0000000 --- a/test-utils/src/execution_payload_header.rs +++ /dev/null @@ -1,73 +0,0 @@ -// The Licensed Work is (c) 2023 ChainSafe -// Code: https://github.com/ChainSafe/Spectre -// SPDX-License-Identifier: LGPL-3.0-only - -use crate::{ - test_types::{ByteList, ByteVector, ExecutionAddress}, - U256_BYTE_COUNT, -}; -use ssz_rs::prelude::*; -use std::ops::Deref; -#[derive(Default, Debug, Clone, SimpleSerialize, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct ExecutionPayloadHeader< - const BYTES_PER_LOGS_BLOOM: usize, - const MAX_EXTRA_DATA_BYTES: usize, -> { - pub parent_hash: Node, - pub fee_recipient: ExecutionAddress, - pub state_root: Node, - pub receipts_root: Node, - pub logs_bloom: ByteVector, - pub prev_randao: Node, - pub block_number: u64, - pub gas_limit: u64, - pub gas_used: u64, - pub timestamp: u64, - pub extra_data: ByteList, - pub base_fee_per_gas: U256, - pub block_hash: Node, - pub transactions_root: Node, - pub withdrawals_root: Node, -} - -impl - From< - ethereum_consensus_types::light_client::ExecutionPayloadHeader< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - >, - > for ExecutionPayloadHeader -{ - fn from( - header: ethereum_consensus_types::light_client::ExecutionPayloadHeader< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - >, - ) -> Self { - Self { - parent_hash: header.parent_hash, - fee_recipient: ByteVector( - Vector::try_from(header.fee_recipient.0.as_ref().to_vec()).unwrap(), - ), - state_root: header.state_root.deref().try_into().unwrap(), - receipts_root: header.receipts_root.deref().try_into().unwrap(), - logs_bloom: ByteVector( - Vector::try_from(header.logs_bloom.0.as_ref().to_vec()).unwrap(), - ), - prev_randao: header.prev_randao, - block_number: header.block_number, - gas_limit: header.gas_limit, - gas_used: header.gas_used, - timestamp: header.timestamp, - extra_data: ByteList(List::try_from(header.extra_data.0.as_ref().to_vec()).unwrap()), - base_fee_per_gas: U256::from_le_bytes::( - header.base_fee_per_gas.as_le_slice().try_into().unwrap(), - ), - block_hash: header.block_hash, - transactions_root: header.transactions_root, - - withdrawals_root: header.withdrawals_root, - } - } -} diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index f406405..55d54a1 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -5,22 +5,15 @@ #![allow(incomplete_features)] #![feature(generic_const_exprs)] -// mod execution_payload_header; mod test_types; -// use crate::execution_payload_header::ExecutionPayloadHeader; use crate::test_types::{TestMeta, TestStep}; use blst::min_pk as bls; use eth_types::{Minimal, LIMB_BITS}; -// use ethereum_consensus_types::presets::minimal::{ -// LightClientBootstrap, LightClientUpdateCapella, BYTES_PER_LOGS_BLOOM, MAX_EXTRA_DATA_BYTES, -// }; - use ethereum_types::{ - BeaconBlockHeader, EthSpec, FixedVector, ForkData, Hash256, LightClientBootstrap, - LightClientBootstrapCapella, LightClientFinalityUpdate, LightClientFinalityUpdateCapella, - LightClientFinalityUpdateDeneb, LightClientUpdateCapella, MinimalEthSpec, PublicKeyBytes, - SyncCommittee, + BeaconBlockHeader, Domain, EthSpec, ExecutionPayloadHeader, ForkData, Hash256, + LightClientBootstrapCapella, LightClientUpdateCapella, MinimalEthSpec, SyncCommittee, }; +use ethers::types::H256; use itertools::Itertools; use lightclient_circuits::poseidon::poseidon_committee_commitment_from_uncompressed; use lightclient_circuits::witness::{CommitteeUpdateArgs, SyncStepArgs}; @@ -31,9 +24,6 @@ use std::fs::File; use std::io::Read; use std::path::Path; use std::sync::Arc; -// use test_utils::{load_snappy_ssz, load_yaml}; - -pub(crate) const U256_BYTE_COUNT: usize = 32; // loads the boostrap on the path and return the initial sync committee poseidon and sync period pub fn get_initial_sync_committee_poseidon( @@ -61,14 +51,14 @@ pub fn get_initial_sync_committee_poseidon Hash256 { +pub fn validators_root_from_test_path(path: &Path) -> H256 { let meta: TestMeta = load_yaml(path.join("meta.yaml").to_str().unwrap()); - Hash256::try_from( + H256( hex::decode(meta.genesis_validators_root.trim_start_matches("0x")) .unwrap() - .as_slice(), + .try_into() + .unwrap(), ) - .unwrap() } // Load the updates for a given test and only includes the first sequence of steps that Spectre can perform @@ -181,7 +171,7 @@ pub fn read_test_files_and_gen_witness( (sync_wit, rotation_wit) } -fn to_sync_ciruit_witness( +fn to_sync_ciruit_witness( committee: Arc>, light_client_update: &LightClientUpdateCapella, genesis_validators_root: Hash256, @@ -230,8 +220,13 @@ fn to_sync_ciruit_witness( current_version: [3, 0, 0, 1], genesis_validators_root, }; - let signing_domain = compute_domain(DomainType::SyncCommittee, &fork_data).unwrap(); - args.domain = signing_domain; + + let domain = MinimalEthSpec::default_spec().compute_domain( + Domain::SyncCommittee, + [3, 0, 0, 1], + genesis_validators_root, + ); + args.domain = domain.into(); args.execution_payload_branch = light_client_update .finalized_header .execution_branch @@ -239,20 +234,14 @@ fn to_sync_ciruit_witness( .map(|b| b.0.as_ref().to_vec()) .collect(); args.execution_payload_root = { - let mut execution_payload_header: ExecutionPayloadHeader< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - > = light_client_update - .finalized_header - .execution - .clone() - .into(); - - execution_payload_header - .hash_tree_root() - .unwrap() - .deref() - .to_vec() + let mut execution_payload_header: ExecutionPayloadHeader = + light_client_update + .finalized_header + .execution + .clone() + .into(); + + execution_payload_header.tree_hash_root().0.to_vec() }; args.finality_branch = light_client_update .finality_branch diff --git a/test-utils/src/test_types.rs b/test-utils/src/test_types.rs index f0c8b3e..0f90606 100644 --- a/test-utils/src/test_types.rs +++ b/test-utils/src/test_types.rs @@ -2,8 +2,6 @@ // Code: https://github.com/ChainSafe/Spectre // SPDX-License-Identifier: LGPL-3.0-only -use ssz_rs::prelude::*; - #[allow(dead_code)] #[derive(Debug, serde::Deserialize)] pub struct TestMeta { From 857e247b056180c3cdd4266ee93f6a7d38af457e Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 20 Mar 2024 23:04:25 +0000 Subject: [PATCH 07/30] prover wip --- prover/Cargo.toml | 8 ++++++-- prover/src/rpc.rs | 9 +++++---- prover/src/utils.rs | 44 +++++++++++++++++++++----------------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 0d8faa4..4872bd6 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -47,8 +47,12 @@ ethers = { version = "2.0.7", default_features = false, features = [ ] } primitive-types = "0.12.2" reqwest = "0.11.22" -ethereum-consensus-types.workspace = true -ssz_rs.workspace = true + + +ethereum-types = {workspace = true, default-features = false } +eth2.workspace = true +tree_hash.workspace = true +ethereum_ssz = { workspace = true, default-features = false } [features] default = [] diff --git a/prover/src/rpc.rs b/prover/src/rpc.rs index edc78bf..1476e38 100644 --- a/prover/src/rpc.rs +++ b/prover/src/rpc.rs @@ -4,6 +4,7 @@ use ark_std::{end_timer, start_timer}; use axum::{http::StatusCode, response::IntoResponse, routing::post, Router}; +use ethereum_types::{EthSpec, LightClientUpdate}; use ethers::prelude::*; use jsonrpc_v2::{Data, RequestObject as JsonRpcRequestObject}; use jsonrpc_v2::{Error as JsonRpcError, Params}; @@ -27,7 +28,7 @@ use crate::rpc_api::{ RPC_EVM_PROOF_STEP_CIRCUIT_COMPRESSED, }; -pub(crate) fn jsonrpc_server( +pub(crate) fn jsonrpc_server( state: ProverState, ) -> JsonRpcServer where @@ -43,7 +44,7 @@ where .with_data(Data::new(state)) .with_method( RPC_EVM_PROOF_COMMITTEE_UPDATE_CIRCUIT_COMPRESSED, - gen_evm_proof_committee_update_handler::, + gen_evm_proof_committee_update_handler::, ) .with_method( RPC_EVM_PROOF_STEP_CIRCUIT_COMPRESSED, @@ -52,7 +53,7 @@ where .finish_unwrapped() } -pub(crate) async fn gen_evm_proof_committee_update_handler( +pub(crate) async fn gen_evm_proof_committee_update_handler( Data(state): Data, Params(params): Params, ) -> Result @@ -78,7 +79,7 @@ where light_client_update, } = params; - let update = ssz_rs::deserialize(&light_client_update)?; + let update = LightClientUpdate::from_ssz_bytes(&light_client_update)?; let witness = rotation_args_from_update(&update).await?; let params = state.params.get(state.committee_update.degree()).unwrap(); diff --git a/prover/src/utils.rs b/prover/src/utils.rs index e24670b..bd355cd 100644 --- a/prover/src/utils.rs +++ b/prover/src/utils.rs @@ -2,54 +2,52 @@ // Code: https://github.com/ChainSafe/Spectre // SPDX-License-Identifier: LGPL-3.0-only -use std::{ops::Deref, sync::Arc}; +use std::{ops::Deref, sync::Arc, time::Duration}; -use beacon_api_client::{BlockId, VersionedValue}; +use eth2::{types::BlockId, BeaconNodeHttpClient, SensitiveUrl, Timeouts}; use eth_types::LIMB_BITS; -use ethereum_consensus_types::LightClientBootstrap; +use ethereum_types::{LightClientBootstrap, MainnetEthSpec}; use itertools::Itertools; use lightclient_circuits::poseidon::poseidon_committee_commitment_from_uncompressed; -use ssz_rs::Merkleized; use url::Url; -use beacon_api_client::mainnet::Client as MainnetBeaconClient; - use crate::args::UtilsCmd; pub(crate) async fn utils_cli(method: UtilsCmd) -> eyre::Result<()> { match method { UtilsCmd::CommitteePoseidon { beacon_api } => { let reqwest_client = reqwest::Client::new(); - let beacon_client = Arc::new(MainnetBeaconClient::new_with_client( - reqwest_client.clone(), - Url::parse(&beacon_api).unwrap(), + let beacon_client = Arc::new(BeaconNodeHttpClient::new( + SensitiveUrl::parse(&beacon_api).unwrap(), + Timeouts::set_all(Duration::from_secs(10)), )); - let block = beacon_client - .get_beacon_block_root(BlockId::Head) + + let block_root = beacon_client + .get_beacon_blocks_root(BlockId::Head) .await - .unwrap(); - let route = format!("eth/v1/beacon/light_client/bootstrap/{block:?}"); - let mut bootstrap = match beacon_client - .get::>>(&route) + .unwrap() + .unwrap() + .data + .root; + + let bootstrap = beacon_client + .get_light_client_bootstrap::(block_root) .await - { - Ok(v) => v.data, - Err(e) => { - return Err(eyre::eyre!("Failed to fetch bootstrap: {}", e)); - } - }; + .map_err(|e| eyre::eyre!("Failed to get bootstrap: {:?}", e))? + .ok_or(eyre::eyre!("Failed to get bootstrap: None"))? + .data; let sync_period = bootstrap.header.beacon.slot / (32 * 256); println!("Sync period: {}", sync_period); let pubkeys_uncompressed = bootstrap - .current_sync_committee + .current_sync_committee() .pubkeys .iter() .map(|pk| pk.decompressed_bytes()) .collect_vec(); let ssz_root = bootstrap - .current_sync_committee + .current_sync_committee() .pubkeys .hash_tree_root() .unwrap(); From 9a749e92c9668ca2f8364f1abecdbaa8ad032672 Mon Sep 17 00:00:00 2001 From: eric Date: Wed, 20 Mar 2024 23:04:40 +0000 Subject: [PATCH 08/30] lint --- test-utils/src/lib.rs | 84 +++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index 55d54a1..d250936 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -84,48 +84,6 @@ pub fn valid_updates_from_test_path(path: &Path) -> Vec Deserialize<'de>>(path: &str) -> T { - let mut file = File::open(path).unwrap_or_else(|_| { - panic!( - "File {} does not exist from dir {:?}", - path, - std::env::current_dir().unwrap() - ) - }); - let deserializer = serde_yaml::Deserializer::from_reader(&mut file); - let test_case: Result = - serde_yaml::with::singleton_map_recursive::deserialize(deserializer); - match test_case { - Ok(test_case) => test_case, - Err(err) => { - let content = std::fs::read_to_string(path).unwrap(); - panic!("{err} from {content} at {path:?}") - } - } -} - -pub fn load_snappy_ssz_bytes(path: &Path) -> Vec { - let mut file = File::open(path).unwrap(); - let mut data = vec![]; - file.read_to_end(&mut data).unwrap(); - - let mut decoder = snap::raw::Decoder::new(); - decoder.decompress_vec(&data).unwrap() -} - -pub fn load_snappy_ssz(path: &str) -> Option { - let path = Path::new(path); - if !path.exists() { - // panic!("Path to snappy_ssz file does not exist: {:?} from dir {:?}", path, std::env::current_dir()); - return None; - } - let buffer = load_snappy_ssz_bytes(path); - - let result = ::from_ssz_bytes(&buffer).unwrap(); - - Some(result) -} - pub fn read_test_files_and_gen_witness( path: &Path, ) -> (SyncStepArgs, CommitteeUpdateArgs) { @@ -250,3 +208,45 @@ fn to_sync_ciruit_witness( .collect(); args } + +pub fn load_yaml Deserialize<'de>>(path: &str) -> T { + let mut file = File::open(path).unwrap_or_else(|_| { + panic!( + "File {} does not exist from dir {:?}", + path, + std::env::current_dir().unwrap() + ) + }); + let deserializer = serde_yaml::Deserializer::from_reader(&mut file); + let test_case: Result = + serde_yaml::with::singleton_map_recursive::deserialize(deserializer); + match test_case { + Ok(test_case) => test_case, + Err(err) => { + let content = std::fs::read_to_string(path).unwrap(); + panic!("{err} from {content} at {path:?}") + } + } +} + +pub fn load_snappy_ssz_bytes(path: &Path) -> Vec { + let mut file = File::open(path).unwrap(); + let mut data = vec![]; + file.read_to_end(&mut data).unwrap(); + + let mut decoder = snap::raw::Decoder::new(); + decoder.decompress_vec(&data).unwrap() +} + +pub fn load_snappy_ssz(path: &str) -> Option { + let path = Path::new(path); + if !path.exists() { + // panic!("Path to snappy_ssz file does not exist: {:?} from dir {:?}", path, std::env::current_dir()); + return None; + } + let buffer = load_snappy_ssz_bytes(path); + + let result = ::from_ssz_bytes(&buffer).unwrap(); + + Some(result) +} From beb108e1ce969eb3b948b40bb8289fdb5fe87dd6 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Tue, 26 Mar 2024 11:10:41 -0400 Subject: [PATCH 09/30] switch to lighthouse unstable branch --- Cargo.toml | 4 ++-- prover/src/main.rs | 5 +++-- prover/src/rpc.rs | 4 ++-- prover/src/utils.rs | 17 ++++++++++------- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cc3042e..e62d0d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,9 +72,9 @@ beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus.g ssz_rs = "0.9" -ethereum-types = { package = "types", git = "https://github.com/eserilev/lighthouse/", branch = "capella_deneb_light_client_types", default-features = false} +ethereum-types = { package = "types", git = "https://github.com/sigp/lighthouse/", branch = "unstable", default-features = false} tree_hash = { version = "0.5" } -eth2 = { package = "eth2", git = "https://github.com/eserilev/lighthouse/", branch = "capella_deneb_light_client_types" } +eth2 = { package = "eth2", git = "https://github.com/sigp/lighthouse/", branch = "unstable" } ethereum_ssz = "0.5.3" # crypto diff --git a/prover/src/main.rs b/prover/src/main.rs index 7365484..fda9972 100644 --- a/prover/src/main.rs +++ b/prover/src/main.rs @@ -13,6 +13,7 @@ mod utils; use crate::{cli::spec_app, rpc::run_rpc}; use args::Cli; use clap::Parser; +use ethereum_types::MainnetEthSpec; use utils::utils_cli; mod args; @@ -26,7 +27,7 @@ async fn app(options: Cli) -> eyre::Result<()> { } => { match spec { args::Spec::Testnet => { - run_rpc::( + run_rpc::( port.parse().unwrap(), options.args.config_dir, build_dir, @@ -35,7 +36,7 @@ async fn app(options: Cli) -> eyre::Result<()> { .await } args::Spec::Mainnet => { - run_rpc::( + run_rpc::( port.parse().unwrap(), options.args.config_dir, build_dir, diff --git a/prover/src/rpc.rs b/prover/src/rpc.rs index 1476e38..74546c9 100644 --- a/prover/src/rpc.rs +++ b/prover/src/rpc.rs @@ -181,7 +181,7 @@ where )?) } -pub async fn run_rpc( +pub async fn run_rpc( port: usize, config_dir: impl AsRef, build_dir: impl AsRef, @@ -200,7 +200,7 @@ where let timer = start_timer!(|| "Load Prover State and Context"); let state = ProverState::new::(config_dir.as_ref(), build_dir.as_ref(), concurrency); end_timer!(timer); - let rpc_server = Arc::new(jsonrpc_server::(state)); + let rpc_server = Arc::new(jsonrpc_server::(state)); let router = Router::new() .route("/rpc", post(handler)) .with_state(rpc_server); diff --git a/prover/src/utils.rs b/prover/src/utils.rs index bd355cd..963e172 100644 --- a/prover/src/utils.rs +++ b/prover/src/utils.rs @@ -9,6 +9,7 @@ use eth_types::LIMB_BITS; use ethereum_types::{LightClientBootstrap, MainnetEthSpec}; use itertools::Itertools; use lightclient_circuits::poseidon::poseidon_committee_commitment_from_uncompressed; +use tree_hash::TreeHash; use url::Url; use crate::args::UtilsCmd; @@ -37,7 +38,12 @@ pub(crate) async fn utils_cli(method: UtilsCmd) -> eyre::Result<()> { .ok_or(eyre::eyre!("Failed to get bootstrap: None"))? .data; - let sync_period = bootstrap.header.beacon.slot / (32 * 256); + let sync_period = match bootstrap { + LightClientBootstrap::Altair(_) => unimplemented!("Altair not implemented"), + LightClientBootstrap::Capella(bootstrap) => bootstrap.header.beacon.slot, + LightClientBootstrap::Deneb(bootstrap) => bootstrap.header.beacon.slot, + } / (32 * 256); + println!("Sync period: {}", sync_period); let pubkeys_uncompressed = bootstrap .current_sync_committee() @@ -46,12 +52,9 @@ pub(crate) async fn utils_cli(method: UtilsCmd) -> eyre::Result<()> { .map(|pk| pk.decompressed_bytes()) .collect_vec(); - let ssz_root = bootstrap - .current_sync_committee() - .pubkeys - .hash_tree_root() - .unwrap(); - println!("SSZ root: {:?}", hex::encode(ssz_root.deref())); + let ssz_root = bootstrap.current_sync_committee().pubkeys.tree_hash_root(); + + println!("SSZ root: {:?}", hex::encode(ssz_root.0)); let mut committee_poseidon = poseidon_committee_commitment_from_uncompressed(&pubkeys_uncompressed, LIMB_BITS) From 1da5c959012471b37c1a28a75cef039eb00eb533 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Tue, 26 Mar 2024 12:22:37 -0400 Subject: [PATCH 10/30] Add fork version to RPC request --- prover/Cargo.toml | 1 + prover/src/rpc.rs | 40 +++++++++++++++++++++++++++++++++------- prover/src/rpc_api.rs | 3 ++- prover/src/utils.rs | 27 +++++++++++++++++++-------- 4 files changed, 55 insertions(+), 16 deletions(-) diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 4872bd6..9f853e6 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -39,6 +39,7 @@ serde_json.workspace = true getset.workspace = true log.workspace = true url = "2" +blst = { version = "0.3.11", default-features = false, features = [ "portable", "no-threads" ]} # ethereum ethers = { version = "2.0.7", default_features = false, features = [ diff --git a/prover/src/rpc.rs b/prover/src/rpc.rs index 74546c9..93c16a1 100644 --- a/prover/src/rpc.rs +++ b/prover/src/rpc.rs @@ -4,7 +4,9 @@ use ark_std::{end_timer, start_timer}; use axum::{http::StatusCode, response::IntoResponse, routing::post, Router}; -use ethereum_types::{EthSpec, LightClientUpdate}; +use ethereum_types::{ + EthSpec, FixedVector, ForkName, LightClientFinalityUpdate, LightClientUpdate, PublicKeyBytes, +}; use ethers::prelude::*; use jsonrpc_v2::{Data, RequestObject as JsonRpcRequestObject}; use jsonrpc_v2::{Error as JsonRpcError, Params}; @@ -18,7 +20,9 @@ use preprocessor::{rotation_args_from_update, step_args_from_finality_update}; use snark_verifier_sdk::evm::encode_calldata; use snark_verifier_sdk::{halo2::aggregation::AggregationCircuit, Snark}; use spectre_prover::prover::ProverState; +use ssz::Decode; use std::path::{Path, PathBuf}; +use std::str::FromStr; use std::sync::Arc; pub type JsonRpcServerState = Arc>; @@ -48,7 +52,7 @@ where ) .with_method( RPC_EVM_PROOF_STEP_CIRCUIT_COMPRESSED, - gen_evm_proof_sync_step_compressed_handler::, + gen_evm_proof_sync_step_compressed_handler::, ) .finish_unwrapped() } @@ -77,9 +81,19 @@ where let GenProofCommitteeUpdateParams { light_client_update, + fork_name, } = params; - let update = LightClientUpdate::from_ssz_bytes(&light_client_update)?; + let fork_name = ForkName::from_str(&fork_name) + .map_err(|e| JsonRpcError::internal(format!("Failed to parse fork version: {}", e)))?; + + let update = + LightClientUpdate::::from_ssz_bytes(&light_client_update, fork_name).map_err(|e| { + JsonRpcError::internal(format!( + "Failed to deserialize light client update: {:?}", + e + )) + })?; let witness = rotation_args_from_update(&update).await?; let params = state.params.get(state.committee_update.degree()).unwrap(); @@ -112,7 +126,7 @@ where }) } -pub(crate) async fn gen_evm_proof_sync_step_compressed_handler( +pub(crate) async fn gen_evm_proof_sync_step_compressed_handler( Data(state): Data, Params(params): Params, ) -> Result @@ -135,11 +149,23 @@ where light_client_finality_update, domain, pubkeys, + fork_name, } = params; - let update = ssz_rs::deserialize(&light_client_finality_update)?; - let pubkeys = ssz_rs::deserialize(&pubkeys)?; - let witness = step_args_from_finality_update(update, pubkeys, domain).await?; + let fork_name = ForkName::from_str(&fork_name) + .map_err(|e| JsonRpcError::internal(format!("Failed to parse fork version: {}", e)))?; + + let update = + LightClientFinalityUpdate::::from_ssz_bytes(&light_client_finality_update, fork_name) + .map_err(|e| { + JsonRpcError::internal(format!( + "Failed to deserialize light client finality update: {:?}", + e + )) + })?; + let pubkeys = FixedVector::::from_ssz_bytes(&pubkeys) + .map_err(|e| JsonRpcError::internal(format!("Failed to deserialize pubkeys: {:?}", e)))?; + let witness = step_args_from_finality_update(update, &pubkeys, domain).await?; let params = state.params.get(state.step.degree()).unwrap(); let snark = gen_uncompressed_snark::>( diff --git a/prover/src/rpc_api.rs b/prover/src/rpc_api.rs index a65ba17..34ef230 100644 --- a/prover/src/rpc_api.rs +++ b/prover/src/rpc_api.rs @@ -14,7 +14,7 @@ pub struct GenProofStepParams { // Serializing as Vec so that we can differentiate between Mainnet, Testnet, Minimal at runtime pub light_client_finality_update: Vec, pub pubkeys: Vec, - + pub fork_name: String, pub domain: [u8; 32], } @@ -22,6 +22,7 @@ pub struct GenProofStepParams { pub struct GenProofCommitteeUpdateParams { // Serializing as Vec so that we can differentiate between Mainnet, Testnet, Minimal at runtime pub light_client_update: Vec, + pub fork_name: String, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/prover/src/utils.rs b/prover/src/utils.rs index 963e172..a74e584 100644 --- a/prover/src/utils.rs +++ b/prover/src/utils.rs @@ -2,22 +2,20 @@ // Code: https://github.com/ChainSafe/Spectre // SPDX-License-Identifier: LGPL-3.0-only -use std::{ops::Deref, sync::Arc, time::Duration}; +use std::{sync::Arc, time::Duration}; +use crate::args::UtilsCmd; +use blst::min_pk as bls; use eth2::{types::BlockId, BeaconNodeHttpClient, SensitiveUrl, Timeouts}; use eth_types::LIMB_BITS; use ethereum_types::{LightClientBootstrap, MainnetEthSpec}; use itertools::Itertools; use lightclient_circuits::poseidon::poseidon_committee_commitment_from_uncompressed; use tree_hash::TreeHash; -use url::Url; - -use crate::args::UtilsCmd; pub(crate) async fn utils_cli(method: UtilsCmd) -> eyre::Result<()> { match method { UtilsCmd::CommitteePoseidon { beacon_api } => { - let reqwest_client = reqwest::Client::new(); let beacon_client = Arc::new(BeaconNodeHttpClient::new( SensitiveUrl::parse(&beacon_api).unwrap(), Timeouts::set_all(Duration::from_secs(10)), @@ -40,18 +38,31 @@ pub(crate) async fn utils_cli(method: UtilsCmd) -> eyre::Result<()> { let sync_period = match bootstrap { LightClientBootstrap::Altair(_) => unimplemented!("Altair not implemented"), - LightClientBootstrap::Capella(bootstrap) => bootstrap.header.beacon.slot, - LightClientBootstrap::Deneb(bootstrap) => bootstrap.header.beacon.slot, + LightClientBootstrap::Capella(ref bootstrap) => bootstrap.header.beacon.slot, + LightClientBootstrap::Deneb(ref bootstrap) => bootstrap.header.beacon.slot, } / (32 * 256); println!("Sync period: {}", sync_period); + let pubkeys_uncompressed = bootstrap .current_sync_committee() .pubkeys .iter() - .map(|pk| pk.decompressed_bytes()) + .map(|pk| { + bls::PublicKey::uncompress(&pk.serialize()) + .unwrap() + .serialize() + .to_vec() + }) .collect_vec(); + // let pubkeys_uncompressed = bootstrap + // .current_sync_committee() + // .pubkeys + // .iter() + // .map(|pk| pk.decompressed_bytes()) + // .collect_vec(); + let ssz_root = bootstrap.current_sync_committee().pubkeys.tree_hash_root(); println!("SSZ root: {:?}", hex::encode(ssz_root.0)); From bfed59855367f187597dbce5f3b2fbf1545c98bd Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Tue, 26 Mar 2024 12:39:27 -0400 Subject: [PATCH 11/30] Everything builds --- Cargo.toml | 5 ----- contract-tests/Cargo.toml | 3 ++- contract-tests/tests/step_input_encoding.rs | 16 ++++------------ test-utils/src/lib.rs | 18 ++++++------------ 4 files changed, 12 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e62d0d5..b8a1e05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,11 +67,6 @@ snark-verifier-sdk = { git = "https://github.com/axiom-crypto/snark-verifier.git ] } # ethereum types -ethereum-consensus-types = { git = "https://github.com/ChainSafe/ethereum-consensus-types", branch = "capella" } -beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus.git", rev = "f3bff52e9c43866f231ec40c8ab0e34125a8957f" } -ssz_rs = "0.9" - - ethereum-types = { package = "types", git = "https://github.com/sigp/lighthouse/", branch = "unstable", default-features = false} tree_hash = { version = "0.5" } eth2 = { package = "eth2", git = "https://github.com/sigp/lighthouse/", branch = "unstable" } diff --git a/contract-tests/Cargo.toml b/contract-tests/Cargo.toml index 61800d7..6138c95 100644 --- a/contract-tests/Cargo.toml +++ b/contract-tests/Cargo.toml @@ -16,7 +16,8 @@ itertools = "0.11.0" test-utils = { workspace = true } halo2curves = { workspace = true } eth-types = { workspace = true } -ssz_rs = { workspace = true } halo2-base = { workspace = true } snark-verifier-sdk = { workspace = true } contracts = { workspace = true } + +tree_hash.workspace = true \ No newline at end of file diff --git a/contract-tests/tests/step_input_encoding.rs b/contract-tests/tests/step_input_encoding.rs index cf2c2e6..b6ae700 100644 --- a/contract-tests/tests/step_input_encoding.rs +++ b/contract-tests/tests/step_input_encoding.rs @@ -2,7 +2,6 @@ // Code: https://github.com/ChainSafe/Spectre // SPDX-License-Identifier: LGPL-3.0-only -use std::ops::Deref; use std::path::PathBuf; use contract_tests::make_client; @@ -11,8 +10,8 @@ use ethers::contract::abigen; use lightclient_circuits::halo2_proofs::halo2curves::bn256; use lightclient_circuits::witness::SyncStepArgs; use rstest::rstest; -use ssz_rs::Merkleized; use test_utils::read_test_files_and_gen_witness; +use tree_hash::TreeHash; abigen!( StepExternal, @@ -28,20 +27,13 @@ impl From> for StepInput { .map(|v| *v as u64) .sum::(); - let finalized_header_root: [u8; 32] = args - .finalized_header - .clone() - .hash_tree_root() - .unwrap() - .deref() - .try_into() - .unwrap(); + let finalized_header_root: [u8; 32] = args.finalized_header.clone().tree_hash_root().0; let execution_payload_root: [u8; 32] = args.execution_payload_root.try_into().unwrap(); StepInput { - attested_slot: args.attested_header.slot, - finalized_slot: args.finalized_header.slot, + attested_slot: args.attested_header.slot.into(), + finalized_slot: args.finalized_header.slot.into(), participation, finalized_header_root, execution_payload_root, diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index d250936..5e5fd73 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -10,7 +10,7 @@ use crate::test_types::{TestMeta, TestStep}; use blst::min_pk as bls; use eth_types::{Minimal, LIMB_BITS}; use ethereum_types::{ - BeaconBlockHeader, Domain, EthSpec, ExecutionPayloadHeader, ForkData, Hash256, + BeaconBlockHeader, Domain, EthSpec, ExecutionPayloadHeader, Hash256, LightClientBootstrapCapella, LightClientUpdateCapella, MinimalEthSpec, SyncCommittee, }; use ethers::types::H256; @@ -174,11 +174,6 @@ fn to_sync_ciruit_witness( state_root: light_client_update.finalized_header.beacon.state_root, body_root: light_client_update.finalized_header.beacon.body_root, }; - let fork_data = ForkData { - current_version: [3, 0, 0, 1], - genesis_validators_root, - }; - let domain = MinimalEthSpec::default_spec().compute_domain( Domain::SyncCommittee, [3, 0, 0, 1], @@ -192,12 +187,11 @@ fn to_sync_ciruit_witness( .map(|b| b.0.as_ref().to_vec()) .collect(); args.execution_payload_root = { - let mut execution_payload_header: ExecutionPayloadHeader = - light_client_update - .finalized_header - .execution - .clone() - .into(); + let execution_payload_header: ExecutionPayloadHeader = light_client_update + .finalized_header + .execution + .clone() + .into(); execution_payload_header.tree_hash_root().0.to_vec() }; From dc9f1aa44ebe31e3fa3bde0ae4f7756bb752e96b Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Tue, 26 Mar 2024 13:03:15 -0400 Subject: [PATCH 12/30] remove prints --- preprocessor/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/preprocessor/src/lib.rs b/preprocessor/src/lib.rs index a00b862..f50c418 100644 --- a/preprocessor/src/lib.rs +++ b/preprocessor/src/lib.rs @@ -38,15 +38,12 @@ pub async fn get_light_client_update_at_period( path.query_pairs_mut() .append_pair("start_period", &period.to_string()) .append_pair("count", "1"); - println!("Path: {:?}", path); let resp = client .get_response(path, |b| b.accept(Accept::Json)) .await .map_err(|e| eyre::eyre!("Failed to get light client update: {:?}", e))?; - println!("resp: {:?}", resp); let mut updates: Vec>> = resp.json().await?; - println!("Updates: {:?}", updates); assert!(updates.len() == 1, "should only get one update"); Ok(updates.pop().unwrap().data) From abaab08b6b54e7b43d390434605c6460b5cbd278 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Tue, 26 Mar 2024 13:40:28 -0400 Subject: [PATCH 13/30] merkle proof asserts --- Cargo.toml | 1 + preprocessor/Cargo.toml | 1 + preprocessor/src/rotation.rs | 55 ++++++++++++------------ preprocessor/src/step.rs | 81 +++++++++++++++++++----------------- 4 files changed, 71 insertions(+), 67 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b8a1e05..a7b56bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,6 +70,7 @@ snark-verifier-sdk = { git = "https://github.com/axiom-crypto/snark-verifier.git ethereum-types = { package = "types", git = "https://github.com/sigp/lighthouse/", branch = "unstable", default-features = false} tree_hash = { version = "0.5" } eth2 = { package = "eth2", git = "https://github.com/sigp/lighthouse/", branch = "unstable" } +merkle_proof = { package = "merkle_proof", git = "https://github.com/sigp/lighthouse/", branch = "unstable" } ethereum_ssz = "0.5.3" # crypto diff --git a/preprocessor/Cargo.toml b/preprocessor/Cargo.toml index bdf4848..0575563 100644 --- a/preprocessor/Cargo.toml +++ b/preprocessor/Cargo.toml @@ -31,6 +31,7 @@ serde.workspace = true ethereum-types = {workspace = true, default-features = false } eth2.workspace = true tree_hash.workspace = true +merkle_proof.workspace = true # local eth-types.workspace = true diff --git a/preprocessor/src/rotation.rs b/preprocessor/src/rotation.rs index 82aa21c..2f583cf 100644 --- a/preprocessor/src/rotation.rs +++ b/preprocessor/src/rotation.rs @@ -12,7 +12,7 @@ use crate::get_light_client_update_at_period; use eth2::{types::BlockId, BeaconNodeHttpClient}; use ethereum_types::{EthSpec, LightClientUpdate}; use lightclient_circuits::witness::CommitteeUpdateArgs; -use tree_hash::TreeHash; +use tree_hash::{Hash256, TreeHash}; /// Fetches LightClientUpdate from the beacon client and converts it to a [`CommitteeUpdateArgs`] witness pub async fn fetch_rotation_args( @@ -61,43 +61,40 @@ where [(); S::FINALIZED_HEADER_INDEX]:, { let update = update.clone(); - let pubkeys_compressed = update - .next_sync_committee() + let next_sync_committee = update.next_sync_committee().clone(); + + let pubkeys_compressed = next_sync_committee .pubkeys .iter() .map(|pk| pk.serialize().to_vec()) .collect_vec(); let mut sync_committee_branch = update.next_sync_committee_branch().as_ref().to_vec(); - sync_committee_branch.insert( - 0, - update - .next_sync_committee() - .aggregate_pubkey - .tree_hash_root(), - ); - - // assert!( - // ssz_rs::is_valid_merkle_branch( - // update.next_sync_committee.pubkeys.hash_tree_root().unwrap(), - // &sync_committee_branch - // .iter() - // .map(|n| n.as_ref()) - // .collect_vec(), - // S::SYNC_COMMITTEE_PUBKEYS_DEPTH, - // S::SYNC_COMMITTEE_PUBKEYS_ROOT_INDEX, - // update.attested_header.beacon.state_root, - // ) - // .is_ok(), - // "Execution payload merkle proof verification failed" - // ); - let finalized_header_beacon = match update { + sync_committee_branch.insert(0, next_sync_committee.aggregate_pubkey.tree_hash_root()); + let (attested_header_beacon, finalized_header_beacon) = match update { LightClientUpdate::Altair(_) => unimplemented!(), - LightClientUpdate::Capella(update) => update.finalized_header.beacon, - - LightClientUpdate::Deneb(update) => update.finalized_header.beacon, + LightClientUpdate::Capella(update) => ( + update.attested_header.beacon, + update.finalized_header.beacon, + ), + + LightClientUpdate::Deneb(update) => ( + update.attested_header.beacon, + update.finalized_header.beacon, + ), }; + assert!( + merkle_proof::verify_merkle_proof( + next_sync_committee.pubkeys.tree_hash_root(), + &sync_committee_branch, + S::SYNC_COMMITTEE_PUBKEYS_DEPTH, + S::SYNC_COMMITTEE_PUBKEYS_ROOT_INDEX, + attested_header_beacon.state_root, + ), + "Execution payload merkle proof verification failed" + ); + let args = CommitteeUpdateArgs:: { pubkeys_compressed, finalized_header: finalized_header_beacon, diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index 8a9b4e4..04e06ff 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -13,7 +13,7 @@ use eth2::types::StateId; use eth2::BeaconNodeHttpClient; use ethereum_types::Domain; use ethereum_types::{EthSpec, FixedVector, LightClientFinalityUpdate, PublicKeyBytes}; -use tree_hash::TreeHash; +use tree_hash::{Hash256, TreeHash}; /// Fetches the latest `LightClientFinalityUpdate`` and the current sync committee (from LightClientBootstrap) and converts it to a [`SyncStepArgs`] witness. pub async fn fetch_step_args( @@ -97,47 +97,52 @@ pub async fn step_args_from_finality_update( }) .collect_vec(); - let (execution_payload_root, execution_payload_branch) = match &finality_update { - LightClientFinalityUpdate::Altair(_) => unimplemented!(), - LightClientFinalityUpdate::Capella(header) => { - let finalized_header = &header.finalized_header; + let (execution_payload_root, execution_payload_branch, finalized_beacon_body_root) = + match finality_update { + LightClientFinalityUpdate::Altair(_) => unimplemented!(), + LightClientFinalityUpdate::Capella(ref header) => { + let finalized_header = &header.finalized_header; - ( - finalized_header.execution.tree_hash_root().0.to_vec(), - finalized_header - .execution_branch - .iter() - .map(|n| n.0.to_vec()) - .collect_vec(), - ) - } - LightClientFinalityUpdate::Deneb(header) => { - let finalized_header = &header.finalized_header; + ( + finalized_header.execution.tree_hash_root().0.to_vec(), + finalized_header + .execution_branch + .iter() + .map(|n| n.0.to_vec()) + .collect_vec(), + finalized_header.beacon.body_root, + ) + } + LightClientFinalityUpdate::Deneb(ref header) => { + let finalized_header = &header.finalized_header; - ( - finalized_header.execution.tree_hash_root().0.to_vec(), - finalized_header - .execution_branch - .iter() - .map(|n| n.0.to_vec()) - .collect_vec(), - ) - } - }; + ( + finalized_header.execution.tree_hash_root().0.to_vec(), + finalized_header + .execution_branch + .iter() + .map(|n| n.0.to_vec()) + .collect_vec(), + finalized_header.beacon.body_root, + ) + } + }; + assert!( + merkle_proof::verify_merkle_proof( + Hash256::from_slice(&execution_payload_root), + &execution_payload_branch + .iter() + .map(|n| Hash256::from_slice(n)) + .collect_vec(), + S::EXECUTION_STATE_ROOT_DEPTH, + S::EXECUTION_STATE_ROOT_INDEX, + finalized_beacon_body_root, + ), + "Execution payload merkle proof verification failed" + ); // assert!( - // ssz_rs::is_valid_merkle_branch( - // Node::try_from(execution_payload_root.as_slice())?, - // &execution_payload_branch, - // S::EXECUTION_STATE_ROOT_DEPTH, - // S::EXECUTION_STATE_ROOT_INDEX, - // finality_update.finalized_header.beacon.body_root, - // ) - // .is_ok(), - // "Execution payload merkle proof verification failed" - // ); - // assert!( - // ssz_rs::is_valid_merkle_branch( + // merkle_proof::verify_merkle_proof( // finality_update // .finalized_header // .beacon From 1e017749d0800e52238d7693eddcefd092c03e7a Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Tue, 26 Mar 2024 14:13:50 -0400 Subject: [PATCH 14/30] fix preprocessor asserts --- preprocessor/src/rotation.rs | 7 +-- preprocessor/src/step.rs | 111 ++++++++++++++++------------------- 2 files changed, 52 insertions(+), 66 deletions(-) diff --git a/preprocessor/src/rotation.rs b/preprocessor/src/rotation.rs index 2f583cf..6bd05fd 100644 --- a/preprocessor/src/rotation.rs +++ b/preprocessor/src/rotation.rs @@ -6,13 +6,12 @@ use std::marker::PhantomData; use eth_types::Spec; use itertools::Itertools; -use log::debug; use crate::get_light_client_update_at_period; use eth2::{types::BlockId, BeaconNodeHttpClient}; use ethereum_types::{EthSpec, LightClientUpdate}; use lightclient_circuits::witness::CommitteeUpdateArgs; -use tree_hash::{Hash256, TreeHash}; +use tree_hash::TreeHash; /// Fetches LightClientUpdate from the beacon client and converts it to a [`CommitteeUpdateArgs`] witness pub async fn fetch_rotation_args( @@ -38,7 +37,7 @@ where let slot = block.slot.as_u64(); let period = slot / (32 * 256); - debug!( + println!( "Fetching light client update at current Slot: {} at Period: {}", slot, period ); @@ -129,7 +128,7 @@ mod tests { #[tokio::test] async fn test_rotation_circuit_sepolia() { const CONFIG_PATH: &str = "../lightclient-circuits/config/committee_update_testnet.json"; - const K: u32 = 21; + const K: u32 = 20; const URL: &str = "https://lodestar-sepolia.chainsafe.io"; let client = BeaconNodeHttpClient::new( SensitiveUrl::parse(URL).unwrap(), diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index 04e06ff..c8ddf9a 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -97,70 +97,33 @@ pub async fn step_args_from_finality_update( }) .collect_vec(); - let (execution_payload_root, execution_payload_branch, finalized_beacon_body_root) = - match finality_update { - LightClientFinalityUpdate::Altair(_) => unimplemented!(), - LightClientFinalityUpdate::Capella(ref header) => { - let finalized_header = &header.finalized_header; - - ( - finalized_header.execution.tree_hash_root().0.to_vec(), - finalized_header - .execution_branch - .iter() - .map(|n| n.0.to_vec()) - .collect_vec(), - finalized_header.beacon.body_root, - ) - } - LightClientFinalityUpdate::Deneb(ref header) => { - let finalized_header = &header.finalized_header; + let (execution_payload_root, execution_payload_branch) = match finality_update { + LightClientFinalityUpdate::Altair(_) => unimplemented!(), + LightClientFinalityUpdate::Capella(ref header) => { + let finalized_header = &header.finalized_header; - ( - finalized_header.execution.tree_hash_root().0.to_vec(), - finalized_header - .execution_branch - .iter() - .map(|n| n.0.to_vec()) - .collect_vec(), - finalized_header.beacon.body_root, - ) - } - }; + ( + finalized_header.execution.tree_hash_root().0.to_vec(), + finalized_header + .execution_branch + .iter() + .map(|n| n.0.to_vec()) + .collect_vec(), + ) + } + LightClientFinalityUpdate::Deneb(ref header) => { + let finalized_header = &header.finalized_header; - assert!( - merkle_proof::verify_merkle_proof( - Hash256::from_slice(&execution_payload_root), - &execution_payload_branch - .iter() - .map(|n| Hash256::from_slice(n)) - .collect_vec(), - S::EXECUTION_STATE_ROOT_DEPTH, - S::EXECUTION_STATE_ROOT_INDEX, - finalized_beacon_body_root, - ), - "Execution payload merkle proof verification failed" - ); - // assert!( - // merkle_proof::verify_merkle_proof( - // finality_update - // .finalized_header - // .beacon - // .clone() - // .hash_tree_root() - // .unwrap(), - // &finality_update - // .finality_branch - // .iter() - // .map(|n| n.as_ref()) - // .collect_vec(), - // S::FINALIZED_HEADER_DEPTH, - // S::FINALIZED_HEADER_INDEX, - // finality_update.attested_header.beacon.state_root, - // ) - // .is_ok(), - // "Finality merkle proof verification failed" - // ); + ( + finalized_header.execution.tree_hash_root().0.to_vec(), + finalized_header + .execution_branch + .iter() + .map(|n| n.0.to_vec()) + .collect_vec(), + ) + } + }; let attested_header_beacon = match &finality_update { LightClientFinalityUpdate::Altair(_) => unimplemented!(), @@ -176,6 +139,30 @@ pub async fn step_args_from_finality_update( LightClientFinalityUpdate::Deneb(update) => update.finalized_header.beacon.clone(), }; + assert!( + merkle_proof::verify_merkle_proof( + Hash256::from_slice(&execution_payload_root), + &execution_payload_branch + .iter() + .map(|n| Hash256::from_slice(n)) + .collect_vec(), + S::EXECUTION_STATE_ROOT_DEPTH, + S::EXECUTION_STATE_ROOT_INDEX, + finalized_header_beacon.body_root, + ), + "Execution payload merkle proof verification failed" + ); + assert!( + merkle_proof::verify_merkle_proof( + finalized_header_beacon.tree_hash_root(), + &finality_update.finality_branch(), + S::FINALIZED_HEADER_DEPTH, + S::FINALIZED_HEADER_INDEX, + attested_header_beacon.state_root, + ), + "Finality merkle proof verification failed" + ); + Ok(SyncStepArgs { signature_compressed: finality_update .sync_aggregate() From 3b4f0a77d80c19a81943f1fae47663023fe00e5a Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Tue, 26 Mar 2024 14:16:25 -0400 Subject: [PATCH 15/30] pull from finalized not head --- preprocessor/src/rotation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/preprocessor/src/rotation.rs b/preprocessor/src/rotation.rs index 6bd05fd..68fa41f 100644 --- a/preprocessor/src/rotation.rs +++ b/preprocessor/src/rotation.rs @@ -27,7 +27,7 @@ where [(); S::FINALIZED_HEADER_INDEX]:, { let block = client - .get_beacon_headers_block_id(BlockId::Head) + .get_beacon_headers_block_id(BlockId::Finalized) .await .unwrap() .unwrap() From 4d9a018730c56ee7b5e2f3e95d3998260f14f536 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 10:42:13 -0400 Subject: [PATCH 16/30] Update Lighthouse version to tagged release from unstable branch --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a7b56bb..1d786ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,10 +67,10 @@ snark-verifier-sdk = { git = "https://github.com/axiom-crypto/snark-verifier.git ] } # ethereum types -ethereum-types = { package = "types", git = "https://github.com/sigp/lighthouse/", branch = "unstable", default-features = false} +ethereum-types = { package = "types", git = "https://github.com/sigp/lighthouse/", tag = "v5.1.3", default-features = false} tree_hash = { version = "0.5" } -eth2 = { package = "eth2", git = "https://github.com/sigp/lighthouse/", branch = "unstable" } -merkle_proof = { package = "merkle_proof", git = "https://github.com/sigp/lighthouse/", branch = "unstable" } +eth2 = { package = "eth2", git = "https://github.com/sigp/lighthouse/", tag = "v5.1.3" } +merkle_proof = { package = "merkle_proof", git = "https://github.com/sigp/lighthouse/", tag = "v5.1.3" } ethereum_ssz = "0.5.3" # crypto From fee973ffb0dc6c27499cb0e306d6afae5f0e2c7e Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 10:51:36 -0400 Subject: [PATCH 17/30] Move Lighthoust EthSpec as associated type in Spec --- eth-types/Cargo.toml | 1 + eth-types/src/spec.rs | 10 ++++++- preprocessor/src/lib.rs | 32 +++++++++------------- preprocessor/src/rotation.rs | 18 +++++-------- preprocessor/src/step.rs | 22 +++++++--------- prover/src/main.rs | 5 ++-- prover/src/rpc.rs | 51 ++++++++++++++++++++---------------- 7 files changed, 69 insertions(+), 70 deletions(-) diff --git a/eth-types/Cargo.toml b/eth-types/Cargo.toml index 996b84d..cdf0cdc 100644 --- a/eth-types/Cargo.toml +++ b/eth-types/Cargo.toml @@ -15,6 +15,7 @@ serde.workspace = true serde_json.workspace = true itertools.workspace = true halo2curves.workspace = true +ethereum-types.workspace = true regex = "1.5.4" lazy_static = "1.4" subtle = "2.4" diff --git a/eth-types/src/spec.rs b/eth-types/src/spec.rs index ba05992..5cba679 100644 --- a/eth-types/src/spec.rs +++ b/eth-types/src/spec.rs @@ -3,9 +3,11 @@ // SPDX-License-Identifier: LGPL-3.0-only use core::fmt::Debug; - +use ethereum_types::{EthSpec, MainnetEthSpec, MinimalEthSpec}; /// Beacon chain specification. pub trait Spec: 'static + Sized + Copy + Default + Debug { + type EthSpec: EthSpec; + const NAME: &'static str; const SYNC_COMMITTEE_SIZE: usize; const SYNC_COMMITTEE_ROOT_INDEX: usize; @@ -26,6 +28,8 @@ pub trait Spec: 'static + Sized + Copy + Default + Debug { pub struct Minimal; impl Spec for Minimal { + type EthSpec = MinimalEthSpec; + const NAME: &'static str = "minimal"; const SYNC_COMMITTEE_SIZE: usize = 32; const SYNC_COMMITTEE_DEPTH: usize = 5; @@ -47,6 +51,8 @@ impl Spec for Minimal { pub struct Testnet; impl Spec for Testnet { + type EthSpec = MainnetEthSpec; + const NAME: &'static str = "testnet"; const SYNC_COMMITTEE_SIZE: usize = 512; const SYNC_COMMITTEE_DEPTH: usize = 5; @@ -67,6 +73,8 @@ impl Spec for Testnet { pub struct Mainnet; impl Spec for Mainnet { + type EthSpec = MainnetEthSpec; + const NAME: &'static str = "mainnet"; const SYNC_COMMITTEE_SIZE: usize = 512; const SYNC_COMMITTEE_DEPTH: usize = 5; diff --git a/preprocessor/src/lib.rs b/preprocessor/src/lib.rs index f50c418..7b0542a 100644 --- a/preprocessor/src/lib.rs +++ b/preprocessor/src/lib.rs @@ -21,10 +21,10 @@ pub use rotation::*; pub use step::*; use url::Url; -pub async fn get_light_client_update_at_period( +pub async fn get_light_client_update_at_period( client: &BeaconNodeHttpClient, period: u64, -) -> eyre::Result> { +) -> eyre::Result> { let mut path = Url::parse(client.as_ref()).unwrap(); path.path_segments_mut() @@ -43,15 +43,16 @@ pub async fn get_light_client_update_at_period( .await .map_err(|e| eyre::eyre!("Failed to get light client update: {:?}", e))?; - let mut updates: Vec>> = resp.json().await?; + let mut updates: Vec>> = + resp.json().await?; assert!(updates.len() == 1, "should only get one update"); Ok(updates.pop().unwrap().data) } -pub async fn light_client_update_to_args( - update: &LightClientUpdate, - pubkeys_compressed: &FixedVector, +pub async fn light_client_update_to_args( + update: &LightClientUpdate, + pubkeys_compressed: &FixedVector::SyncCommitteeSize>, domain: [u8; 32], ) -> eyre::Result<(SyncStepArgs, CommitteeUpdateArgs)> where @@ -145,12 +146,9 @@ mod tests { // Fetch light client update and create circuit arguments let (s, mut c) = { - let update = get_light_client_update_at_period::( - &client, - period.into(), - ) - .await - .unwrap(); + let update = get_light_client_update_at_period::(&client, period.into()) + .await + .unwrap(); let block_root = block.canonical_root(); @@ -184,13 +182,9 @@ mod tests { genesis_validators_root, ); - light_client_update_to_args::( - &update, - pubkeys_compressed, - domain.into(), - ) - .await - .unwrap() + light_client_update_to_args::(&update, pubkeys_compressed, domain.into()) + .await + .unwrap() }; let mut finalized_sync_committee_branch = { diff --git a/preprocessor/src/rotation.rs b/preprocessor/src/rotation.rs index 68fa41f..02ae60f 100644 --- a/preprocessor/src/rotation.rs +++ b/preprocessor/src/rotation.rs @@ -9,12 +9,12 @@ use itertools::Itertools; use crate::get_light_client_update_at_period; use eth2::{types::BlockId, BeaconNodeHttpClient}; -use ethereum_types::{EthSpec, LightClientUpdate}; +use ethereum_types::LightClientUpdate; use lightclient_circuits::witness::CommitteeUpdateArgs; use tree_hash::TreeHash; /// Fetches LightClientUpdate from the beacon client and converts it to a [`CommitteeUpdateArgs`] witness -pub async fn fetch_rotation_args( +pub async fn fetch_rotation_args( client: &BeaconNodeHttpClient, ) -> eyre::Result> where @@ -42,13 +42,13 @@ where slot, period ); - let update = get_light_client_update_at_period::(client, period).await?; + let update = get_light_client_update_at_period::(client, period).await?; rotation_args_from_update(&update).await } /// Converts a [`LightClientUpdateCapella`] to a [`CommitteeUpdateArgs`] witness. -pub async fn rotation_args_from_update( - update: &LightClientUpdate, +pub async fn rotation_args_from_update( + update: &LightClientUpdate, ) -> eyre::Result> where [(); S::SYNC_COMMITTEE_SIZE]:, @@ -134,9 +134,7 @@ mod tests { SensitiveUrl::parse(URL).unwrap(), Timeouts::set_all(Duration::from_secs(10)), ); - let witness = fetch_rotation_args::(&client) - .await - .unwrap(); + let witness = fetch_rotation_args::(&client).await.unwrap(); let pinning = Eth2ConfigPinning::from_path(CONFIG_PATH); let params: ParamsKZG = gen_srs(K); @@ -170,9 +168,7 @@ mod tests { SensitiveUrl::parse(URL).unwrap(), Timeouts::set_all(Duration::from_secs(10)), ); - let witness = fetch_rotation_args::(&client) - .await - .unwrap(); + let witness = fetch_rotation_args::(&client).await.unwrap(); CommitteeUpdateCircuit::::gen_snark_shplonk( ¶ms, diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index c8ddf9a..53014a4 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -16,7 +16,7 @@ use ethereum_types::{EthSpec, FixedVector, LightClientFinalityUpdate, PublicKeyB use tree_hash::{Hash256, TreeHash}; /// Fetches the latest `LightClientFinalityUpdate`` and the current sync committee (from LightClientBootstrap) and converts it to a [`SyncStepArgs`] witness. -pub async fn fetch_step_args( +pub async fn fetch_step_args( client: &BeaconNodeHttpClient, ) -> eyre::Result> where @@ -28,7 +28,7 @@ where { //TODO Should probably parameterise SyncStepArgs as let finality_update = client - .get_beacon_light_client_finality_update::() + .get_beacon_light_client_finality_update::() .await .map_err(|e| eyre::eyre!("Failed to get finality update: {:?}", e))? .ok_or(eyre::eyre!("Failed to get finality update: None"))? @@ -43,7 +43,7 @@ where }; let bootstrap = client - .get_light_client_bootstrap::(block_root) + .get_light_client_bootstrap::(block_root) .await .map_err(|e| eyre::eyre!("Failed to get bootstrap: {:?}", e))? .ok_or(eyre::eyre!("Failed to get bootstrap: None"))? @@ -72,7 +72,7 @@ where .data .genesis_validators_root; - let domain = T::default_spec().compute_domain( + let domain = S::EthSpec::default_spec().compute_domain( Domain::SyncCommittee, fork_version, genesis_validators_root, @@ -82,9 +82,9 @@ where } /// Converts a [`LightClientFinalityUpdate`] to a [`SyncStepArgs`] witness. -pub async fn step_args_from_finality_update( - finality_update: LightClientFinalityUpdate, - pubkeys_compressed: &FixedVector, +pub async fn step_args_from_finality_update( + finality_update: LightClientFinalityUpdate, + pubkeys_compressed: &FixedVector::SyncCommitteeSize>, domain: [u8; 32], ) -> eyre::Result> { let pubkeys_uncompressed = pubkeys_compressed @@ -217,9 +217,7 @@ mod tests { SensitiveUrl::parse(URL).unwrap(), Timeouts::set_all(Duration::from_secs(10)), ); - let witness = fetch_step_args::(&client) - .await - .unwrap(); + let witness = fetch_step_args::(&client).await.unwrap(); let params: ParamsKZG = gen_srs(K); let circuit = StepCircuit::::create_circuit( @@ -252,9 +250,7 @@ mod tests { SensitiveUrl::parse(URL).unwrap(), Timeouts::set_all(Duration::from_secs(10)), ); - let witness = fetch_step_args::(&client) - .await - .unwrap(); + let witness = fetch_step_args::(&client).await.unwrap(); StepCircuit::::gen_snark_shplonk( ¶ms, diff --git a/prover/src/main.rs b/prover/src/main.rs index fda9972..7365484 100644 --- a/prover/src/main.rs +++ b/prover/src/main.rs @@ -13,7 +13,6 @@ mod utils; use crate::{cli::spec_app, rpc::run_rpc}; use args::Cli; use clap::Parser; -use ethereum_types::MainnetEthSpec; use utils::utils_cli; mod args; @@ -27,7 +26,7 @@ async fn app(options: Cli) -> eyre::Result<()> { } => { match spec { args::Spec::Testnet => { - run_rpc::( + run_rpc::( port.parse().unwrap(), options.args.config_dir, build_dir, @@ -36,7 +35,7 @@ async fn app(options: Cli) -> eyre::Result<()> { .await } args::Spec::Mainnet => { - run_rpc::( + run_rpc::( port.parse().unwrap(), options.args.config_dir, build_dir, diff --git a/prover/src/rpc.rs b/prover/src/rpc.rs index 93c16a1..9263d8e 100644 --- a/prover/src/rpc.rs +++ b/prover/src/rpc.rs @@ -32,7 +32,7 @@ use crate::rpc_api::{ RPC_EVM_PROOF_STEP_CIRCUIT_COMPRESSED, }; -pub(crate) fn jsonrpc_server( +pub(crate) fn jsonrpc_server( state: ProverState, ) -> JsonRpcServer where @@ -48,16 +48,16 @@ where .with_data(Data::new(state)) .with_method( RPC_EVM_PROOF_COMMITTEE_UPDATE_CIRCUIT_COMPRESSED, - gen_evm_proof_committee_update_handler::, + gen_evm_proof_committee_update_handler::, ) .with_method( RPC_EVM_PROOF_STEP_CIRCUIT_COMPRESSED, - gen_evm_proof_sync_step_compressed_handler::, + gen_evm_proof_sync_step_compressed_handler::, ) .finish_unwrapped() } -pub(crate) async fn gen_evm_proof_committee_update_handler( +pub(crate) async fn gen_evm_proof_committee_update_handler( Data(state): Data, Params(params): Params, ) -> Result @@ -87,13 +87,13 @@ where let fork_name = ForkName::from_str(&fork_name) .map_err(|e| JsonRpcError::internal(format!("Failed to parse fork version: {}", e)))?; - let update = - LightClientUpdate::::from_ssz_bytes(&light_client_update, fork_name).map_err(|e| { - JsonRpcError::internal(format!( - "Failed to deserialize light client update: {:?}", - e - )) - })?; + let update = LightClientUpdate::::from_ssz_bytes(&light_client_update, fork_name) + .map_err(|e| { + JsonRpcError::internal(format!( + "Failed to deserialize light client update: {:?}", + e + )) + })?; let witness = rotation_args_from_update(&update).await?; let params = state.params.get(state.committee_update.degree()).unwrap(); @@ -126,7 +126,7 @@ where }) } -pub(crate) async fn gen_evm_proof_sync_step_compressed_handler( +pub(crate) async fn gen_evm_proof_sync_step_compressed_handler( Data(state): Data, Params(params): Params, ) -> Result @@ -155,15 +155,20 @@ where let fork_name = ForkName::from_str(&fork_name) .map_err(|e| JsonRpcError::internal(format!("Failed to parse fork version: {}", e)))?; - let update = - LightClientFinalityUpdate::::from_ssz_bytes(&light_client_finality_update, fork_name) - .map_err(|e| { - JsonRpcError::internal(format!( - "Failed to deserialize light client finality update: {:?}", - e - )) - })?; - let pubkeys = FixedVector::::from_ssz_bytes(&pubkeys) + let update = LightClientFinalityUpdate::::from_ssz_bytes( + &light_client_finality_update, + fork_name, + ) + .map_err(|e| { + JsonRpcError::internal(format!( + "Failed to deserialize light client finality update: {:?}", + e + )) + })?; + let pubkeys = + FixedVector::::SyncCommitteeSize>::from_ssz_bytes( + &pubkeys, + ) .map_err(|e| JsonRpcError::internal(format!("Failed to deserialize pubkeys: {:?}", e)))?; let witness = step_args_from_finality_update(update, &pubkeys, domain).await?; let params = state.params.get(state.step.degree()).unwrap(); @@ -207,7 +212,7 @@ where )?) } -pub async fn run_rpc( +pub async fn run_rpc( port: usize, config_dir: impl AsRef, build_dir: impl AsRef, @@ -226,7 +231,7 @@ where let timer = start_timer!(|| "Load Prover State and Context"); let state = ProverState::new::(config_dir.as_ref(), build_dir.as_ref(), concurrency); end_timer!(timer); - let rpc_server = Arc::new(jsonrpc_server::(state)); + let rpc_server = Arc::new(jsonrpc_server::(state)); let router = Router::new() .route("/rpc", post(handler)) .with_state(rpc_server); From 20b9cc804bc53692a2ddd2b4940f7330da6238a7 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 10:57:19 -0400 Subject: [PATCH 18/30] Pin compiler nightly-2024-04-01 --- rust-toolchain | 1 + 1 file changed, 1 insertion(+) create mode 100644 rust-toolchain diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000..96f6912 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly-2024-04-01 \ No newline at end of file From b5a8a01fd837a8d5544d80822dcf0c94dbba22fd Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 10:57:59 -0400 Subject: [PATCH 19/30] remove comment --- preprocessor/src/step.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index 53014a4..3d4e21c 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -26,7 +26,6 @@ where [(); S::BYTES_PER_LOGS_BLOOM]:, [(); S::MAX_EXTRA_DATA_BYTES]:, { - //TODO Should probably parameterise SyncStepArgs as let finality_update = client .get_beacon_light_client_finality_update::() .await From 382caa3a1404fe7bc6722ef9540e59ea48cf509c Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 11:00:57 -0400 Subject: [PATCH 20/30] Remove comments --- preprocessor/src/rotation.rs | 1 - preprocessor/src/step.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/preprocessor/src/rotation.rs b/preprocessor/src/rotation.rs index 02ae60f..36d6c9e 100644 --- a/preprocessor/src/rotation.rs +++ b/preprocessor/src/rotation.rs @@ -113,7 +113,6 @@ mod tests { use super::*; use eth2::{SensitiveUrl, Timeouts}; use eth_types::Testnet; - use ethereum_types::MainnetEthSpec; use halo2_base::halo2_proofs::halo2curves::bn256::Bn256; use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; use halo2_base::utils::fs::gen_srs; diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index 3d4e21c..adeb2ed 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -195,7 +195,6 @@ mod tests { use eth2::{SensitiveUrl, Timeouts}; use eth_types::Testnet; - use ethereum_types::MainnetEthSpec; use halo2_base::halo2_proofs::halo2curves::bn256::Bn256; use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; use halo2_base::utils::fs::gen_srs; From 5acba9f181679736505bdd66035ed4752adb8d13 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 11:02:05 -0400 Subject: [PATCH 21/30] remove comments --- lightclient-circuits/src/committee_update_circuit.rs | 1 - prover/src/utils.rs | 7 ------- 2 files changed, 8 deletions(-) diff --git a/lightclient-circuits/src/committee_update_circuit.rs b/lightclient-circuits/src/committee_update_circuit.rs index eeecf4b..6af2705 100644 --- a/lightclient-circuits/src/committee_update_circuit.rs +++ b/lightclient-circuits/src/committee_update_circuit.rs @@ -29,7 +29,6 @@ use halo2_ecc::{ fields::FieldChip, }; use itertools::Itertools; -// use ssz_rs::Merkleized; use std::{env::var, iter, marker::PhantomData, vec}; use tree_hash::TreeHash; diff --git a/prover/src/utils.rs b/prover/src/utils.rs index a74e584..d84e9f1 100644 --- a/prover/src/utils.rs +++ b/prover/src/utils.rs @@ -56,13 +56,6 @@ pub(crate) async fn utils_cli(method: UtilsCmd) -> eyre::Result<()> { }) .collect_vec(); - // let pubkeys_uncompressed = bootstrap - // .current_sync_committee() - // .pubkeys - // .iter() - // .map(|pk| pk.decompressed_bytes()) - // .collect_vec(); - let ssz_root = bootstrap.current_sync_committee().pubkeys.tree_hash_root(); println!("SSZ root: {:?}", hex::encode(ssz_root.0)); From fd2cc7d53f6cbaf7dc1b6a95dce69e5190766ac7 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 11:41:27 -0400 Subject: [PATCH 22/30] No unwrap --- preprocessor/src/lib.rs | 2 +- preprocessor/src/rotation.rs | 4 ++-- preprocessor/src/step.rs | 15 +++++++-------- test-utils/src/lib.rs | 1 - 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/preprocessor/src/lib.rs b/preprocessor/src/lib.rs index 7b0542a..acab5e9 100644 --- a/preprocessor/src/lib.rs +++ b/preprocessor/src/lib.rs @@ -25,7 +25,7 @@ pub async fn get_light_client_update_at_period( client: &BeaconNodeHttpClient, period: u64, ) -> eyre::Result> { - let mut path = Url::parse(client.as_ref()).unwrap(); + let mut path = Url::parse(client.as_ref()).map_err(|e| eyre::eyre!("Invalid URL: {:?}", e))?; path.path_segments_mut() .map_err(|()| eyre::eyre!("Invalid URL: {}", client.as_ref()))? diff --git a/preprocessor/src/rotation.rs b/preprocessor/src/rotation.rs index 36d6c9e..ea435ee 100644 --- a/preprocessor/src/rotation.rs +++ b/preprocessor/src/rotation.rs @@ -29,8 +29,8 @@ where let block = client .get_beacon_headers_block_id(BlockId::Finalized) .await - .unwrap() - .unwrap() + .map_err(|e| eyre::eyre!("Failed to get block id: {:?}", e))? + .ok_or(eyre::eyre!("Failed to get block id: None"))? .data .header .message; diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index adeb2ed..2878c6f 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -59,15 +59,15 @@ where let fork_version = client .get_beacon_states_fork(StateId::Root(attested_state_id)) .await - .unwrap() - .unwrap() + .map_err(|e| eyre::eyre!("Failed to get fork version: {:?}", e))? + .ok_or(eyre::eyre!("Failed to get fork version: None"))? .data .current_version; let genesis_validators_root = client .get_beacon_genesis() .await - .unwrap() + .map_err(|e| eyre::eyre!("Failed to get genesis validators root: {:?}", e))? .data .genesis_validators_root; @@ -90,11 +90,11 @@ pub async fn step_args_from_finality_update( .iter() .map(|pk| { bls::PublicKey::uncompress(&pk.serialize()) - .unwrap() - .serialize() - .to_vec() + .map_err(|e| eyre::eyre!("Failed to uncompress public key: {:?}", e)) + .and_then(|k| Ok(bls::PublicKey::serialize(&k))) + .and_then(|b| Ok(b.to_vec())) }) - .collect_vec(); + .collect::>, _>>()?; let (execution_payload_root, execution_payload_branch) = match finality_update { LightClientFinalityUpdate::Altair(_) => unimplemented!(), @@ -173,7 +173,6 @@ pub async fn step_args_from_finality_update( .sync_aggregate() .sync_committee_bits .iter() - // .by_vals() .collect_vec(), attested_header: attested_header_beacon, finalized_header: finalized_header_beacon, diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index 5e5fd73..f34f7db 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -235,7 +235,6 @@ pub fn load_snappy_ssz_bytes(path: &Path) -> Vec { pub fn load_snappy_ssz(path: &str) -> Option { let path = Path::new(path); if !path.exists() { - // panic!("Path to snappy_ssz file does not exist: {:?} from dir {:?}", path, std::env::current_dir()); return None; } let buffer = load_snappy_ssz_bytes(path); From 813541cc7d4990e4e17e08663777b908c1476372 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 11:46:24 -0400 Subject: [PATCH 23/30] Fix cargo toml --- Cargo.toml | 1 - preprocessor/Cargo.toml | 2 -- prover/Cargo.toml | 2 +- test-utils/Cargo.toml | 2 +- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1d786ff..4742218 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,7 +92,6 @@ ark-std = { version = "0.4.0", features = ["print-trace"] } [patch.crates-io] -ssz_rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "5f1ec833718efa07bbbff427ab28a1eeaa706164" } halo2-base = { git = "https://github.com/nulltea/halo2-lib", branch = "feat/bls12-381-hash2curve" } halo2-ecc = { git = "https://github.com/nulltea/halo2-lib", branch = "feat/bls12-381-hash2curve" } zkevm-hashes = { git = "https://github.com/nulltea/halo2-lib", branch = "feat/bls12-381-hash2curve" } diff --git a/preprocessor/Cargo.toml b/preprocessor/Cargo.toml index 0575563..71c8607 100644 --- a/preprocessor/Cargo.toml +++ b/preprocessor/Cargo.toml @@ -38,8 +38,6 @@ eth-types.workspace = true lightclient-circuits.workspace = true reqwest = "0.11.22" -# for test gen binary -# ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus.git", rev = "f3bff52e9c43866f231ec40c8ab0e34125a8957f", optional = true } blst = { version = "0.3.11", default-features = false, features = [ "portable", "no-threads" ]} [dev-dependencies] diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 9f853e6..9908f9c 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -53,7 +53,7 @@ reqwest = "0.11.22" ethereum-types = {workspace = true, default-features = false } eth2.workspace = true tree_hash.workspace = true -ethereum_ssz = { workspace = true, default-features = false } +ethereum_ssz = { workspace = true } [features] default = [] diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 47bbb1d..54d4d30 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -13,7 +13,7 @@ halo2-base = { workspace = true } ethereum-types = {workspace = true, default-features = false } eth2.workspace = true tree_hash.workspace = true -ethereum_ssz = { workspace = true, default-features = false } +ethereum_ssz = { workspace = true } itertools = "0.11.0" From 4a1eec0da08802a24d853ee0b57497c8331392cb Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 11:48:19 -0400 Subject: [PATCH 24/30] Clippy --- lightclient-circuits/src/committee_update_circuit.rs | 7 +------ lightclient-circuits/src/sync_step_circuit.rs | 5 +---- lightclient-circuits/src/witness/rotation.rs | 2 +- lightclient-circuits/src/witness/step.rs | 8 +++----- preprocessor/src/lib.rs | 2 +- preprocessor/src/step.rs | 6 +++--- test-utils/src/lib.rs | 1 - 7 files changed, 10 insertions(+), 21 deletions(-) diff --git a/lightclient-circuits/src/committee_update_circuit.rs b/lightclient-circuits/src/committee_update_circuit.rs index 6af2705..6bd0ae3 100644 --- a/lightclient-circuits/src/committee_update_circuit.rs +++ b/lightclient-circuits/src/committee_update_circuit.rs @@ -279,12 +279,7 @@ mod tests { use ark_std::{end_timer, start_timer}; use eth_types::Testnet; use halo2_base::{ - halo2_proofs::{ - dev::MockProver, - halo2curves::bn256::Fr, - plonk::ProvingKey, - poly::{commitment::Params, kzg::commitment::ParamsKZG}, - }, + halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr, plonk::ProvingKey}, utils::fs::gen_srs, }; use snark_verifier_sdk::evm::{evm_verify, gen_evm_proof_shplonk}; diff --git a/lightclient-circuits/src/sync_step_circuit.rs b/lightclient-circuits/src/sync_step_circuit.rs index 89a47f9..f6d6d78 100644 --- a/lightclient-circuits/src/sync_step_circuit.rs +++ b/lightclient-circuits/src/sync_step_circuit.rs @@ -435,10 +435,7 @@ impl AppCircuit for StepCircuit { mod tests { use std::fs; - use crate::{ - aggregation_circuit::AggregationConfigPinning, util::Halo2ConfigPinning, - witness::SyncStepArgs, - }; + use crate::{aggregation_circuit::AggregationConfigPinning, util::Halo2ConfigPinning}; use super::*; use ark_std::{end_timer, start_timer}; diff --git a/lightclient-circuits/src/witness/rotation.rs b/lightclient-circuits/src/witness/rotation.rs index de48faf..b12681c 100644 --- a/lightclient-circuits/src/witness/rotation.rs +++ b/lightclient-circuits/src/witness/rotation.rs @@ -61,7 +61,7 @@ impl Default for CommitteeUpdateArgs { ); let mut finalized_header = BeaconBlockHeader::empty(); - finalized_header.state_root = state_root.try_into().unwrap(); + finalized_header.state_root = state_root.into(); Self { pubkeys_compressed: iter::repeat(dummy_x_bytes) diff --git a/lightclient-circuits/src/witness/step.rs b/lightclient-circuits/src/witness/step.rs index 805822a..f0ebd0e 100644 --- a/lightclient-circuits/src/witness/step.rs +++ b/lightclient-circuits/src/witness/step.rs @@ -63,7 +63,7 @@ impl Default for SyncStepArgs { ); let mut finalized_header = BeaconBlockHeader::empty(); - finalized_header.body_root = beacon_block_body_root.try_into().unwrap(); + finalized_header.body_root = beacon_block_body_root.into(); let finality_header_root = finalized_header.tree_hash_root(); @@ -76,11 +76,9 @@ impl Default for SyncStepArgs { ); let mut attested_header = BeaconBlockHeader::empty(); - attested_header.state_root = attested_state_root.try_into().unwrap(); + attested_header.state_root = attested_state_root.into(); - let signing_root = attested_header - .tree_hash_root() - .signing_root(DOMAIN.try_into().unwrap()); + let signing_root = attested_header.tree_hash_root().signing_root(DOMAIN.into()); let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0); diff --git a/preprocessor/src/lib.rs b/preprocessor/src/lib.rs index acab5e9..96d0889 100644 --- a/preprocessor/src/lib.rs +++ b/preprocessor/src/lib.rs @@ -205,7 +205,7 @@ mod tests { // Magic swap of sync committee branch finalized_sync_committee_branch.insert(0, c.sync_committee_branch[0].clone()); - finalized_sync_committee_branch[1] = c.sync_committee_branch[1].clone(); + finalized_sync_committee_branch[1].clone_from(&c.sync_committee_branch[1]); c.sync_committee_branch = finalized_sync_committee_branch; // Replaces the attested header with step circuits finalized header c.finalized_header = s.finalized_header.clone(); diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index 2878c6f..14c3fa2 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -91,8 +91,8 @@ pub async fn step_args_from_finality_update( .map(|pk| { bls::PublicKey::uncompress(&pk.serialize()) .map_err(|e| eyre::eyre!("Failed to uncompress public key: {:?}", e)) - .and_then(|k| Ok(bls::PublicKey::serialize(&k))) - .and_then(|b| Ok(b.to_vec())) + .map(|k| bls::PublicKey::serialize(&k)) + .map(|b| b.to_vec()) }) .collect::>, _>>()?; @@ -154,7 +154,7 @@ pub async fn step_args_from_finality_update( assert!( merkle_proof::verify_merkle_proof( finalized_header_beacon.tree_hash_root(), - &finality_update.finality_branch(), + finality_update.finality_branch(), S::FINALIZED_HEADER_DEPTH, S::FINALIZED_HEADER_INDEX, attested_header_beacon.state_root, diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index f34f7db..4f5e28f 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -158,7 +158,6 @@ fn to_sync_ciruit_witness( .sync_aggregate .sync_committee_bits .iter() - .map(|b| b) .collect(); args.attested_header = BeaconBlockHeader { slot: light_client_update.attested_header.beacon.slot, From ea102f3e7c4eb35bedb47f719cb3cc24ef962822 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 12:02:13 -0400 Subject: [PATCH 25/30] cargo udeps --- eth-types/Cargo.toml | 3 --- lightclient-circuits/Cargo.toml | 4 ---- test-utils/Cargo.toml | 1 - 3 files changed, 8 deletions(-) diff --git a/eth-types/Cargo.toml b/eth-types/Cargo.toml index cdf0cdc..200d2a7 100644 --- a/eth-types/Cargo.toml +++ b/eth-types/Cargo.toml @@ -10,16 +10,13 @@ pasta_curves.workspace = true uint.workspace = true hex.workspace = true halo2-base.workspace = true -halo2-ecc.workspace = true serde.workspace = true serde_json.workspace = true -itertools.workspace = true halo2curves.workspace = true ethereum-types.workspace = true regex = "1.5.4" lazy_static = "1.4" subtle = "2.4" -num = "0.4" num-bigint.workspace = true strum_macros = "0.24" strum = "0.24" diff --git a/lightclient-circuits/Cargo.toml b/lightclient-circuits/Cargo.toml index 3ce9f56..9c9df3a 100644 --- a/lightclient-circuits/Cargo.toml +++ b/lightclient-circuits/Cargo.toml @@ -26,14 +26,12 @@ pse-poseidon = { git = "https://github.com/axiom-crypto/pse-poseidon.git" } # ethereum ethereum-types = {workspace = true, default-features = false } -eth2.workspace = true tree_hash.workspace = true # local eth-types.workspace = true # misc -ark-std.workspace = true serde.workspace = true serde_json.workspace = true itertools.workspace = true @@ -41,8 +39,6 @@ log.workspace = true hex.workspace = true rayon = "1.7.0" array-init = "2.0.0" -strum = "0.25" -strum_macros = "0.25" rand = "0.8" lazy_static = "1.4" getset = "0.1.2" diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 54d4d30..02964d0 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -11,7 +11,6 @@ halo2-base = { workspace = true } ethereum-types = {workspace = true, default-features = false } -eth2.workspace = true tree_hash.workspace = true ethereum_ssz = { workspace = true } From 44238efc6133cd1e88430b5f071d0cc511532a7a Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 12:05:25 -0400 Subject: [PATCH 26/30] update contracts submodule --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index a430cae..a5d8d27 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit a430caeb3678582b73e3ee73b6f001bd9d1e75ca +Subproject commit a5d8d270ffa0d67e92770a7bcaa0acdfff76633b From ed0a0c2eb01837ce9561c7e62988a7c8e09caec5 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 12:11:14 -0400 Subject: [PATCH 27/30] fix cargo toml --- lightclient-circuits/Cargo.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lightclient-circuits/Cargo.toml b/lightclient-circuits/Cargo.toml index 9c9df3a..ffd5de2 100644 --- a/lightclient-circuits/Cargo.toml +++ b/lightclient-circuits/Cargo.toml @@ -44,10 +44,8 @@ lazy_static = "1.4" getset = "0.1.2" rand_chacha = "0.3.0" - - - [dev-dependencies] +ark-std.workspace = true rstest = "0.18.2" test-utils = { workspace = true } From 9c286582b8188aac31a8d0b92c08de6da66d4c68 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 12:22:18 -0400 Subject: [PATCH 28/30] lighouse legacy arith --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4742218..0faf803 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,7 @@ snark-verifier-sdk = { git = "https://github.com/axiom-crypto/snark-verifier.git ] } # ethereum types -ethereum-types = { package = "types", git = "https://github.com/sigp/lighthouse/", tag = "v5.1.3", default-features = false} +ethereum-types = { package = "types", git = "https://github.com/sigp/lighthouse/", tag = "v5.1.3", default-features = false, features = ["legacy-arith"] } tree_hash = { version = "0.5" } eth2 = { package = "eth2", git = "https://github.com/sigp/lighthouse/", tag = "v5.1.3" } merkle_proof = { package = "merkle_proof", git = "https://github.com/sigp/lighthouse/", tag = "v5.1.3" } From d22619c453b2239a6b48ac1fab321f93c738609d Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 12:35:59 -0400 Subject: [PATCH 29/30] remove unnecessary generic bounds --- .../src/committee_update_circuit.rs | 5 +-- preprocessor/src/lib.rs | 11 +---- preprocessor/src/rotation.rs | 22 +--------- preprocessor/src/step.rs | 9 +--- prover/src/cli.rs | 11 +---- prover/src/rpc.rs | 41 ++----------------- 6 files changed, 10 insertions(+), 89 deletions(-) diff --git a/lightclient-circuits/src/committee_update_circuit.rs b/lightclient-circuits/src/committee_update_circuit.rs index 6bd0ae3..15bf7e7 100644 --- a/lightclient-circuits/src/committee_update_circuit.rs +++ b/lightclient-circuits/src/committee_update_circuit.rs @@ -198,10 +198,7 @@ impl CommitteeUpdateCircuit { pub fn get_instances( args: &witness::CommitteeUpdateArgs, limb_bits: usize, - ) -> Vec> - where - [(); S::SYNC_COMMITTEE_SIZE]:, - { + ) -> Vec> { let poseidon_commitment = poseidon_committee_commitment_from_compressed(&args.pubkeys_compressed, limb_bits); diff --git a/preprocessor/src/lib.rs b/preprocessor/src/lib.rs index 96d0889..402de3b 100644 --- a/preprocessor/src/lib.rs +++ b/preprocessor/src/lib.rs @@ -54,16 +54,7 @@ pub async fn light_client_update_to_args( update: &LightClientUpdate, pubkeys_compressed: &FixedVector::SyncCommitteeSize>, domain: [u8; 32], -) -> eyre::Result<(SyncStepArgs, CommitteeUpdateArgs)> -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::SYNC_COMMITTEE_ROOT_INDEX]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, - [(); S::FINALIZED_HEADER_INDEX]:, -{ +) -> eyre::Result<(SyncStepArgs, CommitteeUpdateArgs)> { let finality_update = match update { LightClientUpdate::Altair(_) => unimplemented!(), LightClientUpdate::Capella(update) => { diff --git a/preprocessor/src/rotation.rs b/preprocessor/src/rotation.rs index ea435ee..bdbef31 100644 --- a/preprocessor/src/rotation.rs +++ b/preprocessor/src/rotation.rs @@ -16,16 +16,7 @@ use tree_hash::TreeHash; /// Fetches LightClientUpdate from the beacon client and converts it to a [`CommitteeUpdateArgs`] witness pub async fn fetch_rotation_args( client: &BeaconNodeHttpClient, -) -> eyre::Result> -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::SYNC_COMMITTEE_ROOT_INDEX]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, - [(); S::FINALIZED_HEADER_INDEX]:, -{ +) -> eyre::Result> { let block = client .get_beacon_headers_block_id(BlockId::Finalized) .await @@ -49,16 +40,7 @@ where /// Converts a [`LightClientUpdateCapella`] to a [`CommitteeUpdateArgs`] witness. pub async fn rotation_args_from_update( update: &LightClientUpdate, -) -> eyre::Result> -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::SYNC_COMMITTEE_ROOT_INDEX]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, - [(); S::FINALIZED_HEADER_INDEX]:, -{ +) -> eyre::Result> { let update = update.clone(); let next_sync_committee = update.next_sync_committee().clone(); diff --git a/preprocessor/src/step.rs b/preprocessor/src/step.rs index 14c3fa2..dec6a8d 100644 --- a/preprocessor/src/step.rs +++ b/preprocessor/src/step.rs @@ -18,14 +18,7 @@ use tree_hash::{Hash256, TreeHash}; /// Fetches the latest `LightClientFinalityUpdate`` and the current sync committee (from LightClientBootstrap) and converts it to a [`SyncStepArgs`] witness. pub async fn fetch_step_args( client: &BeaconNodeHttpClient, -) -> eyre::Result> -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, -{ +) -> eyre::Result> { let finality_update = client .get_beacon_light_client_finality_update::() .await diff --git a/prover/src/cli.rs b/prover/src/cli.rs index d6f2b55..0e8aeb4 100644 --- a/prover/src/cli.rs +++ b/prover/src/cli.rs @@ -25,16 +25,7 @@ use halo2_solidity_verifier_new::{ pub(crate) async fn spec_app( proof: ProofCmd, base_args: &BaseArgs, -) -> eyre::Result<()> -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::SYNC_COMMITTEE_ROOT_INDEX]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, - [(); S::FINALIZED_HEADER_INDEX]:, -{ +) -> eyre::Result<()> { match proof { ProofCmd::SyncStep { operation, diff --git a/prover/src/rpc.rs b/prover/src/rpc.rs index 9263d8e..34c8980 100644 --- a/prover/src/rpc.rs +++ b/prover/src/rpc.rs @@ -34,16 +34,7 @@ use crate::rpc_api::{ pub(crate) fn jsonrpc_server( state: ProverState, -) -> JsonRpcServer -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::SYNC_COMMITTEE_ROOT_INDEX]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, - [(); S::FINALIZED_HEADER_INDEX]:, -{ +) -> JsonRpcServer { JsonRpcServer::new() .with_data(Data::new(state)) .with_method( @@ -60,16 +51,7 @@ where pub(crate) async fn gen_evm_proof_committee_update_handler( Data(state): Data, Params(params): Params, -) -> Result -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::SYNC_COMMITTEE_ROOT_INDEX]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, - [(); S::FINALIZED_HEADER_INDEX]:, -{ +) -> Result { let _permit = state .concurrency .clone() @@ -129,13 +111,7 @@ where pub(crate) async fn gen_evm_proof_sync_step_compressed_handler( Data(state): Data, Params(params): Params, -) -> Result -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, -{ +) -> Result { let _permit = state .concurrency .clone() @@ -217,16 +193,7 @@ pub async fn run_rpc( config_dir: impl AsRef, build_dir: impl AsRef, concurrency: usize, -) -> Result<(), eyre::Error> -where - [(); S::SYNC_COMMITTEE_SIZE]:, - [(); S::FINALIZED_HEADER_DEPTH]:, - [(); S::BYTES_PER_LOGS_BLOOM]:, - [(); S::MAX_EXTRA_DATA_BYTES]:, - [(); S::SYNC_COMMITTEE_ROOT_INDEX]:, - [(); S::SYNC_COMMITTEE_DEPTH]:, - [(); S::FINALIZED_HEADER_INDEX]:, -{ +) -> Result<(), eyre::Error> { let tcp_listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", port)).await?; let timer = start_timer!(|| "Load Prover State and Context"); let state = ProverState::new::(config_dir.as_ref(), build_dir.as_ref(), concurrency); From 82ed811f18906f30c89b2e084dacf719eacfa352 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Apr 2024 12:44:12 -0400 Subject: [PATCH 30/30] remove blob params from Spec --- eth-types/src/spec.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/eth-types/src/spec.rs b/eth-types/src/spec.rs index 5cba679..82802fa 100644 --- a/eth-types/src/spec.rs +++ b/eth-types/src/spec.rs @@ -20,8 +20,6 @@ pub trait Spec: 'static + Sized + Copy + Default + Debug { const EXECUTION_STATE_ROOT_DEPTH: usize; const FINALIZED_HEADER_INDEX: usize; const FINALIZED_HEADER_DEPTH: usize; - const BYTES_PER_LOGS_BLOOM: usize = 256; - const MAX_EXTRA_DATA_BYTES: usize = 32; } #[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] @@ -42,9 +40,6 @@ impl Spec for Minimal { const EXECUTION_STATE_ROOT_DEPTH: usize = 4; const FINALIZED_HEADER_INDEX: usize = 105; const FINALIZED_HEADER_DEPTH: usize = 6; - - const BYTES_PER_LOGS_BLOOM: usize = 256; - const MAX_EXTRA_DATA_BYTES: usize = 32; } #[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] @@ -64,9 +59,6 @@ impl Spec for Testnet { const EXECUTION_STATE_ROOT_DEPTH: usize = 4; const FINALIZED_HEADER_INDEX: usize = 105; const FINALIZED_HEADER_DEPTH: usize = 6; - - const BYTES_PER_LOGS_BLOOM: usize = 256; - const MAX_EXTRA_DATA_BYTES: usize = 32; } #[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] @@ -86,7 +78,4 @@ impl Spec for Mainnet { const EXECUTION_STATE_ROOT_DEPTH: usize = 4; const FINALIZED_HEADER_INDEX: usize = 105; const FINALIZED_HEADER_DEPTH: usize = 6; - - const BYTES_PER_LOGS_BLOOM: usize = 256; - const MAX_EXTRA_DATA_BYTES: usize = 32; }