From 0e9613154403b29f61cc4a33a856f6e44460abbe Mon Sep 17 00:00:00 2001 From: MRain Date: Tue, 10 Oct 2023 17:37:45 -0400 Subject: [PATCH 01/14] threshold checking circuit --- Cargo.lock | 1 + Cargo.toml | 24 ++-- crates/hotshot-state-prover/Cargo.toml | 34 +++++ crates/hotshot-state-prover/src/circuit.rs | 121 ++++++++++++++++++ .../src/circuit/config.rs | 14 ++ .../hotshot-state-prover/src/circuit/types.rs | 40 ++++++ crates/hotshot-state-prover/src/lib.rs | 3 + crates/types/Cargo.toml | 11 +- crates/types/src/traits/stake_table.rs | 7 + 9 files changed, 237 insertions(+), 18 deletions(-) create mode 100644 crates/hotshot-state-prover/Cargo.toml create mode 100644 crates/hotshot-state-prover/src/circuit.rs create mode 100644 crates/hotshot-state-prover/src/circuit/config.rs create mode 100644 crates/hotshot-state-prover/src/circuit/types.rs create mode 100644 crates/hotshot-state-prover/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index c055a0fb00..ba2baff4a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2867,6 +2867,7 @@ dependencies = [ "hotshot-constants", "hotshot-task", "hotshot-utils", + "jf-plonk", "jf-primitives", "jf-utils", "libp2p-networking", diff --git a/Cargo.toml b/Cargo.toml index 688e9c37d0..94ec183deb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,25 +6,25 @@ rust-version = "1.65.0" homepage = "https://github.com/EspressoSystems/HotShot" documentation = "https://hotshot.docs.espressosys.com" repository = "https://github.com/EspressoSystems/HotShot" - ### Workspace # The hotshot-types crate needs to be a seperate crate, as to not create a circular dependency # when implementing traits externally [workspace] members = [ - "crates/libp2p-networking", - "crates/testing", - "crates/types", - "crates/utils", "crates/constants", - # "testing-macros", - "crates/task", - "crates/task-impls", + "crates/hotshot", "crates/hotshot-qc", "crates/hotshot-signature-key", "crates/hotshot-stake-table", - "crates/hotshot", + "crates/hotshot-state-prover", + "crates/libp2p-networking", + # "testing-macros", + "crates/task", + "crates/task-impls", + "crates/testing", + "crates/types", + "crates/utils", ] resolver = "2" @@ -58,6 +58,7 @@ futures = "0.3.28" generic-array = { version = "0.14.7", features = ["serde"] } jf-primitives = { git = "https://github.com/EspressoSystems/jellyfish" } +jf-plonk = { git = "https://github.com/EspressoSystems/jellyfish" } jf-relation = { git = "https://github.com/EspressoSystems/jellyfish" } jf-utils = { git = "https://github.com/espressosystems/jellyfish" } libp2p-identity = "0.2" @@ -115,10 +116,7 @@ tokio = { version = "1.32.0", features = [ "time", "tracing", ] } - -### Profiles -### -### Note: these only apply to example executables or tests built from within this crate. They have +### Profiles###### Note: these only apply to example executables or tests built from within this crate. They have ### no effect on crates that depend on this crate. ## Apply some optimizations to test dependencies in debug/test builds diff --git a/crates/hotshot-state-prover/Cargo.toml b/crates/hotshot-state-prover/Cargo.toml new file mode 100644 index 0000000000..9d0ce291ef --- /dev/null +++ b/crates/hotshot-state-prover/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "hotshot-state-prover" +description = "Generate state update proof for HotShot light client" +version = { workspace = true } +authors = { workspace = true } +edition = { workspace = true } +rust-version = { workspace = true } + +[dependencies] +ark-bn254 = "0.4.0" +ark-ec = "0.4.0" +ark-ed-on-bn254 = "0.4.0" +ark-ff = "0.4.0" +ark-serialize = { workspace = true } +ark-std = { workspace = true } +bincode = { workspace = true } +bitvec = { workspace = true } +digest = { workspace = true } +displaydoc = { version = "0.2.3", default-features = false } +ethereum-types = { workspace = true } +generic-array = "0.14.7" +hotshot-types = { path = "../types" } +jf-plonk = { workspace = true } +jf-primitives = { workspace = true } +jf-relation = { workspace = true } +jf-utils = { workspace = true } +serde = { workspace = true, features = ["rc"] } +tagged-base64 = { git = "https://github.com/espressosystems/tagged-base64", tag = "0.3.0" } +typenum = { workspace = true } + +[features] +default = ["parallel"] +std = ["ark-std/std", "ark-serialize/std", "ark-ff/std"] +parallel = ["jf-primitives/parallel", "jf-utils/parallel", "ark-ff/parallel"] diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs new file mode 100644 index 0000000000..9aed4db0ba --- /dev/null +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -0,0 +1,121 @@ +//! Circuit implementation for verifying light client state update + +use std::marker::PhantomData; + +use ark_ec::twisted_edwards::TECurveConfig; +use ethereum_types::U256; +use hotshot_types::traits::stake_table::{SnapshotVersion, StakeTableScheme}; +use jf_plonk::errors::PlonkError; +use jf_primitives::{ + circuit::signature::schnorr::VerKeyVar, + rescue::RescueParameter, + signatures::{ + bls_over_bn254::VerKey as BLSVerKey, + schnorr::{Signature, VerKey as SchnorrVerKey}, + }, +}; +use jf_relation::gadgets::ecc::TEPoint; +use jf_relation::{ + errors::CircuitError, gadgets::ecc::SWToTEConParam, BoolVar, Circuit, PlonkCircuit, +}; + +use self::{ + config::{u256_to_field, NUM_ENTRIES}, + types::{HotShotState, StakeTableEntryVar}, +}; + +pub mod config; +pub mod types; + +#[derive(Clone, Debug)] +pub struct StateUpdateBuilder(PhantomData); + +impl StateUpdateBuilder +where + F: RescueParameter + SWToTEConParam, +{ + /// A function that takes as input: + /// - stake table entries (`Vec<(BLSVerKey, SchnorrVerKey, Amount)>`) + /// - schnorr signatures of the updated states (`Vec`) + /// - updated hotshot state (`(view_number, block_height, block_comm, fee_ledger_comm, stake_table_comm)`) + /// - signer bit vector + /// - quorum threshold + /// checks that + /// - the signer's accumulated weight exceeds the quorum threshold + /// - the commitment of the stake table + /// - all schnorr signatures are valid + pub fn build( + stake_table: &ST, + _sigs: &[Signature

], + _hotshot_state: &HotShotState, + signer_bit_vec: &[bool], + threshold: &U256, + ) -> Result, PlonkError> + where + ST: StakeTableScheme), Amount = U256>, + P: TECurveConfig, + { + let mut circuit = PlonkCircuit::new_turbo_plonk(); + + // Dummy circuit implementation, fill in the details later + // TODO(Chengyu): + // - [DONE] the signer's accumulated weight exceeds the quorum threshold + // - The commitment of the stake table as [https://www.notion.so/espressosys/Light-Client-Contract-a416ebbfa9f342d79fccbf90de9706ef?pvs=4#6c0e26d753cd42e9bb0f22db1c519f45] + // - Batch Schnorr signature verification + + // creating variables for stake table entries + let mut stake_table_var = stake_table + .try_iter(SnapshotVersion::LastEpochStart)? + .map(|((_bls_ver_key, schnorr_ver_key), amount)| { + // TODO(Chengyu): create variable for bls_key_var + let schnorr_ver_key = + VerKeyVar(circuit.create_point_variable(schnorr_ver_key.to_affine().into())?); + let stake_amount = circuit.create_variable(u256_to_field::(&amount))?; + Ok(StakeTableEntryVar { + bls_ver_key: (0, 0), // TODO(Chengyu) + schnorr_ver_key, + stake_amount, + }) + }) + .collect::, CircuitError>>()?; + let dummy_ver_key_var = VerKeyVar(circuit.create_point_variable(TEPoint::default())?); + stake_table_var.resize( + NUM_ENTRIES, + StakeTableEntryVar { + bls_ver_key: (0, 0), + schnorr_ver_key: dummy_ver_key_var, + stake_amount: 0, + }, + ); + + let mut signer_bit_vec_var = signer_bit_vec + .into_iter() + .map(|&b| circuit.create_boolean_variable(b)) + .collect::, CircuitError>>()?; + signer_bit_vec_var.resize(NUM_ENTRIES, BoolVar(circuit.zero())); + + let threshold_var = circuit.create_public_variable(u256_to_field::(threshold))?; + + // Checking whether the accumulated weight exceeds the quorum threshold + // We assume that NUM_ENTRIES is always a multiple of 2 + let signed_amount_var = (0..NUM_ENTRIES / 2) + .map(|i| { + circuit.mul_add( + &[ + stake_table_var[2 * i].stake_amount, + signer_bit_vec_var[2 * i].0, + stake_table_var[2 * i + 1].stake_amount, + signer_bit_vec_var[2 * i + 1].0, + ], + &[F::one(), F::one()], + ) + }) + .collect::, CircuitError>>()?; + let acc_amount_var = circuit.sum(&signed_amount_var)?; + circuit.enforce_leq(threshold_var, acc_amount_var)?; + + // circuit.mul_add(wires_in, q_muls) + circuit.finalize_for_arithmetization()?; + Ok(circuit) + } +} diff --git a/crates/hotshot-state-prover/src/circuit/config.rs b/crates/hotshot-state-prover/src/circuit/config.rs new file mode 100644 index 0000000000..98924c51c3 --- /dev/null +++ b/crates/hotshot-state-prover/src/circuit/config.rs @@ -0,0 +1,14 @@ +//! Constant and configs for hotshot state prover + +use ark_ff::PrimeField; +use ethereum_types::U256; + +/// Number of entries/keys in the stake table +pub const NUM_ENTRIES: usize = 1000; + +/// convert a U256 to a field element. +pub(crate) fn u256_to_field(v: &U256) -> F { + let mut bytes = vec![0u8; 32]; + v.to_little_endian(&mut bytes); + F::from_le_bytes_mod_order(&bytes) +} diff --git a/crates/hotshot-state-prover/src/circuit/types.rs b/crates/hotshot-state-prover/src/circuit/types.rs new file mode 100644 index 0000000000..6d244d6497 --- /dev/null +++ b/crates/hotshot-state-prover/src/circuit/types.rs @@ -0,0 +1,40 @@ +//! Types for verification circuit + +use ark_ff::PrimeField; +pub use jf_primitives::circuit::signature::schnorr::{SignatureVar, VerKeyVar}; +use jf_relation::Variable; +use serde::{Deserialize, Serialize}; + +/// Variable for stake table entry +#[derive(Clone, Debug)] +pub struct StakeTableEntryVar { + pub bls_ver_key: (Variable, Variable), + pub schnorr_ver_key: VerKeyVar, + pub stake_amount: Variable, +} + +/// HotShot state Variable +#[derive(Clone, Debug)] +pub struct HotShotStateVar { + pub view_number_var: Variable, + pub block_height_var: Variable, + pub block_comm_var: Variable, + pub fee_ledger_comm_var: Variable, + pub stake_table_comm_var: Variable, +} + +/// HotShot state +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct HotShotState { + pub view_number: usize, + pub block_height: usize, + pub block_comm: F, + pub fee_ledger_comm: F, + pub stake_table_comm: F, +} + +/// +pub trait IntoFields { + const LEN: usize; + fn into_fields() -> Vec; +} diff --git a/crates/hotshot-state-prover/src/lib.rs b/crates/hotshot-state-prover/src/lib.rs new file mode 100644 index 0000000000..13feae9401 --- /dev/null +++ b/crates/hotshot-state-prover/src/lib.rs @@ -0,0 +1,3 @@ +//! SNARK-assisted light client state update verification in HotShot + +pub mod circuit; diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index c0eb7a11e0..e206981ae3 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -13,13 +13,13 @@ demo = [] [dependencies] arbitrary = { version = "1.3", features = ["derive"] } ark-bls12-381 = { workspace = true } -async-compatibility-layer = { workspace = true } -async-lock = { workspace = true } -async-trait = { workspace = true } ark-serialize = { version = "0.3", features = [ "derive", ] } # TODO upgrade to 0.4 and inherit this dep from workspace https://github.com/EspressoSystems/HotShot/issues/1700 ark-std = { workspace = true } +async-compatibility-layer = { workspace = true } +async-lock = { workspace = true } +async-trait = { workspace = true } bincode = { workspace = true } bitvec = { workspace = true } blake3 = { workspace = true } @@ -30,12 +30,14 @@ digest = { workspace = true } displaydoc = { version = "0.2.3", default-features = false } either = { workspace = true, features = ["serde"] } espresso-systems-common = { workspace = true } +ethereum-types = { workspace = true } futures = { workspace = true } generic-array = { workspace = true } hex_fmt = "0.3.0" hotshot-constants = { path = "../constants" } -hotshot-utils = { path = "../utils" } hotshot-task = { path = "../task", default-features = false } +hotshot-utils = { path = "../utils" } +jf-plonk = { workspace = true } jf-primitives = { workspace = true, features = ["test-srs"] } jf-utils = { workspace = true } libp2p-networking = { workspace = true } @@ -48,7 +50,6 @@ snafu = { workspace = true } tagged-base64 = { git = "https://github.com/EspressoSystems/tagged-base64", tag = "0.2.4" } time = { workspace = true } tracing = { workspace = true } -ethereum-types = { workspace = true } typenum = { workspace = true } [dev-dependencies] diff --git a/crates/types/src/traits/stake_table.rs b/crates/types/src/traits/stake_table.rs index 49bcfd150a..b86308d1a5 100644 --- a/crates/types/src/traits/stake_table.rs +++ b/crates/types/src/traits/stake_table.rs @@ -3,6 +3,7 @@ use ark_std::{rand::SeedableRng, string::ToString, vec::Vec}; use digest::crypto_common::rand_core::CryptoRngCore; use displaydoc::Display; +use jf_plonk::errors::PlonkError; use jf_primitives::errors::PrimitivesError; /// Snapshots of the stake table @@ -203,3 +204,9 @@ impl From for PrimitivesError { Self::ParameterError(value.to_string()) } } + +impl From for PlonkError { + fn from(value: StakeTableError) -> Self { + Self::PrimitiveError(PrimitivesError::ParameterError(value.to_string())) + } +} From efa345fe541d6da57bdab15921ac8ee3768fc060 Mon Sep 17 00:00:00 2001 From: MRain Date: Tue, 10 Oct 2023 17:43:10 -0400 Subject: [PATCH 02/14] change some variables to public --- crates/hotshot-state-prover/src/circuit.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index 9aed4db0ba..caac06b5d9 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -68,9 +68,10 @@ where .try_iter(SnapshotVersion::LastEpochStart)? .map(|((_bls_ver_key, schnorr_ver_key), amount)| { // TODO(Chengyu): create variable for bls_key_var - let schnorr_ver_key = - VerKeyVar(circuit.create_point_variable(schnorr_ver_key.to_affine().into())?); - let stake_amount = circuit.create_variable(u256_to_field::(&amount))?; + let schnorr_ver_key = VerKeyVar( + circuit.create_public_point_variable(schnorr_ver_key.to_affine().into())?, + ); + let stake_amount = circuit.create_public_variable(u256_to_field::(&amount))?; Ok(StakeTableEntryVar { bls_ver_key: (0, 0), // TODO(Chengyu) schnorr_ver_key, @@ -78,7 +79,8 @@ where }) }) .collect::, CircuitError>>()?; - let dummy_ver_key_var = VerKeyVar(circuit.create_point_variable(TEPoint::default())?); + let dummy_ver_key_var = + VerKeyVar(circuit.create_public_point_variable(TEPoint::default())?); stake_table_var.resize( NUM_ENTRIES, StakeTableEntryVar { @@ -90,7 +92,7 @@ where let mut signer_bit_vec_var = signer_bit_vec .into_iter() - .map(|&b| circuit.create_boolean_variable(b)) + .map(|&b| circuit.create_public_boolean_variable(b)) .collect::, CircuitError>>()?; signer_bit_vec_var.resize(NUM_ENTRIES, BoolVar(circuit.zero())); From b6a22d40b65e95afe81af0629cce1729d8b0ca94 Mon Sep 17 00:00:00 2001 From: MRain Date: Wed, 11 Oct 2023 11:19:07 -0400 Subject: [PATCH 03/14] comments & tests(TBD) --- Cargo.lock | 1 + Cargo.toml | 4 +- crates/hotshot-state-prover/Cargo.toml | 3 + crates/hotshot-state-prover/src/circuit.rs | 78 +++++++++++++++---- .../src/circuit/config.rs | 14 ---- .../hotshot-state-prover/src/circuit/types.rs | 40 ---------- 6 files changed, 71 insertions(+), 69 deletions(-) delete mode 100644 crates/hotshot-state-prover/src/circuit/config.rs delete mode 100644 crates/hotshot-state-prover/src/circuit/types.rs diff --git a/Cargo.lock b/Cargo.lock index c07ba5c8ca..f32b9206d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2776,6 +2776,7 @@ dependencies = [ "displaydoc", "ethereum-types", "generic-array", + "hotshot-stake-table", "hotshot-types", "jf-plonk", "jf-primitives", diff --git a/Cargo.toml b/Cargo.toml index 94ec183deb..e78c6a4b93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,9 @@ tokio = { version = "1.32.0", features = [ "time", "tracing", ] } -### Profiles###### Note: these only apply to example executables or tests built from within this crate. They have +### Profiles +### +### Note: these only apply to example executables or tests built from within this crate. They have ### no effect on crates that depend on this crate. ## Apply some optimizations to test dependencies in debug/test builds diff --git a/crates/hotshot-state-prover/Cargo.toml b/crates/hotshot-state-prover/Cargo.toml index 9d0ce291ef..e8e8170f4e 100644 --- a/crates/hotshot-state-prover/Cargo.toml +++ b/crates/hotshot-state-prover/Cargo.toml @@ -28,6 +28,9 @@ serde = { workspace = true, features = ["rc"] } tagged-base64 = { git = "https://github.com/espressosystems/tagged-base64", tag = "0.3.0" } typenum = { workspace = true } +[dev-dependencies] +hotshot-stake-table = { path = "../hotshot-stake-table" } + [features] default = ["parallel"] std = ["ark-std/std", "ark-serialize/std", "ark-ff/std"] diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index caac06b5d9..c160e82f50 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -3,6 +3,7 @@ use std::marker::PhantomData; use ark_ec::twisted_edwards::TECurveConfig; +use ark_ff::PrimeField; use ethereum_types::U256; use hotshot_types::traits::stake_table::{SnapshotVersion, StakeTableScheme}; use jf_plonk::errors::PlonkError; @@ -14,18 +15,49 @@ use jf_primitives::{ schnorr::{Signature, VerKey as SchnorrVerKey}, }, }; -use jf_relation::gadgets::ecc::TEPoint; use jf_relation::{ errors::CircuitError, gadgets::ecc::SWToTEConParam, BoolVar, Circuit, PlonkCircuit, }; +use jf_relation::{gadgets::ecc::TEPoint, Variable}; +use serde::{Deserialize, Serialize}; -use self::{ - config::{u256_to_field, NUM_ENTRIES}, - types::{HotShotState, StakeTableEntryVar}, -}; +/// Number of entries/keys in the stake table +pub const NUM_ENTRIES: usize = 1000; + +/// convert a U256 to a field element. +pub(crate) fn u256_to_field(v: &U256) -> F { + let mut bytes = vec![0u8; 32]; + v.to_little_endian(&mut bytes); + F::from_le_bytes_mod_order(&bytes) +} + +/// Variable for stake table entry +#[derive(Clone, Debug)] +pub struct StakeTableEntryVar { + pub bls_ver_key: (Variable, Variable), + pub schnorr_ver_key: VerKeyVar, + pub stake_amount: Variable, +} -pub mod config; -pub mod types; +/// HotShot state Variable +#[derive(Clone, Debug)] +pub struct HotShotStateVar { + pub view_number_var: Variable, + pub block_height_var: Variable, + pub block_comm_var: Variable, + pub fee_ledger_comm_var: Variable, + pub stake_table_comm_var: Variable, +} + +/// HotShot state +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct HotShotState { + pub view_number: usize, + pub block_height: usize, + pub block_comm: F, + pub fee_ledger_comm: F, + pub stake_table_comm: F, +} #[derive(Clone, Debug)] pub struct StateUpdateBuilder(PhantomData); @@ -68,10 +100,9 @@ where .try_iter(SnapshotVersion::LastEpochStart)? .map(|((_bls_ver_key, schnorr_ver_key), amount)| { // TODO(Chengyu): create variable for bls_key_var - let schnorr_ver_key = VerKeyVar( - circuit.create_public_point_variable(schnorr_ver_key.to_affine().into())?, - ); - let stake_amount = circuit.create_public_variable(u256_to_field::(&amount))?; + let schnorr_ver_key = + VerKeyVar(circuit.create_point_variable(schnorr_ver_key.to_affine().into())?); + let stake_amount = circuit.create_variable(u256_to_field::(&amount))?; Ok(StakeTableEntryVar { bls_ver_key: (0, 0), // TODO(Chengyu) schnorr_ver_key, @@ -80,7 +111,7 @@ where }) .collect::, CircuitError>>()?; let dummy_ver_key_var = - VerKeyVar(circuit.create_public_point_variable(TEPoint::default())?); + VerKeyVar(circuit.create_constant_point_variable(TEPoint::default())?); stake_table_var.resize( NUM_ENTRIES, StakeTableEntryVar { @@ -91,8 +122,8 @@ where ); let mut signer_bit_vec_var = signer_bit_vec - .into_iter() - .map(|&b| circuit.create_public_boolean_variable(b)) + .iter() + .map(|&b| circuit.create_boolean_variable(b)) .collect::, CircuitError>>()?; signer_bit_vec_var.resize(NUM_ENTRIES, BoolVar(circuit.zero())); @@ -121,3 +152,22 @@ where Ok(circuit) } } + +// #[cfg(test)] +// mod tests { +// use ark_ed_on_bn254::EdwardsConfig as Config; +// use hotshot_stake_table::mt_based::StakeTable; +// use jf_primitives::{ +// rescue::RescueParameter, +// signatures::{ +// bls_over_bn254::VerKey as BLSVerKey, +// schnorr::{Signature, VerKey as SchnorrVerKey}, +// }, +// }; + +// type Key = (BLSVerKey, SchnorrVerKey); +// #[test] +// fn test_circuit_building() { +// let stake_table = StakeTable::::new(10); +// } +// } diff --git a/crates/hotshot-state-prover/src/circuit/config.rs b/crates/hotshot-state-prover/src/circuit/config.rs deleted file mode 100644 index 98924c51c3..0000000000 --- a/crates/hotshot-state-prover/src/circuit/config.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! Constant and configs for hotshot state prover - -use ark_ff::PrimeField; -use ethereum_types::U256; - -/// Number of entries/keys in the stake table -pub const NUM_ENTRIES: usize = 1000; - -/// convert a U256 to a field element. -pub(crate) fn u256_to_field(v: &U256) -> F { - let mut bytes = vec![0u8; 32]; - v.to_little_endian(&mut bytes); - F::from_le_bytes_mod_order(&bytes) -} diff --git a/crates/hotshot-state-prover/src/circuit/types.rs b/crates/hotshot-state-prover/src/circuit/types.rs deleted file mode 100644 index 6d244d6497..0000000000 --- a/crates/hotshot-state-prover/src/circuit/types.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Types for verification circuit - -use ark_ff::PrimeField; -pub use jf_primitives::circuit::signature::schnorr::{SignatureVar, VerKeyVar}; -use jf_relation::Variable; -use serde::{Deserialize, Serialize}; - -/// Variable for stake table entry -#[derive(Clone, Debug)] -pub struct StakeTableEntryVar { - pub bls_ver_key: (Variable, Variable), - pub schnorr_ver_key: VerKeyVar, - pub stake_amount: Variable, -} - -/// HotShot state Variable -#[derive(Clone, Debug)] -pub struct HotShotStateVar { - pub view_number_var: Variable, - pub block_height_var: Variable, - pub block_comm_var: Variable, - pub fee_ledger_comm_var: Variable, - pub stake_table_comm_var: Variable, -} - -/// HotShot state -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct HotShotState { - pub view_number: usize, - pub block_height: usize, - pub block_comm: F, - pub fee_ledger_comm: F, - pub stake_table_comm: F, -} - -/// -pub trait IntoFields { - const LEN: usize; - fn into_fields() -> Vec; -} From bf3f9dcd7d519bd0500c62ff3fa9cb6e23c013e0 Mon Sep 17 00:00:00 2001 From: MRain Date: Mon, 6 Nov 2023 17:25:41 -0500 Subject: [PATCH 04/14] doing test --- Cargo.lock | 2 +- Cargo.toml | 4 +- crates/hotshot-state-prover/src/circuit.rs | 70 +++++++++++++--------- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da6f281cf0..3bfe440d19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3407,7 +3407,7 @@ dependencies = [ "derivative", "displaydoc", "downcast-rs", - "dyn-clone", + "dyn-clone 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "espresso-systems-common 0.4.0", "hashbrown 0.13.2", "itertools 0.10.5", diff --git a/Cargo.toml b/Cargo.toml index 0a37974cb5..8922c95139 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ members = [ "crates/hotshot-qc", "crates/hotshot-signature-key", "crates/hotshot-stake-table", + "crates/hotshot-state-prover", "crates/libp2p-networking", # "testing-macros", "crates/task", @@ -115,8 +116,7 @@ tokio = { version = "1.32.0", features = [ "time", "tracing", ] } -### Profiles### -### Note: these only apply to example executables or tests built from within this crate. They have +### Profiles###### Note: these only apply to example executables or tests built from within this crate. They have ### no effect on crates that depend on this crate. ## Apply some optimizations to test dependencies in debug/test builds diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index c160e82f50..11fa5746a0 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -34,19 +34,20 @@ pub(crate) fn u256_to_field(v: &U256) -> F { /// Variable for stake table entry #[derive(Clone, Debug)] pub struct StakeTableEntryVar { - pub bls_ver_key: (Variable, Variable), pub schnorr_ver_key: VerKeyVar, pub stake_amount: Variable, } /// HotShot state Variable +/// The stake table commitment is a triple (bls_keys_comm, stake_amount_comm, schnorr_keys_comm). +/// Because we only need a binding between Schnorr keys and the stake amount, we ignore the first term. #[derive(Clone, Debug)] pub struct HotShotStateVar { pub view_number_var: Variable, pub block_height_var: Variable, pub block_comm_var: Variable, pub fee_ledger_comm_var: Variable, - pub stake_table_comm_var: Variable, + pub stake_table_comm_var: (Variable, Variable), } /// HotShot state @@ -56,7 +57,7 @@ pub struct HotShotState { pub block_height: usize, pub block_comm: F, pub fee_ledger_comm: F, - pub stake_table_comm: F, + pub stake_table_comm: (F, F, F), } #[derive(Clone, Debug)] @@ -67,7 +68,7 @@ where F: RescueParameter + SWToTEConParam, { /// A function that takes as input: - /// - stake table entries (`Vec<(BLSVerKey, SchnorrVerKey, Amount)>`) + /// - stake table entries (`Vec<(BLSVerKey, Amount, SchnorrVerKey)>`) /// - schnorr signatures of the updated states (`Vec`) /// - updated hotshot state (`(view_number, block_height, block_comm, fee_ledger_comm, stake_table_comm)`) /// - signer bit vector @@ -84,7 +85,7 @@ where threshold: &U256, ) -> Result, PlonkError> where - ST: StakeTableScheme), Amount = U256>, + ST: StakeTableScheme>, P: TECurveConfig, { let mut circuit = PlonkCircuit::new_turbo_plonk(); @@ -98,13 +99,11 @@ where // creating variables for stake table entries let mut stake_table_var = stake_table .try_iter(SnapshotVersion::LastEpochStart)? - .map(|((_bls_ver_key, schnorr_ver_key), amount)| { - // TODO(Chengyu): create variable for bls_key_var + .map(|(_bls_ver_key, amount, schnorr_ver_key)| { let schnorr_ver_key = VerKeyVar(circuit.create_point_variable(schnorr_ver_key.to_affine().into())?); let stake_amount = circuit.create_variable(u256_to_field::(&amount))?; Ok(StakeTableEntryVar { - bls_ver_key: (0, 0), // TODO(Chengyu) schnorr_ver_key, stake_amount, }) @@ -115,7 +114,6 @@ where stake_table_var.resize( NUM_ENTRIES, StakeTableEntryVar { - bls_ver_key: (0, 0), schnorr_ver_key: dummy_ver_key_var, stake_amount: 0, }, @@ -153,21 +151,39 @@ where } } -// #[cfg(test)] -// mod tests { -// use ark_ed_on_bn254::EdwardsConfig as Config; -// use hotshot_stake_table::mt_based::StakeTable; -// use jf_primitives::{ -// rescue::RescueParameter, -// signatures::{ -// bls_over_bn254::VerKey as BLSVerKey, -// schnorr::{Signature, VerKey as SchnorrVerKey}, -// }, -// }; - -// type Key = (BLSVerKey, SchnorrVerKey); -// #[test] -// fn test_circuit_building() { -// let stake_table = StakeTable::::new(10); -// } -// } +#[cfg(test)] +mod tests { + use ark_ed_on_bn254::EdwardsConfig as Config; + use ethereum_types::U256; + use hotshot_stake_table::vec_based::StakeTable; + use hotshot_types::traits::stake_table::StakeTableScheme; + use jf_primitives::signatures::{ + bls_over_bn254::{BLSOverBN254CurveSignatureScheme, VerKey as BLSVerKey}, + SchnorrSignatureScheme, SignatureScheme, + }; + + type F = ark_ed_on_bn254::Fq; + type SchnorrVerKey = jf_primitives::signatures::schnorr::VerKey; + + #[test] + fn test_circuit_building() { + let mut st = StakeTable::::new(); + let mut prng = jf_utils::test_rng(); + let keys = (0..10) + .map(|_| { + ( + BLSOverBN254CurveSignatureScheme::key_gen(&(), &mut prng) + .unwrap() + .1, + SchnorrSignatureScheme::key_gen(&(), &mut prng).unwrap().1, + ) + }) + .collect::>(); + // Registering keys + keys.iter() + .for_each(|key| st.register(key.0, U256::from(100), key.1.clone()).unwrap()); + // Freeze the stake table + st.advance(); + st.advance(); + } +} From 54b52908fb51486b432a00ce155500ed8eb1c144 Mon Sep 17 00:00:00 2001 From: MRain Date: Mon, 6 Nov 2023 17:42:58 -0500 Subject: [PATCH 05/14] test --- crates/hotshot-state-prover/src/circuit.rs | 45 ++++++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index 11fa5746a0..641b52f5f1 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -15,9 +15,7 @@ use jf_primitives::{ schnorr::{Signature, VerKey as SchnorrVerKey}, }, }; -use jf_relation::{ - errors::CircuitError, gadgets::ecc::SWToTEConParam, BoolVar, Circuit, PlonkCircuit, -}; +use jf_relation::{errors::CircuitError, BoolVar, Circuit, PlonkCircuit}; use jf_relation::{gadgets::ecc::TEPoint, Variable}; use serde::{Deserialize, Serialize}; @@ -51,7 +49,7 @@ pub struct HotShotStateVar { } /// HotShot state -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, Default)] pub struct HotShotState { pub view_number: usize, pub block_height: usize, @@ -65,7 +63,7 @@ pub struct StateUpdateBuilder(PhantomData); impl StateUpdateBuilder where - F: RescueParameter + SWToTEConParam, + F: RescueParameter, { /// A function that takes as input: /// - stake table entries (`Vec<(BLSVerKey, Amount, SchnorrVerKey)>`) @@ -83,7 +81,7 @@ where _hotshot_state: &HotShotState, signer_bit_vec: &[bool], threshold: &U256, - ) -> Result, PlonkError> + ) -> Result<(PlonkCircuit, Vec), PlonkError> where ST: StakeTableScheme>, P: TECurveConfig, @@ -125,7 +123,11 @@ where .collect::, CircuitError>>()?; signer_bit_vec_var.resize(NUM_ENTRIES, BoolVar(circuit.zero())); - let threshold_var = circuit.create_public_variable(u256_to_field::(threshold))?; + let threshold = u256_to_field::(threshold); + let threshold_var = circuit.create_public_variable(threshold)?; + + // TODO(Chengyu): put in the hotshot state + let public_inputs = vec![threshold]; // Checking whether the accumulated weight exceeds the quorum threshold // We assume that NUM_ENTRIES is always a multiple of 2 @@ -147,12 +149,13 @@ where // circuit.mul_add(wires_in, q_muls) circuit.finalize_for_arithmetization()?; - Ok(circuit) + Ok((circuit, public_inputs)) } } #[cfg(test)] mod tests { + use super::{HotShotState, StateUpdateBuilder}; use ark_ed_on_bn254::EdwardsConfig as Config; use ethereum_types::U256; use hotshot_stake_table::vec_based::StakeTable; @@ -161,6 +164,7 @@ mod tests { bls_over_bn254::{BLSOverBN254CurveSignatureScheme, VerKey as BLSVerKey}, SchnorrSignatureScheme, SignatureScheme, }; + use jf_relation::Circuit; type F = ark_ed_on_bn254::Fq; type SchnorrVerKey = jf_primitives::signatures::schnorr::VerKey; @@ -185,5 +189,30 @@ mod tests { // Freeze the stake table st.advance(); st.advance(); + + let bit_vec_6 = [ + true, true, true, true, true, true, false, false, false, false, + ]; + let (circuit, public_inputs) = StateUpdateBuilder::::build( + &st, + &[], + &HotShotState::default(), + &bit_vec_6, + &U256::from(600u32), + ) + .unwrap(); + assert!(circuit.check_circuit_satisfiability(&public_inputs).is_ok()); + + let (bad_circuit, public_inputs) = StateUpdateBuilder::::build( + &st, + &[], + &HotShotState::default(), + &bit_vec_6, + &U256::from(700u32), + ) + .unwrap(); + assert!(bad_circuit + .check_circuit_satisfiability(&public_inputs) + .is_err()); } } From aa3dbf38841704bbf46b088ccda93179cff12656 Mon Sep 17 00:00:00 2001 From: MRain Date: Mon, 6 Nov 2023 18:09:42 -0500 Subject: [PATCH 06/14] Adding back the bls_comm --- crates/hotshot-state-prover/src/circuit.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index 641b52f5f1..1f117f62ef 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -38,14 +38,13 @@ pub struct StakeTableEntryVar { /// HotShot state Variable /// The stake table commitment is a triple (bls_keys_comm, stake_amount_comm, schnorr_keys_comm). -/// Because we only need a binding between Schnorr keys and the stake amount, we ignore the first term. #[derive(Clone, Debug)] pub struct HotShotStateVar { pub view_number_var: Variable, pub block_height_var: Variable, pub block_comm_var: Variable, pub fee_ledger_comm_var: Variable, - pub stake_table_comm_var: (Variable, Variable), + pub stake_table_comm_var: (Variable, Variable, Variable), } /// HotShot state From 671b5015aa4b2613f7998e4d17f65341ae2ecb66 Mon Sep 17 00:00:00 2001 From: MRain Date: Tue, 7 Nov 2023 11:06:14 -0500 Subject: [PATCH 07/14] small refactor for test --- crates/hotshot-state-prover/src/circuit.rs | 23 ++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index 1f117f62ef..98eaafea48 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -168,11 +168,8 @@ mod tests { type F = ark_ed_on_bn254::Fq; type SchnorrVerKey = jf_primitives::signatures::schnorr::VerKey; - #[test] - fn test_circuit_building() { - let mut st = StakeTable::::new(); - let mut prng = jf_utils::test_rng(); - let keys = (0..10) + fn key_pairs_for_testing() -> Vec<(BLSVerKey, SchnorrVerKey)> { + (0..10) .map(|_| { ( BLSOverBN254CurveSignatureScheme::key_gen(&(), &mut prng) @@ -181,13 +178,27 @@ mod tests { SchnorrSignatureScheme::key_gen(&(), &mut prng).unwrap().1, ) }) - .collect::>(); + .collect::>() + } + + fn stake_table_for_testing( + keys: &[(BLSVerKey, SchnorrVerKey)], + ) -> StakeTable { + let mut st = StakeTable::::new(); + let mut prng = jf_utils::test_rng(); // Registering keys keys.iter() .for_each(|key| st.register(key.0, U256::from(100), key.1.clone()).unwrap()); // Freeze the stake table st.advance(); st.advance(); + st + } + + #[test] + fn test_circuit_building() { + let keys = key_pairs_for_testing(); + let st = stake_table_for_testing(&keys); let bit_vec_6 = [ true, true, true, true, true, true, false, false, false, false, From d59fa69378bbfec5d4b6483386fe49a4e1503ae1 Mon Sep 17 00:00:00 2001 From: MRain Date: Tue, 7 Nov 2023 11:16:17 -0500 Subject: [PATCH 08/14] use `STAKE_TABLE_CAPACITY` --- crates/hotshot-state-prover/src/circuit.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index 98eaafea48..4e3b85b869 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -20,7 +20,7 @@ use jf_relation::{gadgets::ecc::TEPoint, Variable}; use serde::{Deserialize, Serialize}; /// Number of entries/keys in the stake table -pub const NUM_ENTRIES: usize = 1000; +use hotshot_types::traits::stake_table::STAKE_TABLE_CAPACITY; /// convert a U256 to a field element. pub(crate) fn u256_to_field(v: &U256) -> F { @@ -109,7 +109,7 @@ where let dummy_ver_key_var = VerKeyVar(circuit.create_constant_point_variable(TEPoint::default())?); stake_table_var.resize( - NUM_ENTRIES, + STAKE_TABLE_CAPACITY, StakeTableEntryVar { schnorr_ver_key: dummy_ver_key_var, stake_amount: 0, @@ -120,7 +120,7 @@ where .iter() .map(|&b| circuit.create_boolean_variable(b)) .collect::, CircuitError>>()?; - signer_bit_vec_var.resize(NUM_ENTRIES, BoolVar(circuit.zero())); + signer_bit_vec_var.resize(STAKE_TABLE_CAPACITY, BoolVar(circuit.zero())); let threshold = u256_to_field::(threshold); let threshold_var = circuit.create_public_variable(threshold)?; @@ -130,7 +130,7 @@ where // Checking whether the accumulated weight exceeds the quorum threshold // We assume that NUM_ENTRIES is always a multiple of 2 - let signed_amount_var = (0..NUM_ENTRIES / 2) + let signed_amount_var = (0..STAKE_TABLE_CAPACITY / 2) .map(|i| { circuit.mul_add( &[ @@ -169,6 +169,7 @@ mod tests { type SchnorrVerKey = jf_primitives::signatures::schnorr::VerKey; fn key_pairs_for_testing() -> Vec<(BLSVerKey, SchnorrVerKey)> { + let mut prng = jf_utils::test_rng(); (0..10) .map(|_| { ( @@ -185,7 +186,6 @@ mod tests { keys: &[(BLSVerKey, SchnorrVerKey)], ) -> StakeTable { let mut st = StakeTable::::new(); - let mut prng = jf_utils::test_rng(); // Registering keys keys.iter() .for_each(|key| st.register(key.0, U256::from(100), key.1.clone()).unwrap()); From 8c8ac94dceacb26ee58fa5fe94897606936f512c Mon Sep 17 00:00:00 2001 From: MRain Date: Wed, 8 Nov 2023 11:41:35 -0500 Subject: [PATCH 09/14] Move state definition to another crate --- Cargo.lock | 1 + crates/hotshot-state-prover/Cargo.toml | 2 -- crates/hotshot-state-prover/src/circuit.rs | 20 +++++--------------- crates/types/Cargo.toml | 3 ++- crates/types/src/traits/state.rs | 16 ++++++++++++++++ 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 596ac1cef4..4eb1590333 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2907,6 +2907,7 @@ version = "0.1.0" dependencies = [ "arbitrary", "ark-bls12-381", + "ark-ff", "ark-serialize 0.3.0", "ark-std 0.4.0", "async-compatibility-layer", diff --git a/crates/hotshot-state-prover/Cargo.toml b/crates/hotshot-state-prover/Cargo.toml index e8e8170f4e..8b2ecfa928 100644 --- a/crates/hotshot-state-prover/Cargo.toml +++ b/crates/hotshot-state-prover/Cargo.toml @@ -27,8 +27,6 @@ jf-utils = { workspace = true } serde = { workspace = true, features = ["rc"] } tagged-base64 = { git = "https://github.com/espressosystems/tagged-base64", tag = "0.3.0" } typenum = { workspace = true } - -[dev-dependencies] hotshot-stake-table = { path = "../hotshot-stake-table" } [features] diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index 4e3b85b869..dd039046a5 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -5,7 +5,11 @@ use std::marker::PhantomData; use ark_ec::twisted_edwards::TECurveConfig; use ark_ff::PrimeField; use ethereum_types::U256; -use hotshot_types::traits::stake_table::{SnapshotVersion, StakeTableScheme}; +use hotshot_stake_table::config::STAKE_TABLE_CAPACITY; +use hotshot_types::traits::{ + stake_table::{SnapshotVersion, StakeTableScheme}, + state::HotShotStateForProver as HotShotState, +}; use jf_plonk::errors::PlonkError; use jf_primitives::{ circuit::signature::schnorr::VerKeyVar, @@ -17,10 +21,6 @@ use jf_primitives::{ }; use jf_relation::{errors::CircuitError, BoolVar, Circuit, PlonkCircuit}; use jf_relation::{gadgets::ecc::TEPoint, Variable}; -use serde::{Deserialize, Serialize}; - -/// Number of entries/keys in the stake table -use hotshot_types::traits::stake_table::STAKE_TABLE_CAPACITY; /// convert a U256 to a field element. pub(crate) fn u256_to_field(v: &U256) -> F { @@ -47,16 +47,6 @@ pub struct HotShotStateVar { pub stake_table_comm_var: (Variable, Variable, Variable), } -/// HotShot state -#[derive(Clone, Debug, Serialize, Deserialize, Default)] -pub struct HotShotState { - pub view_number: usize, - pub block_height: usize, - pub block_comm: F, - pub fee_ledger_comm: F, - pub stake_table_comm: (F, F, F), -} - #[derive(Clone, Debug)] pub struct StateUpdateBuilder(PhantomData); diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index a261c5aacb..2a636cd746 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -13,6 +13,7 @@ demo = [] [dependencies] arbitrary = { version = "1.3", features = ["derive"] } ark-bls12-381 = { workspace = true } +ark-ff = "0.4.0" ark-serialize = { version = "0.3", features = [ "derive", ] } # TODO upgrade to 0.4 and inherit this dep from workspace https://github.com/EspressoSystems/HotShot/issues/1700 @@ -28,6 +29,7 @@ custom_debug = { workspace = true } derivative = "2.2.0" digest = { workspace = true } displaydoc = { version = "0.2.3", default-features = false } +dyn-clone = { git = "https://github.com/dtolnay/dyn-clone", tag = "1.0.14" } either = { workspace = true, features = ["serde"] } espresso-systems-common = { workspace = true } ethereum-types = { workspace = true } @@ -51,7 +53,6 @@ tagged-base64 = { git = "https://github.com/EspressoSystems/tagged-base64", tag time = { workspace = true } tracing = { workspace = true } typenum = { workspace = true } -dyn-clone = { git = "https://github.com/dtolnay/dyn-clone", tag = "1.0.14" } [dev-dependencies] serde_json = "1.0.108" diff --git a/crates/types/src/traits/state.rs b/crates/types/src/traits/state.rs index 4899e9976a..38fa9e93db 100644 --- a/crates/types/src/traits/state.rs +++ b/crates/types/src/traits/state.rs @@ -4,6 +4,7 @@ //! network state, which is modified by the transactions contained within blocks. use crate::traits::BlockPayload; +use ark_ff::PrimeField; use commit::Committable; use espresso_systems_common::hotshot::tag; use serde::{de::DeserializeOwned, Serialize}; @@ -218,3 +219,18 @@ pub mod dummy { } } } + +/// A serialized consensus state for proof generation +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Default)] +pub struct HotShotStateForProver { + /// Current view number + pub view_number: usize, + /// Current block height + pub block_height: usize, + /// Block commitment + pub block_comm: F, + /// Commitment for fee ledger + pub fee_ledger_comm: F, + /// Commitment for the stake table + pub stake_table_comm: (F, F, F), +} From 95af25c82a8f387bad35a99496881075f35d46e9 Mon Sep 17 00:00:00 2001 From: MRain Date: Wed, 8 Nov 2023 11:43:25 -0500 Subject: [PATCH 10/14] Formatting --- Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b821fda1f6..c98a4e7350 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,9 @@ tokio = { version = "1.32.0", features = [ "time", "tracing", ] } -### Profiles###### Note: these only apply to example executables or tests built from within this crate. They have +### Profiles +### +### Note: these only apply to example executables or tests built from within this crate. They have ### no effect on crates that depend on this crate. ## Apply some optimizations to test dependencies in debug/test builds From 34ec656ac16c90abfe6311ce23686392899252f5 Mon Sep 17 00:00:00 2001 From: MRain Date: Wed, 8 Nov 2023 11:57:31 -0500 Subject: [PATCH 11/14] merge imports --- crates/hotshot-state-prover/src/circuit.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index dd039046a5..310a71b641 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -19,8 +19,9 @@ use jf_primitives::{ schnorr::{Signature, VerKey as SchnorrVerKey}, }, }; -use jf_relation::{errors::CircuitError, BoolVar, Circuit, PlonkCircuit}; -use jf_relation::{gadgets::ecc::TEPoint, Variable}; +use jf_relation::{ + errors::CircuitError, gadgets::ecc::TEPoint, BoolVar, Circuit, PlonkCircuit, Variable, +}; /// convert a U256 to a field element. pub(crate) fn u256_to_field(v: &U256) -> F { From de3a6977594c42fab11b93857620156713f1e964 Mon Sep 17 00:00:00 2001 From: MRain Date: Wed, 8 Nov 2023 13:58:23 -0500 Subject: [PATCH 12/14] augment test & comments --- crates/hotshot-state-prover/src/circuit.rs | 27 ++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index 310a71b641..a65301d74e 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -23,7 +23,7 @@ use jf_relation::{ errors::CircuitError, gadgets::ecc::TEPoint, BoolVar, Circuit, PlonkCircuit, Variable, }; -/// convert a U256 to a field element. +/// Lossy conversion of a U256 into a field element. pub(crate) fn u256_to_field(v: &U256) -> F { let mut bytes = vec![0u8; 32]; v.to_little_endian(&mut bytes); @@ -178,8 +178,10 @@ mod tests { ) -> StakeTable { let mut st = StakeTable::::new(); // Registering keys - keys.iter() - .for_each(|key| st.register(key.0, U256::from(100), key.1.clone()).unwrap()); + keys.iter().enumerate().for_each(|(i, key)| { + st.register(key.0, U256::from((i + 1) as u32), key.1.clone()) + .unwrap() + }); // Freeze the stake table st.advance(); st.advance(); @@ -191,25 +193,32 @@ mod tests { let keys = key_pairs_for_testing(); let st = stake_table_for_testing(&keys); - let bit_vec_6 = [ - true, true, true, true, true, true, false, false, false, false, + // bit vector with total weight 26 + let bit_vec = [ + true, true, true, false, true, true, false, false, true, false, ]; + // good path let (circuit, public_inputs) = StateUpdateBuilder::::build( &st, &[], &HotShotState::default(), - &bit_vec_6, - &U256::from(600u32), + &bit_vec, + &U256::from(25u32), ) .unwrap(); assert!(circuit.check_circuit_satisfiability(&public_inputs).is_ok()); + // bad path: total weight doesn't meet the threshold + // bit vector with total weight 23 + let bad_bit_vec = [ + true, true, true, true, true, false, false, true, false, false, + ]; let (bad_circuit, public_inputs) = StateUpdateBuilder::::build( &st, &[], &HotShotState::default(), - &bit_vec_6, - &U256::from(700u32), + &bad_bit_vec, + &U256::from(25u32), ) .unwrap(); assert!(bad_circuit From ccb06e9c6d3580d0e0b189f1fe293835827a3f9b Mon Sep 17 00:00:00 2001 From: MRain Date: Thu, 9 Nov 2023 10:25:46 -0500 Subject: [PATCH 13/14] Addressing comments --- crates/hotshot-state-prover/src/circuit.rs | 22 ++++++++++++++-------- crates/types/src/traits/state.rs | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/crates/hotshot-state-prover/src/circuit.rs b/crates/hotshot-state-prover/src/circuit.rs index a65301d74e..b96284d595 100644 --- a/crates/hotshot-state-prover/src/circuit.rs +++ b/crates/hotshot-state-prover/src/circuit.rs @@ -8,7 +8,7 @@ use ethereum_types::U256; use hotshot_stake_table::config::STAKE_TABLE_CAPACITY; use hotshot_types::traits::{ stake_table::{SnapshotVersion, StakeTableScheme}, - state::HotShotStateForProver as HotShotState, + state::LightClientState, }; use jf_plonk::errors::PlonkError; use jf_primitives::{ @@ -40,7 +40,7 @@ pub struct StakeTableEntryVar { /// HotShot state Variable /// The stake table commitment is a triple (bls_keys_comm, stake_amount_comm, schnorr_keys_comm). #[derive(Clone, Debug)] -pub struct HotShotStateVar { +pub struct LightClientStateVar { pub view_number_var: Variable, pub block_height_var: Variable, pub block_comm_var: Variable, @@ -68,7 +68,7 @@ where pub fn build( stake_table: &ST, _sigs: &[Signature

], - _hotshot_state: &HotShotState, + _hotshot_state: &LightClientState, signer_bit_vec: &[bool], threshold: &U256, ) -> Result<(PlonkCircuit, Vec), PlonkError> @@ -120,8 +120,7 @@ where let public_inputs = vec![threshold]; // Checking whether the accumulated weight exceeds the quorum threshold - // We assume that NUM_ENTRIES is always a multiple of 2 - let signed_amount_var = (0..STAKE_TABLE_CAPACITY / 2) + let mut signed_amount_var = (0..STAKE_TABLE_CAPACITY / 2) .map(|i| { circuit.mul_add( &[ @@ -134,6 +133,13 @@ where ) }) .collect::, CircuitError>>()?; + // Adding the last if STAKE_TABLE_CAPACITY is not a multiple of 2 + if STAKE_TABLE_CAPACITY % 2 == 1 { + signed_amount_var.push(circuit.mul( + stake_table_var[STAKE_TABLE_CAPACITY - 1].stake_amount, + signer_bit_vec_var[STAKE_TABLE_CAPACITY - 1].0, + )?); + } let acc_amount_var = circuit.sum(&signed_amount_var)?; circuit.enforce_leq(threshold_var, acc_amount_var)?; @@ -145,7 +151,7 @@ where #[cfg(test)] mod tests { - use super::{HotShotState, StateUpdateBuilder}; + use super::{LightClientState, StateUpdateBuilder}; use ark_ed_on_bn254::EdwardsConfig as Config; use ethereum_types::U256; use hotshot_stake_table::vec_based::StakeTable; @@ -201,7 +207,7 @@ mod tests { let (circuit, public_inputs) = StateUpdateBuilder::::build( &st, &[], - &HotShotState::default(), + &LightClientState::default(), &bit_vec, &U256::from(25u32), ) @@ -216,7 +222,7 @@ mod tests { let (bad_circuit, public_inputs) = StateUpdateBuilder::::build( &st, &[], - &HotShotState::default(), + &LightClientState::default(), &bad_bit_vec, &U256::from(25u32), ) diff --git a/crates/types/src/traits/state.rs b/crates/types/src/traits/state.rs index 38fa9e93db..6a845088f2 100644 --- a/crates/types/src/traits/state.rs +++ b/crates/types/src/traits/state.rs @@ -222,7 +222,7 @@ pub mod dummy { /// A serialized consensus state for proof generation #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Default)] -pub struct HotShotStateForProver { +pub struct LightClientState { /// Current view number pub view_number: usize, /// Current block height From 6b3a61f5e8ba2c22cb8089f7aa5ca9f161829fd9 Mon Sep 17 00:00:00 2001 From: MRain Date: Thu, 9 Nov 2023 11:16:52 -0500 Subject: [PATCH 14/14] duplicated items --- Cargo.lock | 2 +- crates/types/Cargo.toml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 141da8cc12..9e76cdb6da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3421,7 +3421,7 @@ dependencies = [ "derivative", "displaydoc", "downcast-rs", - "dyn-clone 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "dyn-clone 1.0.14", "espresso-systems-common 0.4.0", "hashbrown 0.13.2", "itertools 0.10.5", diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index 0ce8e3c2a3..601b03b8f5 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -29,7 +29,7 @@ custom_debug = { workspace = true } derivative = "2.2.0" digest = { workspace = true } displaydoc = { version = "0.2.3", default-features = false } -dyn-clone = { git = "https://github.com/dtolnay/dyn-clone", tag = "1.0.14" } +dyn-clone = { git = "https://github.com/dtolnay/dyn-clone", tag = "1.0.16" } either = { workspace = true, features = ["serde"] } espresso-systems-common = { workspace = true } ethereum-types = { workspace = true } @@ -53,7 +53,6 @@ tagged-base64 = { git = "https://github.com/EspressoSystems/tagged-base64", tag time = { workspace = true } tracing = { workspace = true } typenum = { workspace = true } -dyn-clone = { git = "https://github.com/dtolnay/dyn-clone", tag = "1.0.16" } [dev-dependencies] serde_json = "1.0.108"