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 14 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
8 changes: 5 additions & 3 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/", 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
group = "0.13"
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
8 changes: 6 additions & 2 deletions lightclient-circuits/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 }
Expand Down
7 changes: 4 additions & 3 deletions lightclient-circuits/src/committee_update_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ use halo2_ecc::{
fields::FieldChip,
};
use itertools::Itertools;
use ssz_rs::Merkleized;
// use ssz_rs::Merkleized;
ec2 marked this conversation as resolved.
Show resolved Hide resolved
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 +91,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 @@ -205,7 +206,7 @@ impl<S: Spec, F: Field> CommitteeUpdateCircuit<S, F> {
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
16 changes: 8 additions & 8 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
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
14 changes: 7 additions & 7 deletions lightclient-circuits/src/witness/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -60,21 +60,21 @@ impl<S: Spec> Default for CommitteeUpdateArgs<S> {
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<u8>, branch: &[Vec<u8>], mut gindex: usize) -> Vec<u8> {
pub(crate) fn mock_root(leaf: Vec<u8>, branch: &[Vec<u8>], mut gindex: usize) -> [u8; 32] {
let mut last_hash = leaf;

for i in 0..branch.len() {
Expand All @@ -90,7 +90,7 @@ pub(crate) fn mock_root(leaf: Vec<u8>, branch: &[Vec<u8>], mut gindex: usize) ->
gindex /= 2;
}

last_hash
last_hash.try_into().unwrap()
}

#[cfg(test)]
Expand Down
29 changes: 12 additions & 17 deletions lightclient-circuits/src/witness/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@
// 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};
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;

Expand Down Expand Up @@ -64,36 +62,33 @@ impl<S: Spec> Default for SyncStepArgs<S> {
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);

let sks = (0..S::SYNC_COMMITTEE_SIZE)
.map(|_| Fr::random(&mut rng))
.collect_vec();
let msg = <G2 as hash_to_curve::HashToCurve<ExpandMsgXmd<sha2::Sha256>>>::hash_to_curve(
signing_root.deref(),
signing_root.0,
S::DST,
)
.to_affine();
Expand Down
16 changes: 10 additions & 6 deletions preprocessor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,38 @@ 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
merkle_proof.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 }
ec2 marked this conversation as resolved.
Show resolved Hide resolved
# 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
snark-verifier-sdk.workspace = true
ark-std.workspace = true

[features]
test-gen = ["ethereum-consensus", "blst"]
test-gen = []
Loading
Loading