Skip to content

Commit

Permalink
Verify block header & execution root (#4)
Browse files Browse the repository at this point in the history
* feat(preprocessor): merkle proofs for exec & finalized blocks roots

* remove `SyncStateInput`

* add exec state root and finilized header verification

* fix circuit's default impl

* cargo fix
  • Loading branch information
nulltea authored Sep 5, 2023
1 parent 588c5ee commit dfba719
Show file tree
Hide file tree
Showing 16 changed files with 384 additions and 229 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@ snark-verifier-sdk = { git = "https://github.com/timoftime/snark-verifier", bran

# [patch."https://github.com/timoftime/halo2curves"]
# halo2curves = { path = "../halo2curves" }

[patch."https://github.com/ralexstokes/ssz-rs"]
ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "seun/ssz-merkle-multi-proof-phase-1" }
12 changes: 12 additions & 0 deletions eth-types/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ use core::fmt::Debug;
pub trait Spec: 'static + Sized + Copy + Default + Debug {
const SYNC_COMMITTEE_SIZE: usize;
const DST: &'static [u8];
const EXECUTION_STATE_ROOT_INDEX: usize;
const EXECUTION_STATE_ROOT_DEPTH: usize;
const FINALIZED_HEADER_INDEX: usize;
const FINALIZED_HEADER_DEPTH: usize;
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
Expand All @@ -11,6 +15,10 @@ pub struct Test;
impl Spec for Test {
const SYNC_COMMITTEE_SIZE: usize = 512;
const DST: &'static [u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
const EXECUTION_STATE_ROOT_INDEX: usize = 402;
const EXECUTION_STATE_ROOT_DEPTH: usize = 8;
const FINALIZED_HEADER_INDEX: usize = 105;
const FINALIZED_HEADER_DEPTH: usize = 6;
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
Expand All @@ -19,4 +27,8 @@ pub struct Mainnet;
impl Spec for Mainnet {
const SYNC_COMMITTEE_SIZE: usize = 512;
const DST: &'static [u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
const EXECUTION_STATE_ROOT_INDEX: usize = 402;
const EXECUTION_STATE_ROOT_DEPTH: usize = 8;
const FINALIZED_HEADER_INDEX: usize = 105;
const FINALIZED_HEADER_DEPTH: usize = 6;
}
1 change: 1 addition & 0 deletions ligthclient-circuits/config/sync_step_k20.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "strategy": "Vertical", "k": 20, "num_advice_per_phase": [17, 0, 0], "num_lookup_advice_per_phase": [2, 0, 0], "num_fixed": 1 }
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{ "strategy": "Vertical", "k": 21, "num_advice_per_phase": [7, 0, 0], "num_lookup_advice_per_phase": [1, 0, 0], "num_fixed": 1 }
{ "strategy": "Vertical", "k": 21, "num_advice_per_phase": [9, 0, 0], "num_lookup_advice_per_phase": [1, 0, 0], "num_fixed": 1 }
14 changes: 5 additions & 9 deletions ligthclient-circuits/src/committee_update_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
util::{
decode_into_field, gen_pkey, AppCircuitExt, AssignedValueCell, Challenges, IntoWitness,
},
witness::{self, HashInput, HashInputChunk, SyncStateInput},
witness::{self, HashInput, HashInputChunk},
};
use eth_types::{AppCurveExt, Field, Spec};
use ethereum_consensus::phase0::BeaconBlockHeader;
Expand Down Expand Up @@ -79,10 +79,7 @@ pub struct CommitteeUpdateCircuit<S: Spec, F: Field> {
}

impl<S: Spec, F: Field> CommitteeUpdateCircuit<S, F> {
fn new_from_state(
builder: RefCell<GateThreadBuilder<F>>,
state: &witness::SyncState<F>,
) -> Self {
fn new_from_state(builder: RefCell<GateThreadBuilder<F>>, state: &witness::SyncState) -> Self {
let pubkeys_y = state
.sync_committee
.iter()
Expand Down Expand Up @@ -315,7 +312,7 @@ impl<S: Spec, F: Field> CircuitExt<F> for CommitteeUpdateCircuit<S, F> {
impl<S: Spec> AppCircuitExt<bn256::Fr> for CommitteeUpdateCircuit<S, bn256::Fr> {
fn new_from_state(
builder: RefCell<GateThreadBuilder<bn256::Fr>>,
state: &witness::SyncState<bn256::Fr>,
state: &witness::SyncState,
) -> Self {
let pubkeys_y = state
.sync_committee
Expand Down Expand Up @@ -426,7 +423,7 @@ mod tests {
use crate::{
table::Sha256Table,
util::{full_prover, full_verifier, gen_pkey},
witness::{SyncState, SyncStateInput, Validator},
witness::{SyncState, Validator},
};

use super::*;
Expand Down Expand Up @@ -460,9 +457,8 @@ mod tests {

fn get_circuit_with_data(k: usize) -> CommitteeUpdateCircuit<Test, Fr> {
let builder = GateThreadBuilder::new(false);
let state_input: SyncStateInput =
let state: SyncState =
serde_json::from_slice(&fs::read("../test_data/sync_state.json").unwrap()).unwrap();
let state = state_input.into();

let _ = CommitteeUpdateCircuit::<Test, Fr>::parametrize(k);

Expand Down
4 changes: 2 additions & 2 deletions ligthclient-circuits/src/sha256_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1110,8 +1110,8 @@ pub struct Sha256Circuit<'a, F: Field> {
}

impl<'a, F: Field> Sha256Circuit<'a, F> {
fn new_from_state(state: &'a witness::SyncState<F>) -> Self {
Self::new(&state.sha256_inputs)
fn new_from_state(state: &'a witness::SyncState) -> Self {
todo!()
}

/// Make the assignments to the KeccakCircuit
Expand Down
50 changes: 43 additions & 7 deletions ligthclient-circuits/src/ssz_merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,12 @@ pub const ZERO_HASHES: [[u8; 32]; 2] = [
],
];

pub fn ssz_merkleize_chunks<'a, F: Field, I: IntoIterator<Item = HashInputChunk<QuantumCell<F>>>>(
pub fn ssz_merkleize_chunks<F: Field>(
ctx: &mut Context<F>,
region: &mut Region<'_, F>,
hasher: &'a impl HashChip<F>,
chunks: I,
) -> Result<Vec<AssignedValue<F>>, Error>
where
I::IntoIter: ExactSizeIterator,
{
hasher: &impl HashChip<F>,
chunks: impl IntoIterator<Item = HashInputChunk<QuantumCell<F>>>,
) -> Result<Vec<AssignedValue<F>>, Error> {
let mut chunks = chunks.into_iter().collect_vec();
let len_even = chunks.len() + chunks.len() % 2;
let height = (len_even as f64).log2().ceil() as usize;
Expand Down Expand Up @@ -59,3 +56,42 @@ where

Ok(root.bytes)
}

pub fn verify_merkle_proof<F: Field>(
ctx: &mut Context<F>,
region: &mut Region<'_, F>,
hasher: &impl HashChip<F>,
proof: impl IntoIterator<Item = HashInputChunk<QuantumCell<F>>>,
leaf: HashInputChunk<QuantumCell<F>>,
root: &[AssignedValue<F>],
mut gindex: usize,
) -> Result<(), Error> {
let mut computed_hash = leaf;

for witness in proof.into_iter() {
computed_hash = hasher
.digest::<128>(
if gindex % 2 == 0 {
HashInput::TwoToOne(computed_hash, witness)
} else {
HashInput::TwoToOne(witness, computed_hash)
},
ctx,
region,
)?
.output_bytes
.into();
gindex /= 2;
}

let computed_root = computed_hash.bytes.into_iter().map(|b| match b {
QuantumCell::Existing(av) => av,
_ => unreachable!(),
});

computed_root.zip(root.iter()).for_each(|(a, b)| {
ctx.constrain_equal(&a, b);
});

Ok(())
}
Loading

0 comments on commit dfba719

Please sign in to comment.