From 4696d0e6688269d49f33884840d4ad1037b27a67 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:16:38 +0000 Subject: [PATCH 1/2] feat: add proof of correct aggregration --- Cargo.lock | 1 + crates/aggregator/Cargo.toml | 1 + crates/aggregator/src/ext.rs | 34 +- crates/aggregator/src/publickey_aggregator.rs | 381 ++++++++++++++---- .../src/ciphernode_builder.rs | 11 +- .../entrypoint/src/start/aggregator_start.rs | 5 + .../src/enclave_event/compute_request/mod.rs | 1 + .../src/enclave_event/compute_request/zk.rs | 28 ++ .../src/enclave_event/publickey_aggregated.rs | 4 +- crates/multithread/src/multithread.rs | 80 +++- crates/tests/tests/integration.rs | 62 ++- examples/CRISP/test/crisp.spec.ts | 2 +- templates/default/enclave.config.yaml | 14 +- templates/default/server/index.ts | 1 - 14 files changed, 516 insertions(+), 109 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4168fa91f..f5da183ccd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3055,6 +3055,7 @@ dependencies = [ "e3-events", "e3-evm", "e3-fhe", + "e3-fhe-params", "e3-multithread", "e3-request", "e3-sortition", diff --git a/crates/aggregator/Cargo.toml b/crates/aggregator/Cargo.toml index fccc0d3556..fd9dfd3fe6 100644 --- a/crates/aggregator/Cargo.toml +++ b/crates/aggregator/Cargo.toml @@ -16,6 +16,7 @@ e3-data = { workspace = true } e3-events = { workspace = true } e3-evm = { workspace = true } e3-fhe = { workspace = true } +e3-fhe-params = { workspace = true } e3-multithread = { workspace = true } e3-trbfv = { workspace = true } e3-bfv-client = { workspace = true } diff --git a/crates/aggregator/src/ext.rs b/crates/aggregator/src/ext.rs index b87289d50c..263fe5b55c 100644 --- a/crates/aggregator/src/ext.rs +++ b/crates/aggregator/src/ext.rs @@ -20,16 +20,21 @@ use e3_events::{prelude::*, E3id}; use e3_events::{BusHandle, EType, EnclaveEvent, EnclaveEventData}; use e3_fhe::ext::FHE_KEY; use e3_fhe::Fhe; +use e3_fhe_params::BfvPreset; use e3_request::{E3Context, E3ContextSnapshot, E3Extension, META_KEY}; use e3_sortition::Sortition; pub struct PublicKeyAggregatorExtension { bus: BusHandle, + params_preset: BfvPreset, } impl PublicKeyAggregatorExtension { - pub fn create(bus: &BusHandle) -> Box { - Box::new(Self { bus: bus.clone() }) + pub fn create(bus: &BusHandle, params_preset: BfvPreset) -> Box { + Box::new(Self { + bus: bus.clone(), + params_preset, + }) } } @@ -62,10 +67,17 @@ impl E3Extension for PublicKeyAggregatorExtension { let repo = ctx.repositories().publickey(&e3_id); let sync_state = repo.send(Some(PublicKeyAggregatorState::init( meta.threshold_n, + meta.threshold_m, meta.seed, ))); - let value = create_publickey_aggregator(fhe.clone(), self.bus.clone(), e3_id, sync_state); + let value = create_publickey_aggregator( + fhe.clone(), + self.bus.clone(), + e3_id, + sync_state, + self.params_preset.clone(), + ); ctx.set_event_recipient("publickey", Some(value)); } @@ -98,6 +110,7 @@ impl E3Extension for PublicKeyAggregatorExtension { self.bus.clone(), ctx.e3_id.clone(), sync_state, + self.params_preset.clone(), ); // send to context @@ -112,11 +125,20 @@ fn create_publickey_aggregator( bus: BusHandle, e3_id: E3id, sync_state: Persistable, + params_preset: BfvPreset, ) -> Recipient { KeyshareCreatedFilterBuffer::new( - PublicKeyAggregator::new(PublicKeyAggregatorParams { fhe, bus, e3_id }, sync_state) - .start() - .into(), + PublicKeyAggregator::new( + PublicKeyAggregatorParams { + fhe, + bus, + e3_id, + params_preset, + }, + sync_state, + ) + .start() + .into(), ) .start() .into() diff --git a/crates/aggregator/src/publickey_aggregator.rs b/crates/aggregator/src/publickey_aggregator.rs index 1b36c91ad3..dffe6bad5d 100644 --- a/crates/aggregator/src/publickey_aggregator.rs +++ b/crates/aggregator/src/publickey_aggregator.rs @@ -9,27 +9,43 @@ use anyhow::Result; use e3_bfv_client::client::compute_pk_commitment; use e3_data::Persistable; use e3_events::{ - prelude::*, BusHandle, Die, E3id, EnclaveEvent, EnclaveEventData, EventContext, - KeyshareCreated, OrderedSet, PublicKeyAggregated, Seed, Sequenced, TypedEvent, + prelude::*, BusHandle, ComputeRequest, ComputeResponse, ComputeResponseKind, CorrelationId, + Die, E3id, EnclaveEvent, EnclaveEventData, EventContext, KeyshareCreated, OrderedSet, + PartyProofsToVerify, PkAggregationProofRequest, PkAggregationProofResponse, + PublicKeyAggregated, Seed, Sequenced, SignedProofPayload, TypedEvent, VerifyShareProofsRequest, + VerifyShareProofsResponse, ZkRequest, ZkResponse, }; use e3_events::{trap, EType}; use e3_fhe::{Fhe, GetAggregatePublicKey}; +use e3_fhe_params::BfvPreset; use e3_utils::NotifySync; use e3_utils::{ArcBytes, MAILBOX_LIMIT}; use std::sync::Arc; -use tracing::{error, info}; +use tracing::{error, info, warn}; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub enum PublicKeyAggregatorState { Collecting { threshold_n: usize, + threshold_m: usize, keyshares: OrderedSet, + /// C1 proofs collected from KeyshareCreated events, indexed by insertion order. + c1_proofs: Vec>, seed: Seed, nodes: OrderedSet, }, - Computing { + VerifyingC1 { keyshares: OrderedSet, nodes: OrderedSet, + threshold_m: usize, + /// Party indices that submitted no C1 proof — treated as dishonest. + no_proof_parties: Vec, + }, + GeneratingC5Proof { + public_key: Vec, + public_key_hash: [u8; 32], + keyshare_bytes: Vec, + nodes: OrderedSet, }, Complete { public_key: Vec, @@ -39,42 +55,36 @@ pub enum PublicKeyAggregatorState { } impl PublicKeyAggregatorState { - pub fn init(threshold_n: usize, seed: Seed) -> Self { + pub fn init(threshold_n: usize, threshold_m: usize, seed: Seed) -> Self { PublicKeyAggregatorState::Collecting { threshold_n, + threshold_m, keyshares: OrderedSet::new(), + c1_proofs: Vec::new(), seed, nodes: OrderedSet::new(), } } } -#[derive(Message)] -#[rtype(result = "anyhow::Result<()>")] -struct ComputeAggregate { - pub keyshares: OrderedSet, - pub e3_id: E3id, -} - pub struct PublicKeyAggregator { fhe: Arc, bus: BusHandle, e3_id: E3id, state: Persistable, + params_preset: BfvPreset, } pub struct PublicKeyAggregatorParams { pub fhe: Arc, pub bus: BusHandle, pub e3_id: E3id, + pub params_preset: BfvPreset, } /// Aggregate PublicKey for a committee of nodes. This actor listens for KeyshareCreated events -/// around a particular e3_id and aggregates the public key based on this and once done broadcasts -/// a EnclaveEvent::PublicKeyAggregated event on the event bus. Note events are hashed and -/// identical events will not be triggered twice. -/// It is expected to change this mechanism as we work through adversarial scenarios and write tests -/// for them. +/// around a particular e3_id, verifies C1 proofs, aggregates the public key, generates a C5 +/// proof of correct aggregation, and broadcasts a PublicKeyAggregated event on the event bus. impl PublicKeyAggregator { pub fn new( params: PublicKeyAggregatorParams, @@ -85,6 +95,7 @@ impl PublicKeyAggregator { bus: params.bus, e3_id: params.e3_id, state, + params_preset: params.params_preset, } } @@ -92,12 +103,15 @@ impl PublicKeyAggregator { &mut self, keyshare: ArcBytes, node: String, + c1_proof: Option, ec: &EventContext, ) -> Result<()> { self.state.try_mutate(&ec, |mut state| { let PublicKeyAggregatorState::Collecting { threshold_n, + threshold_m, keyshares, + c1_proofs, nodes, .. } = &mut state @@ -106,17 +120,22 @@ impl PublicKeyAggregator { }; keyshares.insert(keyshare); + c1_proofs.push(c1_proof); nodes.insert(node); + let n = *threshold_n; + let m = *threshold_m; info!( "PublicKeyAggregator got keyshares {}/{}", keyshares.len(), - threshold_n + n ); - if keyshares.len() == *threshold_n { - info!("Computing aggregate public key..."); - return Ok(PublicKeyAggregatorState::Computing { + if keyshares.len() == n { + info!("All keyshares collected, transitioning to VerifyingC1..."); + return Ok(PublicKeyAggregatorState::VerifyingC1 { keyshares: std::mem::take(keyshares), nodes: std::mem::take(nodes), + threshold_m: m, + no_proof_parties: Vec::new(), }); } @@ -124,18 +143,237 @@ impl PublicKeyAggregator { }) } - pub fn set_pubkey(&mut self, pubkey: Vec, ec: &EventContext) -> Result<()> { - self.state.try_mutate(ec, |mut state| { - let PublicKeyAggregatorState::Computing { keyshares, nodes } = &mut state else { - return Ok(state); - }; + fn dispatch_c1_verification( + &mut self, + c1_proofs: &[Option], + ec: EventContext, + ) -> Result<()> { + let mut party_proofs = Vec::new(); + let mut no_proof_parties = Vec::new(); + + for (idx, proof_opt) in c1_proofs.iter().enumerate() { + match proof_opt { + Some(proof) => { + party_proofs.push(PartyProofsToVerify { + sender_party_id: idx as u64, + signed_proofs: vec![proof.clone()], + }); + } + None => { + warn!( + "Party {} submitted keyshare without C1 proof — treating as dishonest", + idx + ); + no_proof_parties.push(idx as u64); + } + } + } + + // Store no-proof parties in state for the response handler + if !no_proof_parties.is_empty() { + self.state.try_mutate(&ec, |mut state| { + if let PublicKeyAggregatorState::VerifyingC1 { + no_proof_parties: ref mut stored, + .. + } = state + { + *stored = no_proof_parties.clone(); + } + Ok(state) + })?; + } + + if party_proofs.is_empty() { + return Err(anyhow::anyhow!( + "No C1 proofs to verify — all keyshares must include a signed C1 proof" + )); + } + + info!( + "Dispatching C1 proof verification for {} parties ({} missing proofs)", + party_proofs.len(), + no_proof_parties.len() + ); + + let request = ComputeRequest::zk( + ZkRequest::VerifyShareProofs(VerifyShareProofsRequest { party_proofs }), + CorrelationId::new(), + self.e3_id.clone(), + ); + self.bus.publish(request, ec)?; + Ok(()) + } + + fn handle_c1_verification_response( + &mut self, + response: VerifyShareProofsResponse, + ec: EventContext, + ) -> Result<()> { + let PublicKeyAggregatorState::VerifyingC1 { + keyshares, + nodes, + threshold_m, + no_proof_parties, + } = self + .state + .get() + .ok_or_else(|| anyhow::anyhow!("Expected VerifyingC1 state"))? + else { + return Err(anyhow::anyhow!( + "handle_c1_verification_response called outside VerifyingC1 state" + )); + }; + + // Partition honest/dishonest parties — include those that failed verification + // AND those that submitted no C1 proof at all + let mut dishonest_parties: Vec = no_proof_parties; + for result in &response.party_results { + if !result.all_verified { + warn!( + "Party {} failed C1 proof verification (failed payload: {:?})", + result.sender_party_id, result.failed_signed_payload + ); + dishonest_parties.push(result.sender_party_id); + } + } + + // Filter out dishonest parties from keyshares and nodes + let keyshares_vec: Vec = keyshares.into_iter().collect(); + let nodes_vec: Vec = nodes.into_iter().collect(); + + let (honest_keyshares, honest_nodes): (Vec, Vec) = keyshares_vec + .into_iter() + .zip(nodes_vec.into_iter()) + .enumerate() + .filter(|(idx, _)| !dishonest_parties.contains(&(*idx as u64))) + .map(|(_, (ks, node))| (ks, node)) + .unzip(); + if !dishonest_parties.is_empty() { + warn!( + "Filtered out {} dishonest parties from C1 verification: {:?}", + dishonest_parties.len(), + dishonest_parties + ); + } + + // Check remaining count >= threshold + if honest_keyshares.len() < threshold_m { + return Err(anyhow::anyhow!( + "Not enough honest parties after C1 verification: {} < {}", + honest_keyshares.len(), + threshold_m + )); + } + + // Synchronous aggregation + info!( + "Aggregating public key from {} honest shares...", + honest_keyshares.len() + ); + let honest_keyshares_set = OrderedSet::from(honest_keyshares.clone()); + let pubkey = self.fhe.get_aggregate_public_key(GetAggregatePublicKey { + keyshares: honest_keyshares_set.clone(), + })?; + + let public_key_hash = compute_pk_commitment( + pubkey.clone(), + self.fhe.params.degree(), + self.fhe.params.plaintext(), + self.fhe.params.moduli().to_vec(), + )?; + + let honest_nodes_set = OrderedSet::from(honest_nodes); + + // Transition to GeneratingC5Proof + self.state.try_mutate(&ec, |_| { + Ok(PublicKeyAggregatorState::GeneratingC5Proof { + public_key: pubkey.clone(), + public_key_hash, + keyshare_bytes: honest_keyshares.clone(), + nodes: honest_nodes_set.clone(), + }) + })?; + + // Dispatch C5 proof request + let committee_h = honest_keyshares.len(); + + info!("Dispatching C5 proof generation (pk aggregation)..."); + let request = ComputeRequest::zk( + ZkRequest::PkAggregation(PkAggregationProofRequest { + keyshare_bytes: honest_keyshares, + aggregated_pk_bytes: ArcBytes::from_bytes(&pubkey), + params_preset: self.params_preset.clone(), + committee_n: committee_h, // N = all parties in this aggregation + committee_h, + committee_threshold: 0, // Will be resolved from preset in handler + }), + CorrelationId::new(), + self.e3_id.clone(), + ); + self.bus.publish(request, ec)?; + Ok(()) + } + + fn handle_c5_proof_response( + &mut self, + response: PkAggregationProofResponse, + ec: EventContext, + ) -> Result<()> { + let PublicKeyAggregatorState::GeneratingC5Proof { + public_key, + public_key_hash, + nodes, + .. + } = self + .state + .get() + .ok_or_else(|| anyhow::anyhow!("Expected GeneratingC5Proof state"))? + else { + return Err(anyhow::anyhow!( + "handle_c5_proof_response called outside GeneratingC5Proof state" + )); + }; + + info!("C5 proof generated, publishing PublicKeyAggregated..."); + + let proof = response.proof; + + // Transition to Complete + self.state.try_mutate(&ec, |_| { Ok(PublicKeyAggregatorState::Complete { - public_key: pubkey, - keyshares: std::mem::take(keyshares), - nodes: std::mem::take(nodes), + public_key: public_key.clone(), + keyshares: OrderedSet::new(), + nodes: nodes.clone(), }) - }) + })?; + + // Publish PublicKeyAggregated with C5 proof + let event = PublicKeyAggregated { + pubkey: public_key, + public_key_hash, + e3_id: self.e3_id.clone(), + nodes, + pk_aggregation_proof: Some(proof), + }; + self.bus.publish(event, ec)?; + Ok(()) + } + + fn handle_compute_response( + &mut self, + response: ComputeResponse, + ec: EventContext, + ) -> Result<()> { + match response.response { + ComputeResponseKind::Zk(ZkResponse::VerifyShareProofs(data)) => { + self.handle_c1_verification_response(data, ec) + } + ComputeResponseKind::Zk(ZkResponse::PkAggregation(data)) => { + self.handle_c5_proof_response(data, ec) + } + _ => Ok(()), // Ignore other compute responses + } } } @@ -154,6 +392,12 @@ impl Handler for PublicKeyAggregator { EnclaveEventData::KeyshareCreated(data) => { self.notify_sync(ctx, TypedEvent::new(data, ec)) } + EnclaveEventData::ComputeResponse(data) => { + self.notify_sync(ctx, TypedEvent::new(data, ec)) + } + EnclaveEventData::ComputeRequestError(data) => { + error!("PublicKeyAggregator received ComputeRequestError: {}", data); + } EnclaveEventData::E3RequestComplete(_) => self.notify_sync(ctx, Die), _ => (), }; @@ -166,32 +410,40 @@ impl Handler> for PublicKeyAggregator { fn handle( &mut self, event: TypedEvent, - ctx: &mut Self::Context, + _ctx: &mut Self::Context, ) -> Self::Result { let (event, ec) = event.into_components(); trap(EType::PublickeyAggregation, &self.bus.with_ec(&ec), || { let e3_id = event.e3_id.clone(); let pubkey = event.pubkey.clone(); let node = event.node.clone(); + let c1_proof = event.signed_pk_generation_proof.clone(); if e3_id != self.e3_id { error!("Wrong e3_id sent to aggregator. This should not happen."); return Ok(()); } - self.add_keyshare(pubkey, node, &ec)?; - - if let Some(PublicKeyAggregatorState::Computing { keyshares, .. }) = &self.state.get() { - self.notify_sync( - ctx, - TypedEvent::new( - ComputeAggregate { - keyshares: keyshares.clone(), - e3_id, - }, - ec, - ), - ) + // Extract c1_proofs before state mutation + let c1_proofs_snapshot = match self.state.get() { + Some(PublicKeyAggregatorState::Collecting { c1_proofs, .. }) => { + let mut proofs = c1_proofs.clone(); + proofs.push(c1_proof.clone()); + Some(proofs) + } + _ => None, + }; + + self.add_keyshare(pubkey, node, c1_proof, &ec)?; + + // If we just transitioned to VerifyingC1, dispatch verification + if matches!( + self.state.get(), + Some(PublicKeyAggregatorState::VerifyingC1 { .. }) + ) { + if let Some(c1_proofs) = c1_proofs_snapshot { + self.dispatch_c1_verification(&c1_proofs, ec)?; + } } Ok(()) @@ -199,44 +451,17 @@ impl Handler> for PublicKeyAggregator { } } -impl Handler> for PublicKeyAggregator { +impl Handler> for PublicKeyAggregator { type Result = (); - fn handle(&mut self, msg: TypedEvent, _: &mut Self::Context) -> Self::Result { + fn handle( + &mut self, + msg: TypedEvent, + _ctx: &mut Self::Context, + ) -> Self::Result { let (msg, ec) = msg.into_components(); trap(EType::PublickeyAggregation, &self.bus.with_ec(&ec), || { - info!("Computing Aggregate PublicKey..."); - let pubkey = self.fhe.get_aggregate_public_key(GetAggregatePublicKey { - keyshares: msg.keyshares, - })?; - - let public_key_hash = compute_pk_commitment( - pubkey.clone(), - self.fhe.params.degree(), - self.fhe.params.plaintext(), - self.fhe.params.moduli().to_vec(), - )?; - - // Update the local state - self.set_pubkey(pubkey, &ec)?; - - if let Some(PublicKeyAggregatorState::Complete { - public_key: pubkey, - nodes, - .. - }) = self.state.get() - { - info!("Notifying network of PublicKey"); - info!("Sending PublicKeyAggregated..."); - let event = PublicKeyAggregated { - pubkey, - public_key_hash, - e3_id: msg.e3_id, - nodes, - }; - self.bus.publish(event, ec)?; - } - Ok(()) + self.handle_compute_response(msg, ec) }) } } diff --git a/crates/ciphernode-builder/src/ciphernode_builder.rs b/crates/ciphernode-builder/src/ciphernode_builder.rs index 1e21494717..d6123fc469 100644 --- a/crates/ciphernode-builder/src/ciphernode_builder.rs +++ b/crates/ciphernode-builder/src/ciphernode_builder.rs @@ -463,7 +463,16 @@ impl CiphernodeBuilder { if self.pubkey_agg { info!("Setting up PublicKeyAggregationExtension"); - e3_builder = e3_builder.with(PublicKeyAggregatorExtension::create(&bus)) + // Ensure multithread worker is available for C1 verification and C5 proof generation + let _ = self.ensure_multithread(&bus); + // TODO: Make BfvPreset configurable via builder method. + // Currently hardcoded to InsecureThreshold512 for C5 proof generation. + // Production deployments should use the appropriate threshold preset. + let aggregator_preset = BfvPreset::InsecureThreshold512; + e3_builder = e3_builder.with(PublicKeyAggregatorExtension::create( + &bus, + aggregator_preset, + )) } if self.threshold_plaintext_agg { diff --git a/crates/entrypoint/src/start/aggregator_start.rs b/crates/entrypoint/src/start/aggregator_start.rs index 912c396b40..f43cf0b61b 100644 --- a/crates/entrypoint/src/start/aggregator_start.rs +++ b/crates/entrypoint/src/start/aggregator_start.rs @@ -9,6 +9,7 @@ use e3_ciphernode_builder::{CiphernodeBuilder, CiphernodeHandle}; use e3_config::AppConfig; use e3_crypto::Cipher; use e3_test_helpers::{PlaintextWriter, PublicKeyWriter}; +use e3_zk_prover::ZkBackend; use rand::SeedableRng; use rand_chacha::{rand_core::OsRng, ChaCha20Rng}; use std::{ @@ -23,6 +24,9 @@ pub async fn execute( ) -> Result { let rng = Arc::new(Mutex::new(ChaCha20Rng::from_rng(OsRng)?)); let cipher = Arc::new(Cipher::from_file(config.key_file()).await?); + let backend = ZkBackend::new(config.bb_binary(), config.circuits_dir(), config.work_dir()); + backend.ensure_installed().await?; + let node = CiphernodeBuilder::new(rng.clone(), cipher.clone()) .with_persistence(&config.log_file(), &config.db_file()) .with_chains(&config.chains()) @@ -31,6 +35,7 @@ pub async fn execute( .with_contract_bonding_registry() .with_contract_ciphernode_registry() .with_max_threads() + .with_zkproof(backend) .with_pubkey_aggregation() .with_threshold_plaintext_aggregation() .with_net(config.peers(), config.quic_port()) diff --git a/crates/events/src/enclave_event/compute_request/mod.rs b/crates/events/src/enclave_event/compute_request/mod.rs index 2e790ff44e..c307d6e4d6 100644 --- a/crates/events/src/enclave_event/compute_request/mod.rs +++ b/crates/events/src/enclave_event/compute_request/mod.rs @@ -88,6 +88,7 @@ impl ToString for ComputeRequest { ZkRequest::DkgShareDecryption(_) => "ZkDkgShareDecryption", ZkRequest::VerifyShareProofs(_) => "ZkVerifyShareProofs", ZkRequest::VerifyShareDecryptionProofs(_) => "ZkVerifyShareDecryptionProofs", + ZkRequest::PkAggregation(_) => "ZkPkAggregation", }, } .to_string() diff --git a/crates/events/src/enclave_event/compute_request/zk.rs b/crates/events/src/enclave_event/compute_request/zk.rs index bfe7be131b..588e39b9dd 100644 --- a/crates/events/src/enclave_event/compute_request/zk.rs +++ b/crates/events/src/enclave_event/compute_request/zk.rs @@ -30,6 +30,26 @@ pub enum ZkRequest { VerifyShareProofs(VerifyShareProofsRequest), /// Batch-verify C4 proofs from DecryptionKeyShared events. VerifyShareDecryptionProofs(VerifyShareDecryptionProofsRequest), + /// Generate proof for public key aggregation (C5). + PkAggregation(PkAggregationProofRequest), +} + +/// Request to generate a proof for public key aggregation (C5). +#[derive(Derivative, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derivative(Debug)] +pub struct PkAggregationProofRequest { + /// Serialized PublicKeyShare bytes per party. + pub keyshare_bytes: Vec, + /// Serialized aggregated PublicKey bytes. + pub aggregated_pk_bytes: ArcBytes, + /// BFV preset for parameter resolution. + pub params_preset: BfvPreset, + /// Total committee size (N). + pub committee_n: usize, + /// Honest committee size (H) — number of shares being aggregated. + pub committee_h: usize, + /// Threshold (T). + pub committee_threshold: usize, } /// Request to generate a proof for share computation (C2a or C2b). @@ -177,6 +197,14 @@ pub enum ZkResponse { VerifyShareProofs(VerifyShareProofsResponse), /// Batch verification results for C4 proofs. VerifyShareDecryptionProofs(VerifyShareDecryptionProofsResponse), + /// Proof for public key aggregation (C5). + PkAggregation(PkAggregationProofResponse), +} + +/// Response containing a generated proof for public key aggregation (C5). +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct PkAggregationProofResponse { + pub proof: Proof, } /// Response containing a generated share computation proof. diff --git a/crates/events/src/enclave_event/publickey_aggregated.rs b/crates/events/src/enclave_event/publickey_aggregated.rs index 9190fb6573..df6f2de778 100644 --- a/crates/events/src/enclave_event/publickey_aggregated.rs +++ b/crates/events/src/enclave_event/publickey_aggregated.rs @@ -4,7 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use crate::{E3id, OrderedSet}; +use crate::{E3id, OrderedSet, Proof}; use actix::Message; use derivative::Derivative; use serde::{Deserialize, Serialize}; @@ -19,6 +19,8 @@ pub struct PublicKeyAggregated { pub public_key_hash: [u8; 32], pub e3_id: E3id, pub nodes: OrderedSet, + /// C5 proof: proof of correct pk aggregation. + pub pk_aggregation_proof: Option, } impl Display for PublicKeyAggregated { diff --git a/crates/multithread/src/multithread.rs b/crates/multithread/src/multithread.rs index 4fc7422e0b..c89fd1a91e 100644 --- a/crates/multithread/src/multithread.rs +++ b/crates/multithread/src/multithread.rs @@ -26,11 +26,12 @@ use e3_events::{ BusHandle, ComputeRequest, ComputeRequestError, ComputeRequestErrorKind, ComputeRequestKind, ComputeResponse, DkgShareDecryptionProofRequest, DkgShareDecryptionProofResponse, EnclaveEvent, EnclaveEventData, EventPublisher, EventSubscriber, EventType, PartyVerificationResult, - PkBfvProofRequest, PkBfvProofResponse, PkGenerationProofRequest, PkGenerationProofResponse, - ShareComputationProofRequest, ShareComputationProofResponse, ShareEncryptionProofRequest, - ShareEncryptionProofResponse, TypedEvent, VerifyShareDecryptionProofsRequest, - VerifyShareDecryptionProofsResponse, VerifyShareProofsRequest, VerifyShareProofsResponse, - ZkError as ZkEventError, ZkRequest, ZkResponse, + PkAggregationProofRequest, PkAggregationProofResponse, PkBfvProofRequest, PkBfvProofResponse, + PkGenerationProofRequest, PkGenerationProofResponse, ShareComputationProofRequest, + ShareComputationProofResponse, ShareEncryptionProofRequest, ShareEncryptionProofResponse, + TypedEvent, VerifyShareDecryptionProofsRequest, VerifyShareDecryptionProofsResponse, + VerifyShareProofsRequest, VerifyShareProofsResponse, ZkError as ZkEventError, ZkRequest, + ZkResponse, }; use e3_fhe_params::build_pair_for_preset; use e3_fhe_params::{BfvParamSet, BfvPreset}; @@ -55,6 +56,8 @@ use e3_zk_helpers::computation::DkgInputType; use e3_zk_helpers::dkg::share_computation::{ShareComputationCircuit, ShareComputationCircuitData}; use e3_zk_helpers::dkg::share_decryption::{ShareDecryptionCircuit, ShareDecryptionCircuitData}; use e3_zk_helpers::dkg::share_encryption::{ShareEncryptionCircuit, ShareEncryptionCircuitData}; +use e3_zk_helpers::threshold::pk_aggregation::PkAggregationCircuit; +use e3_zk_helpers::threshold::pk_aggregation::PkAggregationCircuitData; use e3_zk_prover::{Provable, ZkBackend, ZkProver}; use fhe::bfv::{Ciphertext, Encoding, Plaintext, PublicKey, SecretKey}; use fhe_traits::{DeserializeParametrized, FheEncoder}; @@ -258,6 +261,70 @@ async fn handle_compute_request_event( Ok(()) } +fn handle_pk_aggregation_proof( + prover: &ZkProver, + req: PkAggregationProofRequest, + request: ComputeRequest, +) -> Result { + // 1. Build threshold BFV parameters from preset + let (threshold_params, _dkg_params) = build_pair_for_preset(req.params_preset.clone()) + .map_err(|e| make_zk_error(&request, format!("build_pair_for_preset: {}", e)))?; + + // 2. Create deterministic CRP + let crp = e3_fhe_params::create_deterministic_crp_from_default_seed(&threshold_params); + + // 3. Deserialize each keyshare as PublicKeyShare and extract pk0 + let mut pk0_shares = Vec::with_capacity(req.keyshare_bytes.len()); + for (i, ks_bytes) in req.keyshare_bytes.iter().enumerate() { + let pk_share = + fhe::mbfv::PublicKeyShare::deserialize(ks_bytes, &threshold_params, crp.clone()) + .map_err(|e| { + make_zk_error(&request, format!("keyshare[{}] deserialize: {:?}", i, e)) + })?; + pk0_shares.push(CrtPolynomial::from_fhe_polynomial(&pk_share.p0_share())); + } + + // 4. Deserialize aggregated PublicKey + let public_key = PublicKey::from_bytes(&req.aggregated_pk_bytes, &threshold_params) + .map_err(|e| make_zk_error(&request, format!("aggregated_pk deserialize: {:?}", e)))?; + + // 5. Get 'a' (CRP) as CrtPolynomial + let a = CrtPolynomial::from_fhe_polynomial(&crp.poly()); + + // 6. Build committee and circuit data + let committee = e3_zk_helpers::CiphernodesCommittee { + n: req.committee_n, + h: req.committee_h, + threshold: req.committee_threshold, + }; + + let circuit_data = PkAggregationCircuitData { + committee, + public_key, + pk0_shares, + a, + }; + + // 7. Generate proof via Provable trait + let circuit = PkAggregationCircuit; + let e3_id_str = request.e3_id.to_string(); + let proof = circuit + .prove(prover, &req.params_preset, &circuit_data, &e3_id_str) + .map_err(|e| { + ComputeRequestError::new( + ComputeRequestErrorKind::Zk(ZkEventError::ProofGenerationFailed(e.to_string())), + request.clone(), + ) + })?; + + // 8. Return response + Ok(ComputeResponse::zk( + ZkResponse::PkAggregation(PkAggregationProofResponse { proof }), + request.correlation_id, + request.e3_id, + )) +} + fn timefunc( name: &str, id: u8, @@ -431,6 +498,9 @@ fn handle_zk_request( handle_verify_share_decryption_proofs(&prover, req, request.clone()) }) } + ZkRequest::PkAggregation(req) => timefunc("zk_pk_aggregation", id, || { + handle_pk_aggregation_proof(&prover, req, request.clone()) + }), } } diff --git a/crates/tests/tests/integration.rs b/crates/tests/tests/integration.rs index eeb2f43cfe..dab3cb06b9 100644 --- a/crates/tests/tests/integration.rs +++ b/crates/tests/tests/integration.rs @@ -204,6 +204,24 @@ async fn setup_test_zk_backend() -> (ZkBackend, tempfile::TempDir) { .await .unwrap(); + // Copy C5 (pk_aggregation) circuit + let pk_agg_circuit_dir = circuits_dir.join("threshold").join("pk_aggregation"); + tokio::fs::create_dir_all(&pk_agg_circuit_dir) + .await + .unwrap(); + tokio::fs::copy( + threshold_target.join("pk_aggregation.json"), + pk_agg_circuit_dir.join("pk_aggregation.json"), + ) + .await + .unwrap(); + tokio::fs::copy( + threshold_target.join("pk_aggregation.vk"), + pk_agg_circuit_dir.join("pk_aggregation.vk"), + ) + .await + .unwrap(); + let backend = ZkBackend::new(BBPath::Default(bb_binary), circuits_dir, work_dir); (backend, temp) @@ -607,11 +625,13 @@ async fn test_trbfv_actor() -> Result<()> { decryption_key_shared_timer.elapsed(), )); - // Wait for KeyshareCreated + PublicKeyAggregated - // - KeyshareCreated × 5 (passes is_forwardable_event filter) - // - PublicKeyAggregated × 1 (passes is_forwardable_event filter) - // After DecryptionKeySharedCollector collects all shares and C4 proofs are verified, - // each party publishes KeyshareCreated. + // Wait for KeyshareCreated + C1 verification + C5 proof + PublicKeyAggregated + // - KeyshareCreated × 5 (forwarded from committee nodes) + // - ComputeRequest (C1 proof verification dispatched by PublicKeyAggregator) + // - ComputeResponse (C1 proof verification result) + // - ComputeRequest (C5 PkAggregation proof dispatched by PublicKeyAggregator) + // - ComputeResponse (C5 PkAggregation proof result) + // - PublicKeyAggregated × 1 let shares_to_pubkey_agg_timer = Instant::now(); let expected = vec![ "KeyshareCreated", @@ -619,6 +639,10 @@ async fn test_trbfv_actor() -> Result<()> { "KeyshareCreated", "KeyshareCreated", "KeyshareCreated", + "ComputeRequest", + "ComputeResponse", + "ComputeRequest", + "ComputeResponse", "PublicKeyAggregated", ]; let h = nodes @@ -925,9 +949,12 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { addr: &str, store: Option>, cipher: &Arc, + zk_backend: ZkBackend, ) -> Result { let mut builder = CiphernodeBuilder::new(rng.clone(), cipher.clone()) .with_trbfv() + .with_zkproof(zk_backend) + .testmode_with_signer(PrivateKeySigner::random()) .testmode_with_forked_bus(bus.event_bus()) .testmode_with_history() .testmode_with_errors() @@ -952,23 +979,29 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { rng: &e3_utils::SharedRng, count: u32, cipher: &Arc, + zk_backend: ZkBackend, ) -> Result> { let eth_addrs = create_random_eth_addrs(count); let mut result = vec![]; for addr in ð_addrs { println!("Setting up eth addr: {}", addr); - let tuple = setup_local_ciphernode(&bus, &rng, true, addr, None, cipher).await?; + let tuple = + setup_local_ciphernode(&bus, &rng, true, addr, None, cipher, zk_backend.clone()) + .await?; result.push(tuple); } simulate_libp2p_net(&result); Ok(result) } + let (zk_backend, _zk_temp) = setup_test_zk_backend().await; + let e3_id = E3id::new("1234", 1); let (rng, cn1_address, cn1_data, cn2_address, cn2_data, cipher, history, params, crpoly) = { let (bus, rng, seed, params, crpoly, _, _) = get_common_setup(None)?; let cipher = Arc::new(Cipher::from_password("Don't tell anyone my secret").await?); - let ciphernodes = create_local_ciphernodes(&bus, &rng, 2, &cipher).await?; + let ciphernodes = + create_local_ciphernodes(&bus, &rng, 2, &cipher, zk_backend.clone()).await?; let eth_addrs = ciphernodes.iter().map(|n| n.address()).collect::>(); setup_score_sortition_environment(&bus, ð_addrs, 1).await?; @@ -1038,6 +1071,7 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { &cn1_address, Some(InMemStore::from_dump(cn1_data, true)?.start()), &cipher, + zk_backend.clone(), ) .await?; let cn2 = setup_local_ciphernode( @@ -1047,6 +1081,7 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { &cn2_address, Some(InMemStore::from_dump(cn2_data, true)?.start()), &cipher, + zk_backend.clone(), ) .await?; let history_collector = cn1.history().unwrap(); @@ -1132,9 +1167,12 @@ async fn test_duplicate_e3_id_with_different_chain_id() -> Result<()> { addr: &str, store: Option>, cipher: &Arc, + zk_backend: ZkBackend, ) -> Result { let mut builder = CiphernodeBuilder::new(rng.clone(), cipher.clone()) .with_trbfv() + .with_zkproof(zk_backend) + .testmode_with_signer(PrivateKeySigner::random()) .testmode_with_forked_bus(bus.event_bus()) .testmode_with_history() .testmode_with_errors() @@ -1159,12 +1197,15 @@ async fn test_duplicate_e3_id_with_different_chain_id() -> Result<()> { rng: &e3_utils::SharedRng, count: u32, cipher: &Arc, + zk_backend: ZkBackend, ) -> Result> { let eth_addrs = create_random_eth_addrs(count); let mut result = vec![]; for addr in ð_addrs { println!("Setting up eth addr: {}", addr); - let tuple = setup_local_ciphernode(&bus, &rng, true, addr, None, cipher).await?; + let tuple = + setup_local_ciphernode(&bus, &rng, true, addr, None, cipher, zk_backend.clone()) + .await?; result.push(tuple); } simulate_libp2p_net(&result); @@ -1206,9 +1247,10 @@ async fn test_duplicate_e3_id_with_different_chain_id() -> Result<()> { // Setup let (bus, rng, seed, params, crpoly, _, _) = get_common_setup(None)?; let cipher = Arc::new(Cipher::from_password("Don't tell anyone my secret").await?); + let (zk_backend, _zk_temp) = setup_test_zk_backend().await; // Setup actual ciphernodes and dispatch add events - let ciphernodes = create_local_ciphernodes(&bus, &rng, 3, &cipher).await?; + let ciphernodes = create_local_ciphernodes(&bus, &rng, 3, &cipher, zk_backend.clone()).await?; let eth_addrs = ciphernodes.iter().map(|tup| tup.address()).collect(); setup_score_sortition_environment(&bus, ð_addrs, 1).await?; @@ -1254,6 +1296,7 @@ async fn test_duplicate_e3_id_with_different_chain_id() -> Result<()> { public_key_hash, e3_id: E3id::new("1234", 1), nodes: OrderedSet::from(eth_addrs.clone()), + pk_aggregation_proof: None, } .into() ); @@ -1296,6 +1339,7 @@ async fn test_duplicate_e3_id_with_different_chain_id() -> Result<()> { public_key_hash, e3_id: E3id::new("1234", 2), nodes: OrderedSet::from(eth_addrs.clone()), + pk_aggregation_proof: None, } .into() ); diff --git a/examples/CRISP/test/crisp.spec.ts b/examples/CRISP/test/crisp.spec.ts index da5c248586..31fb8a19c5 100644 --- a/examples/CRISP/test/crisp.spec.ts +++ b/examples/CRISP/test/crisp.spec.ts @@ -142,7 +142,7 @@ test('CRISP smoke test', async ({ context, page, metamaskPage, extensionId }) => await page.locator('button:has-text("Cast Vote")').click() log(`confirming MetaMask signature request...`) await metamask.confirmSignature() - const WAIT = parseInt(process.env.E3_DURATION as string, 10) * 1000 + 45_000 // A small buffer for decryption + const WAIT = parseInt(process.env.E3_DURATION as string, 10) * 1000 + 25_000 // A small buffer for decryption log(`waiting ${WAIT}ms...`) await page.waitForTimeout(WAIT) log(`clicking historic polls button...`) diff --git a/templates/default/enclave.config.yaml b/templates/default/enclave.config.yaml index 70c0eb032d..99c421aa85 100644 --- a/templates/default/enclave.config.yaml +++ b/templates/default/enclave.config.yaml @@ -4,19 +4,19 @@ chains: contracts: enclave: address: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e" - deploy_block: 18 + deploy_block: 19 ciphernode_registry: + address: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318" + deploy_block: 17 + bonding_registry: address: "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853" deploy_block: 14 - bonding_registry: - address: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318" - deploy_block: 15 fee_token: address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" - deploy_block: 9 + deploy_block: 10 e3_program: - address: "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8" - deploy_block: 30 + address: "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E" + deploy_block: 32 program: dev: true nodes: diff --git a/templates/default/server/index.ts b/templates/default/server/index.ts index 61f1430895..c477cc70e8 100644 --- a/templates/default/server/index.ts +++ b/templates/default/server/index.ts @@ -135,7 +135,6 @@ async function handleCommitteePublishedEvent(event: any) { console.log(`🎯 Committee Published for: ${e3Id}, expiration: ${expiration}`) console.log(`📥 Setting up session for E3 ${e3Id}...`) - console.log(e3Sessions) if (!e3Sessions.has(e3Id.toString())) { e3Sessions.set(e3Id.toString(), { From c47ca0aa59eeda2e3eaa11de4a3da9f0e711ba27 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Tue, 3 Mar 2026 15:23:06 +0000 Subject: [PATCH 2/2] chore: pr comments --- .../src/ciphernode_builder.rs | 4 +- templates/default/deployed_contracts.json | 74 +++++++++---------- templates/default/enclave.config.yaml | 12 +-- 3 files changed, 44 insertions(+), 46 deletions(-) diff --git a/crates/ciphernode-builder/src/ciphernode_builder.rs b/crates/ciphernode-builder/src/ciphernode_builder.rs index d6123fc469..598f65df4a 100644 --- a/crates/ciphernode-builder/src/ciphernode_builder.rs +++ b/crates/ciphernode-builder/src/ciphernode_builder.rs @@ -20,7 +20,7 @@ use e3_events::{ use e3_evm::{BondingRegistrySolReader, CiphernodeRegistrySolReader, EnclaveSolWriter}; use e3_evm::{CiphernodeRegistrySol, EnclaveSolReader, ProviderConfig}; use e3_fhe::ext::FheExtension; -use e3_fhe_params::BfvPreset; +use e3_fhe_params::{BfvPreset, DEFAULT_BFV_PRESET}; use e3_keyshare::ext::ThresholdKeyshareExtension; use e3_multithread::{Multithread, MultithreadReport, TaskPool}; use e3_net::{setup_net, NetRepositoryFactory}; @@ -468,7 +468,7 @@ impl CiphernodeBuilder { // TODO: Make BfvPreset configurable via builder method. // Currently hardcoded to InsecureThreshold512 for C5 proof generation. // Production deployments should use the appropriate threshold preset. - let aggregator_preset = BfvPreset::InsecureThreshold512; + let aggregator_preset = DEFAULT_BFV_PRESET; e3_builder = e3_builder.with(PublicKeyAggregatorExtension::create( &bus, aggregator_preset, diff --git a/templates/default/deployed_contracts.json b/templates/default/deployed_contracts.json index d19125d5f6..1f39f056e7 100644 --- a/templates/default/deployed_contracts.json +++ b/templates/default/deployed_contracts.json @@ -21,21 +21,21 @@ }, "localhost": { "PoseidonT3": { - "blockNumber": 8, + "blockNumber": 9, "address": "0x3333333C0A88F9BE4fd23ed0536F9B6c427e3B93" }, "MockUSDC": { "constructorArgs": { "initialSupply": "1000000" }, - "blockNumber": 9, + "blockNumber": 10, "address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" }, "EnclaveToken": { "constructorArgs": { "owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, - "blockNumber": 10, + "blockNumber": 11, "address": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" }, "EnclaveTicketToken": { @@ -44,47 +44,45 @@ "registry": "0x0000000000000000000000000000000000000001", "owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, - "blockNumber": 12, + "blockNumber": 13, "address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9" }, "SlashingManager": { "constructorArgs": { - "admin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "bondingRegistry": "0x0000000000000000000000000000000000000001" + "admin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, - "blockNumber": 13, + "blockNumber": 14, "address": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707" }, - "BondingRegistry": { + "CiphernodeRegistryOwnable": { "constructorArgs": { "owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "ticketToken": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", - "licenseToken": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", - "registry": "0x0000000000000000000000000000000000000001", - "slashedFundsTreasury": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "ticketPrice": "10000000", - "licenseRequiredBond": "100000000000000000000", - "minTicketBalance": "1", - "exitDelay": "604800" + "submissionWindow": "10" }, "proxyRecords": { - "initData": "0x7333fa82000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c90000000000000000000000009fe46736679d2d9a65f0992f2272de9f3c7fa6e00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000056bc75e2d6310000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000093a80", + "initData": "0xcd6dc687000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000000a", "initialOwner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "proxyAddress": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", "proxyAdminAddress": "0x9bd03768a7DCc129555dE410FF8E85528A4F88b5", "implementationAddress": "0x0165878A594ca255338adfa4d48449f69242Eb8F" }, - "blockNumber": 13, + "blockNumber": 15, "address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853" }, - "CiphernodeRegistryOwnable": { + "BondingRegistry": { "constructorArgs": { "owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "enclaveAddress": "0x0000000000000000000000000000000000000001", - "submissionWindow": "10" + "ticketToken": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", + "licenseToken": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", + "registry": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", + "slashedFundsTreasury": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "ticketPrice": "10000000", + "licenseRequiredBond": "100000000000000000000", + "minTicketBalance": "1", + "exitDelay": "604800" }, "proxyRecords": { - "initData": "0x1794bb3c000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a", + "initData": "0x7333fa82000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c90000000000000000000000009fe46736679d2d9a65f0992f2272de9f3c7fa6e0000000000000000000000000a513e6e4b8f2a923d98304ec87f64353c4d5c853000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000056bc75e2d6310000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000093a80", "initialOwner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "proxyAddress": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", "proxyAdminAddress": "0x8aCd85898458400f7Db866d53FCFF6f0D49741FF", @@ -96,24 +94,24 @@ "Enclave": { "constructorArgs": { "owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "registry": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", - "bondingRegistry": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", + "registry": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", + "bondingRegistry": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", "e3RefundManager": "0x0000000000000000000000000000000000000001", "feeToken": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", "maxDuration": "2592000", - "timeoutConfig": "{\"committeeFormationWindow\":3600,\"dkgWindow\":7200,\"computeWindow\":86400,\"decryptionWindow\":3600,\"gracePeriod\":600}", + "timeoutConfig": "{\"committeeFormationWindow\":3600,\"dkgWindow\":7200,\"computeWindow\":86400,\"decryptionWindow\":3600}", "params": [ "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000ffffee0010000000000000000000000000000000000000000000000000000000ffffc400100000000000000000000000000000000000000000000000000000000000000013300000000000000000000000000000000000000000000000000000000000000" ] }, "proxyRecords": { - "initData": "0x69c5b347000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000008a791620dd6260079bf849dc5567adc3f2fdc318000000000000000000000000a513e6e4b8f2a923d98304ec87f64353c4d5c8530000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f05120000000000000000000000000000000000000000000000000000000000278d000000000000000000000000000000000000000000000000000000000000001c2000000000000000000000000000000000000000000000000000000000000151800000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000ffffee0010000000000000000000000000000000000000000000000000000000ffffc400100000000000000000000000000000000000000000000000000000000000000013300000000000000000000000000000000000000000000000000000000000000", + "initData": "0x01d12f1c000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000a513e6e4b8f2a923d98304ec87f64353c4d5c8530000000000000000000000008a791620dd6260079bf849dc5567adc3f2fdc3180000000000000000000000000000000000000000000000000000000000000001000000000000000000000000e7f1725e7734ce288f8367e1bb143e90bb3f05120000000000000000000000000000000000000000000000000000000000278d000000000000000000000000000000000000000000000000000000000000001c2000000000000000000000000000000000000000000000000000000000000151800000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000ffffee0010000000000000000000000000000000000000000000000000000000ffffc400100000000000000000000000000000000000000000000000000000000000000013300000000000000000000000000000000000000000000000000000000000000", "initialOwner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "proxyAddress": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e", "proxyAdminAddress": "0x8dAF17A20c9DBA35f005b6324F493785D239719d", "implementationAddress": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788" }, - "blockNumber": 18, + "blockNumber": 19, "address": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e" }, "E3RefundManager": { @@ -129,28 +127,28 @@ "proxyAdminAddress": "0x32467b43BFa67273FC7dDda0999Ee9A12F2AaA08", "implementationAddress": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0" }, - "blockNumber": 20, + "blockNumber": 21, "address": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82" }, "MockComputeProvider": { - "blockNumber": 22, - "address": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44" + "blockNumber": 25, + "address": "0xc5a5C42992dECbae36851359345FE25997F5C42d" }, "MockDecryptionVerifier": { - "blockNumber": 23, - "address": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f" + "blockNumber": 26, + "address": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933" }, "MockE3Program": { - "blockNumber": 24, - "address": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319" + "blockNumber": 27, + "address": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E" }, "ImageID": { - "address": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933", - "blockNumber": 28 + "address": "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9", + "blockNumber": 31 }, "MyProgram": { - "address": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E", - "blockNumber": 30 + "address": "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8", + "blockNumber": 33 } } } \ No newline at end of file diff --git a/templates/default/enclave.config.yaml b/templates/default/enclave.config.yaml index 99c421aa85..cbbafd874c 100644 --- a/templates/default/enclave.config.yaml +++ b/templates/default/enclave.config.yaml @@ -6,17 +6,17 @@ chains: address: "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e" deploy_block: 19 ciphernode_registry: - address: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318" - deploy_block: 17 - bonding_registry: address: "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853" - deploy_block: 14 + deploy_block: 15 + bonding_registry: + address: "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318" + deploy_block: 16 fee_token: address: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" deploy_block: 10 e3_program: - address: "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E" - deploy_block: 32 + address: "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8" + deploy_block: 33 program: dev: true nodes: