Skip to content

Commit

Permalink
Deployment fixes (#43)
Browse files Browse the repository at this point in the history
* serialize ssz instead of json

* config files for mainnet

* update gen verifier justcommands

* CLI main testnet -> mainnet

* gen verifier for agg cirguit

* Debugging the aggregation verifier contract failing to generate

* fmt

* we need to pass witness in?

* un commit some configs

* update contracts. NOTE: I think committee_update contract might be borked... look at the number of pubinputs

* update deps

* add step mainnet config

* print path to pk when fails to find

* mainnet agg config

* update moreconfigs

* attempt to get logging working

* axum tracing

* enable tower log

* update other deps

* jsonrpc logging

* update jsonrpc_v2

* good kids handle errors

* serialize as lowercase for consistancy

* clean some deps

* poseidon CLI

* fix contracts

* Change way we do initial poseidon calculation

* dont need to reverse bytes anymore

* use bls accumulator instances in contract

* add accumulator into rpc response

* regen contract

* add committee_poseidon in rotation rpc

* add accumulator prepending to rotation input encoding tests

* dup code delete

* compiles

* update verifier contracts

* Fix RPC return values

* fix rpc again

* fmt

* minor fixes

* fix input parsing

* refactor cli

* fix evm equivalence tests

* tidy dependencies

* tidy up rpc; remove unused

* rename rpc result structs

---------

Co-authored-by: ec2 <[email protected]>
Co-authored-by: mpetrun5 <[email protected]>
Co-authored-by: Willem Olding <[email protected]>
  • Loading branch information
4 people authored Dec 11, 2023
1 parent f1cb82f commit edd6129
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 434 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ zkevm-hashes = { git = "https://github.com/axiom-crypto/halo2-lib", branch = "co

halo2curves = { package = "halo2curves-axiom", version = "0.4.2" }


# verifier SDK
snark-verifier = { git = "https://github.com/axiom-crypto/snark-verifier.git", branch = "community-edition", default-features = false, features = [
"display",
Expand Down
124 changes: 69 additions & 55 deletions contract-tests/tests/rotation_input_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,20 @@ where
[(); Spec::SYNC_COMMITTEE_SIZE]:,
{
fn from(args: CommitteeRotationArgs<Spec>) -> Self {
let poseidon_commitment_le = poseidon_committee_commitment_from_compressed(
let poseidon_commitment_be = poseidon_committee_commitment_from_compressed(
&args.pubkeys_compressed.iter().cloned().collect_vec(),
)
.unwrap()
.into_iter()
.rev() // need to reverse to match the endianness of the solidity encoding
.collect_vec()
.try_into()
.unwrap();

// Endianess here is super confusing
// This should be solved by having `committee_poseidong` only be `uint256`
// See https://github.com/ChainSafe/Spectre/pull/42

let mut pk_vector: Vector<Vector<u8, 48>, { Spec::SYNC_COMMITTEE_SIZE }> = args
.pubkeys_compressed
.iter()
Expand All @@ -52,66 +61,71 @@ where

RotateInput {
sync_committee_ssz,
sync_committee_poseidon: poseidon_commitment_le,
sync_committee_poseidon: poseidon_commitment_be,
}
}
}

#[rstest]
#[tokio::test]
async fn test_rotate_public_input_evm_equivalence(
#[files("../consensus-spec-tests/tests/minimal/capella/light_client/sync/pyspec_tests/**")]
#[exclude("deneb*")]
path: PathBuf,
) -> anyhow::Result<()> {
let (_, witness) = read_test_files_and_gen_witness(&path);
let accumulator = [bn256::Fr::zero(); 12]; // this can be anything.. The test is just checking it gets correctly concatenated to the start of the encoded input

let instance = CommitteeUpdateCircuit::<Minimal, bn256::Fr>::instance(&witness, LIMB_BITS);
let finalized_block_root = witness
.finalized_header
.clone()
.hash_tree_root()
.unwrap()
.deref()
.try_into()
.unwrap();
#[cfg(test)]
mod tests {
use super::*;

let (_anvil_instance, ethclient) = make_client();
let contract = RotateExternal::deploy(ethclient, ())?.send().await?;
/// Convert a slice of field elements into an array of U256 ready to pass to a soliditiy call via ethers
fn solidity_encode_fr_array<const N: usize>(frs: &[bn256::Fr]) -> [ethers::types::U256; N] {
frs.iter()
.map(|v| ethers::types::U256::from_little_endian(&v.to_bytes()))
.collect_vec()
.try_into()
.expect("incompatible input slice length with return type")
}

let result = contract
.to_public_inputs(
RotateInput::from(witness),
finalized_block_root,
solidity_encode_fr_array(&accumulator),
)
.call()
.await?;

let result_decoded = decode_solidity_u256_array(&result);
// The expected result is the concatenation of the accumulator and the instance
let expected: Vec<_> = accumulator.iter().chain(instance[0].iter()).collect();
assert_eq!(result_decoded.iter().collect::<Vec<_>>(), expected);
Ok(())
}
fn decode_solidity_u256_array(uints: &[ethers::types::U256]) -> Vec<bn256::Fr> {
uints
.iter()
.map(|v| {
let mut b = [0_u8; 32];
v.to_little_endian(&mut b);
bn256::Fr::from_bytes(&b).expect("bad bn256::Fr encoding")
})
.collect()
}

/// Convert a slice of field elements into an array of U256 ready to pass to a soliditiy call via ethers
fn solidity_encode_fr_array<const N: usize>(frs: &[bn256::Fr]) -> [ethers::types::U256; N] {
frs.iter()
.map(|v| ethers::types::U256::from_little_endian(&v.to_bytes()))
.collect_vec()
.try_into()
.expect("incompatible input slice length with return type")
}
#[rstest]
#[tokio::test]
async fn test_rotate_public_input_evm_equivalence(
#[files("../consensus-spec-tests/tests/minimal/capella/light_client/sync/pyspec_tests/**")]
#[exclude("deneb*")]
path: PathBuf,
) -> anyhow::Result<()> {
let (_, witness) = read_test_files_and_gen_witness(&path);
let accumulator = [bn256::Fr::zero(); 12]; // this can be anything.. The test is just checking it gets correctly concatenated to the start of the encoded input

fn decode_solidity_u256_array(uints: &[ethers::types::U256]) -> Vec<bn256::Fr> {
uints
.iter()
.map(|v| {
let mut b = [0_u8; 32];
v.to_little_endian(&mut b);
bn256::Fr::from_bytes(&b).expect("bad bn256::Fr encoding")
})
.collect()
let instance = CommitteeUpdateCircuit::<Minimal, bn256::Fr>::instance(&witness, LIMB_BITS);
let finalized_block_root = witness
.finalized_header
.clone()
.hash_tree_root()
.unwrap()
.deref()
.try_into()
.unwrap();

let (_anvil_instance, ethclient) = make_client();
let contract = RotateExternal::deploy(ethclient, ())?.send().await?;

let result = contract
.to_public_inputs(
RotateInput::from(witness),
finalized_block_root,
solidity_encode_fr_array(&accumulator),
)
.call()
.await?;

let result_decoded = decode_solidity_u256_array(&result);
// The expected result is the concatenation of the accumulator and the instance
let expected: Vec<_> = accumulator.iter().chain(instance[0].iter()).collect();
assert_eq!(result_decoded.iter().collect::<Vec<_>>(), expected);
Ok(())
}
}
23 changes: 0 additions & 23 deletions contracts/snark-verifiers/committee_update_aggregated.sol

This file was deleted.

2 changes: 1 addition & 1 deletion contracts/snark-verifiers/committee_update_verifier.sol

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contracts/snark-verifiers/sync_step.sol

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contracts/src/RotateLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ library RotateLib {
inputs[i] = accumulator[i];
}

inputs[accumulator.length] = uint256(EndianConversions.toLittleEndian(uint256(args.syncCommitteePoseidon)));
inputs[accumulator.length] = uint256(args.syncCommitteePoseidon);

uint256 syncCommitteeSSZNumeric = uint256(args.syncCommitteeSSZ);
for (uint256 i = 0; i < 32; i++) {
Expand Down
8 changes: 3 additions & 5 deletions lightclient-circuits/src/committee_update_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ impl<S: Spec, F: Field> CommitteeUpdateCircuit<S, F> {
};

// Finalized header
let finalized_slot_bytes: HashInputChunk<_> = args.finalized_header.slot.into_witness();
let finalized_state_root = args
.finalized_header
.state_root
Expand All @@ -76,7 +75,7 @@ impl<S: Spec, F: Field> CommitteeUpdateCircuit<S, F> {
builder,
&sha256_chip,
[
finalized_slot_bytes,
args.finalized_header.slot.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 @@ -165,9 +164,8 @@ impl<S: Spec, F: Field> CommitteeUpdateCircuit<S, F> {
[(); S::SYNC_COMMITTEE_SIZE]:,
{
let pubkeys_x = args.pubkeys_compressed.iter().cloned().map(|mut bytes| {
bytes.reverse();
bytes[47] &= 0b00011111;
bls12_381::Fq::from_bytes_le(&bytes)
bytes[0] &= 0b00011111;
bls12_381::Fq::from_bytes_be(&bytes.try_into().unwrap()).unwrap()
});

let poseidon_commitment =
Expand Down
1 change: 1 addition & 0 deletions prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ path = "src/main.rs"
clap = { version = "4.2", features = ["derive"] }
strum = { version = "=0.25", features = ["derive"] }
cli-batteries = "0.5"
hex = "0.4"
eyre = "0.6"
anstyle = "1.0.0"
axum = { version = "0.7", features = ["tracing", "tower-log"] }
Expand Down
37 changes: 22 additions & 15 deletions prover/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,21 @@ pub struct BaseArgs {
#[derive(Clone, clap::Parser)]
#[allow(clippy::large_enum_variant)]
pub enum BaseCmd {
Rpc(RpcOptions),
Circuit(CircuitOptions),
}
#[derive(Clone, clap::Parser)]
pub struct RpcOptions {
#[clap(long, short, default_value = "3000")]
pub port: String,
}

#[derive(Clone, clap::Parser)]
pub struct CircuitOptions {
#[command(subcommand)]
pub proof: ProofCmd,
Rpc {
#[clap(long, short, default_value = "3000")]
port: String,
},
Circuit {
#[command(subcommand)]
proof: ProofCmd,

#[clap(long, short, default_value = "mainnet")]
pub spec: Spec,
#[clap(long, short, default_value = "mainnet")]
spec: Spec,
},
Utils {
#[command(subcommand)]
method: UtilsCmd,
},
}

#[derive(Clone, clap::Subcommand)]
Expand Down Expand Up @@ -93,3 +92,11 @@ pub enum Spec {
#[strum(serialize = "mainnet")]
Mainnet,
}

#[derive(Clone, clap::Subcommand)]
pub enum UtilsCmd {
CommitteePoseidon {
#[clap(long, short)]
beacon_api: String,
},
}
24 changes: 1 addition & 23 deletions prover/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::args::BaseArgs;
use crate::args::{OperationCmd, ProofCmd};

use ark_std::{end_timer, start_timer};
use lightclient_circuits::{
committee_update_circuit::CommitteeUpdateCircuit,
Expand All @@ -15,34 +14,13 @@ use snark_verifier::loader::halo2::halo2_ecc::halo2_base::halo2_proofs::poly::kz
use snark_verifier_sdk::halo2::aggregation::AggregationCircuit;
use snark_verifier_sdk::CircuitExt;
use std::path::PathBuf;
use std::{fs::File, future::Future, io::Write, path::Path};
use std::{fs::File, io::Write, path::Path};

#[cfg(feature = "experimental")]
use halo2_solidity_verifier_new::{
compile_solidity, encode_calldata, BatchOpenScheme, Evm, SolidityGenerator,
};

ethers::contract::abigen!(
SnarkVerifierSol,
r#"[
function verify(uint256[1] calldata pubInputs,bytes calldata proof) public view returns (bool)
]"#,
);

pub trait FetchFn<Arg>: FnOnce(Arg) -> <Self as FetchFn<Arg>>::Fut {
type Fut: Future<Output = <Self as FetchFn<Arg>>::Output>;
type Output;
}

impl<Arg, F, Fut> FetchFn<Arg> for F
where
F: FnOnce(Arg) -> Fut,
Fut: Future,
{
type Fut = Fut;
type Output = Fut::Output;
}

pub(crate) async fn spec_app<S: eth_types::Spec>(
proof: ProofCmd,
base_args: &BaseArgs,
Expand Down
27 changes: 11 additions & 16 deletions prover/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,31 @@ mod cli;
mod rpc;
mod rpc_api;
pub mod rpc_client;
mod utils;

use crate::args::RpcOptions;
use crate::{cli::spec_app, rpc::run_rpc};
use args::Cli;
use cli_batteries::version;
use utils::utils_cli;

mod args;

async fn app(options: Cli) -> eyre::Result<()> {
match options.subcommand {
args::BaseCmd::Rpc(op) => {
let RpcOptions { port } = op;

run_rpc(port.parse().unwrap()).await.unwrap();
args::BaseCmd::Rpc { port } => {
run_rpc(port.parse().unwrap()).await?;

log::info!("Stopped accepting RPC connections");

Ok(())
}
args::BaseCmd::Circuit(op) => match op.spec {
args::Spec::Minimal => spec_app::<eth_types::Minimal>(op.proof, &options.args)
.await
.unwrap(),
args::Spec::Testnet => spec_app::<eth_types::Testnet>(op.proof, &options.args)
.await
.unwrap(),
args::Spec::Mainnet => spec_app::<eth_types::Mainnet>(op.proof, &options.args)
.await
.unwrap(),
args::BaseCmd::Circuit { proof, spec } => match spec {
args::Spec::Minimal => spec_app::<eth_types::Minimal>(proof, &options.args).await,
args::Spec::Testnet => spec_app::<eth_types::Testnet>(proof, &options.args).await,
args::Spec::Mainnet => spec_app::<eth_types::Mainnet>(proof, &options.args).await,
},
args::BaseCmd::Utils { method } => utils_cli(method).await,
}
Ok(())
}

fn main() {
Expand Down
Loading

0 comments on commit edd6129

Please sign in to comment.