Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Lighthouse Types instead of maintaining our own #77

Merged
merged 30 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,11 @@ 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/", 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" }
ethereum_ssz = "0.5.3"

# crypto
group = "0.13"
Expand All @@ -90,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" }
Expand Down
3 changes: 2 additions & 1 deletion contract-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 4 additions & 12 deletions contract-tests/tests/step_input_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -28,20 +27,13 @@ impl<Spec: eth_types::Spec> From<SyncStepArgs<Spec>> for StepInput {
.map(|v| *v as u64)
.sum::<u64>();

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,
Expand Down
4 changes: 1 addition & 3 deletions eth-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +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"
21 changes: 9 additions & 12 deletions eth-types/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -18,14 +20,14 @@ 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)]
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;
Expand All @@ -38,15 +40,14 @@ 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)]
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;
Expand All @@ -58,15 +59,14 @@ 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)]
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;
Expand All @@ -78,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;
}
8 changes: 3 additions & 5 deletions lightclient-circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,27 @@ 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 }
tree_hash.workspace = true

# local
eth-types.workspace = true

# misc
ark-std.workspace = true
serde.workspace = true
serde_json.workspace = true
itertools.workspace = true
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"
rand_chacha = "0.3.0"

[dev-dependencies]
ark-std.workspace = true
rstest = "0.18.2"
test-utils = { workspace = true }

Expand Down
18 changes: 5 additions & 13 deletions lightclient-circuits/src/committee_update_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ use halo2_ecc::{
fields::FieldChip,
};
use itertools::Itertools;
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.
///
Expand Down Expand Up @@ -90,7 +90,7 @@ impl<S: Spec, F: Field> CommitteeUpdateCircuit<S, F> {
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(),
Expand Down Expand Up @@ -198,14 +198,11 @@ impl<S: Spec, F: Field> CommitteeUpdateCircuit<S, F> {
pub fn get_instances(
args: &witness::CommitteeUpdateArgs<S>,
limb_bits: usize,
) -> Vec<Vec<bn256::Fr>>
where
[(); S::SYNC_COMMITTEE_SIZE]:,
{
) -> Vec<Vec<bn256::Fr>> {
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();
Expand Down Expand Up @@ -279,12 +276,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};
Expand Down
21 changes: 9 additions & 12 deletions lightclient-circuits/src/sync_step_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -110,7 +110,8 @@ impl<S: Spec, F: Field> StepCircuit<S, F> {
)?;

// 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
Expand Down Expand Up @@ -138,7 +139,8 @@ impl<S: Spec, F: Field> StepCircuit<S, F> {
.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,
Expand Down Expand Up @@ -230,11 +232,11 @@ impl<S: Spec, F: Field> StepCircuit<S, F> {
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);

Expand All @@ -250,9 +252,7 @@ impl<S: Spec, F: Field> StepCircuit<S, F> {

let finalized_header_root: [u8; 32] = args
.finalized_header
.clone()
.hash_tree_root()
.unwrap()
.tree_hash_root()
.as_ref()
.try_into()
.unwrap();
Expand Down Expand Up @@ -435,10 +435,7 @@ impl<S: Spec> AppCircuit for StepCircuit<S, bn256::Fr> {
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};
Expand Down
21 changes: 12 additions & 9 deletions lightclient-circuits/src/witness/multiproof.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -93,7 +93,7 @@ pub fn get_helper_indices(indices: &[GeneralizedIndex]) -> Vec<GeneralizedIndex>
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;

Expand All @@ -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<usize, Node> = indices
let mut objects: HashMap<usize, Hash256> = indices
.iter()
.chain(helper_indices.iter())
.copied()
Expand Down Expand Up @@ -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<Node> {
pub fn merkle_tree(leaves: &[Hash256]) -> Vec<Hash256> {
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();
Expand All @@ -178,7 +178,10 @@ pub fn merkle_tree(leaves: &[Node]) -> Vec<Node> {
o
}

pub fn create_multiproof(merkle_tree: &[Node], indices_to_prove: &[GeneralizedIndex]) -> Vec<Node> {
pub fn create_multiproof(
ec2 marked this conversation as resolved.
Show resolved Hide resolved
merkle_tree: &[Hash256],
indices_to_prove: &[GeneralizedIndex],
) -> Vec<Hash256> {
get_helper_indices(indices_to_prove)
.into_iter()
.map(|i| merkle_tree[i])
Expand Down
Loading