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

Step and Rotate with same update #52

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions contract-tests/tests/step_input_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl<Spec: eth_types::Spec> From<SyncStepArgs<Spec>> for SyncStepInput {
participation,
finalized_header_root,
execution_payload_root,
accumulator: Default::default()
accumulator: Default::default(),
}
}
}
Expand All @@ -68,7 +68,10 @@ async fn test_step_instance_commitment_evm_equivalence(
let contract = SyncStepExternal::deploy(ethclient, ())?.send().await?;

let result = contract
.to_public_inputs(SyncStepInput::from(witness), U256::from_little_endian(&instance[0][1].to_bytes()))
.to_public_inputs(
SyncStepInput::from(witness),
U256::from_little_endian(&instance[0][1].to_bytes()),
)
.call()
.await?;
let result_decoded = decode_solidity_u256_array(&result);
Expand Down
8 changes: 4 additions & 4 deletions lightclient-circuits/src/poseidon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ const R_P: usize = N_ROUNDS_PC[T - 2];
const R_F: usize = 8;

/// Generates Poseidon hash commitment to a list of BLS12-381 Fq elements.
///
///
/// Fields elements are initially represented as `NUM_LIMBS` limbs of `LIMB_BITS` bits each.
/// By composing element two limbs in one, we reduce the number of inputs to Poseidon in half.
///
///
/// Each Poseidon sponge absorbs `POSEIDON_SIZE`-2 elements and previos sponge output if it's not the first batch, ie. onion commitment.
///
///
/// Assumes that LIMB_BITS * 2 < 254 (BN254).
pub fn fq_array_poseidon<'a, F: Field>(
ctx: &mut Context<F>,
Expand Down Expand Up @@ -74,7 +74,7 @@ pub fn fq_array_poseidon<'a, F: Field>(
}

/// Generates Poseidon hash commitment to a list of BLS12-381 Fq elements.
///
///
/// This is the off-circuit analog of `fq_array_poseidon`.
pub fn poseidon_hash_fq_array<F: Field>(elems: impl Iterator<Item = Fq>, limb_bits: usize) -> F {
let limbs = elems
Expand Down
1 change: 0 additions & 1 deletion lightclient-circuits/src/sync_step_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@ impl<S: Spec> AppCircuit for StepCircuit<S, bn256::Fr> {
}
}


#[cfg(test)]
mod tests {
use std::fs;
Expand Down
3 changes: 2 additions & 1 deletion lightclient-circuits/src/util/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ pub trait AppCircuit {
) -> ProvingKey<G1Affine> {
let pinning = Self::Pinning::from_path(pinning_path);
let circuit =
Self::create_circuit(CircuitBuilderStage::Keygen, Some(pinning), witness, params).unwrap();
Self::create_circuit(CircuitBuilderStage::Keygen, Some(pinning), witness, params)
.unwrap();
custom_read_pk(path, &circuit)
}

Expand Down
2 changes: 1 addition & 1 deletion lightclient-circuits/src/witness/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use sha2::{Digest, Sha256};
use std::{iter, marker::PhantomData};

/// Input datum for the `CommitteeUpdateCircuit` to map 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.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommitteeUpdateArgs<S: Spec> {
Expand Down
12 changes: 4 additions & 8 deletions lightclient-circuits/src/witness/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ 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.
Expand Down Expand Up @@ -138,13 +138,9 @@ mod tests {
const K: u32 = 20;
let witness = SyncStepArgs::<Testnet>::default();

let circuit = StepCircuit::<Testnet, Fr>::mock_circuit(
CircuitBuilderStage::Mock,
None,
&witness,
K,
)
.unwrap();
let circuit =
StepCircuit::<Testnet, Fr>::mock_circuit(CircuitBuilderStage::Mock, None, &witness, K)
.unwrap();

let prover = MockProver::<Fr>::run(K, &circuit, circuit.instances()).unwrap();
prover.assert_satisfied_par();
Expand Down
169 changes: 166 additions & 3 deletions preprocessor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ use beacon_api_client::{BlockId, Client, ClientTypes, Value, VersionedValue};
use eth_types::Spec;
use ethereum_consensus_types::bls::BlsSignature;
use ethereum_consensus_types::{
BeaconBlockHeader, LightClientBootstrap, LightClientFinalityUpdate, LightClientUpdateCapella,
Root,
BeaconBlockHeader, BlsPublicKey, ByteVector, LightClientBootstrap, LightClientFinalityUpdate,
LightClientUpdateCapella, Root,
};

use itertools::Itertools;
use lightclient_circuits::witness::{CommitteeUpdateArgs, SyncStepArgs};
pub use rotation::*;
use serde::{Deserialize, Serialize};
use ssz_rs::Node;
use ssz_rs::{Node, Vector};
pub use step::*;

pub async fn get_light_client_update_at_period<S: Spec, C: ClientTypes>(
Expand Down Expand Up @@ -122,3 +124,164 @@ pub async fn get_block_header<C: ClientTypes>(
let block: BeaconHeaderSummary = client.get::<Value<_>>(&route).await?.data;
Ok(block.header.message)
}

pub async fn light_client_update_to_args<S: Spec>(
update: &mut 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<BlsPublicKey, { S::SYNC_COMMITTEE_SIZE }>,
domain: [u8; 32],
) -> eyre::Result<(SyncStepArgs<S>, CommitteeUpdateArgs<S>)>
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 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 rotation_args = rotation::rotation_args_from_update(update).await?;

let sync_args =
step::step_args_from_finality_update(finality_update, pubkeys_compressed, domain).await?;

Ok((sync_args, rotation_args))
}

#[cfg(test)]
mod tests {
use beacon_api_client::StateId;
use eth_types::Testnet;
use ethereum_consensus_types::signing::{compute_domain, DomainType};
use ethereum_consensus_types::ForkData;
use lightclient_circuits::committee_update_circuit::CommitteeUpdateCircuit;
use lightclient_circuits::halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr};
use lightclient_circuits::util::{Eth2ConfigPinning, Halo2ConfigPinning};
use lightclient_circuits::{
halo2_base::gates::circuit::CircuitBuilderStage, sync_step_circuit::StepCircuit,
util::AppCircuit,
};
use snark_verifier_sdk::CircuitExt;

use super::*;
use beacon_api_client::mainnet::Client as MainnetClient;
use reqwest::Url;

#[tokio::test]
async fn test_both_circuit_sepolia() {
const K: u32 = 21;
let client =
MainnetClient::new(Url::parse("https://lodestar-sepolia.chainsafe.io").unwrap());

let block = get_block_header(&client, BlockId::Finalized).await.unwrap();
let slot = block.slot;
let period = slot / (32 * 256);

println!(
"Fetching light client update at current Slot: {} at Period: {}",
slot, period
);

// Fetch light client update and create circuit arguments
let (s, mut c) = {
let mut update = get_light_client_update_at_period(&client, period)
.await
.unwrap();

let block_root = client
.get_beacon_block_root(BlockId::Slot(slot))
.await
.unwrap();

let bootstrap = get_light_client_bootstrap(&client, block_root)
.await
.unwrap();

let pubkeys_compressed = bootstrap.current_sync_committee.pubkeys;

let fork_version = client
.get_fork(StateId::Head)
.await
.unwrap()
.current_version;
let genesis_validators_root = client
.get_genesis_details()
.await
.unwrap()
.genesis_validators_root;
let fork_data = ForkData {
genesis_validators_root,
fork_version,
};
let domain = compute_domain(DomainType::SyncCommittee, &fork_data).unwrap();
light_client_update_to_args::<Testnet>(&mut update, pubkeys_compressed, domain)
.await
.unwrap()
};

let mut finalized_sync_committee_branch = {
let block_root = client
.get_beacon_block_root(BlockId::Slot(s.finalized_header.slot))
.await
.unwrap();

get_light_client_bootstrap::<Testnet, _>(&client, block_root)
.await
.unwrap()
.current_sync_committee_branch
.iter()
.map(|n| n.to_vec())
.collect_vec()
};

// 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();
c.sync_committee_branch = finalized_sync_committee_branch;
// Replaces the attested header with step circuits finalized header
c.finalized_header = s.finalized_header.clone();

let circuit =
StepCircuit::<Testnet, Fr>::mock_circuit(CircuitBuilderStage::Mock, None, &s, K)
.unwrap();

let prover = MockProver::<Fr>::run(K, &circuit, circuit.instances()).unwrap();
prover.assert_satisfied_par();

const CONFIG_PATH: &str = "../lightclient-circuits/config/committee_update_testnet.json";

let pinning = Eth2ConfigPinning::from_path(CONFIG_PATH);
let circuit = CommitteeUpdateCircuit::<Testnet, Fr>::mock_circuit(
CircuitBuilderStage::Mock,
Some(pinning),
&c,
K,
)
.unwrap();

let prover = MockProver::<Fr>::run(K, &circuit, circuit.instances()).unwrap();
prover.assert_satisfied_par();
}
}
7 changes: 4 additions & 3 deletions preprocessor/src/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ where

/// Converts a [`LightClientUpdateCapella`] to a [`CommitteeUpdateArgs`] witness.
pub async fn rotation_args_from_update<S: Spec>(
update: &mut LightClientUpdateCapella<
update: &LightClientUpdateCapella<
{ S::SYNC_COMMITTEE_SIZE },
{ S::SYNC_COMMITTEE_ROOT_INDEX },
{ S::SYNC_COMMITTEE_DEPTH },
Expand All @@ -60,6 +60,7 @@ where
[(); S::SYNC_COMMITTEE_DEPTH]:,
[(); S::FINALIZED_HEADER_INDEX]:,
{
let mut update = update.clone();
let pubkeys_compressed = update
.next_sync_committee
.pubkeys
Expand Down Expand Up @@ -94,7 +95,7 @@ where

let args = CommitteeUpdateArgs::<S> {
pubkeys_compressed,
finalized_header: update.attested_header.beacon.clone(),
finalized_header: update.finalized_header.beacon.clone(),
sync_committee_branch: sync_committee_branch
.into_iter()
.map(|n| n.to_vec())
Expand All @@ -121,7 +122,7 @@ mod tests {

#[tokio::test]
async fn test_rotation_circuit_sepolia() {
const CONFIG_PATH: &str = "../lightclient-circuits/config/committee_update.json";
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());
Expand Down
5 changes: 3 additions & 2 deletions prover/src/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use url::Url;

use crate::rpc_api::{
CommitteeUpdateEvmProofResult, GenProofStepParams, SyncStepCompressedEvmProofResult,
RPC_EVM_PROOF_COMMITTEE_UPDATE_CIRCUIT_COMPRESSED, RPC_EVM_PROOF_STEP_CIRCUIT_COMPRESSED, GenProofCommitteeUpdateParams,
CommitteeUpdateEvmProofResult, GenProofCommitteeUpdateParams, GenProofStepParams,
SyncStepCompressedEvmProofResult, RPC_EVM_PROOF_COMMITTEE_UPDATE_CIRCUIT_COMPRESSED,
RPC_EVM_PROOF_STEP_CIRCUIT_COMPRESSED,
};

/// Error object in a response
Expand Down
2 changes: 1 addition & 1 deletion prover/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Code: https://github.com/ChainSafe/Spectre
// SPDX-License-Identifier: LGPL-3.0-only

use std::{env, ops::Deref, sync::Arc};
use std::{ops::Deref, sync::Arc};

use beacon_api_client::{BlockId, VersionedValue};
use ethereum_consensus_types::LightClientBootstrap;
Expand Down
Loading