From 3984c2f688010aa85b30f1be05dadf9752bb77cf Mon Sep 17 00:00:00 2001 From: dndll Date: Fri, 2 Feb 2024 20:07:14 +0000 Subject: [PATCH] feat: expose to succinctx --- bin/operator/Cargo.toml | 8 ++- bin/operator/src/main.rs | 13 +++- circuits/plonky2x/src/lib.rs | 98 +++++++++-------------------- circuits/plonky2x/src/test_utils.rs | 8 +-- crates/rpc/src/lib.rs | 10 +++ succinct.json | 12 +++- 6 files changed, 73 insertions(+), 76 deletions(-) diff --git a/bin/operator/Cargo.toml b/bin/operator/Cargo.toml index 2437e53..4b51c4c 100644 --- a/bin/operator/Cargo.toml +++ b/bin/operator/Cargo.toml @@ -11,10 +11,16 @@ name = "sync" path = "src/main.rs" required-features = [ "sync" ] +[[bin]] +name = "verify" +path = "src/main.rs" +required-features = [ "verify" ] + [dependencies] cfg-if = "*" near-light-clientx.workspace = true [features] -default = [ "sync" ] +default = [ ] sync = [ ] +verify = [ ] diff --git a/bin/operator/src/main.rs b/bin/operator/src/main.rs index 25f8fb4..3c4b437 100644 --- a/bin/operator/src/main.rs +++ b/bin/operator/src/main.rs @@ -1,9 +1,18 @@ -use near_light_clientx::{plonky2x::backend::function::Plonky2xFunction, SyncCircuit}; +use near_light_clientx::plonky2x::backend::function::Plonky2xFunction; + +// Testnet +const NETWORK: usize = 1; fn main() { cfg_if::cfg_if! { if #[cfg(feature = "sync")] { - SyncCircuit::entrypoint(); + use near_light_clientx::SyncCircuit; + SyncCircuit::::entrypoint(); + } else if #[cfg(feature = "verify")] { + const PROOF_AMT: usize = 64; + const PROOF_BATCH_SIZE: usize = 8; + use near_light_clientx::VerifyCircuit; + VerifyCircuit::::entrypoint(); } else { panic!("No circuit feature enabled"); } diff --git a/circuits/plonky2x/src/lib.rs b/circuits/plonky2x/src/lib.rs index 1635c61..76dbc4a 100644 --- a/circuits/plonky2x/src/lib.rs +++ b/circuits/plonky2x/src/lib.rs @@ -1,21 +1,11 @@ -#![feature(generic_const_exprs)] - -use std::collections::VecDeque; - use builder::Sync; use hint::FetchNextHeaderInputs; -use near_light_client_protocol::prelude::Itertools; use plonky2x::frontend::hint::simple::hint::Hint; -use plonky2x::frontend::mapreduce::generator::{MapReduceDynamicGenerator, MapReduceGenerator}; -use plonky2x::prelude::plonky2::hash::hashing::PlonkyPermutation; -use plonky2x::prelude::plonky2::iop::target::BoolTarget; +use plonky2x::frontend::mapreduce::generator::MapReduceDynamicGenerator; pub use plonky2x::{self, backend::circuit::Circuit, prelude::*}; use serde::{Deserialize, Serialize}; -use variables::{ - BlockHeightVariable, BpsArr, CryptoHashVariable, HashBpsInputs, HeaderVariable, - ValidatorStakeVariable, -}; -use variables::{BuildEndorsement, EncodeInner, SyncedVariable}; +use variables::{BlockHeightVariable, HashBpsInputs, HeaderVariable}; +use variables::{BuildEndorsement, EncodeInner}; use crate::builder::Verify; use crate::hint::FetchProofInputs; @@ -44,28 +34,30 @@ mod test_utils; // protocol crate // TODO: determine fees, allows integrators to charge #[derive(Debug, Clone)] -pub struct SyncCircuit; +pub struct SyncCircuit; -impl Circuit for SyncCircuit { +impl Circuit for SyncCircuit { fn define, const D: usize>(b: &mut CircuitBuilder) where <>::Config as plonky2::plonk::config::GenericConfig>::Hasher: plonky2::plonk::config::AlgebraicHasher<>::Field>, { - let network = near_light_client_rpc::Network::Testnet; let trusted_head = b.evm_read::(); - // This is a very interesting cheat to be able to get the BPS for the next epoch - // without the need to store the BPS, we can verify the hash of the BPS in the circuit - let bps = FetchNextHeaderInputs(near_light_client_rpc::Network::Testnet) + // This is a very interesting trick to be able to get the BPS for the next epoch + // without the need to store the BPS, we verify the hash of the BPS in the circuit + let bps = FetchNextHeaderInputs(NETWORK.into()) .fetch(b, &trusted_head.inner_lite.next_epoch_id) .unwrap() .next_bps; + let bps_hash = HashBpsInputs.hash(b, &bps); b.assert_is_equal(trusted_head.inner_lite.next_bp_hash, bps_hash); let head_hash = trusted_head.hash(b); - let next_block = FetchNextHeaderInputs(network).fetch(b, &head_hash).unwrap(); + let next_block = FetchNextHeaderInputs(NETWORK.into()) + .fetch(b, &head_hash) + .unwrap(); b.watch(&bps_hash, "calculate_bps_hash"); let synced = b.sync(&trusted_head, &bps, &next_block); @@ -97,36 +89,34 @@ pub struct ProofMapReduceCtx { } #[derive(Debug, Clone)] -pub struct ProofCircuit; +pub struct VerifyCircuit; -impl Circuit for ProofCircuit { +impl Circuit + for VerifyCircuit +{ fn define, const D: usize>(b: &mut CircuitBuilder) where <>::Config as plonky2::plonk::config::GenericConfig>::Hasher: plonky2::plonk::config::AlgebraicHasher<>::Field>, { - assert!(N % B == 0, "Cannot batch by this configuration"); - - let network = near_light_client_rpc::Network::Testnet; + assert!( + N % B == 0, + "Cannot batch by this configuration, must be a power of 2" + ); let trusted_head = b.read::(); let ids = b.read::>(); - let proofs = FetchProofInputs::(network).fetch(b, &trusted_head, &ids.data); - - let zero = b.zero::(); - let _false = b._false(); - - let ctx = ProofMapReduceCtx { - zero, - result: _false, - }; + let proofs = FetchProofInputs::(NETWORK.into()).fetch(b, &trusted_head, &ids.data); let output = b .mapreduce_dynamic::<_, ProofVariable, ProofMapReduceState, Self, B, _, _>( - ctx, + (), proofs.data, |ctx, proofs, b| { + let zero = b.zero::(); + let _false = b._false(); + let mut heights = vec![]; let mut results = vec![]; for p in proofs.data { @@ -136,8 +126,8 @@ impl Circuit for ProofCircuit { b.watch_slice(&heights, "map job -- heights"); b.watch_slice(&results, "map job -- results"); - heights.resize(N, ctx.zero); - results.resize(N, ctx.result); + heights.resize(N, zero); + results.resize(N, _false); let state = ProofMapReduceState { height_indices: heights.into(), @@ -250,18 +240,18 @@ mod beefy_tests { }; use ::test_utils::CryptoHash; use near_light_client_protocol::{prelude::Itertools, ValidatorStake}; - use near_light_client_rpc::{LightClientRpc, NearRpcClient}; use near_primitives::types::{AccountId, TransactionOrReceiptId}; use serial_test::serial; + const NETWORK: usize = 1; + #[test] #[serial] fn beefy_test_sync_e2e() { - const SYNC_AMT: usize = 1; let (header, _, _) = testnet_state(); let define = |b: &mut B| { - SyncCircuit::define(b); + SyncCircuit::::define(b); }; let writer = |input: &mut PI| { input.evm_write::(header.into()); @@ -272,32 +262,6 @@ mod beefy_tests { builder_suite(define, writer, assertions); } - fn account_ids>(bps: Vec) -> Vec { - bps.into_iter() - .map(Into::::into) - .map(|x| x.account_id().clone()) - .collect_vec() - } - - #[tokio::test] - async fn test_epoch_madness() { - use pretty_assertions::assert_eq; - let c = NearRpcClient::new(near_light_client_rpc::Network::Testnet); - let (h, bps, n) = testnet_state(); - println!("{:#?}", h); - - assert_eq!(h.inner_lite.next_bp_hash, CryptoHash::hash_borsh(&bps)); - let bps = account_ids(bps); - - let next_epoch = c.fetch_latest_header(&h.inner_lite.next_epoch_id).await; - let ne_nbps = account_ids(next_epoch.unwrap().unwrap().next_bps.unwrap()); - assert_eq!(ne_nbps, bps); - - let nb_epoch = c.fetch_latest_header(&n.inner_lite.epoch_id).await; - let nb_nbps = account_ids(nb_epoch.unwrap().unwrap().next_bps.unwrap()); - assert_eq!(nb_nbps, bps); - } - #[test] #[serial] fn beefy_test_verify_e2e() { @@ -358,7 +322,7 @@ mod beefy_tests { assert_eq!(txs.len(), AMT); let define = |b: &mut B| { - ProofCircuit::::define(b); + VerifyCircuit::::define(b); }; let writer = |input: &mut PI| { input.write::(header.into()); diff --git a/circuits/plonky2x/src/test_utils.rs b/circuits/plonky2x/src/test_utils.rs index 7af59be..bdac923 100644 --- a/circuits/plonky2x/src/test_utils.rs +++ b/circuits/plonky2x/src/test_utils.rs @@ -27,11 +27,9 @@ pub fn builder_suite( let mut inputs = circuit.input(); writer(&mut inputs); - // if let PublicInput::Bytes(bytes) = &mut inputs { - // std::fs::write("input.bin", hex!(bytes)).unwrap(); - // } else { - // panic!("input is not bytes"); - // } + if let PublicInput::Bytes(bytes) = &mut inputs { + std::fs::write("input.bin", hex!(bytes)).unwrap(); + } let (proof, output) = circuit.prove(&inputs); diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs index 205c6fc..b5b9013 100644 --- a/crates/rpc/src/lib.rs +++ b/crates/rpc/src/lib.rs @@ -45,6 +45,16 @@ impl Network { } } +impl From for Network { + fn from(n: usize) -> Self { + match n { + 0 => Self::Mainnet, + 1 => Self::Testnet, + _ => Self::Localnet, + } + } +} + impl Display for Network { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { diff --git a/succinct.json b/succinct.json index b87fd55..105efea 100644 --- a/succinct.json +++ b/succinct.json @@ -4,11 +4,21 @@ "name": "sync", "framework": "plonky2x", "baseDir": ".", - "buildCommand": "cargo build --release --bin sync && mv target/release/sync build/ && RUST_LOG=debug ./build/sync build", + "buildCommand": "cargo build --release --bin sync --features=sync && mv target/release/sync build/ && RUST_LOG=debug ./build/sync build", "proveCommand": "RUST_LOG=debug ./build/sync prove input.json", "requiredArtifacts": [ "sync" ] + }, + { + "name": "verify", + "framework": "plonky2x", + "baseDir": ".", + "buildCommand": "cargo build --release --bin verify --features=verify && mv target/release/verify build/ && RUST_LOG=debug ./build/verify build", + "proveCommand": "RUST_LOG=debug ./build/verify prove input.json", + "requiredArtifacts": [ + "verify" + ] } ] }