Skip to content

Commit

Permalink
docs (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
nulltea committed Dec 14, 2023
1 parent 684dbed commit 1a25f2f
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 23 deletions.
10 changes: 6 additions & 4 deletions lightclient-circuits/src/aggregation_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::{
path::Path,
};

/// Configuration for the aggregation circuit.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AggregationConfigPinning {
pub params: AggregationConfigParams,
Expand Down Expand Up @@ -79,12 +80,12 @@ impl AppCircuit for AggregationCircuit {
snark: &Self::Witness,
k: u32,
) -> Result<impl crate::util::PinnableCircuit<Fr>, Error> {
// let lookup_bits = k as usize - 1;
let lookup_bits = k as usize - 1;
let params = gen_srs(k);
let circuit_params = pinning.clone().map_or(
AggregationConfigParams {
degree: k,
lookup_bits: 8,
lookup_bits,
..Default::default()
},
|p| p.params,
Expand All @@ -97,14 +98,15 @@ impl AppCircuit for AggregationCircuit {
Default::default(),
);

// We assume that `AggregationCircuit` will only be used for a single aggregation/compression layer.
circuit.expose_previous_instances(false);

match stage {
CircuitBuilderStage::Prover => {
circuit.expose_previous_instances(false);
circuit.set_params(circuit_params);
circuit.set_break_points(pinning.map_or(vec![], |p| p.break_points));
}
_ => {
circuit.expose_previous_instances(false);
set_var(
"AGG_CONFIG_PARAMS",
serde_json::to_string(&circuit.calculate_params(Some(10))).unwrap(),
Expand Down
12 changes: 10 additions & 2 deletions lightclient-circuits/src/committee_update_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ use std::{env::var, iter, marker::PhantomData, vec};

/// `CommitteeUpdateCircuit` maps next sync committee SSZ root in the finalized state root to the corresponding Poseidon commitment to the public keys.
///
///
/// Assumes that public keys are BLS12-381 points on G1; `sync_committee_branch` is exactly `S::SYNC_COMMITTEE_PUBKEYS_DEPTH` hashes in lenght.
///
/// The circuit exposes two public inputs:
/// - `poseidon_commit` is a Poseidon "onion" commitment to the X coordinates of sync committee public keys. Coordinates are expressed as big-integer with two limbs of LIMB_BITS * 2 bits.
/// - `committee_root_ssz` is a Merkle SSZ root of the list of sync committee public keys.
/// - `finalized_header_root` is a Merkle SSZ root of the finalized header.
#[derive(Clone, Debug, Default)]
pub struct CommitteeUpdateCircuit<S: Spec, F: Field> {
_f: PhantomData<F>,
Expand Down Expand Up @@ -53,7 +58,7 @@ impl<S: Spec, F: Field> CommitteeUpdateCircuit<S, F> {
})
.collect_vec();

// Note: This is the root of the public keys in the SyncCommittee struct
// Note: This is the root of the public keys list in the SyncCommittee struct
// not the root of the SyncCommittee struct itself.
let committee_root_ssz =
Self::sync_committee_root_ssz(builder, &sha256_chip, compressed_encodings.clone())?;
Expand Down Expand Up @@ -103,6 +108,9 @@ impl<S: Spec, F: Field> CommitteeUpdateCircuit<S, F> {
Ok(public_inputs)
}

/// Decodes the pub keys bytes into and X coordinate reperesented as a big integers.
///
/// Assumes that input bytes are in Big-Endian encoding.
fn decode_pubkeys_x(
ctx: &mut Context<F>,
fp_chip: &FpChip<'_, F>,
Expand Down
27 changes: 21 additions & 6 deletions lightclient-circuits/src/ssz_merkle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
gadget::crypto::HashInstructions,
util::IntoConstant,
witness::{HashInput, HashInputChunk},
};
use eth_types::Field;
Expand All @@ -11,19 +12,25 @@ use itertools::Itertools;

/// Computes Merkle root of a list of SSZ chunks.
///
/// Assumes that number if chunks is a power of two.
/// Can work with numbers of chunks that are not a power of two, in which case the tree level is padded with zero hashes.
/// However, zero hashes are only precomputed for the first two levels.
pub fn ssz_merkleize_chunks<F: Field, CircuitBuilder: CommonCircuitBuilder<F>>(
builder: &mut CircuitBuilder,
hasher: &impl HashInstructions<F, CircuitBuilder = CircuitBuilder>,
chunks: impl IntoIterator<Item = HashInputChunk<QuantumCell<F>>>,
) -> Result<Vec<AssignedValue<F>>, Error> {
let mut chunks = chunks.into_iter().collect_vec();
assert!(chunks.len().is_power_of_two());

let height = (chunks.len() as f64).log2() as usize;
let len_even = chunks.len() + chunks.len() % 2;
let height = (len_even as f64).log2().ceil() as usize;
for depth in 0..height {
// Pad to even length using 32 zero bytes assigned as constants.
let len_even = chunks.len() + chunks.len() % 2;
let padded_chunks = chunks
.into_iter()
.pad_using(len_even, |_| ZERO_HASHES[depth].as_slice().into_constant())
.collect_vec();

for _ in 0..height {
chunks = chunks
chunks = padded_chunks
.into_iter()
.tuples()
.map(|(left, right)| {
Expand Down Expand Up @@ -82,3 +89,11 @@ pub fn verify_merkle_proof<F: Field, CircuitBuilder: CommonCircuitBuilder<F>>(

Ok(())
}

pub const ZERO_HASHES: [[u8; 32]; 2] = [
[0; 32],
[
245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35,
32, 217, 240, 232, 234, 152, 49, 169, 39, 89, 251, 75,
],
];
7 changes: 7 additions & 0 deletions lightclient-circuits/src/witness/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ use std::ops::Deref;

use super::mock_root;

/// Input datum for the `StepCircuit` to verify `attested_header` singed by the lightclient sync committee,
/// and the `execution_payload_root` via Merkle `finality_branch` against the `finalized_header` root.
///
/// Assumes that aggregated BLS signarure is represented as a compressed G2 point and the public keys are uncompressed G1 points;
/// `pariticipation_bits` vector has exactly `S::SYNC_COMMITTEE_SIZE`` bits;
/// `finality_branch` and `execution_payload_branch` are exactly `S::FINALIZED_HEADER_DEPTH` and `S::EXECUTION_STATE_ROOT_DEPTH` long respectively.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncStepArgs<S: Spec> {
pub signature_compressed: Vec<u8>,
Expand All @@ -37,6 +43,7 @@ pub struct SyncStepArgs<S: Spec> {
pub _spec: PhantomData<S>,
}

// This default witness is used for the test-cases in the `test-utils` crate.
impl<S: Spec> Default for SyncStepArgs<S> {
fn default() -> Self {
const DOMAIN: [u8; 32] = [
Expand Down
7 changes: 0 additions & 7 deletions prover/src/rpc_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,6 @@ pub struct SyncStepCompressedEvmProofResult {
pub public_inputs: Vec<U256>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncStepCompressedEvmProofResult {
pub proof: Vec<u8>,
pub accumulator: [U256; 12],
pub public_inputs: Vec<U256>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommitteeUpdateEvmProofResult {
pub proof: Vec<u8>,
Expand Down
3 changes: 2 additions & 1 deletion prover/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ pub(crate) async fn utils_cli(method: UtilsCmd) -> eyre::Result<()> {
.unwrap();
println!("ssz root: {:?}", hex::encode(ssz_root.deref()));

let committee_poseidon =
let mut committee_poseidon =
poseidon_committee_commitment_from_uncompressed(&pubkeys_uncompressed).to_bytes();
committee_poseidon.reverse();
println!("poseidon commitment: {}", hex::encode(committee_poseidon));

Ok(())
Expand Down
6 changes: 3 additions & 3 deletions test-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ 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::{CommitteeRotationArgs, SyncStepArgs};
use lightclient_circuits::witness::{CommitteeUpdateArgs, SyncStepArgs};
use ssz_rs::prelude::*;
use ssz_rs::Merkleized;
use std::ops::Deref;
Expand Down Expand Up @@ -80,7 +80,7 @@ pub fn valid_updates_from_test_path(

pub fn read_test_files_and_gen_witness(
path: &Path,
) -> (SyncStepArgs<Minimal>, CommitteeRotationArgs<Minimal>) {
) -> (SyncStepArgs<Minimal>, CommitteeUpdateArgs<Minimal>) {
let bootstrap: LightClientBootstrap =
load_snappy_ssz(path.join("bootstrap.ssz_snappy").to_str().unwrap()).unwrap();

Expand Down Expand Up @@ -109,7 +109,7 @@ pub fn read_test_files_and_gen_witness(

sync_committee_branch.insert(0, agg_pk.hash_tree_root().unwrap().deref().to_vec());

let rotation_wit = CommitteeRotationArgs::<Minimal> {
let rotation_wit = CommitteeUpdateArgs::<Minimal> {
pubkeys_compressed: updates[0]
.next_sync_committee
.pubkeys
Expand Down

0 comments on commit 1a25f2f

Please sign in to comment.