From 616243e30945d94e7e12e0d22176ef6ec5b8019e Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 23 Mar 2026 09:53:44 +0000 Subject: [PATCH 01/43] add basic command to query events --- crates/cli/src/cli.rs | 8 +++++++ crates/cli/src/events.rs | 47 ++++++++++++++++++++++++++++++++++++++++ crates/cli/src/main.rs | 1 + 3 files changed, 56 insertions(+) create mode 100644 crates/cli/src/events.rs diff --git a/crates/cli/src/cli.rs b/crates/cli/src/cli.rs index d42eed453c..28933bc1d4 100644 --- a/crates/cli/src/cli.rs +++ b/crates/cli/src/cli.rs @@ -5,6 +5,7 @@ // or FITNESS FOR A PARTICULAR PURPOSE. use crate::ciphernode::{self, ChainArgs, CiphernodeCommands}; +use crate::events::{self, EventsCommands}; use crate::helpers::telemetry::{setup_simple_tracing, setup_tracing}; use crate::net::{self, NetCommands}; use crate::nodes::{self, NodeCommands}; @@ -181,6 +182,7 @@ impl Cli { Commands::Ciphernode { command } => ciphernode::execute(out, command, &config).await?, Commands::Noir { command } => noir::execute(out, command, &config).await?, Commands::Net { command } => net::execute(&out, command, &config).await?, + Commands::Events { command } => events::execute(command).await?, Commands::Rev => rev::execute(out).await?, } @@ -297,6 +299,12 @@ pub enum Commands { #[command(subcommand)] command: NetCommands, }, + + /// Query events + Events { + #[command(subcommand)] + command: EventsCommands, + }, } #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs new file mode 100644 index 0000000000..b993d17f7e --- /dev/null +++ b/crates/cli/src/events.rs @@ -0,0 +1,47 @@ +use anyhow::Result; +use clap::Subcommand; + +#[derive(Subcommand, Clone, Debug)] +pub enum EventsCommands { + /// Query events + Query { + #[arg(long)] + aggregate: u64, + + #[arg(long)] + since: u64, + + #[arg(long)] + limit: u64, + }, +} + +pub async fn execute(command: EventsCommands) -> Result<()> { + match command { + EventsCommands::Query { + aggregate, + since, + limit, + } => { + query_events(aggregate, since, limit).await?; + } + } + Ok(()) +} + +async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { + tracing::info!( + "Querying events: aggregate={}, since={}, limit={}", + aggregate, + since, + limit + ); + + let url = format!( + "TODO: construct event query endpoint: /events?aggregate={}&since={}&limit={}", + aggregate, since, limit + ); + tracing::debug!("Endpoint: {}", url); + + Ok(()) +} diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 56e50674e8..0faa84c2ac 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -14,6 +14,7 @@ use tracing::info; mod ciphernode; mod cli; +mod events; pub mod helpers; mod init; mod net; From 627ad2cae0a8fc2cd54867ee2fc6f44df3095520 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 23 Mar 2026 10:00:18 +0000 Subject: [PATCH 02/43] add fake json output --- crates/cli/src/events.rs | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index b993d17f7e..29927f8e46 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Subcommand; +use serde::Serialize; #[derive(Subcommand, Clone, Debug)] pub enum EventsCommands { @@ -16,6 +17,14 @@ pub enum EventsCommands { }, } +#[derive(Serialize, Debug)] +struct Event { + id: u64, + aggregate: u64, + event_type: String, + data: serde_json::Value, +} + pub async fn execute(command: EventsCommands) -> Result<()> { match command { EventsCommands::Query { @@ -37,11 +46,30 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { limit ); - let url = format!( - "TODO: construct event query endpoint: /events?aggregate={}&since={}&limit={}", - aggregate, since, limit - ); - tracing::debug!("Endpoint: {}", url); + let events = vec![ + Event { + id: since + 1, + aggregate, + event_type: "PublicKeyAggregated".to_string(), + data: serde_json::json!({ + "public_key": "0x1234567890abcdef", + "threshold": 3, + "total_shares": 5 + }), + }, + Event { + id: since + 2, + aggregate, + event_type: "EncryptionKeyCreated".to_string(), + data: serde_json::json!({ + "key_id": "key_abc123", + "ciphernode": "node_42" + }), + }, + ]; + for event in events { + println!("{}", serde_json::to_string(&event)?); + } Ok(()) } From 025ab686a9f11337d4546ef193395ac5eff3d163 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 23 Mar 2026 10:14:01 +0000 Subject: [PATCH 03/43] use enclave event based serialization --- crates/cli/src/events.rs | 74 +++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 29927f8e46..52323d2d98 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -1,6 +1,17 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use anyhow::Result; use clap::Subcommand; -use serde::Serialize; +use e3_events::{ + E3id, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCreated, + EventConstructorWithTimestamp, PublicKeyAggregated, Unsequenced, +}; +use e3_utils::ArcBytes; +use std::sync::Arc; #[derive(Subcommand, Clone, Debug)] pub enum EventsCommands { @@ -17,14 +28,6 @@ pub enum EventsCommands { }, } -#[derive(Serialize, Debug)] -struct Event { - id: u64, - aggregate: u64, - event_type: String, - data: serde_json::Value, -} - pub async fn execute(command: EventsCommands) -> Result<()> { match command { EventsCommands::Query { @@ -46,29 +49,38 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { limit ); - let events = vec![ - Event { - id: since + 1, - aggregate, - event_type: "PublicKeyAggregated".to_string(), - data: serde_json::json!({ - "public_key": "0x1234567890abcdef", - "threshold": 3, - "total_shares": 5 - }), - }, - Event { - id: since + 2, - aggregate, - event_type: "EncryptionKeyCreated".to_string(), - data: serde_json::json!({ - "key_id": "key_abc123", - "ciphernode": "node_42" - }), - }, - ]; + let event1 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::PublicKeyAggregated(PublicKeyAggregated { + pubkey: ArcBytes::from_bytes(&[0x12, 0x34, 0x56]), + e3_id: E3id::new("test1", 1), + nodes: Default::default(), + pk_aggregation_proof: None, + dkg_aggregated_proof: None, + }), + None, + 1700000000000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(1); + + let event2 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::EncryptionKeyCreated(EncryptionKeyCreated { + e3_id: E3id::new("test2", 1), + key: Arc::new(EncryptionKey::new( + 42, + ArcBytes::from_bytes(&[0xab, 0xcd, 0xef]), + )), + external: false, + }), + None, + 1700000001000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(2); - for event in events { + for event in [event1, event2] { println!("{}", serde_json::to_string(&event)?); } Ok(()) From ed182dc0cde87fc773f97ae39188acb40243b732 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 23 Mar 2026 14:48:44 +0000 Subject: [PATCH 04/43] add derive macro to make json format more concise over the wire --- Cargo.lock | 158 ++++++++++++++++-------------- Cargo.toml | 5 + crates/Dockerfile | 1 + crates/cli/src/events.rs | 126 +++++++++++++++++++++++- crates/events/src/event_id.rs | 15 ++- crates/events/src/seed.rs | 16 ++- crates/utils-derive/Cargo.toml | 16 +++ crates/utils-derive/src/lib.rs | 96 ++++++++++++++++++ crates/utils/Cargo.toml | 2 + crates/utils/src/lib.rs | 4 + crates/utils/src/serde_bytes.rs | 49 +++++++++ crates/utils/src/utility_types.rs | 26 ++--- examples/CRISP/server/Dockerfile | 1 + 13 files changed, 417 insertions(+), 98 deletions(-) create mode 100644 crates/utils-derive/Cargo.toml create mode 100644 crates/utils-derive/src/lib.rs create mode 100644 crates/utils/src/serde_bytes.rs diff --git a/Cargo.lock b/Cargo.lock index 2f4746ac98..0381b43b8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,7 +131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -248,7 +248,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -259,7 +259,7 @@ checksum = "b6ac1e58cded18cb28ddc17143c4dea5345b3ad575e14f32f66e4054a56eb271" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -804,7 +804,7 @@ checksum = "ce8849c74c9ca0f5a03da1c865e3eb6f768df816e67dd3721a398a8a7e398011" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1002,7 +1002,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1019,7 +1019,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "syn-solidity", "tiny-keccak", ] @@ -1038,7 +1038,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.114", + "syn 2.0.117", "syn-solidity", ] @@ -1166,7 +1166,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1403,7 +1403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1441,7 +1441,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1538,7 +1538,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1610,7 +1610,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] @@ -1622,7 +1622,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1724,7 +1724,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1773,7 +1773,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1790,7 +1790,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1851,7 +1851,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2351,7 +2351,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2746,7 +2746,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2771,7 +2771,7 @@ dependencies = [ "quote", "serde", "strsim", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2782,7 +2782,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2822,7 +2822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de" dependencies = [ "data-encoding", - "syn 2.0.114", + "syn 1.0.109", ] [[package]] @@ -2890,7 +2890,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.114", + "syn 2.0.117", "unicode-xid", ] @@ -2996,7 +2996,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3828,6 +3828,8 @@ dependencies = [ "alloy", "anyhow", "derivative", + "e3-utils-derive", + "hex", "rand 0.8.5", "rand_chacha 0.3.1", "regex", @@ -3836,6 +3838,16 @@ dependencies = [ "tracing", ] +[[package]] +name = "e3-utils-derive" +version = "0.1.15" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "e3-wasm" version = "0.1.15" @@ -3973,7 +3985,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4047,7 +4059,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4067,7 +4079,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4453,7 +4465,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -5225,7 +5237,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -5932,7 +5944,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6130,7 +6142,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6141,7 +6153,7 @@ checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6735,7 +6747,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6823,7 +6835,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7009,7 +7021,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7109,7 +7121,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7223,7 +7235,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7252,7 +7264,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7385,7 +7397,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7447,7 +7459,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7467,7 +7479,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "version_check", "yansi", ] @@ -7492,7 +7504,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7551,7 +7563,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.114", + "syn 2.0.117", "tempfile", ] @@ -7561,8 +7573,8 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.4.1", - "itertools 0.10.5", + "heck 0.5.0", + "itertools 0.14.0", "log", "multimap", "once_cell", @@ -7571,7 +7583,7 @@ dependencies = [ "prost 0.13.5", "prost-types 0.13.5", "regex", - "syn 2.0.114", + "syn 2.0.117", "tempfile", ] @@ -7585,7 +7597,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7598,7 +7610,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7769,9 +7781,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -8003,7 +8015,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8250,7 +8262,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.114", + "syn 2.0.117", "walkdir", ] @@ -8654,7 +8666,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8719,7 +8731,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8767,7 +8779,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9087,7 +9099,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9109,9 +9121,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.114" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -9127,7 +9139,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9147,7 +9159,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9249,7 +9261,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9260,7 +9272,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9384,7 +9396,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9655,7 +9667,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9744,7 +9756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10075,7 +10087,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -10231,7 +10243,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10242,7 +10254,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10670,7 +10682,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] @@ -10691,7 +10703,7 @@ checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10711,7 +10723,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] @@ -10732,7 +10744,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10765,7 +10777,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f32c173941..63da4e7164 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ members = [ "crates/tests", "crates/trbfv", "crates/utils", + "crates/utils-derive", "crates/wasm", "crates/zk-helpers", "crates/zk-prover", @@ -108,6 +109,7 @@ e3-test-helpers = { version = "0.1.15", path = "./crates/test-helpers" } e3-tests = { version = "0.1.15", path = "./crates/tests" } e3-trbfv = { version = "0.1.15", path = "./crates/trbfv" } e3-utils = { version = "0.1.15", path = "./crates/utils" } +e3-utils-derive = { version = "0.1.15", path = "./crates/utils-derive" } e3-safe = { version = "0.1.15", path = "./crates/safe" } e3-zk-prover = { version = "0.1.15", path = "./crates/zk-prover" } e3-zk-helpers = { version = "0.1.15", path = "./crates/zk-helpers" } @@ -169,6 +171,8 @@ path-clean = "=1.0.1" petname = "=2.0.2" phf = { version = "=0.11.3", features = ["macros"] } proptest = "=1.9.0" +proc-macro2 = "=1.0.106" +quote = "=1.0.45" rand_chacha = "=0.3.1" rand = "=0.8.5" rayon = "=1.10.0" @@ -183,6 +187,7 @@ sha2 = "=0.10.9" shellexpand = "=3.1.1" sled = "=0.34.7" strum = { version = "=0.27.2", features = ["derive"] } +syn = { version = "=2.0.117", features = ["full"] } tempfile = "=3.20.0" thiserror = { version = "=1.0.69" } tokio = { version = "=1.46.1", features = ["full"] } diff --git a/crates/Dockerfile b/crates/Dockerfile index 54f81f8187..a4c2ccb3d3 100644 --- a/crates/Dockerfile +++ b/crates/Dockerfile @@ -82,6 +82,7 @@ COPY crates/test-helpers/Cargo.toml ./test-helpers/Cargo.toml COPY crates/tests/Cargo.toml ./tests/Cargo.toml COPY crates/trbfv/Cargo.toml ./trbfv/Cargo.toml COPY crates/utils/Cargo.toml ./utils/Cargo.toml +COPY crates/utils-derive/Cargo.toml ./utils-derive/Cargo.toml COPY crates/wasm/Cargo.toml ./wasm/Cargo.toml COPY crates/zk-helpers/Cargo.toml ./zk-helpers/Cargo.toml diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 52323d2d98..985ccda2e9 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -7,8 +7,10 @@ use anyhow::Result; use clap::Subcommand; use e3_events::{ - E3id, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCreated, - EventConstructorWithTimestamp, PublicKeyAggregated, Unsequenced, + CiphertextOutputPublished, ConfigurationUpdated, DecryptionshareCreated, E3Requested, E3id, + EType, EnclaveError, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCreated, + EventConstructorWithTimestamp, KeyshareCreated, PlaintextAggregated, PublicKeyAggregated, Seed, + TestEvent, Unsequenced, }; use e3_utils::ArcBytes; use std::sync::Arc; @@ -80,7 +82,125 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { ) .into_sequenced(2); - for event in [event1, event2] { + let event3 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::E3Requested(E3Requested { + e3_id: E3id::new("test3", 1), + threshold_m: 3, + threshold_n: 5, + seed: Seed([1u8; 32]), + error_size: ArcBytes::from_bytes(&[0xDE, 0xAD]), + esi_per_ct: 2, + params: ArcBytes::from_bytes(&[0xBE, 0xEF]), + proof_aggregation_enabled: true, + }), + None, + 1700000002000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(3); + + let event4 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::KeyshareCreated(KeyshareCreated { + pubkey: ArcBytes::from_bytes(&[0x11, 0x22, 0x33]), + e3_id: E3id::new("test4", 1), + node: "node_abc".to_string(), + signed_pk_generation_proof: None, + }), + None, + 1700000003000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(4); + + let event5 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::CiphertextOutputPublished(CiphertextOutputPublished { + e3_id: E3id::new("test5", 1), + ciphertext_output: vec![ + ArcBytes::from_bytes(&[0xAA, 0xBB, 0xCC]), + ArcBytes::from_bytes(&[0xDD, 0xEE, 0xFF]), + ], + }), + None, + 1700000004000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(5); + + let event6 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::DecryptionshareCreated(DecryptionshareCreated { + party_id: 2, + decryption_share: vec![ArcBytes::from_bytes(&[0x01, 0x02])], + e3_id: E3id::new("test6", 1), + node: "node_xyz".to_string(), + signed_decryption_proofs: vec![], + wrapped_proofs: vec![], + }), + None, + 1700000005000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(6); + + let event7 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::PlaintextAggregated(PlaintextAggregated { + e3_id: E3id::new("test7", 1), + decrypted_output: vec![ArcBytes::from_bytes(&[0x99, 0x88])], + aggregation_proofs: vec![], + c6_aggregated_proof: None, + }), + None, + 1700000006000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(7); + + let event8 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::EnclaveError(EnclaveError { + err_type: EType::Computation, + message: "Computation failed: overflow detected".to_string(), + }), + None, + 1700000007000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(8); + + let event9 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::TestEvent(TestEvent { + msg: "Test message from CLI".to_string(), + entropy: 42, + e3_id: Some(E3id::new("test9", 1)), + }), + None, + 1700000008000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(9); + + let event10 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ConfigurationUpdated(ConfigurationUpdated { + parameter: "max_committee_size".to_string(), + old_value: alloy::primitives::U256::from(10), + new_value: alloy::primitives::U256::from(20), + chain_id: 1, + }), + None, + 1700000009000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(10); + + for event in [ + event1, event2, event3, event4, event5, event6, event7, event8, event9, event10, + ] { println!("{}", serde_json::to_string(&event)?); } Ok(()) diff --git a/crates/events/src/event_id.rs b/crates/events/src/event_id.rs index cec880d5fc..353e153106 100644 --- a/crates/events/src/event_id.rs +++ b/crates/events/src/event_id.rs @@ -5,14 +5,14 @@ // or FITNESS FOR A PARTICULAR PURPOSE. use derivative::Derivative; -use serde::{Deserialize, Serialize}; +use e3_utils::{AsBytesSerde, BytesSerde}; use sha2::{Digest, Sha256}; use std::{ fmt, hash::{DefaultHasher, Hash, Hasher}, }; -#[derive(Derivative, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Derivative, BytesSerde, Clone, Copy, PartialEq, Eq, Hash)] #[derivative(Debug)] pub struct EventId(#[derivative(Debug(format_with = "e3_utils::formatters::hexf"))] pub [u8; 32]); @@ -34,6 +34,17 @@ impl fmt::Display for EventId { } } +impl AsBytesSerde for EventId { + fn as_bytes(&self) -> &[u8] { + &self.0 + } + fn try_from_bytes(bytes: Vec) -> Result { + Ok(EventId( + bytes.try_into().map_err(|_| "EventId requires 32 bytes")?, + )) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/events/src/seed.rs b/crates/events/src/seed.rs index a43e88d087..6eabbd3bd8 100644 --- a/crates/events/src/seed.rs +++ b/crates/events/src/seed.rs @@ -7,10 +7,10 @@ use alloy::hex; use alloy_primitives::Uint; use derivative::Derivative; -use serde::{Deserialize, Serialize}; +use e3_utils::{AsBytesSerde, BytesSerde}; use std::fmt::{self, Display}; -#[derive(Derivative, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Derivative, BytesSerde, Clone, Copy, PartialEq, Eq, Hash)] #[derivative(Debug)] pub struct Seed(#[derivative(Debug(format_with = "e3_utils::formatters::hexf"))] pub [u8; 32]); impl From for u64 { @@ -31,6 +31,18 @@ impl From> for Seed { } } +impl AsBytesSerde for Seed { + fn as_bytes(&self) -> &[u8] { + &self.0 + } + + fn try_from_bytes(bytes: Vec) -> Result { + Ok(Seed( + bytes.try_into().map_err(|_| "EventId requires 32 bytes")?, + )) + } +} + impl Display for Seed { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Seed(0x{})", hex::encode(self.0)) diff --git a/crates/utils-derive/Cargo.toml b/crates/utils-derive/Cargo.toml new file mode 100644 index 0000000000..835ef2e226 --- /dev/null +++ b/crates/utils-derive/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "e3-utils-derive" +version.workspace = true +edition.workspace = true +license.workspace = true +description.workspace = true +repository.workspace = true + +[lib] +proc-macro = true + +[dependencies] +hex.workspace = true +syn.workspace = true +proc-macro2.workspace = true +quote.workspace = true diff --git a/crates/utils-derive/src/lib.rs b/crates/utils-derive/src/lib.rs new file mode 100644 index 0000000000..7b1a5c4229 --- /dev/null +++ b/crates/utils-derive/src/lib.rs @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, Data, DeriveInput, Error, Fields}; + +/// Derives `Serialize` and `Deserialize` for types that implement `BytesSerde`. +/// +/// - Human-readable formats (JSON, TOML): hex string with `0x` prefix +/// - Binary formats (bincode, postcard): raw bytes +/// +/// The type must also implement `e3_utils::serde_bytes::AsBytesSerde`. +/// +/// # Example +/// +/// ```rust +/// use e3_utils::BytesSerde; +/// use e3_utils::AsBytesSerde; +/// +/// #[derive(BytesSerde)] +/// pub struct EventId(pub [u8; 32]); +/// +/// impl AsBytesSerde for EventId { +/// fn as_bytes(&self) -> &[u8] { &self.0 } +/// fn try_from_bytes(bytes: Vec) -> Result { +/// Ok(EventId(bytes.try_into().map_err(|_| "requires 32 bytes".to_string())?)) +/// } +/// } +/// ``` +#[proc_macro_derive(BytesSerde)] +pub fn derive_bytes_serde(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let name = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + + // Sanity check: must be a struct + match &input.data { + Data::Struct(data) => match &data.fields { + Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {} + _ => { + return Error::new_spanned( + &input, + "BytesSerde can only be derived for newtype structs (e.g., `struct Foo(pub [u8; 32])`)", + ) + .to_compile_error() + .into(); + } + }, + _ => { + return Error::new_spanned(&input, "BytesSerde can only be derived for structs") + .to_compile_error() + .into(); + } + } + + let expanded = quote! { + impl #impl_generics ::serde::Serialize for #name #ty_generics #where_clause { + fn serialize(&self, serializer: S) -> ::core::result::Result + where + S: ::serde::Serializer, + { + use ::e3_utils::serde_bytes::AsBytesSerde; + if serializer.is_human_readable() { + serializer.serialize_str(&::std::format!("0x{}", ::hex::encode(self.as_bytes()))) + } else { + serializer.serialize_bytes(self.as_bytes()) + } + } + } + + impl<'de> ::serde::Deserialize<'de> for #name #ty_generics #where_clause { + fn deserialize(deserializer: D) -> ::core::result::Result + where + D: ::serde::Deserializer<'de>, + { + use ::e3_utils::serde_bytes::AsBytesSerde; + let bytes = if deserializer.is_human_readable() { + let s = <::std::string::String as ::serde::Deserialize>::deserialize( + deserializer, + )?; + let stripped = s.strip_prefix("0x").unwrap_or(&s); + ::hex::decode(stripped).map_err(::serde::de::Error::custom)? + } else { + <::std::vec::Vec as ::serde::Deserialize>::deserialize(deserializer)? + }; + Self::try_from_bytes(bytes).map_err(::serde::de::Error::custom) + } + } + }; + + expanded.into() +} diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index b031a29e86..cebe484273 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -12,7 +12,9 @@ alloy.workspace = true anyhow.workspace = true derivative.workspace = true rand.workspace = true +hex.workspace = true regex.workspace = true +e3-utils-derive.workspace = true rand_chacha.workspace = true serde.workspace = true tokio.workspace = true diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index 857daf3a6d..d76f7b6b5e 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -4,6 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +extern crate self as e3_utils; // need this for e3_utils_derive to reference this crate pub mod actix; pub mod alloy; pub mod constants; @@ -12,13 +13,16 @@ pub mod formatters; pub mod helpers; pub mod path; pub mod retry; +pub mod serde_bytes; pub mod utility_types; pub use actix::NotifySync; pub use alloy::*; pub use constants::*; +pub use e3_utils_derive::BytesSerde; pub use error::*; pub use formatters::*; pub use helpers::*; pub use path::*; pub use retry::*; +pub use serde_bytes::AsBytesSerde; pub use utility_types::*; diff --git a/crates/utils/src/serde_bytes.rs b/crates/utils/src/serde_bytes.rs new file mode 100644 index 0000000000..6119b1d028 --- /dev/null +++ b/crates/utils/src/serde_bytes.rs @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +/// A trait for types that can be serialized to and deserialized from raw bytes. +/// +/// This trait is used by the [`BytesSerde`] derive macro to implement `serde::Serialize` +/// and `serde::Deserialize`. Human-readable formats (e.g. JSON) encode the bytes as +/// a `0x`-prefixed hex string, while binary formats (e.g. bincode) use raw bytes directly. +/// +/// # Implementors +/// +/// Implementations should ensure that `try_from_bytes(self.as_bytes().to_vec())` +/// round-trips successfully. +/// +/// # Example +/// +/// ```rust +/// use e3_utils::AsBytesSerde; +/// +/// pub struct EventId(pub [u8; 32]); +/// +/// impl AsBytesSerde for EventId { +/// fn as_bytes(&self) -> &[u8] { +/// &self.0 +/// } +/// +/// fn try_from_bytes(bytes: Vec) -> Result { +/// let arr: [u8; 32] = bytes +/// .try_into() +/// .map_err(|_| "EventId requires exactly 32 bytes".to_string())?; +/// Ok(EventId(arr)) +/// } +/// } +/// ``` +pub trait AsBytesSerde: Sized { + /// Returns the byte representation of this type. + fn as_bytes(&self) -> &[u8]; + + /// Attempts to construct an instance from a byte vector. + /// + /// # Errors + /// + /// Returns a descriptive error string if the bytes are invalid for this type + /// (e.g. wrong length or malformed content). + fn try_from_bytes(bytes: Vec) -> Result; +} diff --git a/crates/utils/src/utility_types.rs b/crates/utils/src/utility_types.rs index 59b2fedd8e..a7ff97a4bf 100644 --- a/crates/utils/src/utility_types.rs +++ b/crates/utils/src/utility_types.rs @@ -11,14 +11,14 @@ use std::{ sync::{Arc, Mutex}, }; +use e3_utils_derive::BytesSerde; use rand_chacha::ChaCha20Rng; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use crate::formatters::hexf; +use crate::{formatters::hexf, AsBytesSerde}; pub type SharedRng = Arc>; -#[derive(Clone, Default, PartialEq, Eq, Hash)] +#[derive(BytesSerde, Clone, Default, PartialEq, Eq, Hash)] pub struct ArcBytes(Arc>); impl ArcBytes { @@ -49,22 +49,12 @@ impl fmt::Debug for ArcBytes { } } -impl Serialize for ArcBytes { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.0.serialize(serializer) +impl AsBytesSerde for ArcBytes { + fn as_bytes(&self) -> &[u8] { + &self.0.as_ref() } -} - -impl<'de> Deserialize<'de> for ArcBytes { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let vec: Vec = Vec::deserialize(deserializer)?; - Ok(ArcBytes(Arc::new(vec))) + fn try_from_bytes(bytes: Vec) -> Result { + Ok(ArcBytes(Arc::new(bytes))) } } diff --git a/examples/CRISP/server/Dockerfile b/examples/CRISP/server/Dockerfile index 888feee3f5..e9c3ad2bd7 100644 --- a/examples/CRISP/server/Dockerfile +++ b/examples/CRISP/server/Dockerfile @@ -92,6 +92,7 @@ COPY crates/test-helpers/Cargo.toml crates/test-helpers/Cargo.toml COPY crates/tests/Cargo.toml crates/tests/Cargo.toml COPY crates/trbfv/Cargo.toml crates/trbfv/Cargo.toml COPY crates/utils/Cargo.toml crates/utils/Cargo.toml +COPY crates/utils-derive/Cargo.toml crates/utils-derive/Cargo.toml COPY crates/wasm/Cargo.toml crates/wasm/Cargo.toml COPY crates/zk-helpers/Cargo.toml crates/zk-helpers/Cargo.toml From 3ca1049bb845cf0b4755e9662a54e197829c34bd Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 23 Mar 2026 14:57:26 +0000 Subject: [PATCH 05/43] tidy up input args --- crates/cli/src/events.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 985ccda2e9..ecd358f308 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -19,25 +19,25 @@ use std::sync::Arc; pub enum EventsCommands { /// Query events Query { + /// Aggregate ID - will default to 0 #[arg(long)] - aggregate: u64, + agg: Option, + /// Sequence to read from will read from 0 if absent #[arg(long)] - since: u64, + since: Option, + /// Max limit to read at a time. If this is greater than the internal limit the internal + /// limit will be respected. #[arg(long)] - limit: u64, + limit: Option, }, } pub async fn execute(command: EventsCommands) -> Result<()> { match command { - EventsCommands::Query { - aggregate, - since, - limit, - } => { - query_events(aggregate, since, limit).await?; + EventsCommands::Query { agg, since, limit } => { + query_events(agg.unwrap_or(0), since.unwrap_or(0), limit.unwrap_or(10)).await?; } } Ok(()) From 643d5ce1c09016210b07410d4084805fb0d8c35a Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 23 Mar 2026 15:19:32 +0000 Subject: [PATCH 06/43] add more dummy events --- crates/cli/src/events.rs | 312 +++++++++++++++++++++++++++++++++++---- 1 file changed, 285 insertions(+), 27 deletions(-) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index ecd358f308..f46cf614fa 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -4,17 +4,63 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +use alloy::primitives::{Address, FixedBytes, I256, U256}; use anyhow::Result; use clap::Subcommand; use e3_events::{ - CiphertextOutputPublished, ConfigurationUpdated, DecryptionshareCreated, E3Requested, E3id, - EType, EnclaveError, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCreated, - EventConstructorWithTimestamp, KeyshareCreated, PlaintextAggregated, PublicKeyAggregated, Seed, - TestEvent, Unsequenced, + AccusationOutcome, AccusationQuorumReached, AccusationVote, CiphernodeAdded, + CiphernodeSelected, CiphertextOutputPublished, CircuitName, CommitteePublished, + ConfigurationUpdated, DecryptionshareCreated, E3Failed, E3Requested, E3Stage, E3id, EType, + EnclaveError, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCreated, + EventConstructorWithTimestamp, FailureReason, KeyshareCreated, PlaintextAggregated, Proof, + ProofPayload, ProofType, ProofVerificationFailed, PublicKeyAggregated, Seed, + SignedProofPayload, TestEvent, TicketBalanceUpdated, TicketGenerated, TicketId, Unsequenced, }; use e3_utils::ArcBytes; use std::sync::Arc; +fn dummy_proof(circuit: CircuitName) -> Proof { + Proof::new( + circuit, + ArcBytes::from_bytes(&[ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, + ]), + ArcBytes::from_bytes(&[ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, + ]), + ) +} + +fn dummy_signed_proof_payload(e3_id: E3id, proof_type: ProofType) -> SignedProofPayload { + SignedProofPayload { + payload: ProofPayload { + e3_id, + proof_type, + proof: dummy_proof(CircuitName::PkBfv), + }, + signature: ArcBytes::from_bytes(&[ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + ]), + } +} + +fn dummy_accusation_vote(e3_id: E3id, voter: Address, agrees: bool) -> AccusationVote { + AccusationVote { + e3_id, + accusation_id: [0xaa; 32], + voter, + agrees, + data_hash: [0xbb; 32], + signature: vec![0xcc; 64], + } +} + #[derive(Subcommand, Clone, Debug)] pub enum EventsCommands { /// Query events @@ -53,11 +99,18 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event1 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::PublicKeyAggregated(PublicKeyAggregated { - pubkey: ArcBytes::from_bytes(&[0x12, 0x34, 0x56]), + pubkey: ArcBytes::from_bytes(&[ + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x77, 0x88, + ]), e3_id: E3id::new("test1", 1), - nodes: Default::default(), - pk_aggregation_proof: None, - dkg_aggregated_proof: None, + nodes: vec![ + "0x1234567890123456789012345678901234567890".to_string(), + "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd".to_string(), + ] + .into(), + pk_aggregation_proof: Some(dummy_proof(CircuitName::PkAggregation)), + dkg_aggregated_proof: Some(dummy_proof(CircuitName::Fold)), }), None, 1700000000000_u128, @@ -71,7 +124,10 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { e3_id: E3id::new("test2", 1), key: Arc::new(EncryptionKey::new( 42, - ArcBytes::from_bytes(&[0xab, 0xcd, 0xef]), + ArcBytes::from_bytes(&[ + 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0x0a, 0xbc, 0xde, 0xf1, 0x23, + 0x45, 0x67, 0x89, + ]), )), external: false, }), @@ -87,10 +143,18 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { e3_id: E3id::new("test3", 1), threshold_m: 3, threshold_n: 5, - seed: Seed([1u8; 32]), - error_size: ArcBytes::from_bytes(&[0xDE, 0xAD]), + seed: Seed([ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x1d, 0x1e, 0x1f, 0x20, + ]), + error_size: ArcBytes::from_bytes(&[ + 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE, 0xDE, 0xAD, 0xC0, 0xDE, + ]), esi_per_ct: 2, - params: ArcBytes::from_bytes(&[0xBE, 0xEF]), + params: ArcBytes::from_bytes(&[ + 0xBE, 0xEF, 0xFA, 0xCE, 0xDE, 0xAD, 0xFE, 0xED, 0xFE, 0xED, 0xCA, 0xFE, + ]), proof_aggregation_enabled: true, }), None, @@ -102,10 +166,16 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event4 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::KeyshareCreated(KeyshareCreated { - pubkey: ArcBytes::from_bytes(&[0x11, 0x22, 0x33]), + pubkey: ArcBytes::from_bytes(&[ + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, + 0xff, 0x00, + ]), e3_id: E3id::new("test4", 1), - node: "node_abc".to_string(), - signed_pk_generation_proof: None, + node: "0xabcd1234abcd1234abcd1234abcd1234abcd1234".to_string(), + signed_pk_generation_proof: Some(dummy_signed_proof_payload( + E3id::new("test4", 1), + ProofType::C1PkGeneration, + )), }), None, 1700000003000_u128, @@ -118,8 +188,12 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { EnclaveEventData::CiphertextOutputPublished(CiphertextOutputPublished { e3_id: E3id::new("test5", 1), ciphertext_output: vec![ - ArcBytes::from_bytes(&[0xAA, 0xBB, 0xCC]), - ArcBytes::from_bytes(&[0xDD, 0xEE, 0xFF]), + ArcBytes::from_bytes(&[ + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + ]), + ArcBytes::from_bytes(&[ + 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + ]), ], }), None, @@ -132,11 +206,16 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event6 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::DecryptionshareCreated(DecryptionshareCreated { party_id: 2, - decryption_share: vec![ArcBytes::from_bytes(&[0x01, 0x02])], + decryption_share: vec![ArcBytes::from_bytes(&[ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + ])], e3_id: E3id::new("test6", 1), - node: "node_xyz".to_string(), - signed_decryption_proofs: vec![], - wrapped_proofs: vec![], + node: "0xfedc9876543210fedc9876543210fedc9876543210".to_string(), + signed_decryption_proofs: vec![dummy_signed_proof_payload( + E3id::new("test6", 1), + ProofType::C6ThresholdShareDecryption, + )], + wrapped_proofs: vec![dummy_proof(CircuitName::ThresholdShareDecryption)], }), None, 1700000005000_u128, @@ -148,9 +227,11 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event7 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::PlaintextAggregated(PlaintextAggregated { e3_id: E3id::new("test7", 1), - decrypted_output: vec![ArcBytes::from_bytes(&[0x99, 0x88])], - aggregation_proofs: vec![], - c6_aggregated_proof: None, + decrypted_output: vec![ArcBytes::from_bytes(&[ + 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, + ])], + aggregation_proofs: vec![dummy_proof(CircuitName::DecryptedSharesAggregation)], + c6_aggregated_proof: Some(dummy_proof(CircuitName::ThresholdShareDecryption)), }), None, 1700000006000_u128, @@ -162,7 +243,7 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event8 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::EnclaveError(EnclaveError { err_type: EType::Computation, - message: "Computation failed: overflow detected".to_string(), + message: "Computation failed: overflow detected in batch processing".to_string(), }), None, 1700000007000_u128, @@ -173,7 +254,7 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event9 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::TestEvent(TestEvent { - msg: "Test message from CLI".to_string(), + msg: "Test message from CLI with full data".to_string(), entropy: 42, e3_id: Some(E3id::new("test9", 1)), }), @@ -198,8 +279,185 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { ) .into_sequenced(10); + let accuser: Address = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + .parse() + .unwrap(); + let accused: Address = "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + .parse() + .unwrap(); + + let event11 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::AccusationQuorumReached(AccusationQuorumReached { + e3_id: E3id::new("test11", 1), + accuser, + accused, + proof_type: ProofType::C6ThresholdShareDecryption, + votes_for: vec![ + dummy_accusation_vote(E3id::new("test11", 1), accuser, true), + dummy_accusation_vote( + E3id::new("test11", 1), + "0xcccccccccccccccccccccccccccccccccccccccc" + .parse() + .unwrap(), + true, + ), + ], + votes_against: vec![], + outcome: AccusationOutcome::AccusedFaulted, + }), + None, + 1700000010000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(11); + + let event12 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::CiphernodeSelected(CiphernodeSelected { + e3_id: E3id::new("test12", 1), + threshold_m: 3, + threshold_n: 5, + seed: Seed([0x21; 32]), + error_size: ArcBytes::from_bytes(&[0xFE; 16]), + esi_per_ct: 4, + params: ArcBytes::from_bytes(&[0xCA; 32]), + party_id: 2, + }), + None, + 1700000011000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(12); + + let event13 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::CommitteePublished(CommitteePublished { + e3_id: E3id::new("test13", 1), + nodes: vec![ + "0x1111111111111111111111111111111111111111".to_string(), + "0x2222222222222222222222222222222222222222".to_string(), + "0x3333333333333333333333333333333333333333".to_string(), + ], + public_key: vec![0xAB; 64], + }), + None, + 1700000012000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(13); + + let event14 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::TicketGenerated(TicketGenerated { + e3_id: E3id::new("test14", 1), + ticket_id: TicketId::Score(42), + node: "0x4444444444444444444444444444444444444444".to_string(), + }), + None, + 1700000013000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(14); + + let event15 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::TicketBalanceUpdated(TicketBalanceUpdated { + operator: "0x5555555555555555555555555555555555555555".to_string(), + delta: I256::MIN, + new_balance: U256::from(900), + reason: FixedBytes::from([0x66; 32]), + chain_id: 1, + }), + None, + 1700000014000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(15); + + let event16 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::E3Failed(E3Failed { + e3_id: E3id::new("test16", 1), + failed_at_stage: E3Stage::Failed, + reason: FailureReason::ComputeTimeout, + }), + None, + 1700000015000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(16); + + let event17 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::CiphernodeAdded(CiphernodeAdded { + address: "0x7777777777777777777777777777777777777777".to_string(), + index: 5, + num_nodes: 10, + chain_id: 1, + }), + None, + 1700000016000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(17); + + let accused_addr: Address = "0x8888888888888888888888888888888888888888" + .parse() + .unwrap(); + + let event18 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ProofVerificationFailed(ProofVerificationFailed { + e3_id: E3id::new("test18", 1), + accused_party_id: 3, + accused_address: accused_addr, + proof_type: ProofType::C1PkGeneration, + data_hash: [0x99; 32], + signed_payload: dummy_signed_proof_payload( + E3id::new("test18", 1), + ProofType::C1PkGeneration, + ), + }), + None, + 1700000017000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(18); + + let event19 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::EnclaveError(EnclaveError { + err_type: EType::KeyGeneration, + message: "DKG timeout: insufficient shares received from peers".to_string(), + }), + None, + 1700000018000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(19); + + let event20 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::AccusationVote(AccusationVote { + e3_id: E3id::new("test20", 1), + accusation_id: [0xaa; 32], + voter: "0x9999999999999999999999999999999999999999" + .parse() + .unwrap(), + agrees: true, + data_hash: [0xbb; 32], + signature: vec![0xcc; 64], + }), + None, + 1700000019000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(20); + for event in [ - event1, event2, event3, event4, event5, event6, event7, event8, event9, event10, + event1, event2, event3, event4, event5, event6, event7, event8, event9, event10, event11, + event12, event13, event14, event15, event16, event17, event18, event19, event20, ] { println!("{}", serde_json::to_string(&event)?); } From 821a93b9d7a686dca49460159515a8fa6c330354 Mon Sep 17 00:00:00 2001 From: ryardley Date: Tue, 24 Mar 2026 03:24:49 +0000 Subject: [PATCH 07/43] convert event fields to ArcBytes --- crates/cli/src/events.rs | 6 ++--- .../src/enclave_event/accusation_vote.rs | 3 ++- .../src/enclave_event/committee_published.rs | 3 ++- .../plaintext_output_published.rs | 3 ++- crates/evm/src/slashing_manager_sol_writer.rs | 2 +- .../src/actors/accusation_manager.rs | 23 ++++++++++--------- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index f46cf614fa..29e02f7a70 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -57,7 +57,7 @@ fn dummy_accusation_vote(e3_id: E3id, voter: Address, agrees: bool) -> Accusatio voter, agrees, data_hash: [0xbb; 32], - signature: vec![0xcc; 64], + signature: ArcBytes::from_bytes(&[0xcc; 64]), } } @@ -338,7 +338,7 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { "0x2222222222222222222222222222222222222222".to_string(), "0x3333333333333333333333333333333333333333".to_string(), ], - public_key: vec![0xAB; 64], + public_key: ArcBytes::from_bytes(&[0xAB; 64]), }), None, 1700000012000_u128, @@ -446,7 +446,7 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { .unwrap(), agrees: true, data_hash: [0xbb; 32], - signature: vec![0xcc; 64], + signature: ArcBytes::from_bytes(&[0xcc; 64]), }), None, 1700000019000_u128, diff --git a/crates/events/src/enclave_event/accusation_vote.rs b/crates/events/src/enclave_event/accusation_vote.rs index e2ff7fba6b..c07a49731a 100644 --- a/crates/events/src/enclave_event/accusation_vote.rs +++ b/crates/events/src/enclave_event/accusation_vote.rs @@ -7,6 +7,7 @@ use crate::E3id; use actix::Message; use alloy::primitives::Address; +use e3_utils::ArcBytes; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; @@ -27,7 +28,7 @@ pub struct AccusationVote { /// keccak256 hash of the data as this node received it — for equivocation detection. pub data_hash: [u8; 32], /// ECDSA signature of the voter over the vote fields. - pub signature: Vec, + pub signature: ArcBytes, } impl Display for AccusationVote { diff --git a/crates/events/src/enclave_event/committee_published.rs b/crates/events/src/enclave_event/committee_published.rs index abb2e79dfa..7c8a9bb01c 100644 --- a/crates/events/src/enclave_event/committee_published.rs +++ b/crates/events/src/enclave_event/committee_published.rs @@ -6,6 +6,7 @@ use crate::E3id; use actix::Message; +use e3_utils::ArcBytes; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; @@ -14,7 +15,7 @@ use std::fmt::{self, Display}; pub struct CommitteePublished { pub e3_id: E3id, pub nodes: Vec, - pub public_key: Vec, + pub public_key: ArcBytes, } impl Display for CommitteePublished { diff --git a/crates/events/src/enclave_event/plaintext_output_published.rs b/crates/events/src/enclave_event/plaintext_output_published.rs index aa0c715afc..6e4abd5cf4 100644 --- a/crates/events/src/enclave_event/plaintext_output_published.rs +++ b/crates/events/src/enclave_event/plaintext_output_published.rs @@ -6,6 +6,7 @@ use crate::E3id; use actix::Message; +use e3_utils::ArcBytes; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; @@ -13,7 +14,7 @@ use std::fmt::{self, Display}; #[rtype(result = "()")] pub struct PlaintextOutputPublished { pub e3_id: E3id, - pub plaintext_output: Vec, + pub plaintext_output: ArcBytes, } impl Display for PlaintextOutputPublished { diff --git a/crates/evm/src/slashing_manager_sol_writer.rs b/crates/evm/src/slashing_manager_sol_writer.rs index 7a67b5277a..adf1ea3e83 100644 --- a/crates/evm/src/slashing_manager_sol_writer.rs +++ b/crates/evm/src/slashing_manager_sol_writer.rs @@ -206,7 +206,7 @@ fn encode_attestation_evidence(data: &AccusationQuorumReached) -> Vec { let data_hashes: Vec<[u8; 32]> = votes.iter().map(|v| v.data_hash).collect(); let signatures: Vec = votes .iter() - .map(|v| Bytes::from(v.signature.clone())) + .map(|v| Bytes::from(v.signature.extract_bytes())) .collect(); (proof_type, voters, agrees, data_hashes, signatures).abi_encode() diff --git a/crates/zk-prover/src/actors/accusation_manager.rs b/crates/zk-prover/src/actors/accusation_manager.rs index 4b72bd8e3b..3d2bf32ba7 100644 --- a/crates/zk-prover/src/actors/accusation_manager.rs +++ b/crates/zk-prover/src/actors/accusation_manager.rs @@ -42,7 +42,7 @@ use e3_events::{ ProofVerificationPassed, Sequenced, SignedProofPayload, SlashExecuted, TypedEvent, VerifyShareProofsRequest, ZkRequest, ZkResponse, }; -use e3_utils::NotifySync; +use e3_utils::{ArcBytes, NotifySync}; use tracing::{error, info, warn}; /// How long to wait for votes before declaring the accusation inconclusive. @@ -295,10 +295,11 @@ impl AccusationManager { fn verify_vote_signature(&self, vote: &AccusationVote) -> bool { let digest = Self::vote_digest(vote); - let sig = match alloy::primitives::Signature::try_from(vote.signature.as_slice()) { - Ok(s) => s, - Err(_) => return false, - }; + let sig = + match alloy::primitives::Signature::try_from(vote.signature.extract_bytes().as_ref()) { + Ok(s) => s, + Err(_) => return false, + }; match sig.recover_address_from_msg(&digest) { Ok(addr) => addr == vote.voter, Err(_) => false, @@ -396,9 +397,9 @@ impl AccusationManager { voter: self.my_address, agrees: true, data_hash: event.data_hash, - signature: Vec::new(), + signature: ArcBytes::default(), }; - own_vote.signature = self.sign_vote_digest(&own_vote); + own_vote.signature = ArcBytes::from_bytes(&self.sign_vote_digest(&own_vote)); if let Err(err) = self.bus.publish(own_vote.clone(), ec.clone()) { error!("Failed to broadcast own AccusationVote: {err}"); @@ -601,9 +602,9 @@ impl AccusationManager { voter: self.my_address, agrees, data_hash: our_data_hash, - signature: Vec::new(), + signature: ArcBytes::default(), }; - vote.signature = self.sign_vote_digest(&vote); + vote.signature = ArcBytes::from_bytes(&self.sign_vote_digest(&vote)); info!( "Voting {} on accusation against {} for {:?}", @@ -1039,9 +1040,9 @@ impl AccusationManager { voter: self.my_address, agrees, data_hash: reverif.data_hash, - signature: Vec::new(), + signature: ArcBytes::default(), }; - vote.signature = self.sign_vote_digest(&vote); + vote.signature = ArcBytes::from_bytes(&self.sign_vote_digest(&vote)); info!( "C3a/C3b re-verification complete — voting {} on accusation against {:?}", From f4caf1df9de1fcc1de83d6c6b891f053cb32f142 Mon Sep 17 00:00:00 2001 From: ryardley Date: Tue, 24 Mar 2026 03:55:11 +0000 Subject: [PATCH 08/43] add new events --- Cargo.lock | 4 + crates/cli/Cargo.toml | 4 + crates/cli/src/events.rs | 531 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 531 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0381b43b8c..f098d43181 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3122,6 +3122,7 @@ dependencies = [ "actix", "alloy", "anyhow", + "chrono", "clap", "compile-time", "dialoguer", @@ -3133,10 +3134,13 @@ dependencies = [ "e3-entrypoint", "e3-events", "e3-evm", + "e3-fhe-params", "e3-init", "e3-socket-server", "e3-support-scripts", + "e3-trbfv", "e3-utils", + "e3-zk-helpers", "e3-zk-prover", "hex", "opentelemetry", diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 8a4492cab1..1bb474e659 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -26,6 +26,10 @@ e3-crypto = { workspace = true } e3-entrypoint = { workspace = true } e3-events = { workspace = true } e3-evm = { workspace = true } +e3-trbfv = { workspace = true } +e3-fhe-params = { workspace = true } +e3-zk-helpers = { workspace = true } +chrono = { workspace = true } e3-init = { workspace = true } e3-support-scripts = { workspace = true } e3-socket-server = { workspace = true } diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 29e02f7a70..8fab69473b 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -6,17 +6,30 @@ use alloy::primitives::{Address, FixedBytes, I256, U256}; use anyhow::Result; +use chrono::Utc; use clap::Subcommand; use e3_events::{ - AccusationOutcome, AccusationQuorumReached, AccusationVote, CiphernodeAdded, - CiphernodeSelected, CiphertextOutputPublished, CircuitName, CommitteePublished, - ConfigurationUpdated, DecryptionshareCreated, E3Failed, E3Requested, E3Stage, E3id, EType, - EnclaveError, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCreated, - EventConstructorWithTimestamp, FailureReason, KeyshareCreated, PlaintextAggregated, Proof, - ProofPayload, ProofType, ProofVerificationFailed, PublicKeyAggregated, Seed, - SignedProofPayload, TestEvent, TicketBalanceUpdated, TicketGenerated, TicketId, Unsequenced, + AccusationOutcome, AccusationQuorumReached, AccusationVote, CiphernodeAdded, CiphernodeRemoved, + CiphernodeSelected, CiphertextOutputPublished, CircuitName, CommitteeFinalizeRequested, + CommitteeFinalized, CommitteeMemberExpelled, CommitteeRequested, CommitteePublished, + ConfigurationUpdated, DecryptionKeyShared, DecryptionShareProofSigned, DecryptionshareCreated, + DocumentKind, DocumentMeta, DocumentReceived, DkgProofSigned, E3Failed, E3RequestComplete, + E3Requested, E3Stage, E3StageChanged, E3id, EffectsEnabled, EncryptionKey, + EncryptionKeyCollectionFailed, EncryptionKeyCreated, EncryptionKeyPending, EncryptionKeyReceived, + EnclaveError, EnclaveEvent, EnclaveEventData, EvmEventConfig, EvmEventConfigChain, + EventConstructorWithTimestamp, FailureReason, HistoricalEvmSyncStart, + HistoricalNetSyncEventsReceived, HistoricalNetSyncStart, KeyshareCreated, NetReady, + OperatorActivationChanged, OutgoingSyncRequested, PkGenerationProofSigned, + PlaintextAggregated, PlaintextOutputPublished, Proof, ProofPayload, ProofType, + ProofVerificationFailed, ProofVerificationPassed, ProofFailureAccusation, PublicKeyAggregated, + PublishDocumentRequested, Seed, SignedProofFailed, SignedProofPayload, SlashExecuted, + SyncEffect, SyncEnded, TestEvent, ThresholdShareCollectionFailed, Shutdown, + TicketBalanceUpdated, TicketGenerated, TicketId, TicketSubmitted, Unsequenced, EType, + DKGInnerProofReady, DKGRecursiveAggregationComplete, AggregationProofSigned, }; +use e3_events::AggregateId; use e3_utils::ArcBytes; +use std::collections::BTreeMap; use std::sync::Arc; fn dummy_proof(circuit: CircuitName) -> Proof { @@ -455,9 +468,511 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { ) .into_sequenced(20); + // Missing event types start here (event21 onwards) + let event21 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ProofFailureAccusation(ProofFailureAccusation { + e3_id: E3id::new("test21", 1), + accuser: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".parse().unwrap(), + accused: "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb".parse().unwrap(), + accused_party_id: 2, + proof_type: ProofType::C3aSkShareEncryption, + data_hash: [0xdd; 32], + signed_payload: Some(dummy_signed_proof_payload( + E3id::new("test21", 1), + ProofType::C3aSkShareEncryption, + )), + signature: vec![0xee; 64], + }), + None, + 1700000020000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(21); + + let event22 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ProofVerificationPassed(ProofVerificationPassed { + e3_id: E3id::new("test22", 1), + party_id: 1, + address: "0x1111111111111111111111111111111111111111".parse().unwrap(), + proof_type: ProofType::C1PkGeneration, + data_hash: [0x22; 32], + }), + None, + 1700000021000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(22); + + let event23 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::DecryptionKeyShared(DecryptionKeyShared { + e3_id: E3id::new("test23", 1), + party_id: 1, + node: "0x3333333333333333333333333333333333333333".to_string(), + sk_poly_sum: ArcBytes::from_bytes(&[0x44; 32]), + es_poly_sum: vec![ArcBytes::from_bytes(&[0x55; 32])], + signed_sk_decryption_proof: dummy_signed_proof_payload( + E3id::new("test23", 1), + ProofType::C4DkgShareDecryption, + ), + signed_e_sm_decryption_proofs: vec![dummy_signed_proof_payload( + E3id::new("test23", 1), + ProofType::C4DkgShareDecryption, + )], + external: false, + }), + None, + 1700000022000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(23); + + let event24 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::PublishDocumentRequested(PublishDocumentRequested { + meta: DocumentMeta::new( + E3id::new("test24", 1), + DocumentKind::TrBFV, + vec![], + Some(Utc::now()), + ), + value: ArcBytes::from_bytes(&[0x66; 64]), + }), + None, + 1700000023000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(24); + + let event25 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::PkGenerationProofSigned(PkGenerationProofSigned { + e3_id: E3id::new("test25", 1), + party_id: 1, + signed_proof: dummy_signed_proof_payload( + E3id::new("test25", 1), + ProofType::C1PkGeneration, + ), + }), + None, + 1700000024000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(25); + + let event26 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::DkgProofSigned(DkgProofSigned { + e3_id: E3id::new("test26", 1), + party_id: 1, + signed_proof: dummy_signed_proof_payload( + E3id::new("test26", 1), + ProofType::C2aSkShareComputation, + ), + }), + None, + 1700000025000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(26); + + let event27 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::E3RequestComplete(E3RequestComplete { + e3_id: E3id::new("test27", 1), + }), + None, + 1700000026000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(27); + + let event28 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::E3StageChanged(E3StageChanged { + e3_id: E3id::new("test28", 1), + previous_stage: E3Stage::CiphertextReady, + new_stage: E3Stage::Complete, + }), + None, + 1700000027000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(28); + + let event29 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::CiphernodeRemoved(CiphernodeRemoved { + address: "0x9999999999999999999999999999999999999999".to_string(), + index: 3, + num_nodes: 9, + chain_id: 1, + }), + None, + 1700000028000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(29); + + let event30 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::OperatorActivationChanged(OperatorActivationChanged { + operator: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string(), + active: true, + chain_id: 1, + }), + None, + 1700000029000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(30); + + let event31 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::CommitteeRequested(CommitteeRequested { + e3_id: E3id::new("test31", 1), + seed: Seed([0xaa; 32]), + threshold: [3, 5], + request_block: 100, + committee_deadline: 200, + chain_id: 1, + }), + None, + 1700000030000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(31); + + let event32 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::CommitteeFinalizeRequested(CommitteeFinalizeRequested { + e3_id: E3id::new("test32", 1), + }), + None, + 1700000031000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(32); + + let event33 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::CommitteeFinalized(CommitteeFinalized { + e3_id: E3id::new("test33", 1), + committee: vec![ + "0x1111111111111111111111111111111111111111".to_string(), + "0x2222222222222222222222222222222222222222".to_string(), + ], + chain_id: 1, + }), + None, + 1700000032000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(33); + + let event34 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::TicketSubmitted(TicketSubmitted { + e3_id: E3id::new("test34", 1), + node: "0x4444444444444444444444444444444444444444".to_string(), + ticket_id: 123, + score: "0.95".to_string(), + chain_id: 1, + }), + None, + 1700000033000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(34); + + let event35 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::PlaintextOutputPublished(PlaintextOutputPublished { + e3_id: E3id::new("test35", 1), + plaintext_output: ArcBytes::from_bytes(&[0x55; 32]), + }), + None, + 1700000034000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(35); + + let event36 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::Shutdown(Shutdown), + None, + 1700000035000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(36); + + let event37 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::DocumentReceived(DocumentReceived { + meta: DocumentMeta::new( + E3id::new("test37", 1), + DocumentKind::TrBFV, + vec![], + Some(Utc::now()), + ), + value: ArcBytes::from_bytes(&[0x66; 64]), + }), + None, + 1700000036000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(37); + + let event38 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::EncryptionKeyPending(EncryptionKeyPending { + e3_id: E3id::new("test40", 1), + key: Arc::new(EncryptionKey::new( + 42, + ArcBytes::from_bytes(&[0x33; 16]), + )), + params_preset: e3_fhe_params::BfvPreset::InsecureThreshold512, + }), + None, + 1700000039000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(38); + + let event39 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::EncryptionKeyReceived(EncryptionKeyReceived { + e3_id: E3id::new("test41", 1), + key: Arc::new(EncryptionKey::new( + 42, + ArcBytes::from_bytes(&[0x44; 16]), + )), + }), + None, + 1700000040000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(39); + + let event40 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::EncryptionKeyCollectionFailed(EncryptionKeyCollectionFailed { + e3_id: E3id::new("test42", 1), + reason: "Timeout waiting for encryption keys".to_string(), + missing_parties: vec![2, 4], + }), + None, + 1700000041000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(40); + + let event41 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ThresholdShareCollectionFailed(ThresholdShareCollectionFailed { + e3_id: E3id::new("test43", 1), + reason: "Insufficient shares received".to_string(), + missing_parties: vec![3, 5], + }), + None, + 1700000042000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(41); + + let event42 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::SignedProofFailed(SignedProofFailed { + e3_id: E3id::new("test47", 1), + faulting_node: "0x7777777777777777777777777777777777777777".parse().unwrap(), + proof_type: ProofType::C1PkGeneration, + signed_payload: dummy_signed_proof_payload( + E3id::new("test47", 1), + ProofType::C1PkGeneration, + ), + }), + None, + 1700000046000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(42); + + let event43 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::SlashExecuted(SlashExecuted { + e3_id: E3id::new("test51", 1), + proposal_id: 12345, + operator: "0x9999999999999999999999999999999999999999".parse().unwrap(), + reason: [0xaa; 32], + ticket_amount: 1000, + license_amount: 500, + }), + None, + 1700000050000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(43); + + let event44 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::CommitteeMemberExpelled(CommitteeMemberExpelled { + e3_id: E3id::new("test52", 1), + node: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".parse().unwrap(), + reason: [0xbb; 32], + active_count_after: 9, + party_id: Some(2), + }), + None, + 1700000051000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(44); + + let event45 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::OutgoingSyncRequested(OutgoingSyncRequested { + since: vec![(AggregateId::new(0), 1700000000000_u128)], + }), + None, + 1700000052000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(45); + + let event46 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::HistoricalEvmSyncStart(HistoricalEvmSyncStart { + evm_config: EvmEventConfig::from_config( + [(1, EvmEventConfigChain::new(100))].into_iter().collect::>(), + ), + sender: None, + }), + None, + 1700000053000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(46); + + let event47 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::HistoricalNetSyncStart(HistoricalNetSyncStart { + since: BTreeMap::from([(AggregateId::new(0), 1700000000000_u128)]), + }), + None, + 1700000054000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(47); + + let event48 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::HistoricalNetSyncEventsReceived(HistoricalNetSyncEventsReceived { + events: vec![], + }), + None, + 1700000055000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(48); + + let event49 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::SyncEffect(SyncEffect::new()), + None, + 1700000056000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(49); + + let event50 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::SyncEnded(SyncEnded::new()), + None, + 1700000057000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(50); + + let event51 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::EffectsEnabled(EffectsEnabled::new()), + None, + 1700000058000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(51); + + let event52 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::NetReady(NetReady::new()), + None, + 1700000059000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(52); + + let event53 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::DecryptionShareProofSigned(DecryptionShareProofSigned { + e3_id: E3id::new("test61", 1), + }), + None, + 1700000060000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(53); + + let event54 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::AggregationProofSigned(AggregationProofSigned { + e3_id: E3id::new("test66", 1), + signed_proofs: vec![dummy_signed_proof_payload( + E3id::new("test66", 1), + ProofType::C7DecryptedSharesAggregation, + )], + }), + None, + 1700000065000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(54); + + let event55 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::DKGInnerProofReady(DKGInnerProofReady { + e3_id: E3id::new("test67", 1), + party_id: 1, + wrapped_proof: dummy_proof(CircuitName::Fold), + seq: 0, + }), + None, + 1700000066000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(55); + + let event56 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::DKGRecursiveAggregationComplete(DKGRecursiveAggregationComplete { + e3_id: E3id::new("test68", 1), + party_id: 1, + aggregated_proof: Some(dummy_proof(CircuitName::Fold)), + }), + None, + 1700000067000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(56); + for event in [ event1, event2, event3, event4, event5, event6, event7, event8, event9, event10, event11, - event12, event13, event14, event15, event16, event17, event18, event19, event20, + event12, event13, event14, event15, event16, event17, event18, event19, event20, event21, + event22, event23, event24, event25, event26, event27, event28, event29, event30, event31, + event32, event33, event34, event35, event36, event37, event38, event39, event40, event41, + event42, event43, event44, event45, event46, event47, event48, event49, event50, event51, + event52, event53, event54, event55, event56, ] { println!("{}", serde_json::to_string(&event)?); } From f59f1d6a4d7db9c5e9766f50a9ce85627b530992 Mon Sep 17 00:00:00 2001 From: ryardley Date: Tue, 24 Mar 2026 04:11:22 +0000 Subject: [PATCH 09/43] ensure ArcBytes --- Cargo.lock | 6 +- Cargo.toml | 2 +- crates/cli/src/events.rs | 357 ++++++++++++++++-- crates/crypto/src/sensitive.rs | 7 + .../enclave_event/proof_failure_accusation.rs | 3 +- .../src/actors/accusation_manager.rs | 8 +- 6 files changed, 340 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f098d43181..381c9ffe3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2822,7 +2822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de" dependencies = [ "data-encoding", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -7785,9 +7785,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] diff --git a/Cargo.toml b/Cargo.toml index 63da4e7164..fd1ad86e97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -172,7 +172,7 @@ petname = "=2.0.2" phf = { version = "=0.11.3", features = ["macros"] } proptest = "=1.9.0" proc-macro2 = "=1.0.106" -quote = "=1.0.45" +quote = "=1.0.44" rand_chacha = "=0.3.1" rand = "=0.8.5" rayon = "=1.10.0" diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 8fab69473b..140900d0e6 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -8,28 +8,42 @@ use alloy::primitives::{Address, FixedBytes, I256, U256}; use anyhow::Result; use chrono::Utc; use clap::Subcommand; +use e3_crypto::SensitiveBytes; +use e3_events::AggregateId; use e3_events::{ - AccusationOutcome, AccusationQuorumReached, AccusationVote, CiphernodeAdded, CiphernodeRemoved, - CiphernodeSelected, CiphertextOutputPublished, CircuitName, CommitteeFinalizeRequested, - CommitteeFinalized, CommitteeMemberExpelled, CommitteeRequested, CommitteePublished, - ConfigurationUpdated, DecryptionKeyShared, DecryptionShareProofSigned, DecryptionshareCreated, - DocumentKind, DocumentMeta, DocumentReceived, DkgProofSigned, E3Failed, E3RequestComplete, - E3Requested, E3Stage, E3StageChanged, E3id, EffectsEnabled, EncryptionKey, - EncryptionKeyCollectionFailed, EncryptionKeyCreated, EncryptionKeyPending, EncryptionKeyReceived, - EnclaveError, EnclaveEvent, EnclaveEventData, EvmEventConfig, EvmEventConfigChain, - EventConstructorWithTimestamp, FailureReason, HistoricalEvmSyncStart, - HistoricalNetSyncEventsReceived, HistoricalNetSyncStart, KeyshareCreated, NetReady, - OperatorActivationChanged, OutgoingSyncRequested, PkGenerationProofSigned, - PlaintextAggregated, PlaintextOutputPublished, Proof, ProofPayload, ProofType, - ProofVerificationFailed, ProofVerificationPassed, ProofFailureAccusation, PublicKeyAggregated, - PublishDocumentRequested, Seed, SignedProofFailed, SignedProofPayload, SlashExecuted, - SyncEffect, SyncEnded, TestEvent, ThresholdShareCollectionFailed, Shutdown, - TicketBalanceUpdated, TicketGenerated, TicketId, TicketSubmitted, Unsequenced, EType, - DKGInnerProofReady, DKGRecursiveAggregationComplete, AggregationProofSigned, + AccusationOutcome, AccusationQuorumReached, AccusationVote, AggregationProofPending, + AggregationProofSigned, CiphernodeAdded, CiphernodeRemoved, CiphernodeSelected, + CiphertextOutputPublished, CircuitName, CommitteeFinalizeRequested, CommitteeFinalized, + CommitteeMemberExpelled, CommitteePublished, CommitteeRequested, ComputeRequest, + ComputeRequestError, ComputeRequestErrorKind, ComputeRequestKind, ComputeResponse, + ComputeResponseKind, ConfigurationUpdated, CorrelationId, DKGInnerProofReady, + DKGRecursiveAggregationComplete, DecryptedSharesAggregationProofRequest, DecryptionKeyShared, + DecryptionShareProofSigned, DecryptionShareProofsPending, DecryptionshareCreated, + DkgProofSigned, DkgShareDecryptionProofRequest, DocumentKind, DocumentMeta, DocumentReceived, + E3Failed, E3RequestComplete, E3Requested, E3Stage, E3StageChanged, E3id, EType, EffectsEnabled, + EnclaveError, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCollectionFailed, + EncryptionKeyCreated, EncryptionKeyPending, EncryptionKeyReceived, + EventConstructorWithTimestamp, EvmEventConfig, EvmEventConfigChain, FailureReason, + HistoricalEvmSyncStart, HistoricalNetSyncEventsReceived, HistoricalNetSyncStart, + KeyshareCreated, NetReady, OperatorActivationChanged, OrderedSet, OutgoingSyncRequested, + PartyProofsToVerify, PkAggregationProofPending, PkAggregationProofRequest, + PkAggregationProofSigned, PkBfvProofResponse, PkGenerationProofRequest, + PkGenerationProofSigned, PlaintextAggregated, PlaintextOutputPublished, Proof, + ProofFailureAccusation, ProofPayload, ProofType, ProofVerificationFailed, + ProofVerificationPassed, PublicKeyAggregated, PublishDocumentRequested, Seed, + ShareComputationProofRequest, ShareDecryptionProofPending, ShareEncryptionProofRequest, + ShareVerificationComplete, ShareVerificationDispatched, Shutdown, SignedProofFailed, + SignedProofPayload, SlashExecuted, SyncEffect, SyncEnded, TestEvent, ThresholdShare, + ThresholdShareCollectionFailed, ThresholdShareCreated, ThresholdShareDecryptionProofRequest, + ThresholdSharePending, TicketBalanceUpdated, TicketGenerated, TicketId, TicketSubmitted, + Unsequenced, VerificationKind, ZkResponse, }; -use e3_events::AggregateId; +use e3_fhe_params::BfvPreset; +use e3_trbfv::shares::BfvEncryptedShares; use e3_utils::ArcBytes; +use e3_zk_helpers::{computation::DkgInputType, CiphernodesCommitteeSize}; use std::collections::BTreeMap; +use std::collections::BTreeSet; use std::sync::Arc; fn dummy_proof(circuit: CircuitName) -> Proof { @@ -74,6 +88,101 @@ fn dummy_accusation_vote(e3_id: E3id, voter: Address, agrees: bool) -> Accusatio } } +fn dummy_sensitive_bytes(data: &[u8]) -> SensitiveBytes { + SensitiveBytes::from_encrypted(data) +} + +fn dummy_threshold_share() -> ThresholdShare { + ThresholdShare { + party_id: 1, + pk_share: ArcBytes::from_bytes(&[0x11; 32]), + sk_sss: BfvEncryptedShares::default(), + esi_sss: vec![BfvEncryptedShares::default()], + } +} + +fn dummy_pk_generation_proof_request() -> PkGenerationProofRequest { + PkGenerationProofRequest::new( + ArcBytes::from_bytes(&[0x22; 32]), + dummy_sensitive_bytes(&[0x33; 32]), + dummy_sensitive_bytes(&[0x44; 32]), + dummy_sensitive_bytes(&[0x55; 32]), + BfvPreset::InsecureThreshold512, + CiphernodesCommitteeSize::Small, + ) +} + +fn dummy_share_computation_proof_request() -> ShareComputationProofRequest { + ShareComputationProofRequest { + secret_raw: dummy_sensitive_bytes(&[0x66; 32]), + secret_sss_raw: dummy_sensitive_bytes(&[0x77; 32]), + dkg_input_type: DkgInputType::SecretKey, + params_preset: BfvPreset::InsecureThreshold512, + committee_size: CiphernodesCommitteeSize::Small, + } +} + +fn dummy_share_encryption_proof_request() -> ShareEncryptionProofRequest { + ShareEncryptionProofRequest { + share_row_raw: dummy_sensitive_bytes(&[0x88; 32]), + ciphertext_raw: ArcBytes::from_bytes(&[0x99; 64]), + recipient_pk_raw: ArcBytes::from_bytes(&[0xaa; 32]), + u_rns_raw: dummy_sensitive_bytes(&[0xbb; 32]), + e0_rns_raw: dummy_sensitive_bytes(&[0xcc; 32]), + e1_rns_raw: dummy_sensitive_bytes(&[0xdd; 32]), + dkg_input_type: DkgInputType::SecretKey, + params_preset: BfvPreset::InsecureThreshold512, + committee_size: CiphernodesCommitteeSize::Small, + recipient_party_id: 2, + row_index: 0, + esi_index: 0, + } +} + +fn dummy_dkg_share_decryption_proof_request() -> DkgShareDecryptionProofRequest { + DkgShareDecryptionProofRequest { + sk_bfv: dummy_sensitive_bytes(&[0xee; 32]), + honest_ciphertexts_raw: vec![ArcBytes::from_bytes(&[0xff; 64])], + num_honest_parties: 3, + num_moduli: 2, + dkg_input_type: DkgInputType::SecretKey, + params_preset: BfvPreset::InsecureThreshold512, + } +} + +fn dummy_threshold_share_decryption_proof_request() -> ThresholdShareDecryptionProofRequest { + ThresholdShareDecryptionProofRequest { + ciphertext_bytes: vec![ArcBytes::from_bytes(&[0x11; 64])], + aggregated_pk_bytes: ArcBytes::from_bytes(&[0x22; 32]), + sk_poly_sum: dummy_sensitive_bytes(&[0x33; 64]), + es_poly_sum: vec![dummy_sensitive_bytes(&[0x44; 64])], + d_share_bytes: vec![ArcBytes::from_bytes(&[0x55; 32])], + params_preset: BfvPreset::InsecureThreshold512, + proof_aggregation_enabled: true, + } +} + +fn dummy_pk_aggregation_proof_request() -> PkAggregationProofRequest { + PkAggregationProofRequest { + keyshare_bytes: vec![ArcBytes::from_bytes(&[0x66; 32])], + aggregated_pk_bytes: ArcBytes::from_bytes(&[0x77; 32]), + params_preset: BfvPreset::InsecureThreshold512, + committee_n: 5, + committee_h: 3, + committee_threshold: 3, + } +} + +fn dummy_decrypted_shares_aggregation_proof_request() -> DecryptedSharesAggregationProofRequest { + DecryptedSharesAggregationProofRequest { + d_share_polys: vec![(1, vec![ArcBytes::from_bytes(&[0x88; 64])])], + plaintext: vec![ArcBytes::from_bytes(&[0x99; 32])], + params_preset: BfvPreset::InsecureThreshold512, + threshold_m: 3, + threshold_n: 5, + } +} + #[derive(Subcommand, Clone, Debug)] pub enum EventsCommands { /// Query events @@ -472,8 +581,12 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event21 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::ProofFailureAccusation(ProofFailureAccusation { e3_id: E3id::new("test21", 1), - accuser: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".parse().unwrap(), - accused: "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb".parse().unwrap(), + accuser: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + .parse() + .unwrap(), + accused: "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + .parse() + .unwrap(), accused_party_id: 2, proof_type: ProofType::C3aSkShareEncryption, data_hash: [0xdd; 32], @@ -481,7 +594,7 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { E3id::new("test21", 1), ProofType::C3aSkShareEncryption, )), - signature: vec![0xee; 64], + signature: ArcBytes::from_bytes(&[0xee; 64]), }), None, 1700000020000_u128, @@ -494,7 +607,9 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { EnclaveEventData::ProofVerificationPassed(ProofVerificationPassed { e3_id: E3id::new("test22", 1), party_id: 1, - address: "0x1111111111111111111111111111111111111111".parse().unwrap(), + address: "0x1111111111111111111111111111111111111111" + .parse() + .unwrap(), proof_type: ProofType::C1PkGeneration, data_hash: [0x22; 32], }), @@ -728,10 +843,7 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event38 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::EncryptionKeyPending(EncryptionKeyPending { e3_id: E3id::new("test40", 1), - key: Arc::new(EncryptionKey::new( - 42, - ArcBytes::from_bytes(&[0x33; 16]), - )), + key: Arc::new(EncryptionKey::new(42, ArcBytes::from_bytes(&[0x33; 16]))), params_preset: e3_fhe_params::BfvPreset::InsecureThreshold512, }), None, @@ -744,10 +856,7 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event39 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::EncryptionKeyReceived(EncryptionKeyReceived { e3_id: E3id::new("test41", 1), - key: Arc::new(EncryptionKey::new( - 42, - ArcBytes::from_bytes(&[0x44; 16]), - )), + key: Arc::new(EncryptionKey::new(42, ArcBytes::from_bytes(&[0x44; 16]))), }), None, 1700000040000_u128, @@ -785,7 +894,9 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event42 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::SignedProofFailed(SignedProofFailed { e3_id: E3id::new("test47", 1), - faulting_node: "0x7777777777777777777777777777777777777777".parse().unwrap(), + faulting_node: "0x7777777777777777777777777777777777777777" + .parse() + .unwrap(), proof_type: ProofType::C1PkGeneration, signed_payload: dummy_signed_proof_payload( E3id::new("test47", 1), @@ -803,7 +914,9 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { EnclaveEventData::SlashExecuted(SlashExecuted { e3_id: E3id::new("test51", 1), proposal_id: 12345, - operator: "0x9999999999999999999999999999999999999999".parse().unwrap(), + operator: "0x9999999999999999999999999999999999999999" + .parse() + .unwrap(), reason: [0xaa; 32], ticket_amount: 1000, license_amount: 500, @@ -818,7 +931,9 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event44 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::CommitteeMemberExpelled(CommitteeMemberExpelled { e3_id: E3id::new("test52", 1), - node: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".parse().unwrap(), + node: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + .parse() + .unwrap(), reason: [0xbb; 32], active_count_after: 9, party_id: Some(2), @@ -844,7 +959,9 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { let event46 = EnclaveEvent::::new_with_timestamp( EnclaveEventData::HistoricalEvmSyncStart(HistoricalEvmSyncStart { evm_config: EvmEventConfig::from_config( - [(1, EvmEventConfigChain::new(100))].into_iter().collect::>(), + [(1, EvmEventConfigChain::new(100))] + .into_iter() + .collect::>(), ), sender: None, }), @@ -966,13 +1083,183 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { ) .into_sequenced(56); + let event57 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ThresholdSharePending(ThresholdSharePending { + e3_id: E3id::new("test57", 1), + full_share: Arc::new(dummy_threshold_share()), + proof_request: dummy_pk_generation_proof_request(), + sk_share_computation_request: dummy_share_computation_proof_request(), + e_sm_share_computation_request: dummy_share_computation_proof_request(), + sk_share_encryption_requests: vec![dummy_share_encryption_proof_request()], + e_sm_share_encryption_requests: vec![dummy_share_encryption_proof_request()], + recipient_party_ids: vec![1, 2, 3, 4, 5], + proof_aggregation_enabled: true, + }), + None, + 1700000070000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(57); + + let event58 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ThresholdShareCreated(ThresholdShareCreated { + e3_id: E3id::new("test58", 1), + share: Arc::new(dummy_threshold_share()), + target_party_id: 1, + external: false, + signed_c2a_proof: Some(dummy_signed_proof_payload( + E3id::new("test58", 1), + ProofType::C2aSkShareComputation, + )), + signed_c2b_proof: None, + signed_c3a_proofs: vec![], + signed_c3b_proofs: vec![], + }), + None, + 1700000071000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(58); + + let event59 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ShareDecryptionProofPending(ShareDecryptionProofPending { + e3_id: E3id::new("test59", 1), + party_id: 1, + node: "0x1111111111111111111111111111111111111111".to_string(), + decryption_share: vec![ArcBytes::from_bytes(&[0x11; 64])], + proof_request: dummy_threshold_share_decryption_proof_request(), + }), + None, + 1700000072000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(59); + + let event60 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::DecryptionShareProofsPending(DecryptionShareProofsPending { + e3_id: E3id::new("test60", 1), + party_id: 1, + node: "0x2222222222222222222222222222222222222222".to_string(), + sk_poly_sum: ArcBytes::from_bytes(&[0x33; 32]), + es_poly_sum: vec![ArcBytes::from_bytes(&[0x44; 32])], + sk_request: dummy_dkg_share_decryption_proof_request(), + esm_requests: vec![dummy_dkg_share_decryption_proof_request()], + }), + None, + 1700000073000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(60); + + let event61 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::PkAggregationProofPending(PkAggregationProofPending { + e3_id: E3id::new("test61", 1), + proof_request: dummy_pk_aggregation_proof_request(), + public_key: ArcBytes::from_bytes(&[0x55; 32]), + nodes: vec![ + "0x1111111111111111111111111111111111111111".to_string(), + "0x2222222222222222222222222222222222222222".to_string(), + ] + .into(), + }), + None, + 1700000074000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(61); + + let event62 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::AggregationProofPending(AggregationProofPending { + e3_id: E3id::new("test62", 1), + proof_request: dummy_decrypted_shares_aggregation_proof_request(), + plaintext: vec![ArcBytes::from_bytes(&[0x66; 32])], + shares: vec![(1, vec![ArcBytes::from_bytes(&[0x77; 32])])], + }), + None, + 1700000075000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(62); + + let event63 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ShareVerificationDispatched(ShareVerificationDispatched { + e3_id: E3id::new("test63", 1), + kind: VerificationKind::ShareProofs, + share_proofs: vec![PartyProofsToVerify { + sender_party_id: 2, + signed_proofs: vec![dummy_signed_proof_payload( + E3id::new("test63", 1), + ProofType::C2aSkShareComputation, + )], + }], + decryption_proofs: vec![], + pre_dishonest: BTreeSet::new(), + }), + None, + 1700000076000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(63); + + let event64 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ShareVerificationComplete(ShareVerificationComplete { + e3_id: E3id::new("test64", 1), + kind: VerificationKind::ShareProofs, + dishonest_parties: BTreeSet::from([3, 5]), + }), + None, + 1700000077000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(64); + + let event65 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::ComputeResponse(ComputeResponse { + response: ComputeResponseKind::Zk(ZkResponse::PkBfv(PkBfvProofResponse { + proof: dummy_proof(CircuitName::PkBfv), + wrapped_proof: dummy_proof(CircuitName::PkBfv), + })), + correlation_id: CorrelationId::new(), + e3_id: E3id::new("test65", 1), + }), + None, + 1700000078000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(65); + + let event66 = EnclaveEvent::::new_with_timestamp( + EnclaveEventData::PkAggregationProofSigned(PkAggregationProofSigned { + e3_id: E3id::new("test66", 1), + signed_proof: dummy_signed_proof_payload( + E3id::new("test66", 1), + ProofType::C5PkAggregation, + ), + }), + None, + 1700000079000_u128, + None, + e3_events::EventSource::Local, + ) + .into_sequenced(66); + for event in [ event1, event2, event3, event4, event5, event6, event7, event8, event9, event10, event11, event12, event13, event14, event15, event16, event17, event18, event19, event20, event21, event22, event23, event24, event25, event26, event27, event28, event29, event30, event31, event32, event33, event34, event35, event36, event37, event38, event39, event40, event41, event42, event43, event44, event45, event46, event47, event48, event49, event50, event51, - event52, event53, event54, event55, event56, + event52, event53, event54, event55, event56, event57, event58, event59, event60, event61, + event62, event63, event64, event65, event66, ] { println!("{}", serde_json::to_string(&event)?); } diff --git a/crates/crypto/src/sensitive.rs b/crates/crypto/src/sensitive.rs index 78516d1069..9a7700af08 100644 --- a/crates/crypto/src/sensitive.rs +++ b/crates/crypto/src/sensitive.rs @@ -35,6 +35,13 @@ impl SensitiveBytes { .collect::>() } + /// Helper method mainly for testing + pub fn from_encrypted(encrypted: &[u8]) -> Self { + SensitiveBytes { + encrypted: ArcBytes::from_bytes(encrypted), + } + } + /// Access the decrypted data, wrapped in a ZeroizeOnDrop container // TODO: rename try_access pub fn access(&self, cipher: &Cipher) -> Result>> { diff --git a/crates/events/src/enclave_event/proof_failure_accusation.rs b/crates/events/src/enclave_event/proof_failure_accusation.rs index 6871e4e15b..185b5830e9 100644 --- a/crates/events/src/enclave_event/proof_failure_accusation.rs +++ b/crates/events/src/enclave_event/proof_failure_accusation.rs @@ -7,6 +7,7 @@ use crate::{E3id, ProofType, SignedProofPayload}; use actix::Message; use alloy::primitives::Address; +use e3_utils::ArcBytes; use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; @@ -36,7 +37,7 @@ pub struct ProofFailureAccusation { /// `None` for proofs that all nodes already received. pub signed_payload: Option, /// ECDSA signature of the accuser over the accusation fields. - pub signature: Vec, + pub signature: ArcBytes, } impl Display for ProofFailureAccusation { diff --git a/crates/zk-prover/src/actors/accusation_manager.rs b/crates/zk-prover/src/actors/accusation_manager.rs index 3d2bf32ba7..7477a4c485 100644 --- a/crates/zk-prover/src/actors/accusation_manager.rs +++ b/crates/zk-prover/src/actors/accusation_manager.rs @@ -244,7 +244,9 @@ impl AccusationManager { fn verify_accusation_signature(&self, accusation: &ProofFailureAccusation) -> bool { let digest = Self::accusation_digest(accusation); - let sig = match alloy::primitives::Signature::try_from(accusation.signature.as_slice()) { + let sig = match alloy::primitives::Signature::try_from( + accusation.signature.extract_bytes().as_ref(), + ) { Ok(s) => s, Err(_) => return false, }; @@ -373,9 +375,9 @@ impl AccusationManager { proof_type: event.proof_type, data_hash: event.data_hash, signed_payload: forwarded_payload, - signature: Vec::new(), + signature: ArcBytes::default(), }; - accusation.signature = self.sign_accusation_digest(&accusation); + accusation.signature = ArcBytes::from_bytes(&self.sign_accusation_digest(&accusation)); let accusation_id = Self::accusation_id(&accusation); From 6c49ba5521cb2f81c8fed23185a52822e968d9a5 Mon Sep 17 00:00:00 2001 From: ryardley Date: Tue, 24 Mar 2026 04:13:42 +0000 Subject: [PATCH 10/43] whitespace --- crates/cli/src/events.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 140900d0e6..2f9b3748fd 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -1263,5 +1263,6 @@ async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { ] { println!("{}", serde_json::to_string(&event)?); } + Ok(()) } From f94d60078a747644c3ea66eb4e7f6800cfa933a6 Mon Sep 17 00:00:00 2001 From: ryardley Date: Tue, 24 Mar 2026 04:17:50 +0000 Subject: [PATCH 11/43] update syn version --- Cargo.lock | 140 ++++++++++++++++++++++++++--------------------------- Cargo.toml | 2 +- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 381c9ffe3e..d52a84607a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,7 +131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -248,7 +248,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -259,7 +259,7 @@ checksum = "b6ac1e58cded18cb28ddc17143c4dea5345b3ad575e14f32f66e4054a56eb271" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -804,7 +804,7 @@ checksum = "ce8849c74c9ca0f5a03da1c865e3eb6f768df816e67dd3721a398a8a7e398011" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1002,7 +1002,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1019,7 +1019,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", "syn-solidity", "tiny-keccak", ] @@ -1038,7 +1038,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.117", + "syn 2.0.116", "syn-solidity", ] @@ -1166,7 +1166,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1403,7 +1403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1441,7 +1441,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1538,7 +1538,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1610,7 +1610,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", "synstructure", ] @@ -1622,7 +1622,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1724,7 +1724,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1773,7 +1773,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1790,7 +1790,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -1851,7 +1851,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -2351,7 +2351,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -2746,7 +2746,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -2771,7 +2771,7 @@ dependencies = [ "quote", "serde", "strsim", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -2782,7 +2782,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -2822,7 +2822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de" dependencies = [ "data-encoding", - "syn 2.0.117", + "syn 1.0.109", ] [[package]] @@ -2890,7 +2890,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.117", + "syn 2.0.116", "unicode-xid", ] @@ -2996,7 +2996,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -3849,7 +3849,7 @@ dependencies = [ "hex", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -3989,7 +3989,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -4063,7 +4063,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -4083,7 +4083,7 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -4469,7 +4469,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -5241,7 +5241,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -5948,7 +5948,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -6146,7 +6146,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -6157,7 +6157,7 @@ checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -6751,7 +6751,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -6839,7 +6839,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -7025,7 +7025,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -7125,7 +7125,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -7239,7 +7239,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -7268,7 +7268,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -7401,7 +7401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -7463,7 +7463,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -7483,7 +7483,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", "version_check", "yansi", ] @@ -7508,7 +7508,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -7567,7 +7567,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.117", + "syn 2.0.116", "tempfile", ] @@ -7587,7 +7587,7 @@ dependencies = [ "prost 0.13.5", "prost-types 0.13.5", "regex", - "syn 2.0.117", + "syn 2.0.116", "tempfile", ] @@ -7601,7 +7601,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -7614,7 +7614,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -8019,7 +8019,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -8266,7 +8266,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.117", + "syn 2.0.116", "walkdir", ] @@ -8670,7 +8670,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -8735,7 +8735,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -8783,7 +8783,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -9103,7 +9103,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -9125,9 +9125,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" dependencies = [ "proc-macro2", "quote", @@ -9143,7 +9143,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -9163,7 +9163,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -9265,7 +9265,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -9276,7 +9276,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -9400,7 +9400,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -9671,7 +9671,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -9760,7 +9760,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -10091,7 +10091,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", "wasm-bindgen-shared", ] @@ -10247,7 +10247,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -10258,7 +10258,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -10686,7 +10686,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", "synstructure", ] @@ -10707,7 +10707,7 @@ checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -10727,7 +10727,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", "synstructure", ] @@ -10748,7 +10748,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] @@ -10781,7 +10781,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.116", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index fd1ad86e97..031bb0b974 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -187,7 +187,7 @@ sha2 = "=0.10.9" shellexpand = "=3.1.1" sled = "=0.34.7" strum = { version = "=0.27.2", features = ["derive"] } -syn = { version = "=2.0.117", features = ["full"] } +syn = { version = "=2.0.116", features = ["full"] } tempfile = "=3.20.0" thiserror = { version = "=1.0.69" } tokio = { version = "=1.46.1", features = ["full"] } From 193e99122c038d0a7d2fbf27dba147d15a7f27b3 Mon Sep 17 00:00:00 2001 From: ryardley Date: Tue, 24 Mar 2026 04:25:31 +0000 Subject: [PATCH 12/43] update Cargo lock --- examples/CRISP/Cargo.lock | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/examples/CRISP/Cargo.lock b/examples/CRISP/Cargo.lock index ad4276264f..1c63454476 100644 --- a/examples/CRISP/Cargo.lock +++ b/examples/CRISP/Cargo.lock @@ -2521,6 +2521,8 @@ dependencies = [ "alloy", "anyhow", "derivative", + "e3-utils-derive", + "hex", "rand 0.8.5", "rand_chacha 0.3.1", "regex", @@ -2529,6 +2531,16 @@ dependencies = [ "tracing", ] +[[package]] +name = "e3-utils-derive" +version = "0.1.15" +dependencies = [ + "hex", + "proc-macro2 1.0.106", + "quote 1.0.44", + "syn 2.0.116", +] + [[package]] name = "e3-zk-helpers" version = "0.1.15" From df7a56ab8bb59aaf52af5eb396c66952f655fcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=B3=CE=BB?= Date: Thu, 26 Mar 2026 02:04:37 +0000 Subject: [PATCH 13/43] Update committee_published.rs --- crates/events/src/enclave_event/committee_published.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/events/src/enclave_event/committee_published.rs b/crates/events/src/enclave_event/committee_published.rs index 9557857ade..dc3ba1c29c 100644 --- a/crates/events/src/enclave_event/committee_published.rs +++ b/crates/events/src/enclave_event/committee_published.rs @@ -15,12 +15,8 @@ use std::fmt::{self, Display}; pub struct CommitteePublished { pub e3_id: E3id, pub nodes: Vec, -<<<<<<< ry/1468-event-feed pub public_key: ArcBytes, -======= - pub public_key: Vec, pub proof: Vec, ->>>>>>> main } impl Display for CommitteePublished { From 6e50d0fb754a359594681fd2eea9c736a4824063 Mon Sep 17 00:00:00 2001 From: ryardley Date: Tue, 24 Mar 2026 12:40:16 +0000 Subject: [PATCH 14/43] implement event fetch without cursor --- crates/cli/src/cli.rs | 22 +++++++++++-- crates/cli/src/events.rs | 71 +++++++++++++++++++++++++++++++++------- 2 files changed, 79 insertions(+), 14 deletions(-) diff --git a/crates/cli/src/cli.rs b/crates/cli/src/cli.rs index 28933bc1d4..1f38416a43 100644 --- a/crates/cli/src/cli.rs +++ b/crates/cli/src/cli.rs @@ -182,7 +182,7 @@ impl Cli { Commands::Ciphernode { command } => ciphernode::execute(out, command, &config).await?, Commands::Noir { command } => noir::execute(out, command, &config).await?, Commands::Net { command } => net::execute(&out, command, &config).await?, - Commands::Events { command } => events::execute(command).await?, + Commands::Events { command } => events::execute(out, command, &config).await?, Commands::Rev => rev::execute(out).await?, } @@ -320,11 +320,21 @@ pub struct RemoteCli { #[derive(Clone, Debug, Serialize, Deserialize)] pub enum RemoteCommand { NetGetPeerId, - CiphernodeStatus { chain: ChainArgs }, + CiphernodeStatus { + chain: ChainArgs, + }, NoirStatus, WalletGet, + EventsQuery { + agg: Option, + since: Option, + limit: Option, + }, Rev, - PrintEnv { vite: bool, chain: String }, + PrintEnv { + vite: bool, + chain: String, + }, } impl TryFrom for RemoteCommand { @@ -343,6 +353,9 @@ impl TryFrom for RemoteCommand { command: CiphernodeCommands::Status { chain }, } => Ok(RemoteCommand::CiphernodeStatus { chain }), Commands::PrintEnv { chain, vite } => Ok(RemoteCommand::PrintEnv { vite, chain }), + Commands::Events { + command: EventsCommands::Query { agg, since, limit }, + } => Ok(RemoteCommand::EventsQuery { agg, since, limit }), Commands::Wallet { command: WalletCommands::Get, } => Ok(RemoteCommand::WalletGet), @@ -397,6 +410,9 @@ impl TryFrom for Commands { RemoteCommand::NetGetPeerId => Commands::Net { command: NetCommands::GetPeerId, }, + RemoteCommand::EventsQuery { agg, since, limit } => Commands::Events { + command: EventsCommands::Query { agg, since, limit }, + }, }; // We might have to hold this stuff on RemoteCommand Ok(command) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 2f9b3748fd..e76ec76db6 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -8,14 +8,16 @@ use alloy::primitives::{Address, FixedBytes, I256, U256}; use anyhow::Result; use chrono::Utc; use clap::Subcommand; +use e3_ciphernode_builder::global_eventstore_cache::EventStoreReader; +use e3_config::AppConfig; +use e3_console::{log, Console}; use e3_crypto::SensitiveBytes; -use e3_events::AggregateId; +use e3_entrypoint::helpers::datastore::get_eventstore_reader; use e3_events::{ AccusationOutcome, AccusationQuorumReached, AccusationVote, AggregationProofPending, AggregationProofSigned, CiphernodeAdded, CiphernodeRemoved, CiphernodeSelected, CiphertextOutputPublished, CircuitName, CommitteeFinalizeRequested, CommitteeFinalized, - CommitteeMemberExpelled, CommitteePublished, CommitteeRequested, ComputeRequest, - ComputeRequestError, ComputeRequestErrorKind, ComputeRequestKind, ComputeResponse, + CommitteeMemberExpelled, CommitteePublished, CommitteeRequested, ComputeResponse, ComputeResponseKind, ConfigurationUpdated, CorrelationId, DKGInnerProofReady, DKGRecursiveAggregationComplete, DecryptedSharesAggregationProofRequest, DecryptionKeyShared, DecryptionShareProofSigned, DecryptionShareProofsPending, DecryptionshareCreated, @@ -23,9 +25,9 @@ use e3_events::{ E3Failed, E3RequestComplete, E3Requested, E3Stage, E3StageChanged, E3id, EType, EffectsEnabled, EnclaveError, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCollectionFailed, EncryptionKeyCreated, EncryptionKeyPending, EncryptionKeyReceived, - EventConstructorWithTimestamp, EvmEventConfig, EvmEventConfigChain, FailureReason, - HistoricalEvmSyncStart, HistoricalNetSyncEventsReceived, HistoricalNetSyncStart, - KeyshareCreated, NetReady, OperatorActivationChanged, OrderedSet, OutgoingSyncRequested, + EventConstructorWithTimestamp, EventStoreQueryResponse, EvmEventConfig, EvmEventConfigChain, + FailureReason, HistoricalEvmSyncStart, HistoricalNetSyncEventsReceived, HistoricalNetSyncStart, + KeyshareCreated, NetReady, OperatorActivationChanged, OutgoingSyncRequested, PartyProofsToVerify, PkAggregationProofPending, PkAggregationProofRequest, PkAggregationProofSigned, PkBfvProofResponse, PkGenerationProofRequest, PkGenerationProofSigned, PlaintextAggregated, PlaintextOutputPublished, Proof, @@ -38,12 +40,14 @@ use e3_events::{ ThresholdSharePending, TicketBalanceUpdated, TicketGenerated, TicketId, TicketSubmitted, Unsequenced, VerificationKind, ZkResponse, }; +use e3_events::{AggregateId, EventStoreQueryBy, SeqAgg}; use e3_fhe_params::BfvPreset; use e3_trbfv::shares::BfvEncryptedShares; +use e3_utils::actix::channel as actix_toolbox; use e3_utils::ArcBytes; use e3_zk_helpers::{computation::DkgInputType, CiphernodesCommitteeSize}; -use std::collections::BTreeMap; use std::collections::BTreeSet; +use std::collections::{BTreeMap, HashMap}; use std::sync::Arc; fn dummy_proof(circuit: CircuitName) -> Proof { @@ -189,7 +193,7 @@ pub enum EventsCommands { Query { /// Aggregate ID - will default to 0 #[arg(long)] - agg: Option, + agg: Option, /// Sequence to read from will read from 0 if absent #[arg(long)] @@ -202,16 +206,61 @@ pub enum EventsCommands { }, } -pub async fn execute(command: EventsCommands) -> Result<()> { +pub async fn execute(out: Console, command: EventsCommands, config: &AppConfig) -> Result<()> { match command { EventsCommands::Query { agg, since, limit } => { - query_events(agg.unwrap_or(0), since.unwrap_or(0), limit.unwrap_or(10)).await?; + query_events(out, config, agg, since, limit).await? } } Ok(()) } -async fn query_events(aggregate: u64, since: u64, limit: u64) -> Result<()> { +async fn query_events( + out: Console, + config: &AppConfig, + aggregate: Option, + since: Option, + limit: Option, +) -> Result<()> { + let eventstore = get_eventstore_reader(config)?; + let events = fetch_events(eventstore, aggregate, since, limit).await?; + print_events(out, events)?; + Ok(()) +} + +async fn fetch_events( + eventstore: EventStoreReader, + aggregate: Option, + since: Option, + limit: Option, +) -> Result> { + let aggregate = aggregate.unwrap_or(0); + let since = since.unwrap_or(0); + let limit = limit.unwrap_or(10); + let (addr, rx) = actix_toolbox::oneshot::(); + + let msg = EventStoreQueryBy::::new( + CorrelationId::new(), + HashMap::from([(AggregateId::new(aggregate), since)]), + addr, + ) + .with_limit(limit); + + eventstore.seq().do_send(msg); + let events = rx.await?.into_events(); + + Ok(events) +} + +fn print_events(out: Console, events: Vec) -> Result<()> { + for event in events { + log!(out, "{}", serde_json::to_string(&event)?); + } + Ok(()) +} + +/// This just prints fake events to ensure serialization works +async fn query_events_fake(aggregate: u64, since: u64, limit: u64) -> Result<()> { tracing::info!( "Querying events: aggregate={}, since={}, limit={}", aggregate, From bd85a6c0faa06a662adb1defb616a50a25e00345 Mon Sep 17 00:00:00 2001 From: ryardley Date: Thu, 26 Mar 2026 02:14:57 +0000 Subject: [PATCH 15/43] use ArcBytes --- crates/cli/src/events.rs | 2 ++ crates/events/src/enclave_event/committee_published.rs | 2 +- crates/events/src/enclave_event/plaintext_output_published.rs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index e76ec76db6..62cad83638 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -510,6 +510,7 @@ async fn query_events_fake(aggregate: u64, since: u64, limit: u64) -> Result<()> "0x3333333333333333333333333333333333333333".to_string(), ], public_key: ArcBytes::from_bytes(&[0xAB; 64]), + proof: ArcBytes::from_bytes(&[0xAB; 64]), }), None, 1700000012000_u128, @@ -855,6 +856,7 @@ async fn query_events_fake(aggregate: u64, since: u64, limit: u64) -> Result<()> EnclaveEventData::PlaintextOutputPublished(PlaintextOutputPublished { e3_id: E3id::new("test35", 1), plaintext_output: ArcBytes::from_bytes(&[0x55; 32]), + proof: ArcBytes::from_bytes(&[0x66; 64]), }), None, 1700000034000_u128, diff --git a/crates/events/src/enclave_event/committee_published.rs b/crates/events/src/enclave_event/committee_published.rs index dc3ba1c29c..22785e1c15 100644 --- a/crates/events/src/enclave_event/committee_published.rs +++ b/crates/events/src/enclave_event/committee_published.rs @@ -16,7 +16,7 @@ pub struct CommitteePublished { pub e3_id: E3id, pub nodes: Vec, pub public_key: ArcBytes, - pub proof: Vec, + pub proof: ArcBytes, } impl Display for CommitteePublished { diff --git a/crates/events/src/enclave_event/plaintext_output_published.rs b/crates/events/src/enclave_event/plaintext_output_published.rs index e48c25cff0..b415fd6a2c 100644 --- a/crates/events/src/enclave_event/plaintext_output_published.rs +++ b/crates/events/src/enclave_event/plaintext_output_published.rs @@ -15,7 +15,7 @@ use std::fmt::{self, Display}; pub struct PlaintextOutputPublished { pub e3_id: E3id, pub plaintext_output: ArcBytes, - pub proof: Vec, + pub proof: ArcBytes, } impl Display for PlaintextOutputPublished { From fa165f50f96668a0eb24987d56ecc8f8d7814c7c Mon Sep 17 00:00:00 2001 From: ryardley Date: Thu, 26 Mar 2026 02:25:07 +0000 Subject: [PATCH 16/43] fix dockerfile proc macro issues --- crates/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/Dockerfile b/crates/Dockerfile index 39b4c3ab66..f1aa47a435 100644 --- a/crates/Dockerfile +++ b/crates/Dockerfile @@ -93,6 +93,9 @@ RUN for d in ./*/ ; do \ if [ "$d" = "./cli/" ] || [ "$d" = "./enclaveup/" ]; then \ mkdir -p "$d/src" && \ echo "fn main() {}" > "$d/src/main.rs"; \ + elif [ "$d" = "./utils-derive/" ]; then \ + mkdir -p "$d/src" && \ + echo "" > "$d/src/lib.rs"; \ else \ mkdir -p "$d/src" && \ echo "pub fn main() {}" > "$d/src/lib.rs"; \ From d9df47acac4c5e3b4f25caf33add76efb97a9722 Mon Sep 17 00:00:00 2001 From: ryardley Date: Thu, 26 Mar 2026 08:57:20 +0000 Subject: [PATCH 17/43] fix custom bb not working in tests --- crates/config/src/app_config.rs | 10 ++++++++++ crates/tests/tests/integration.rs | 15 +++++++-------- crates/zk-prover/src/backend/tests.rs | 2 +- crates/zk-prover/tests/common/helpers.rs | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/crates/config/src/app_config.rs b/crates/config/src/app_config.rs index 7e027c5a0c..a2e5b31ee8 100644 --- a/crates/config/src/app_config.rs +++ b/crates/config/src/app_config.rs @@ -202,6 +202,16 @@ impl BBPath { BBPath::Default(p) => p.clone(), } } + + /// Check the environment variable and if found use that otherwisse use the given path + pub fn check(default_path: PathBuf) -> Result { + let bb_path = if let Some(bb_path) = env::var("E3_CUSTOM_BB").ok() { + BBPath::Custom(bb_path.try_into()?) + } else { + BBPath::Default(default_path) + }; + Ok(bb_path) + } } impl AppConfig { diff --git a/crates/tests/tests/integration.rs b/crates/tests/tests/integration.rs index ae7e495501..053a7d3e45 100644 --- a/crates/tests/tests/integration.rs +++ b/crates/tests/tests/integration.rs @@ -47,7 +47,7 @@ use tokio::{ /// Create a ZkBackend for integration tests. /// If a local bb binary is found, uses it with fixture files (fast path). /// Otherwise, calls `ensure_installed()` to download bb + circuits (CI path). -async fn setup_test_zk_backend() -> (ZkBackend, tempfile::TempDir) { +async fn setup_test_zk_backend() -> Result<(ZkBackend, tempfile::TempDir)> { let temp = get_tempdir().unwrap(); let temp_path = temp.path(); let noir_dir = temp_path.join("noir"); @@ -375,9 +375,8 @@ async fn setup_test_zk_backend() -> (ZkBackend, tempfile::TempDir) { ".vk_hash", ) .await; - - let backend = ZkBackend::new(BBPath::Default(bb_binary), circuits_dir, work_dir); - (backend, temp) + let backend = ZkBackend::new(BBPath::check(bb_binary)?, circuits_dir, work_dir); + Ok((backend, temp)) } else { println!("bb binary not found locally, downloading via ensure_installed()..."); let backend = ZkBackend::new(BBPath::Default(bb_binary), circuits_dir, work_dir); @@ -385,7 +384,7 @@ async fn setup_test_zk_backend() -> (ZkBackend, tempfile::TempDir) { .ensure_installed() .await .expect("Failed to download and install ZK backend"); - (backend, temp) + Ok((backend, temp)) } } @@ -623,7 +622,7 @@ async fn test_trbfv_actor() -> Result<()> { let multithread_report = MultithreadReport::new(max_threadroom, concurrent_jobs).start(); // Setup ZK backend for proof generation/verification - let (zk_backend, _zk_temp) = setup_test_zk_backend().await; + let (zk_backend, _zk_temp) = setup_test_zk_backend().await?; let nodes = CiphernodeSystemBuilder::new() // Adding 20 total nodes: 3 for committee + 3 buffer = 6 selected, 14 unselected @@ -1200,7 +1199,7 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { Ok(result) } - let (zk_backend, _zk_temp) = setup_test_zk_backend().await; + 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) = { @@ -1454,7 +1453,7 @@ 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; + 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, zk_backend.clone()).await?; diff --git a/crates/zk-prover/src/backend/tests.rs b/crates/zk-prover/src/backend/tests.rs index b9620795cf..33cf448330 100644 --- a/crates/zk-prover/src/backend/tests.rs +++ b/crates/zk-prover/src/backend/tests.rs @@ -11,7 +11,7 @@ use tokio::fs; fn test_backend(temp_path: &std::path::Path, config: ZkConfig) -> ZkBackend { let noir_dir = temp_path.join("noir"); - let bb_binary = BBPath::Default(noir_dir.join("bin").join("bb")); + let bb_binary = BBPath::check(noir_dir.join("bin").join("bb")).unwrap(); let circuits_dir = noir_dir.join("circuits"); let work_dir = noir_dir.join("work").join("test_node"); ZkBackend::with_config(bb_binary, circuits_dir, work_dir, config) diff --git a/crates/zk-prover/tests/common/helpers.rs b/crates/zk-prover/tests/common/helpers.rs index 867b122380..91ebd7bff5 100644 --- a/crates/zk-prover/tests/common/helpers.rs +++ b/crates/zk-prover/tests/common/helpers.rs @@ -139,7 +139,7 @@ pub async fn setup_test_prover(bb: &PathBuf) -> (ZkBackend, TempDir) { let temp_path = temp.path(); let noir_dir = temp_path.join("noir"); - let bb_binary = BBPath::Default(noir_dir.join("bin").join("bb")); + let bb_binary = BBPath::check(noir_dir.join("bin").join("bb")).unwrap(); let circuits_dir = noir_dir.join("circuits"); let work_dir = noir_dir.join("work").join("test_node"); let backend = ZkBackend::new(bb_binary.clone(), circuits_dir.clone(), work_dir.clone()); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30327b5641..1cd2bacd24 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -728,7 +728,7 @@ importers: version: 5.3.0 '@risc0/ethereum': specifier: file:lib/risc0-ethereum - version: file:templates/default/lib/risc0-ethereum + version: risc0-ethereum@file:templates/default/lib/risc0-ethereum '@types/chai': specifier: ^4.2.0 version: 4.3.20 @@ -3100,9 +3100,6 @@ packages: '@reown/appkit@1.7.8': resolution: {integrity: sha512-51kTleozhA618T1UvMghkhKfaPcc9JlKwLJ5uV+riHyvSoWPKPRIa5A6M1Wano5puNyW0s3fwywhyqTHSilkaA==} - '@risc0/ethereum@file:templates/default/lib/risc0-ethereum': - resolution: {directory: templates/default/lib/risc0-ethereum, type: directory} - '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} @@ -8786,6 +8783,9 @@ packages: resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} engines: {node: '>= 0.8'} + risc0-ethereum@file:templates/default/lib/risc0-ethereum: + resolution: {directory: templates/default/lib/risc0-ethereum, type: directory} + robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} @@ -13241,8 +13241,6 @@ snapshots: - utf-8-validate - zod - '@risc0/ethereum@file:templates/default/lib/risc0-ethereum': {} - '@rolldown/pluginutils@1.0.0-beta.27': {} '@rollup/plugin-inject@5.0.5(rollup@4.52.5)': @@ -20114,7 +20112,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.1.1(typescript@5.8.3)(zod@3.25.76) + abitype: 1.1.1(typescript@5.8.3)(zod@3.22.4) eventemitter3: 5.0.1 optionalDependencies: typescript: 5.8.3 @@ -20968,6 +20966,8 @@ snapshots: hash-base: 3.1.2 inherits: 2.0.4 + risc0-ethereum@file:templates/default/lib/risc0-ethereum: {} + robust-predicates@3.0.2: {} rollup@4.52.5: @@ -22168,7 +22168,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.1.0(typescript@5.8.3)(zod@3.25.76) + abitype: 1.1.0(typescript@5.8.3)(zod@3.22.4) isows: 1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) ox: 0.9.6(typescript@5.8.3) ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) From 12cee6b7ac4a4e535a6ee90d0d64de743a6418bf Mon Sep 17 00:00:00 2001 From: ryardley Date: Thu, 26 Mar 2026 10:08:27 +0000 Subject: [PATCH 18/43] fix test --- crates/utils-derive/src/lib.rs | 2 +- crates/zk-prover/src/backend/tests.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/utils-derive/src/lib.rs b/crates/utils-derive/src/lib.rs index 7b1a5c4229..6c3b6e9423 100644 --- a/crates/utils-derive/src/lib.rs +++ b/crates/utils-derive/src/lib.rs @@ -17,7 +17,7 @@ use syn::{parse_macro_input, Data, DeriveInput, Error, Fields}; /// /// # Example /// -/// ```rust +/// ```ignore /// use e3_utils::BytesSerde; /// use e3_utils::AsBytesSerde; /// diff --git a/crates/zk-prover/src/backend/tests.rs b/crates/zk-prover/src/backend/tests.rs index 33cf448330..b9a3138746 100644 --- a/crates/zk-prover/src/backend/tests.rs +++ b/crates/zk-prover/src/backend/tests.rs @@ -4,6 +4,8 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +use std::env; + use super::*; use crate::{config::VersionInfo, error::ZkError, test_utils::get_tempdir}; use sha2::{Digest, Sha256}; @@ -59,6 +61,10 @@ async fn test_version_info_roundtrip() { #[tokio::test] async fn test_check_status_full_setup_needed() { + if let Some(_) = env::var("E3_CUSTOM_BB").ok() { + return; + } + let temp = get_tempdir().unwrap(); let backend = test_backend(temp.path(), ZkConfig::default()); @@ -72,6 +78,10 @@ async fn test_check_status_full_setup_needed() { #[tokio::test] async fn test_check_status_ready_when_installed() { + if let Some(_) = env::var("E3_CUSTOM_BB").ok() { + return; + } + let temp = get_tempdir().unwrap(); let config = ZkConfig::default(); let backend = test_backend(temp.path(), config.clone()); @@ -101,6 +111,10 @@ async fn test_check_status_ready_when_installed() { #[tokio::test] async fn test_check_status_bb_needs_update() { + if let Some(_) = env::var("E3_CUSTOM_BB").ok() { + return; + } + let temp = get_tempdir().unwrap(); let config = ZkConfig::default(); let backend = test_backend(temp.path(), config.clone()); From 42efe9ce703b5533dfd8452a19a56979bca4aafc Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Mar 2026 01:24:47 +0000 Subject: [PATCH 19/43] update dummy vals --- crates/cli/src/events.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 62cad83638..9904b79d54 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -662,6 +662,7 @@ async fn query_events_fake(aggregate: u64, since: u64, limit: u64) -> Result<()> .unwrap(), proof_type: ProofType::C1PkGeneration, data_hash: [0x22; 32], + public_signals: ArcBytes::from_bytes(&[0xaa; 64]), }), None, 1700000021000_u128, @@ -829,6 +830,7 @@ async fn query_events_fake(aggregate: u64, since: u64, limit: u64) -> Result<()> "0x2222222222222222222222222222222222222222".to_string(), ], chain_id: 1, + scores: Vec::new(), }), None, 1700000032000_u128, From 7fbae139443f0ef5ec6fd90ae2a4aeb01ac7f316 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Mar 2026 02:22:05 +0000 Subject: [PATCH 20/43] update ciphernode build timeout --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f9ecc6806..3766272c19 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -301,7 +301,7 @@ jobs: build_ciphernode_image: needs: [detect_changes] if: needs.detect_changes.outputs.docker_ciphernode == 'true' - timeout-minutes: 30 + timeout-minutes: 60 runs-on: 'ubuntu-latest' steps: - uses: actions/checkout@v6 From 7bc73fa0c6194ec875a42399941138e85ef6bf18 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Mar 2026 04:14:43 +0000 Subject: [PATCH 21/43] use REST parsing over TCP --- Cargo.lock | 1 + crates/cli/src/main.rs | 8 +-- crates/cli/src/start.rs | 32 +++++------- crates/socket-server/Cargo.toml | 1 + crates/socket-server/src/lib.rs | 91 ++++++++++++++++++++++++++------- 5 files changed, 91 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d24290cc0..9ec4ccee6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3658,6 +3658,7 @@ dependencies = [ "anyhow", "e3-config", "e3-console", + "reqwest", "serde", "serde_json", "tokio", diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 0faa84c2ac..628f378df7 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -8,7 +8,7 @@ use anyhow::Result; use clap::Parser; use cli::{Cli, RemoteCli}; use e3_console::Console; -use e3_socket_server::{connect_socket, run_on_socket}; +use e3_socket_server::{connect_daemon, run_on_daemon}; use e3_utils::{colorize, Color}; use tracing::info; @@ -70,13 +70,13 @@ pub async fn main() -> Result<()> { let cli = Cli::parse(); let config_result = cli.load_config(); - let maybe_stream = connect_socket(config_result.as_ref().ok()).await; + let maybe_server = connect_daemon(config_result.as_ref().ok()).await; let maybe_remote_command = TryInto::::try_into(cli.clone()).ok(); // If the socket exists and the command can be parsed as remote - if let Err(err) = if let (Some(stream), Some(command)) = (maybe_stream, maybe_remote_command) { + if let Err(err) = if let (Some(server), Some(command)) = (maybe_server, maybe_remote_command) { // Run the command over the socket - run_on_socket(out, stream, command).await + run_on_daemon(out, server, command).await } else { // Run the command locally cli.execute(out, config_result).await diff --git a/crates/cli/src/start.rs b/crates/cli/src/start.rs index 3f5c54416e..090125da60 100644 --- a/crates/cli/src/start.rs +++ b/crates/cli/src/start.rs @@ -15,9 +15,8 @@ use e3_ciphernode_builder::CiphernodeHandle; use e3_config::{AppConfig, NodeRole}; use e3_console::Console; use e3_events::{prelude::*, Shutdown}; -use e3_socket_server::start_socket_server; +use e3_socket_server::start_rest_server; use e3_utils::{colorize, Color}; -use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use tokio::signal::unix::{signal, SignalKind}; use tracing::{error, info, instrument}; @@ -56,24 +55,19 @@ pub async fn execute(mut config: AppConfig, peers: Vec) -> Result<()> { /// Launch a socket server to read RemoteCli commands pub fn launch_socket_server(ctrl_port: u16) { // Setup socket server for daemon - tokio::task::spawn_local(start_socket_server(ctrl_port, |stream| async move { - let (reader, mut writer) = stream.into_split(); - let mut lines = BufReader::new(reader).lines(); - - if let Some(line) = lines.next_line().await? { - let (out, mut rx) = Console::channel(); - info!("CMD: {}", &colorize(&line, Color::Blue)); - let remote_cli: RemoteCli = serde_json::from_str(&line)?; - let cli: Cli = remote_cli.try_into()?; - let config_result = cli.load_config(); - cli.execute(out, config_result).await?; - while let Some(msg) = rx.recv().await { - writer.write_all(format!("{msg}\n").as_bytes()).await?; - } + tokio::task::spawn_local(start_rest_server(ctrl_port, |body| async move { + let (out, mut rx) = Console::channel(); + info!("CMD: {}", &colorize(&body, Color::Blue)); + let remote_cli: RemoteCli = serde_json::from_str(&body)?; + let cli: Cli = remote_cli.try_into()?; + let config_result = cli.load_config(); + cli.execute(out, config_result).await?; + + let mut output = String::new(); + while let Some(msg) = rx.recv().await { + output.push_str(&format!("{msg}\n")); } - - writer.shutdown().await?; - Ok(()) + Ok(output) })); } diff --git a/crates/socket-server/Cargo.toml b/crates/socket-server/Cargo.toml index c21bbc1420..333691ce7d 100644 --- a/crates/socket-server/Cargo.toml +++ b/crates/socket-server/Cargo.toml @@ -12,5 +12,6 @@ e3-console.workspace = true e3-config.workspace = true serde.workspace = true serde_json.workspace = true +reqwest.workspace = true tokio.workspace = true tracing.workspace = true diff --git a/crates/socket-server/src/lib.rs b/crates/socket-server/src/lib.rs index c3ff33ae64..72ad401caa 100644 --- a/crates/socket-server/src/lib.rs +++ b/crates/socket-server/src/lib.rs @@ -18,35 +18,48 @@ const TCP_ADDRESS: &str = "127.0.0.1"; // using localhost specifically so that i // externally. We might change this if we need to control // externally and add authentication or TLS -pub async fn connect_socket(maybe_config: Option<&AppConfig>) -> Option { +pub struct ServerInfo { + pub port: u16, +} + +pub async fn connect_daemon(maybe_config: Option<&AppConfig>) -> Option { let config = maybe_config?; - let addr = format!("{}:{}", TCP_ADDRESS, config.ctrl_port()); - TcpStream::connect(addr).await.ok() + let port = config.ctrl_port(); + let url = format!("http://{}:{}", TCP_ADDRESS, port); + reqwest::Client::new() + .head(&url) + .timeout(std::time::Duration::from_secs(1)) + .send() + .await + .ok()?; + Some(ServerInfo { port }) } -pub async fn run_on_socket( +pub async fn run_on_daemon( out: Console, - stream: TcpStream, + server: ServerInfo, cli: T, ) -> anyhow::Result<()> { - let (reader, mut writer) = stream.into_split(); - let payload = serde_json::to_string(&cli)?; - writer.write_all(payload.as_bytes()).await?; - writer.write_all(b"\n").await?; - writer.shutdown().await?; + let url = format!("http://{}:{}", TCP_ADDRESS, server.port); + let client = reqwest::Client::new(); + let resp = client + .post(&url) + .json(&cli) + .send() + .await? + .error_for_status()?; - let mut lines = BufReader::new(reader).lines(); - while let Some(line) = lines.next_line().await? { + let text = resp.text().await?; + for line in text.lines() { log!(out, "{}", line); } - Ok(()) } -pub async fn start_socket_server(tcp_port: u16, handler: F) +pub async fn start_rest_server(tcp_port: u16, handler: F) where - F: Fn(TcpStream) -> Fut + Send + Sync + 'static, - Fut: Future> + 'static, + F: Fn(String) -> Fut + 'static, + Fut: Future> + 'static, { let addr = format!("{}:{}", TCP_ADDRESS, tcp_port); let listener = match tokio::net::TcpListener::bind(addr).await { @@ -56,15 +69,13 @@ where return; } }; - let handler = Arc::new(handler); loop { match listener.accept().await { Ok((stream, _)) => { let handler = Arc::clone(&handler); - tokio::task::spawn_local(async move { - if let Err(e) = handler(stream).await { + if let Err(e) = handle_http(stream, &handler.as_ref()).await { error!("Connection error: {e}"); } }); @@ -76,3 +87,45 @@ where } } } + +async fn handle_http(stream: TcpStream, handler: &F) -> Result<()> +where + F: Fn(String) -> Fut, + Fut: Future>, +{ + let (reader, mut writer) = stream.into_split(); + let mut buf_reader = BufReader::new(reader); + + // Read headers until blank line + let mut content_length: usize = 0; + loop { + let mut line = String::new(); + buf_reader.read_line(&mut line).await?; + if line.trim().is_empty() { + break; + } + if let Some(val) = line.to_ascii_lowercase().strip_prefix("content-length:") { + content_length = val.trim().parse().unwrap_or(0); + } + } + + // Read body + let mut body = vec![0u8; content_length]; + tokio::io::AsyncReadExt::read_exact(&mut buf_reader, &mut body).await?; + let body = String::from_utf8(body)?; + + // Run the existing logic + let (status, response_body) = match handler(body).await { + Ok(output) => ("200 OK", output), + Err(e) => ("500 Internal Server Error", e.to_string()), + }; + + let response = format!( + "HTTP/1.1 {status}\r\nContent-Type: text/plain\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}", + response_body.len(), + response_body + ); + writer.write_all(response.as_bytes()).await?; + writer.shutdown().await?; + Ok(()) +} From b28e8be929159e0fb20d3d62d01606427da22ac2 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Mar 2026 04:17:49 +0000 Subject: [PATCH 22/43] add explanation comment --- crates/socket-server/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/socket-server/src/lib.rs b/crates/socket-server/src/lib.rs index 72ad401caa..22baded4c4 100644 --- a/crates/socket-server/src/lib.rs +++ b/crates/socket-server/src/lib.rs @@ -93,6 +93,7 @@ where F: Fn(String) -> Fut, Fut: Future>, { + // We do manual http parsing as actix-web requires running on a separate thread and is too heavy let (reader, mut writer) = stream.into_split(); let mut buf_reader = BufReader::new(reader); From 4ea665163ce0bcfc0f6d45e774feabe3b5cf5e27 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Mar 2026 04:21:22 +0000 Subject: [PATCH 23/43] socket-server -> daemon-server --- Cargo.lock | 32 +++++++++---------- Cargo.toml | 4 +-- crates/Dockerfile | 2 +- crates/cli/Cargo.toml | 2 +- crates/cli/src/start.rs | 4 +-- .../Cargo.toml | 2 +- .../src/lib.rs | 2 +- crates/entrypoint/Cargo.toml | 2 +- examples/CRISP/server/Dockerfile | 2 +- 9 files changed, 26 insertions(+), 26 deletions(-) rename crates/{socket-server => daemon-server}/Cargo.toml (93%) rename crates/{socket-server => daemon-server}/src/lib.rs (98%) diff --git a/Cargo.lock b/Cargo.lock index 9ec4ccee6b..018c773ca8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3131,12 +3131,12 @@ dependencies = [ "e3-config", "e3-console", "e3-crypto", + "e3-daemon-server", "e3-entrypoint", "e3-events", "e3-evm", "e3-fhe-params", "e3-init", - "e3-socket-server", "e3-support-scripts", "e3-trbfv", "e3-utils", @@ -3225,6 +3225,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "e3-daemon-server" +version = "0.1.15" +dependencies = [ + "anyhow", + "e3-config", + "e3-console", + "reqwest", + "serde", + "serde_json", + "tokio", + "tracing", +] + [[package]] name = "e3-data" version = "0.1.15" @@ -3260,6 +3274,7 @@ dependencies = [ "e3-ciphernode-builder", "e3-config", "e3-crypto", + "e3-daemon-server", "e3-data", "e3-events", "e3-evm", @@ -3268,7 +3283,6 @@ dependencies = [ "e3-logger", "e3-net", "e3-request", - "e3-socket-server", "e3-sortition", "e3-test-helpers", "e3-zk-prover", @@ -3651,20 +3665,6 @@ dependencies = [ "e3-indexer", ] -[[package]] -name = "e3-socket-server" -version = "0.1.15" -dependencies = [ - "anyhow", - "e3-config", - "e3-console", - "reqwest", - "serde", - "serde_json", - "tokio", - "tracing", -] - [[package]] name = "e3-sortition" version = "0.1.15" diff --git a/Cargo.toml b/Cargo.toml index 031bb0b974..b1c4ab9fe4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ members = [ "crates/request", "crates/safe", "crates/sdk", - "crates/socket-server", + "crates/daemon-server", "crates/sortition", "crates/support-scripts", "crates/sync", @@ -100,7 +100,7 @@ e3-logger = { version = "0.1.15", path = "./crates/logger" } e3-net = { version = "0.1.15", path = "./crates/net" } e3-compute-provider = { version = "0.1.15", path = "./crates/compute-provider" } e3-sortition = { version = "0.1.15", path = "./crates/sortition" } -e3-socket-server = { version = "0.1.15", path = "./crates/socket-server" } +e3-daemon-server = { version = "0.1.15", path = "./crates/daemon-server" } e3-program-server = { version = "0.1.15", path = "./crates/program-server" } e3-polynomial = { version = "0.1.15", path = "./crates/polynomial" } e3-support-scripts = { version = "0.1.15", path = "./crates/support-scripts" } diff --git a/crates/Dockerfile b/crates/Dockerfile index f1aa47a435..ca289fe2aa 100644 --- a/crates/Dockerfile +++ b/crates/Dockerfile @@ -75,7 +75,7 @@ COPY crates/request/Cargo.toml ./request/Cargo.toml COPY crates/safe/Cargo.toml ./safe/Cargo.toml COPY crates/sdk/Cargo.toml ./sdk/Cargo.toml COPY crates/sortition/Cargo.toml ./sortition/Cargo.toml -COPY crates/socket-server/Cargo.toml ./socket-server/Cargo.toml +COPY crates/daemon-server/Cargo.toml ./daemon-server/Cargo.toml COPY crates/support-scripts/Cargo.toml ./support-scripts/Cargo.toml COPY crates/sync/Cargo.toml ./sync/Cargo.toml COPY crates/test-helpers/Cargo.toml ./test-helpers/Cargo.toml diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 1bb474e659..96c229d69b 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -32,7 +32,7 @@ e3-zk-helpers = { workspace = true } chrono = { workspace = true } e3-init = { workspace = true } e3-support-scripts = { workspace = true } -e3-socket-server = { workspace = true } +e3-daemon-server = { workspace = true } e3-utils = { workspace = true } e3-zk-prover = { workspace = true } hex = { workspace = true } diff --git a/crates/cli/src/start.rs b/crates/cli/src/start.rs index 090125da60..a20b120e6a 100644 --- a/crates/cli/src/start.rs +++ b/crates/cli/src/start.rs @@ -15,7 +15,7 @@ use e3_ciphernode_builder::CiphernodeHandle; use e3_config::{AppConfig, NodeRole}; use e3_console::Console; use e3_events::{prelude::*, Shutdown}; -use e3_socket_server::start_rest_server; +use e3_socket_server::start_daemon_server; use e3_utils::{colorize, Color}; use tokio::signal::unix::{signal, SignalKind}; use tracing::{error, info, instrument}; @@ -55,7 +55,7 @@ pub async fn execute(mut config: AppConfig, peers: Vec) -> Result<()> { /// Launch a socket server to read RemoteCli commands pub fn launch_socket_server(ctrl_port: u16) { // Setup socket server for daemon - tokio::task::spawn_local(start_rest_server(ctrl_port, |body| async move { + tokio::task::spawn_local(start_daemon_server(ctrl_port, |body| async move { let (out, mut rx) = Console::channel(); info!("CMD: {}", &colorize(&body, Color::Blue)); let remote_cli: RemoteCli = serde_json::from_str(&body)?; diff --git a/crates/socket-server/Cargo.toml b/crates/daemon-server/Cargo.toml similarity index 93% rename from crates/socket-server/Cargo.toml rename to crates/daemon-server/Cargo.toml index 333691ce7d..021cc3b8d7 100644 --- a/crates/socket-server/Cargo.toml +++ b/crates/daemon-server/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "e3-socket-server" +name = "e3-daemon-server" version.workspace = true edition.workspace = true license.workspace = true diff --git a/crates/socket-server/src/lib.rs b/crates/daemon-server/src/lib.rs similarity index 98% rename from crates/socket-server/src/lib.rs rename to crates/daemon-server/src/lib.rs index 22baded4c4..57e21274a0 100644 --- a/crates/socket-server/src/lib.rs +++ b/crates/daemon-server/src/lib.rs @@ -56,7 +56,7 @@ pub async fn run_on_daemon( Ok(()) } -pub async fn start_rest_server(tcp_port: u16, handler: F) +pub async fn start_daemon_server(tcp_port: u16, handler: F) where F: Fn(String) -> Fut + 'static, Fut: Future> + 'static, diff --git a/crates/entrypoint/Cargo.toml b/crates/entrypoint/Cargo.toml index a7e090a404..f819ca753c 100644 --- a/crates/entrypoint/Cargo.toml +++ b/crates/entrypoint/Cargo.toml @@ -23,7 +23,7 @@ dirs = { workspace = true } e3-events = { workspace = true } e3-evm = { workspace = true } e3-fhe = { workspace = true } -e3-socket-server = { workspace = true } +e3-daemon-server = { workspace = true } hex = { workspace = true } e3-keyshare = { workspace = true } e3-logger = { workspace = true } diff --git a/examples/CRISP/server/Dockerfile b/examples/CRISP/server/Dockerfile index e9c3ad2bd7..c8fd2bc4b3 100644 --- a/examples/CRISP/server/Dockerfile +++ b/examples/CRISP/server/Dockerfile @@ -85,7 +85,7 @@ COPY crates/program-server/Cargo.toml crates/program-server/Cargo.toml COPY crates/request/Cargo.toml crates/request/Cargo.toml COPY crates/sdk/Cargo.toml crates/sdk/Cargo.toml COPY crates/sortition/Cargo.toml crates/sortition/Cargo.toml -COPY crates/socket-server/Cargo.toml crates/socket-server/Cargo.toml +COPY crates/daemon-server/Cargo.toml crates/daemon-server/Cargo.toml COPY crates/support-scripts/Cargo.toml crates/support-scripts/Cargo.toml COPY crates/sync/Cargo.toml crates/sync/Cargo.toml COPY crates/test-helpers/Cargo.toml crates/test-helpers/Cargo.toml From 9ce00fa9644f0c779ccd07acce2fe738d7d47c68 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Mar 2026 04:37:57 +0000 Subject: [PATCH 24/43] add test call to write events to file --- tests/integration/base.sh | 3 +++ tests/integration/fns.sh | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/tests/integration/base.sh b/tests/integration/base.sh index 16b9c22548..b09c0cc43b 100755 --- a/tests/integration/base.sh +++ b/tests/integration/base.sh @@ -78,6 +78,9 @@ pnpm committee:new \ waiton "$SCRIPT_DIR/output/pubkey.bin" +heading "Query events via daemon REST API" +daemon_query_events ag "$SCRIPT_DIR/output/events.txt" + heading "Mock encrypted plaintext" $SCRIPT_DIR/lib/fake_encrypt.sh --input "$SCRIPT_DIR/output/pubkey.bin" --output "$SCRIPT_DIR/output/output.bin" --plaintext $PLAINTEXT --params "$ENCODED_PARAMS" diff --git a/tests/integration/fns.sh b/tests/integration/fns.sh index 2b24b9c1de..08d5599f41 100644 --- a/tests/integration/fns.sh +++ b/tests/integration/fns.sh @@ -200,6 +200,22 @@ gracefull_shutdown() { kill_em_all } +daemon_query_events() { + local node_name="${1:-ag}" + local output_file="${2:-$SCRIPT_DIR/output/events.txt}" + local ctrl_port + + ctrl_port=$($ENCLAVE_BIN config get --field "nodes.${node_name}.ctrl_port" --config "$SCRIPT_DIR/enclave.config.yaml") + + local json_payload='{"command":{"EventsQuery":{"since":0,"limit":100}}}' + + curl -sf -X POST "http://127.0.0.1:${ctrl_port}" \ + -H "Content-Type: application/json" \ + -d "$json_payload" > "$output_file" + + echo "Events written to: $output_file" +} + # Run this at the start of every test to ensure we start with a clean slate kill_em_all From 4d9e94df6c78141c35c8be15c04bd3e982128aeb Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Mar 2026 22:12:28 +0000 Subject: [PATCH 25/43] fix bad references --- crates/cli/src/main.rs | 2 +- crates/cli/src/start.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 628f378df7..727815679f 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -8,7 +8,7 @@ use anyhow::Result; use clap::Parser; use cli::{Cli, RemoteCli}; use e3_console::Console; -use e3_socket_server::{connect_daemon, run_on_daemon}; +use e3_daemon_server::{connect_daemon, run_on_daemon}; use e3_utils::{colorize, Color}; use tracing::info; diff --git a/crates/cli/src/start.rs b/crates/cli/src/start.rs index a20b120e6a..be5eadb9cb 100644 --- a/crates/cli/src/start.rs +++ b/crates/cli/src/start.rs @@ -14,8 +14,8 @@ use anyhow::Result; use e3_ciphernode_builder::CiphernodeHandle; use e3_config::{AppConfig, NodeRole}; use e3_console::Console; +use e3_daemon_server::start_daemon_server; use e3_events::{prelude::*, Shutdown}; -use e3_socket_server::start_daemon_server; use e3_utils::{colorize, Color}; use tokio::signal::unix::{signal, SignalKind}; use tracing::{error, info, instrument}; From 52d5fb1087df74cb498fc2793205f314b9382bf1 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Mar 2026 22:39:08 +0000 Subject: [PATCH 26/43] update dummy data --- crates/cli/src/events.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 9904b79d54..a30c58e2fa 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -680,11 +680,11 @@ async fn query_events_fake(aggregate: u64, since: u64, limit: u64) -> Result<()> es_poly_sum: vec![ArcBytes::from_bytes(&[0x55; 32])], signed_sk_decryption_proof: dummy_signed_proof_payload( E3id::new("test23", 1), - ProofType::C4DkgShareDecryption, + ProofType::C2aSkShareComputation, ), signed_e_sm_decryption_proofs: vec![dummy_signed_proof_payload( E3id::new("test23", 1), - ProofType::C4DkgShareDecryption, + ProofType::C2aSkShareComputation, )], external: false, }), From ca93be85760bac3663db9e4f9407345ca90f2b6a Mon Sep 17 00:00:00 2001 From: ryardley Date: Tue, 31 Mar 2026 13:29:42 +0000 Subject: [PATCH 27/43] fix test --- tests/integration/base.sh | 4 ++-- tests/integration/fns.sh | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/integration/base.sh b/tests/integration/base.sh index b09c0cc43b..053063249a 100755 --- a/tests/integration/base.sh +++ b/tests/integration/base.sh @@ -76,10 +76,10 @@ pnpm committee:new \ --e3-params "$ENCODED_PARAMS" \ --committee-size 0 -waiton "$SCRIPT_DIR/output/pubkey.bin" +waiton "$SCRIPT_DIR/output/pubkey.bin" 2000 heading "Query events via daemon REST API" -daemon_query_events ag "$SCRIPT_DIR/output/events.txt" +daemon_query_events 50506 "$SCRIPT_DIR/output/events.txt" heading "Mock encrypted plaintext" $SCRIPT_DIR/lib/fake_encrypt.sh --input "$SCRIPT_DIR/output/pubkey.bin" --output "$SCRIPT_DIR/output/output.bin" --plaintext $PLAINTEXT --params "$ENCODED_PARAMS" diff --git a/tests/integration/fns.sh b/tests/integration/fns.sh index 08d5599f41..f945a1e343 100644 --- a/tests/integration/fns.sh +++ b/tests/integration/fns.sh @@ -201,11 +201,9 @@ gracefull_shutdown() { } daemon_query_events() { - local node_name="${1:-ag}" + local ctrl_port="${1:50505}" local output_file="${2:-$SCRIPT_DIR/output/events.txt}" - local ctrl_port - ctrl_port=$($ENCLAVE_BIN config get --field "nodes.${node_name}.ctrl_port" --config "$SCRIPT_DIR/enclave.config.yaml") local json_payload='{"command":{"EventsQuery":{"since":0,"limit":100}}}' From 00e84d527dc5e35546b8b8af11799a80d279793b Mon Sep 17 00:00:00 2001 From: ryardley Date: Sat, 4 Apr 2026 03:32:16 +0000 Subject: [PATCH 28/43] add config command for cli config parsing --- crates/cli/src/cli.rs | 8 +++ crates/cli/src/config.rs | 111 +++++++++++++++++++++++++++++++++++++++ crates/cli/src/main.rs | 1 + 3 files changed, 120 insertions(+) create mode 100644 crates/cli/src/config.rs diff --git a/crates/cli/src/cli.rs b/crates/cli/src/cli.rs index 1f38416a43..93032ce8d0 100644 --- a/crates/cli/src/cli.rs +++ b/crates/cli/src/cli.rs @@ -5,6 +5,7 @@ // or FITNESS FOR A PARTICULAR PURPOSE. use crate::ciphernode::{self, ChainArgs, CiphernodeCommands}; +use crate::config::{self, ConfigCommands}; use crate::events::{self, EventsCommands}; use crate::helpers::telemetry::{setup_simple_tracing, setup_tracing}; use crate::net::{self, NetCommands}; @@ -184,6 +185,7 @@ impl Cli { Commands::Net { command } => net::execute(&out, command, &config).await?, Commands::Events { command } => events::execute(out, command, &config).await?, Commands::Rev => rev::execute(out).await?, + Commands::Config { command } => config::execute(out, command, &config).await?, } close_all_connections(); @@ -305,6 +307,12 @@ pub enum Commands { #[command(subcommand)] command: EventsCommands, }, + + /// Get config values + Config { + #[command(subcommand)] + command: ConfigCommands, + }, } #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/crates/cli/src/config.rs b/crates/cli/src/config.rs new file mode 100644 index 0000000000..fb23b13a16 --- /dev/null +++ b/crates/cli/src/config.rs @@ -0,0 +1,111 @@ +use anyhow::Result; +use clap::Subcommand; +use e3_config::AppConfig; +use e3_console::{log, Console}; + +#[derive(Subcommand, Clone, Debug)] +pub enum ConfigCommands { + /// Get a config parameter + Get { + /// The config parameter to get. If not provided, prints all config values + param: Option, + }, +} + +pub async fn execute(out: Console, command: ConfigCommands, config: &AppConfig) -> Result<()> { + let ConfigCommands::Get { param } = command; + match param.as_deref() { + Some("name") => { + log!(out, "{}", config.name()); + } + Some("peers") => { + for peer in config.peers() { + log!(out, "{}", peer); + } + } + Some("quic_port") => { + log!(out, "{}", config.quic_port()); + } + Some("ctrl_port") => { + log!(out, "{}", config.ctrl_port()); + } + Some("address") => { + if let Some(addr) = config.address() { + log!(out, "{}", addr); + } + } + Some("role") => { + log!(out, "{:?}", config.role()); + } + Some("autonetkey") => { + log!(out, "{}", config.autonetkey()); + } + Some("autopassword") => { + log!(out, "{}", config.autopassword()); + } + Some("autowallet") => { + log!(out, "{}", config.autowallet()); + } + Some("otel") => { + if let Some(otel) = config.otel() { + log!(out, "{}", otel); + } + } + Some("config_file") => { + log!(out, "{}", config.config_file().display()); + } + Some("config_yaml") => { + log!(out, "{}", config.config_yaml().display()); + } + Some("db_file") => { + log!(out, "{}", config.db_file().display()); + } + Some("key_file") => { + log!(out, "{}", config.key_file().display()); + } + Some("log_file") => { + log!(out, "{}", config.log_file().display()); + } + Some("work_dir") => { + log!(out, "{}", config.work_dir().display()); + } + Some("chains") => { + for chain in config.chains() { + log!(out, "{}", chain.name); + } + } + Some("nodes") => { + for (name, node_def) in config.nodes() { + log!(out, "{}: {:?}", name, node_def); + } + } + Some("program") => { + log!(out, "{:?}", config.program()); + } + Some(param) => { + anyhow::bail!("Unknown config parameter: {}", param); + } + None => { + log!(out, "name: {}", config.name()); + log!(out, "peers: {:?}", config.peers()); + log!(out, "quic_port: {}", config.quic_port()); + log!(out, "ctrl_port: {}", config.ctrl_port()); + log!(out, "address: {:?}", config.address()); + log!(out, "role: {:?}", config.role()); + log!(out, "autonetkey: {}", config.autonetkey()); + log!(out, "autopassword: {}", config.autopassword()); + log!(out, "autowallet: {}", config.autowallet()); + log!(out, "otel: {:?}", config.otel()); + log!(out, "config_file: {}", config.config_file().display()); + log!(out, "config_yaml: {}", config.config_yaml().display()); + log!(out, "db_file: {}", config.db_file().display()); + log!(out, "key_file: {}", config.key_file().display()); + log!(out, "log_file: {}", config.log_file().display()); + log!(out, "work_dir: {}", config.work_dir().display()); + log!(out, "chains: {:?}", config.chains()); + log!(out, "nodes: {:?}", config.nodes()); + log!(out, "program: {:?}", config.program()); + } + } + Ok(()) +} diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 727815679f..1b0d8c6801 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -14,6 +14,7 @@ use tracing::info; mod ciphernode; mod cli; +mod config; mod events; pub mod helpers; mod init; From 1794eb1744ef3208204aa323a86d6b00449b6c90 Mon Sep 17 00:00:00 2001 From: ryardley Date: Sat, 4 Apr 2026 03:33:32 +0000 Subject: [PATCH 29/43] add header --- crates/cli/src/config.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/cli/src/config.rs b/crates/cli/src/config.rs index fb23b13a16..1d50989a20 100644 --- a/crates/cli/src/config.rs +++ b/crates/cli/src/config.rs @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use anyhow::Result; use clap::Subcommand; use e3_config::AppConfig; From 64e463eb3655665236d63afd085c3bfa5d4654b7 Mon Sep 17 00:00:00 2001 From: ryardley Date: Sat, 4 Apr 2026 03:44:07 +0000 Subject: [PATCH 30/43] query events from ag --- crates/cli/src/cli.rs | 9 +++++++++ tests/integration/base.sh | 2 +- tests/integration/fns.sh | 7 +++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/crates/cli/src/cli.rs b/crates/cli/src/cli.rs index 93032ce8d0..69726bb29a 100644 --- a/crates/cli/src/cli.rs +++ b/crates/cli/src/cli.rs @@ -343,6 +343,9 @@ pub enum RemoteCommand { vite: bool, chain: String, }, + ConfigGet { + param: Option, + }, } impl TryFrom for RemoteCommand { @@ -367,6 +370,9 @@ impl TryFrom for RemoteCommand { Commands::Wallet { command: WalletCommands::Get, } => Ok(RemoteCommand::WalletGet), + Commands::Config { + command: ConfigCommands::Get { param }, + } => Ok(RemoteCommand::ConfigGet { param }), _ => bail!("Command not allowed while node is running."), } } @@ -421,6 +427,9 @@ impl TryFrom for Commands { RemoteCommand::EventsQuery { agg, since, limit } => Commands::Events { command: EventsCommands::Query { agg, since, limit }, }, + RemoteCommand::ConfigGet { param } => Commands::Config { + command: ConfigCommands::Get { param }, + }, }; // We might have to hold this stuff on RemoteCommand Ok(command) diff --git a/tests/integration/base.sh b/tests/integration/base.sh index 053063249a..ff6b265168 100755 --- a/tests/integration/base.sh +++ b/tests/integration/base.sh @@ -79,7 +79,7 @@ pnpm committee:new \ waiton "$SCRIPT_DIR/output/pubkey.bin" 2000 heading "Query events via daemon REST API" -daemon_query_events 50506 "$SCRIPT_DIR/output/events.txt" +daemon_query_events ag "$SCRIPT_DIR/output/events.txt" heading "Mock encrypted plaintext" $SCRIPT_DIR/lib/fake_encrypt.sh --input "$SCRIPT_DIR/output/pubkey.bin" --output "$SCRIPT_DIR/output/output.bin" --plaintext $PLAINTEXT --params "$ENCODED_PARAMS" diff --git a/tests/integration/fns.sh b/tests/integration/fns.sh index f945a1e343..f98b9e9dd5 100644 --- a/tests/integration/fns.sh +++ b/tests/integration/fns.sh @@ -201,9 +201,12 @@ gracefull_shutdown() { } daemon_query_events() { - local ctrl_port="${1:50505}" + local name="$1" local output_file="${2:-$SCRIPT_DIR/output/events.txt}" + local ctrl_port=$($ENCLAVE_BIN config get ctrl_port \ + --name $name \ + --config "$SCRIPT_DIR/enclave.config.yaml") local json_payload='{"command":{"EventsQuery":{"since":0,"limit":100}}}' @@ -211,7 +214,7 @@ daemon_query_events() { -H "Content-Type: application/json" \ -d "$json_payload" > "$output_file" - echo "Events written to: $output_file" + echo "Events from $name written to: $output_file" } # Run this at the start of every test to ensure we start with a clean slate From f7b36f0a5683c9f6d25396cd6e3262d5a1de6de2 Mon Sep 17 00:00:00 2001 From: ryardley Date: Sat, 4 Apr 2026 03:46:56 +0000 Subject: [PATCH 31/43] tidy up output --- tests/integration/fns.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/integration/fns.sh b/tests/integration/fns.sh index f98b9e9dd5..b9e091c2f6 100644 --- a/tests/integration/fns.sh +++ b/tests/integration/fns.sh @@ -214,7 +214,9 @@ daemon_query_events() { -H "Content-Type: application/json" \ -d "$json_payload" > "$output_file" - echo "Events from $name written to: $output_file" + echo "Events from $name written:" + cat $output_file + echo "End" } # Run this at the start of every test to ensure we start with a clean slate From fab46848c5906efe88256b8e1ffd2be8eb94dd0d Mon Sep 17 00:00:00 2001 From: ryardley Date: Sat, 4 Apr 2026 03:55:23 +0000 Subject: [PATCH 32/43] remove fake events --- crates/cli/src/config.rs | 4 - crates/cli/src/events.rs | 1239 +------------------------------------- 2 files changed, 4 insertions(+), 1239 deletions(-) diff --git a/crates/cli/src/config.rs b/crates/cli/src/config.rs index 1d50989a20..23579bd1de 100644 --- a/crates/cli/src/config.rs +++ b/crates/cli/src/config.rs @@ -40,9 +40,6 @@ pub async fn execute(out: Console, command: ConfigCommands, config: &AppConfig) log!(out, "{}", addr); } } - Some("role") => { - log!(out, "{:?}", config.role()); - } Some("autonetkey") => { log!(out, "{}", config.autonetkey()); } @@ -97,7 +94,6 @@ pub async fn execute(out: Console, command: ConfigCommands, config: &AppConfig) log!(out, "quic_port: {}", config.quic_port()); log!(out, "ctrl_port: {}", config.ctrl_port()); log!(out, "address: {:?}", config.address()); - log!(out, "role: {:?}", config.role()); log!(out, "autonetkey: {}", config.autonetkey()); log!(out, "autopassword: {}", config.autopassword()); log!(out, "autowallet: {}", config.autowallet()); diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index a30c58e2fa..6493f4cdb8 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -4,188 +4,18 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use alloy::primitives::{Address, FixedBytes, I256, U256}; use anyhow::Result; -use chrono::Utc; use clap::Subcommand; use e3_ciphernode_builder::global_eventstore_cache::EventStoreReader; use e3_config::AppConfig; use e3_console::{log, Console}; -use e3_crypto::SensitiveBytes; use e3_entrypoint::helpers::datastore::get_eventstore_reader; -use e3_events::{ - AccusationOutcome, AccusationQuorumReached, AccusationVote, AggregationProofPending, - AggregationProofSigned, CiphernodeAdded, CiphernodeRemoved, CiphernodeSelected, - CiphertextOutputPublished, CircuitName, CommitteeFinalizeRequested, CommitteeFinalized, - CommitteeMemberExpelled, CommitteePublished, CommitteeRequested, ComputeResponse, - ComputeResponseKind, ConfigurationUpdated, CorrelationId, DKGInnerProofReady, - DKGRecursiveAggregationComplete, DecryptedSharesAggregationProofRequest, DecryptionKeyShared, - DecryptionShareProofSigned, DecryptionShareProofsPending, DecryptionshareCreated, - DkgProofSigned, DkgShareDecryptionProofRequest, DocumentKind, DocumentMeta, DocumentReceived, - E3Failed, E3RequestComplete, E3Requested, E3Stage, E3StageChanged, E3id, EType, EffectsEnabled, - EnclaveError, EnclaveEvent, EnclaveEventData, EncryptionKey, EncryptionKeyCollectionFailed, - EncryptionKeyCreated, EncryptionKeyPending, EncryptionKeyReceived, - EventConstructorWithTimestamp, EventStoreQueryResponse, EvmEventConfig, EvmEventConfigChain, - FailureReason, HistoricalEvmSyncStart, HistoricalNetSyncEventsReceived, HistoricalNetSyncStart, - KeyshareCreated, NetReady, OperatorActivationChanged, OutgoingSyncRequested, - PartyProofsToVerify, PkAggregationProofPending, PkAggregationProofRequest, - PkAggregationProofSigned, PkBfvProofResponse, PkGenerationProofRequest, - PkGenerationProofSigned, PlaintextAggregated, PlaintextOutputPublished, Proof, - ProofFailureAccusation, ProofPayload, ProofType, ProofVerificationFailed, - ProofVerificationPassed, PublicKeyAggregated, PublishDocumentRequested, Seed, - ShareComputationProofRequest, ShareDecryptionProofPending, ShareEncryptionProofRequest, - ShareVerificationComplete, ShareVerificationDispatched, Shutdown, SignedProofFailed, - SignedProofPayload, SlashExecuted, SyncEffect, SyncEnded, TestEvent, ThresholdShare, - ThresholdShareCollectionFailed, ThresholdShareCreated, ThresholdShareDecryptionProofRequest, - ThresholdSharePending, TicketBalanceUpdated, TicketGenerated, TicketId, TicketSubmitted, - Unsequenced, VerificationKind, ZkResponse, -}; +use e3_events::CorrelationId; +use e3_events::EnclaveEvent; +use e3_events::EventStoreQueryResponse; use e3_events::{AggregateId, EventStoreQueryBy, SeqAgg}; -use e3_fhe_params::BfvPreset; -use e3_trbfv::shares::BfvEncryptedShares; use e3_utils::actix::channel as actix_toolbox; -use e3_utils::ArcBytes; -use e3_zk_helpers::{computation::DkgInputType, CiphernodesCommitteeSize}; -use std::collections::BTreeSet; -use std::collections::{BTreeMap, HashMap}; -use std::sync::Arc; - -fn dummy_proof(circuit: CircuitName) -> Proof { - Proof::new( - circuit, - ArcBytes::from_bytes(&[ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, - ]), - ArcBytes::from_bytes(&[ - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, - 0x1f, 0x20, - ]), - ) -} - -fn dummy_signed_proof_payload(e3_id: E3id, proof_type: ProofType) -> SignedProofPayload { - SignedProofPayload { - payload: ProofPayload { - e3_id, - proof_type, - proof: dummy_proof(CircuitName::PkBfv), - }, - signature: ArcBytes::from_bytes(&[ - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, - 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, - 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - ]), - } -} - -fn dummy_accusation_vote(e3_id: E3id, voter: Address, agrees: bool) -> AccusationVote { - AccusationVote { - e3_id, - accusation_id: [0xaa; 32], - voter, - agrees, - data_hash: [0xbb; 32], - signature: ArcBytes::from_bytes(&[0xcc; 64]), - } -} - -fn dummy_sensitive_bytes(data: &[u8]) -> SensitiveBytes { - SensitiveBytes::from_encrypted(data) -} - -fn dummy_threshold_share() -> ThresholdShare { - ThresholdShare { - party_id: 1, - pk_share: ArcBytes::from_bytes(&[0x11; 32]), - sk_sss: BfvEncryptedShares::default(), - esi_sss: vec![BfvEncryptedShares::default()], - } -} - -fn dummy_pk_generation_proof_request() -> PkGenerationProofRequest { - PkGenerationProofRequest::new( - ArcBytes::from_bytes(&[0x22; 32]), - dummy_sensitive_bytes(&[0x33; 32]), - dummy_sensitive_bytes(&[0x44; 32]), - dummy_sensitive_bytes(&[0x55; 32]), - BfvPreset::InsecureThreshold512, - CiphernodesCommitteeSize::Small, - ) -} - -fn dummy_share_computation_proof_request() -> ShareComputationProofRequest { - ShareComputationProofRequest { - secret_raw: dummy_sensitive_bytes(&[0x66; 32]), - secret_sss_raw: dummy_sensitive_bytes(&[0x77; 32]), - dkg_input_type: DkgInputType::SecretKey, - params_preset: BfvPreset::InsecureThreshold512, - committee_size: CiphernodesCommitteeSize::Small, - } -} - -fn dummy_share_encryption_proof_request() -> ShareEncryptionProofRequest { - ShareEncryptionProofRequest { - share_row_raw: dummy_sensitive_bytes(&[0x88; 32]), - ciphertext_raw: ArcBytes::from_bytes(&[0x99; 64]), - recipient_pk_raw: ArcBytes::from_bytes(&[0xaa; 32]), - u_rns_raw: dummy_sensitive_bytes(&[0xbb; 32]), - e0_rns_raw: dummy_sensitive_bytes(&[0xcc; 32]), - e1_rns_raw: dummy_sensitive_bytes(&[0xdd; 32]), - dkg_input_type: DkgInputType::SecretKey, - params_preset: BfvPreset::InsecureThreshold512, - committee_size: CiphernodesCommitteeSize::Small, - recipient_party_id: 2, - row_index: 0, - esi_index: 0, - } -} - -fn dummy_dkg_share_decryption_proof_request() -> DkgShareDecryptionProofRequest { - DkgShareDecryptionProofRequest { - sk_bfv: dummy_sensitive_bytes(&[0xee; 32]), - honest_ciphertexts_raw: vec![ArcBytes::from_bytes(&[0xff; 64])], - num_honest_parties: 3, - num_moduli: 2, - dkg_input_type: DkgInputType::SecretKey, - params_preset: BfvPreset::InsecureThreshold512, - } -} - -fn dummy_threshold_share_decryption_proof_request() -> ThresholdShareDecryptionProofRequest { - ThresholdShareDecryptionProofRequest { - ciphertext_bytes: vec![ArcBytes::from_bytes(&[0x11; 64])], - aggregated_pk_bytes: ArcBytes::from_bytes(&[0x22; 32]), - sk_poly_sum: dummy_sensitive_bytes(&[0x33; 64]), - es_poly_sum: vec![dummy_sensitive_bytes(&[0x44; 64])], - d_share_bytes: vec![ArcBytes::from_bytes(&[0x55; 32])], - params_preset: BfvPreset::InsecureThreshold512, - proof_aggregation_enabled: true, - } -} - -fn dummy_pk_aggregation_proof_request() -> PkAggregationProofRequest { - PkAggregationProofRequest { - keyshare_bytes: vec![ArcBytes::from_bytes(&[0x66; 32])], - aggregated_pk_bytes: ArcBytes::from_bytes(&[0x77; 32]), - params_preset: BfvPreset::InsecureThreshold512, - committee_n: 5, - committee_h: 3, - committee_threshold: 3, - } -} - -fn dummy_decrypted_shares_aggregation_proof_request() -> DecryptedSharesAggregationProofRequest { - DecryptedSharesAggregationProofRequest { - d_share_polys: vec![(1, vec![ArcBytes::from_bytes(&[0x88; 64])])], - plaintext: vec![ArcBytes::from_bytes(&[0x99; 32])], - params_preset: BfvPreset::InsecureThreshold512, - threshold_m: 3, - threshold_n: 5, - } -} +use std::collections::HashMap; #[derive(Subcommand, Clone, Debug)] pub enum EventsCommands { @@ -258,1064 +88,3 @@ fn print_events(out: Console, events: Vec) -> Result<()> { } Ok(()) } - -/// This just prints fake events to ensure serialization works -async fn query_events_fake(aggregate: u64, since: u64, limit: u64) -> Result<()> { - tracing::info!( - "Querying events: aggregate={}, since={}, limit={}", - aggregate, - since, - limit - ); - - let event1 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::PublicKeyAggregated(PublicKeyAggregated { - pubkey: ArcBytes::from_bytes(&[ - 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, - 0x77, 0x88, - ]), - e3_id: E3id::new("test1", 1), - nodes: vec![ - "0x1234567890123456789012345678901234567890".to_string(), - "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd".to_string(), - ] - .into(), - pk_aggregation_proof: Some(dummy_proof(CircuitName::PkAggregation)), - dkg_aggregated_proof: Some(dummy_proof(CircuitName::Fold)), - }), - None, - 1700000000000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(1); - - let event2 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::EncryptionKeyCreated(EncryptionKeyCreated { - e3_id: E3id::new("test2", 1), - key: Arc::new(EncryptionKey::new( - 42, - ArcBytes::from_bytes(&[ - 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0x0a, 0xbc, 0xde, 0xf1, 0x23, - 0x45, 0x67, 0x89, - ]), - )), - external: false, - }), - None, - 1700000001000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(2); - - let event3 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::E3Requested(E3Requested { - e3_id: E3id::new("test3", 1), - threshold_m: 3, - threshold_n: 5, - seed: Seed([ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, - 0x1d, 0x1e, 0x1f, 0x20, - ]), - error_size: ArcBytes::from_bytes(&[ - 0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE, 0xDE, 0xAD, 0xC0, 0xDE, - ]), - esi_per_ct: 2, - params: ArcBytes::from_bytes(&[ - 0xBE, 0xEF, 0xFA, 0xCE, 0xDE, 0xAD, 0xFE, 0xED, 0xFE, 0xED, 0xCA, 0xFE, - ]), - proof_aggregation_enabled: true, - }), - None, - 1700000002000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(3); - - let event4 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::KeyshareCreated(KeyshareCreated { - pubkey: ArcBytes::from_bytes(&[ - 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, - 0xff, 0x00, - ]), - e3_id: E3id::new("test4", 1), - node: "0xabcd1234abcd1234abcd1234abcd1234abcd1234".to_string(), - signed_pk_generation_proof: Some(dummy_signed_proof_payload( - E3id::new("test4", 1), - ProofType::C1PkGeneration, - )), - }), - None, - 1700000003000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(4); - - let event5 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::CiphertextOutputPublished(CiphertextOutputPublished { - e3_id: E3id::new("test5", 1), - ciphertext_output: vec![ - ArcBytes::from_bytes(&[ - 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, - ]), - ArcBytes::from_bytes(&[ - 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, - ]), - ], - }), - None, - 1700000004000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(5); - - let event6 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::DecryptionshareCreated(DecryptionshareCreated { - party_id: 2, - decryption_share: vec![ArcBytes::from_bytes(&[ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, - ])], - e3_id: E3id::new("test6", 1), - node: "0xfedc9876543210fedc9876543210fedc9876543210".to_string(), - signed_decryption_proofs: vec![dummy_signed_proof_payload( - E3id::new("test6", 1), - ProofType::C6ThresholdShareDecryption, - )], - wrapped_proofs: vec![dummy_proof(CircuitName::ThresholdShareDecryption)], - }), - None, - 1700000005000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(6); - - let event7 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::PlaintextAggregated(PlaintextAggregated { - e3_id: E3id::new("test7", 1), - decrypted_output: vec![ArcBytes::from_bytes(&[ - 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, - ])], - aggregation_proofs: vec![dummy_proof(CircuitName::DecryptedSharesAggregation)], - c6_aggregated_proof: Some(dummy_proof(CircuitName::ThresholdShareDecryption)), - }), - None, - 1700000006000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(7); - - let event8 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::EnclaveError(EnclaveError { - err_type: EType::Computation, - message: "Computation failed: overflow detected in batch processing".to_string(), - }), - None, - 1700000007000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(8); - - let event9 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::TestEvent(TestEvent { - msg: "Test message from CLI with full data".to_string(), - entropy: 42, - e3_id: Some(E3id::new("test9", 1)), - }), - None, - 1700000008000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(9); - - let event10 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ConfigurationUpdated(ConfigurationUpdated { - parameter: "max_committee_size".to_string(), - old_value: alloy::primitives::U256::from(10), - new_value: alloy::primitives::U256::from(20), - chain_id: 1, - }), - None, - 1700000009000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(10); - - let accuser: Address = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - .parse() - .unwrap(); - let accused: Address = "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - .parse() - .unwrap(); - - let event11 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::AccusationQuorumReached(AccusationQuorumReached { - e3_id: E3id::new("test11", 1), - accuser, - accused, - proof_type: ProofType::C6ThresholdShareDecryption, - votes_for: vec![ - dummy_accusation_vote(E3id::new("test11", 1), accuser, true), - dummy_accusation_vote( - E3id::new("test11", 1), - "0xcccccccccccccccccccccccccccccccccccccccc" - .parse() - .unwrap(), - true, - ), - ], - votes_against: vec![], - outcome: AccusationOutcome::AccusedFaulted, - }), - None, - 1700000010000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(11); - - let event12 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::CiphernodeSelected(CiphernodeSelected { - e3_id: E3id::new("test12", 1), - threshold_m: 3, - threshold_n: 5, - seed: Seed([0x21; 32]), - error_size: ArcBytes::from_bytes(&[0xFE; 16]), - esi_per_ct: 4, - params: ArcBytes::from_bytes(&[0xCA; 32]), - party_id: 2, - }), - None, - 1700000011000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(12); - - let event13 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::CommitteePublished(CommitteePublished { - e3_id: E3id::new("test13", 1), - nodes: vec![ - "0x1111111111111111111111111111111111111111".to_string(), - "0x2222222222222222222222222222222222222222".to_string(), - "0x3333333333333333333333333333333333333333".to_string(), - ], - public_key: ArcBytes::from_bytes(&[0xAB; 64]), - proof: ArcBytes::from_bytes(&[0xAB; 64]), - }), - None, - 1700000012000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(13); - - let event14 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::TicketGenerated(TicketGenerated { - e3_id: E3id::new("test14", 1), - ticket_id: TicketId::Score(42), - node: "0x4444444444444444444444444444444444444444".to_string(), - }), - None, - 1700000013000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(14); - - let event15 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::TicketBalanceUpdated(TicketBalanceUpdated { - operator: "0x5555555555555555555555555555555555555555".to_string(), - delta: I256::MIN, - new_balance: U256::from(900), - reason: FixedBytes::from([0x66; 32]), - chain_id: 1, - }), - None, - 1700000014000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(15); - - let event16 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::E3Failed(E3Failed { - e3_id: E3id::new("test16", 1), - failed_at_stage: E3Stage::Failed, - reason: FailureReason::ComputeTimeout, - }), - None, - 1700000015000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(16); - - let event17 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::CiphernodeAdded(CiphernodeAdded { - address: "0x7777777777777777777777777777777777777777".to_string(), - index: 5, - num_nodes: 10, - chain_id: 1, - }), - None, - 1700000016000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(17); - - let accused_addr: Address = "0x8888888888888888888888888888888888888888" - .parse() - .unwrap(); - - let event18 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ProofVerificationFailed(ProofVerificationFailed { - e3_id: E3id::new("test18", 1), - accused_party_id: 3, - accused_address: accused_addr, - proof_type: ProofType::C1PkGeneration, - data_hash: [0x99; 32], - signed_payload: dummy_signed_proof_payload( - E3id::new("test18", 1), - ProofType::C1PkGeneration, - ), - }), - None, - 1700000017000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(18); - - let event19 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::EnclaveError(EnclaveError { - err_type: EType::KeyGeneration, - message: "DKG timeout: insufficient shares received from peers".to_string(), - }), - None, - 1700000018000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(19); - - let event20 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::AccusationVote(AccusationVote { - e3_id: E3id::new("test20", 1), - accusation_id: [0xaa; 32], - voter: "0x9999999999999999999999999999999999999999" - .parse() - .unwrap(), - agrees: true, - data_hash: [0xbb; 32], - signature: ArcBytes::from_bytes(&[0xcc; 64]), - }), - None, - 1700000019000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(20); - - // Missing event types start here (event21 onwards) - let event21 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ProofFailureAccusation(ProofFailureAccusation { - e3_id: E3id::new("test21", 1), - accuser: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - .parse() - .unwrap(), - accused: "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - .parse() - .unwrap(), - accused_party_id: 2, - proof_type: ProofType::C3aSkShareEncryption, - data_hash: [0xdd; 32], - signed_payload: Some(dummy_signed_proof_payload( - E3id::new("test21", 1), - ProofType::C3aSkShareEncryption, - )), - signature: ArcBytes::from_bytes(&[0xee; 64]), - }), - None, - 1700000020000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(21); - - let event22 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ProofVerificationPassed(ProofVerificationPassed { - e3_id: E3id::new("test22", 1), - party_id: 1, - address: "0x1111111111111111111111111111111111111111" - .parse() - .unwrap(), - proof_type: ProofType::C1PkGeneration, - data_hash: [0x22; 32], - public_signals: ArcBytes::from_bytes(&[0xaa; 64]), - }), - None, - 1700000021000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(22); - - let event23 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::DecryptionKeyShared(DecryptionKeyShared { - e3_id: E3id::new("test23", 1), - party_id: 1, - node: "0x3333333333333333333333333333333333333333".to_string(), - sk_poly_sum: ArcBytes::from_bytes(&[0x44; 32]), - es_poly_sum: vec![ArcBytes::from_bytes(&[0x55; 32])], - signed_sk_decryption_proof: dummy_signed_proof_payload( - E3id::new("test23", 1), - ProofType::C2aSkShareComputation, - ), - signed_e_sm_decryption_proofs: vec![dummy_signed_proof_payload( - E3id::new("test23", 1), - ProofType::C2aSkShareComputation, - )], - external: false, - }), - None, - 1700000022000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(23); - - let event24 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::PublishDocumentRequested(PublishDocumentRequested { - meta: DocumentMeta::new( - E3id::new("test24", 1), - DocumentKind::TrBFV, - vec![], - Some(Utc::now()), - ), - value: ArcBytes::from_bytes(&[0x66; 64]), - }), - None, - 1700000023000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(24); - - let event25 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::PkGenerationProofSigned(PkGenerationProofSigned { - e3_id: E3id::new("test25", 1), - party_id: 1, - signed_proof: dummy_signed_proof_payload( - E3id::new("test25", 1), - ProofType::C1PkGeneration, - ), - }), - None, - 1700000024000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(25); - - let event26 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::DkgProofSigned(DkgProofSigned { - e3_id: E3id::new("test26", 1), - party_id: 1, - signed_proof: dummy_signed_proof_payload( - E3id::new("test26", 1), - ProofType::C2aSkShareComputation, - ), - }), - None, - 1700000025000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(26); - - let event27 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::E3RequestComplete(E3RequestComplete { - e3_id: E3id::new("test27", 1), - }), - None, - 1700000026000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(27); - - let event28 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::E3StageChanged(E3StageChanged { - e3_id: E3id::new("test28", 1), - previous_stage: E3Stage::CiphertextReady, - new_stage: E3Stage::Complete, - }), - None, - 1700000027000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(28); - - let event29 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::CiphernodeRemoved(CiphernodeRemoved { - address: "0x9999999999999999999999999999999999999999".to_string(), - index: 3, - num_nodes: 9, - chain_id: 1, - }), - None, - 1700000028000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(29); - - let event30 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::OperatorActivationChanged(OperatorActivationChanged { - operator: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string(), - active: true, - chain_id: 1, - }), - None, - 1700000029000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(30); - - let event31 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::CommitteeRequested(CommitteeRequested { - e3_id: E3id::new("test31", 1), - seed: Seed([0xaa; 32]), - threshold: [3, 5], - request_block: 100, - committee_deadline: 200, - chain_id: 1, - }), - None, - 1700000030000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(31); - - let event32 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::CommitteeFinalizeRequested(CommitteeFinalizeRequested { - e3_id: E3id::new("test32", 1), - }), - None, - 1700000031000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(32); - - let event33 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::CommitteeFinalized(CommitteeFinalized { - e3_id: E3id::new("test33", 1), - committee: vec![ - "0x1111111111111111111111111111111111111111".to_string(), - "0x2222222222222222222222222222222222222222".to_string(), - ], - chain_id: 1, - scores: Vec::new(), - }), - None, - 1700000032000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(33); - - let event34 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::TicketSubmitted(TicketSubmitted { - e3_id: E3id::new("test34", 1), - node: "0x4444444444444444444444444444444444444444".to_string(), - ticket_id: 123, - score: "0.95".to_string(), - chain_id: 1, - }), - None, - 1700000033000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(34); - - let event35 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::PlaintextOutputPublished(PlaintextOutputPublished { - e3_id: E3id::new("test35", 1), - plaintext_output: ArcBytes::from_bytes(&[0x55; 32]), - proof: ArcBytes::from_bytes(&[0x66; 64]), - }), - None, - 1700000034000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(35); - - let event36 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::Shutdown(Shutdown), - None, - 1700000035000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(36); - - let event37 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::DocumentReceived(DocumentReceived { - meta: DocumentMeta::new( - E3id::new("test37", 1), - DocumentKind::TrBFV, - vec![], - Some(Utc::now()), - ), - value: ArcBytes::from_bytes(&[0x66; 64]), - }), - None, - 1700000036000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(37); - - let event38 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::EncryptionKeyPending(EncryptionKeyPending { - e3_id: E3id::new("test40", 1), - key: Arc::new(EncryptionKey::new(42, ArcBytes::from_bytes(&[0x33; 16]))), - params_preset: e3_fhe_params::BfvPreset::InsecureThreshold512, - }), - None, - 1700000039000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(38); - - let event39 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::EncryptionKeyReceived(EncryptionKeyReceived { - e3_id: E3id::new("test41", 1), - key: Arc::new(EncryptionKey::new(42, ArcBytes::from_bytes(&[0x44; 16]))), - }), - None, - 1700000040000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(39); - - let event40 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::EncryptionKeyCollectionFailed(EncryptionKeyCollectionFailed { - e3_id: E3id::new("test42", 1), - reason: "Timeout waiting for encryption keys".to_string(), - missing_parties: vec![2, 4], - }), - None, - 1700000041000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(40); - - let event41 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ThresholdShareCollectionFailed(ThresholdShareCollectionFailed { - e3_id: E3id::new("test43", 1), - reason: "Insufficient shares received".to_string(), - missing_parties: vec![3, 5], - }), - None, - 1700000042000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(41); - - let event42 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::SignedProofFailed(SignedProofFailed { - e3_id: E3id::new("test47", 1), - faulting_node: "0x7777777777777777777777777777777777777777" - .parse() - .unwrap(), - proof_type: ProofType::C1PkGeneration, - signed_payload: dummy_signed_proof_payload( - E3id::new("test47", 1), - ProofType::C1PkGeneration, - ), - }), - None, - 1700000046000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(42); - - let event43 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::SlashExecuted(SlashExecuted { - e3_id: E3id::new("test51", 1), - proposal_id: 12345, - operator: "0x9999999999999999999999999999999999999999" - .parse() - .unwrap(), - reason: [0xaa; 32], - ticket_amount: 1000, - license_amount: 500, - }), - None, - 1700000050000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(43); - - let event44 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::CommitteeMemberExpelled(CommitteeMemberExpelled { - e3_id: E3id::new("test52", 1), - node: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - .parse() - .unwrap(), - reason: [0xbb; 32], - active_count_after: 9, - party_id: Some(2), - }), - None, - 1700000051000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(44); - - let event45 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::OutgoingSyncRequested(OutgoingSyncRequested { - since: vec![(AggregateId::new(0), 1700000000000_u128)], - }), - None, - 1700000052000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(45); - - let event46 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::HistoricalEvmSyncStart(HistoricalEvmSyncStart { - evm_config: EvmEventConfig::from_config( - [(1, EvmEventConfigChain::new(100))] - .into_iter() - .collect::>(), - ), - sender: None, - }), - None, - 1700000053000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(46); - - let event47 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::HistoricalNetSyncStart(HistoricalNetSyncStart { - since: BTreeMap::from([(AggregateId::new(0), 1700000000000_u128)]), - }), - None, - 1700000054000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(47); - - let event48 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::HistoricalNetSyncEventsReceived(HistoricalNetSyncEventsReceived { - events: vec![], - }), - None, - 1700000055000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(48); - - let event49 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::SyncEffect(SyncEffect::new()), - None, - 1700000056000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(49); - - let event50 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::SyncEnded(SyncEnded::new()), - None, - 1700000057000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(50); - - let event51 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::EffectsEnabled(EffectsEnabled::new()), - None, - 1700000058000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(51); - - let event52 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::NetReady(NetReady::new()), - None, - 1700000059000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(52); - - let event53 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::DecryptionShareProofSigned(DecryptionShareProofSigned { - e3_id: E3id::new("test61", 1), - }), - None, - 1700000060000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(53); - - let event54 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::AggregationProofSigned(AggregationProofSigned { - e3_id: E3id::new("test66", 1), - signed_proofs: vec![dummy_signed_proof_payload( - E3id::new("test66", 1), - ProofType::C7DecryptedSharesAggregation, - )], - }), - None, - 1700000065000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(54); - - let event55 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::DKGInnerProofReady(DKGInnerProofReady { - e3_id: E3id::new("test67", 1), - party_id: 1, - wrapped_proof: dummy_proof(CircuitName::Fold), - seq: 0, - }), - None, - 1700000066000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(55); - - let event56 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::DKGRecursiveAggregationComplete(DKGRecursiveAggregationComplete { - e3_id: E3id::new("test68", 1), - party_id: 1, - aggregated_proof: Some(dummy_proof(CircuitName::Fold)), - }), - None, - 1700000067000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(56); - - let event57 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ThresholdSharePending(ThresholdSharePending { - e3_id: E3id::new("test57", 1), - full_share: Arc::new(dummy_threshold_share()), - proof_request: dummy_pk_generation_proof_request(), - sk_share_computation_request: dummy_share_computation_proof_request(), - e_sm_share_computation_request: dummy_share_computation_proof_request(), - sk_share_encryption_requests: vec![dummy_share_encryption_proof_request()], - e_sm_share_encryption_requests: vec![dummy_share_encryption_proof_request()], - recipient_party_ids: vec![1, 2, 3, 4, 5], - proof_aggregation_enabled: true, - }), - None, - 1700000070000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(57); - - let event58 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ThresholdShareCreated(ThresholdShareCreated { - e3_id: E3id::new("test58", 1), - share: Arc::new(dummy_threshold_share()), - target_party_id: 1, - external: false, - signed_c2a_proof: Some(dummy_signed_proof_payload( - E3id::new("test58", 1), - ProofType::C2aSkShareComputation, - )), - signed_c2b_proof: None, - signed_c3a_proofs: vec![], - signed_c3b_proofs: vec![], - }), - None, - 1700000071000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(58); - - let event59 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ShareDecryptionProofPending(ShareDecryptionProofPending { - e3_id: E3id::new("test59", 1), - party_id: 1, - node: "0x1111111111111111111111111111111111111111".to_string(), - decryption_share: vec![ArcBytes::from_bytes(&[0x11; 64])], - proof_request: dummy_threshold_share_decryption_proof_request(), - }), - None, - 1700000072000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(59); - - let event60 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::DecryptionShareProofsPending(DecryptionShareProofsPending { - e3_id: E3id::new("test60", 1), - party_id: 1, - node: "0x2222222222222222222222222222222222222222".to_string(), - sk_poly_sum: ArcBytes::from_bytes(&[0x33; 32]), - es_poly_sum: vec![ArcBytes::from_bytes(&[0x44; 32])], - sk_request: dummy_dkg_share_decryption_proof_request(), - esm_requests: vec![dummy_dkg_share_decryption_proof_request()], - }), - None, - 1700000073000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(60); - - let event61 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::PkAggregationProofPending(PkAggregationProofPending { - e3_id: E3id::new("test61", 1), - proof_request: dummy_pk_aggregation_proof_request(), - public_key: ArcBytes::from_bytes(&[0x55; 32]), - nodes: vec![ - "0x1111111111111111111111111111111111111111".to_string(), - "0x2222222222222222222222222222222222222222".to_string(), - ] - .into(), - }), - None, - 1700000074000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(61); - - let event62 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::AggregationProofPending(AggregationProofPending { - e3_id: E3id::new("test62", 1), - proof_request: dummy_decrypted_shares_aggregation_proof_request(), - plaintext: vec![ArcBytes::from_bytes(&[0x66; 32])], - shares: vec![(1, vec![ArcBytes::from_bytes(&[0x77; 32])])], - }), - None, - 1700000075000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(62); - - let event63 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ShareVerificationDispatched(ShareVerificationDispatched { - e3_id: E3id::new("test63", 1), - kind: VerificationKind::ShareProofs, - share_proofs: vec![PartyProofsToVerify { - sender_party_id: 2, - signed_proofs: vec![dummy_signed_proof_payload( - E3id::new("test63", 1), - ProofType::C2aSkShareComputation, - )], - }], - decryption_proofs: vec![], - pre_dishonest: BTreeSet::new(), - }), - None, - 1700000076000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(63); - - let event64 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ShareVerificationComplete(ShareVerificationComplete { - e3_id: E3id::new("test64", 1), - kind: VerificationKind::ShareProofs, - dishonest_parties: BTreeSet::from([3, 5]), - }), - None, - 1700000077000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(64); - - let event65 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::ComputeResponse(ComputeResponse { - response: ComputeResponseKind::Zk(ZkResponse::PkBfv(PkBfvProofResponse { - proof: dummy_proof(CircuitName::PkBfv), - wrapped_proof: dummy_proof(CircuitName::PkBfv), - })), - correlation_id: CorrelationId::new(), - e3_id: E3id::new("test65", 1), - }), - None, - 1700000078000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(65); - - let event66 = EnclaveEvent::::new_with_timestamp( - EnclaveEventData::PkAggregationProofSigned(PkAggregationProofSigned { - e3_id: E3id::new("test66", 1), - signed_proof: dummy_signed_proof_payload( - E3id::new("test66", 1), - ProofType::C5PkAggregation, - ), - }), - None, - 1700000079000_u128, - None, - e3_events::EventSource::Local, - ) - .into_sequenced(66); - - for event in [ - event1, event2, event3, event4, event5, event6, event7, event8, event9, event10, event11, - event12, event13, event14, event15, event16, event17, event18, event19, event20, event21, - event22, event23, event24, event25, event26, event27, event28, event29, event30, event31, - event32, event33, event34, event35, event36, event37, event38, event39, event40, event41, - event42, event43, event44, event45, event46, event47, event48, event49, event50, event51, - event52, event53, event54, event55, event56, event57, event58, event59, event60, event61, - event62, event63, event64, event65, event66, - ] { - println!("{}", serde_json::to_string(&event)?); - } - - Ok(()) -} From 4d7475029ce4b9bf675e200c06ffb1bc16400ccf Mon Sep 17 00:00:00 2001 From: ryardley Date: Sun, 5 Apr 2026 04:35:42 +0000 Subject: [PATCH 33/43] use cn1 --- tests/integration/base.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/base.sh b/tests/integration/base.sh index e44d05d558..3c3a441ce6 100755 --- a/tests/integration/base.sh +++ b/tests/integration/base.sh @@ -77,7 +77,7 @@ pnpm committee:new \ wait_for_committee_pubkey 0 "$SCRIPT_DIR/output/pubkey.bin" heading "Query events via daemon REST API" -daemon_query_events ag "$SCRIPT_DIR/output/events.txt" +daemon_query_events cn1 "$SCRIPT_DIR/output/events.txt" heading "Mock encrypted plaintext" $SCRIPT_DIR/lib/fake_encrypt.sh --input "$SCRIPT_DIR/output/pubkey.bin" --output "$SCRIPT_DIR/output/output.bin" --plaintext $PLAINTEXT --params "$ENCODED_PARAMS" From d6168bfda2057b3ffd6740878480f954dbe565df Mon Sep 17 00:00:00 2001 From: ryardley Date: Sun, 5 Apr 2026 10:21:14 +0000 Subject: [PATCH 34/43] fix event feed --- crates/ciphernode-builder/src/ciphernode_builder.rs | 3 +++ crates/cli/src/cli.rs | 5 +++++ crates/events/src/events.rs | 2 ++ 3 files changed, 10 insertions(+) diff --git a/crates/ciphernode-builder/src/ciphernode_builder.rs b/crates/ciphernode-builder/src/ciphernode_builder.rs index 054965d17c..1ee2a11ff2 100644 --- a/crates/ciphernode-builder/src/ciphernode_builder.rs +++ b/crates/ciphernode-builder/src/ciphernode_builder.rs @@ -408,17 +408,20 @@ impl CiphernodeBuilder { .with_event_bus(local_bus) .with_aggregate_config(aggregate_config.clone()) .with_global_shared_store(self.global_shared_store) + .with_global_shared_eventstore(self.global_shared_eventstore) } else { if let Some(ref store) = self.in_mem_store { EventSystem::in_mem_from_store(store) .with_event_bus(local_bus) .with_aggregate_config(aggregate_config.clone()) .with_global_shared_store(self.global_shared_store) + .with_global_shared_eventstore(self.global_shared_eventstore) } else { EventSystem::in_mem() .with_event_bus(local_bus) .with_aggregate_config(aggregate_config.clone()) .with_global_shared_store(self.global_shared_store) + .with_global_shared_eventstore(self.global_shared_eventstore) } }; let store = event_system.store()?; diff --git a/crates/cli/src/cli.rs b/crates/cli/src/cli.rs index 69726bb29a..0c22d0f3e3 100644 --- a/crates/cli/src/cli.rs +++ b/crates/cli/src/cli.rs @@ -317,10 +317,15 @@ pub enum Commands { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct RemoteCli { + #[serde(default)] name: Option, + #[serde(default)] otel: Option, + #[serde(default)] quiet: bool, + #[serde(default)] config: Option, + #[serde(default)] verbose: u8, command: RemoteCommand, } diff --git a/crates/events/src/events.rs b/crates/events/src/events.rs index 24d6b33142..bad4d1c3eb 100644 --- a/crates/events/src/events.rs +++ b/crates/events/src/events.rs @@ -75,12 +75,14 @@ pub trait QueryKind { } /// Query by aggregated sequence +#[derive(Debug)] pub struct SeqAgg; impl QueryKind for SeqAgg { type Shape = HashMap; } /// Query by aggregated timestamp +#[derive(Debug)] pub struct TsAgg; impl QueryKind for TsAgg { type Shape = HashMap; From 3f86bd2f37b1c5aef856de21f8c231344d848c31 Mon Sep 17 00:00:00 2001 From: ryardley Date: Sun, 5 Apr 2026 12:23:47 +0000 Subject: [PATCH 35/43] check that cursor functionality works --- crates/cli/src/events.rs | 22 ++++++++++++++++++---- tests/integration/base.sh | 2 ++ tests/integration/fns.sh | 13 +++++++++++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 6493f4cdb8..50f3dbc3b6 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -12,6 +12,7 @@ use e3_console::{log, Console}; use e3_entrypoint::helpers::datastore::get_eventstore_reader; use e3_events::CorrelationId; use e3_events::EnclaveEvent; +use e3_events::EventContextSeq; use e3_events::EventStoreQueryResponse; use e3_events::{AggregateId, EventStoreQueryBy, SeqAgg}; use e3_utils::actix::channel as actix_toolbox; @@ -45,6 +46,12 @@ pub async fn execute(out: Console, command: EventsCommands, config: &AppConfig) Ok(()) } +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub enum BatchCursor { + Done, + Next(u64), +} + async fn query_events( out: Console, config: &AppConfig, @@ -53,8 +60,9 @@ async fn query_events( limit: Option, ) -> Result<()> { let eventstore = get_eventstore_reader(config)?; - let events = fetch_events(eventstore, aggregate, since, limit).await?; - print_events(out, events)?; + let (events, next) = fetch_events(eventstore, aggregate, since, limit).await?; + print_events(out.clone(), events)?; + log!(out, "{}", serde_json::to_string(&next)?); Ok(()) } @@ -63,7 +71,7 @@ async fn fetch_events( aggregate: Option, since: Option, limit: Option, -) -> Result> { +) -> Result<(Vec, BatchCursor)> { let aggregate = aggregate.unwrap_or(0); let since = since.unwrap_or(0); let limit = limit.unwrap_or(10); @@ -78,8 +86,14 @@ async fn fetch_events( eventstore.seq().do_send(msg); let events = rx.await?.into_events(); + let next = if events.len() == limit as usize { + let last_event_seq = events.last().map(|e| e.seq()).unwrap_or(0); + BatchCursor::Next(last_event_seq) + } else { + BatchCursor::Done + }; - Ok(events) + Ok((events, next)) } fn print_events(out: Console, events: Vec) -> Result<()> { diff --git a/tests/integration/base.sh b/tests/integration/base.sh index 3c3a441ce6..4ab21fa397 100755 --- a/tests/integration/base.sh +++ b/tests/integration/base.sh @@ -79,6 +79,8 @@ wait_for_committee_pubkey 0 "$SCRIPT_DIR/output/pubkey.bin" heading "Query events via daemon REST API" daemon_query_events cn1 "$SCRIPT_DIR/output/events.txt" +check_last_line "$SCRIPT_DIR/output/events.txt" '{"Next":10}' + heading "Mock encrypted plaintext" $SCRIPT_DIR/lib/fake_encrypt.sh --input "$SCRIPT_DIR/output/pubkey.bin" --output "$SCRIPT_DIR/output/output.bin" --plaintext $PLAINTEXT --params "$ENCODED_PARAMS" diff --git a/tests/integration/fns.sh b/tests/integration/fns.sh index dd4d768f14..5eacf839a3 100644 --- a/tests/integration/fns.sh +++ b/tests/integration/fns.sh @@ -284,8 +284,7 @@ daemon_query_events() { --name $name \ --config "$SCRIPT_DIR/enclave.config.yaml") - local json_payload='{"command":{"EventsQuery":{"since":0,"limit":100}}}' - + local json_payload='{"command":{"EventsQuery":{"since":0,"limit":10}}}' curl -sf -X POST "http://127.0.0.1:${ctrl_port}" \ -H "Content-Type: application/json" \ -d "$json_payload" > "$output_file" @@ -295,6 +294,16 @@ daemon_query_events() { echo "End" } +check_last_line() { + local file="$1" + local expected="$2" + if [[ "$(tail -1 "$file")" == "$expected" ]]; then + return 0 + else + return 1 + fi +} + # Run this at the start of every test to ensure we start with a clean slate kill_em_all From aa57aa0ac5f9b1efaef9b722cf2c8156fd9c1138 Mon Sep 17 00:00:00 2001 From: ryardley Date: Sun, 5 Apr 2026 12:24:45 +0000 Subject: [PATCH 36/43] dont print events --- tests/integration/fns.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/integration/fns.sh b/tests/integration/fns.sh index 5eacf839a3..76afc0029a 100644 --- a/tests/integration/fns.sh +++ b/tests/integration/fns.sh @@ -289,9 +289,6 @@ daemon_query_events() { -H "Content-Type: application/json" \ -d "$json_payload" > "$output_file" - echo "Events from $name written:" - cat $output_file - echo "End" } check_last_line() { From e20e50382bf24aeb5f9d9ef4ef550e86ee042b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=B3=CE=BB?= Date: Sun, 5 Apr 2026 13:13:32 +0000 Subject: [PATCH 37/43] Update crates/events/src/seed.rs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- crates/events/src/seed.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/events/src/seed.rs b/crates/events/src/seed.rs index 6eabbd3bd8..4567f0b093 100644 --- a/crates/events/src/seed.rs +++ b/crates/events/src/seed.rs @@ -38,9 +38,10 @@ impl AsBytesSerde for Seed { fn try_from_bytes(bytes: Vec) -> Result { Ok(Seed( - bytes.try_into().map_err(|_| "EventId requires 32 bytes")?, + bytes.try_into().map_err(|_| "Seed requires 32 bytes")?, )) } + } } impl Display for Seed { From 101a1540a8917d5b0b081a769f95927f96049efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=B3=CE=BB?= Date: Sun, 5 Apr 2026 13:13:51 +0000 Subject: [PATCH 38/43] Update crates/config/src/app_config.rs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- crates/config/src/app_config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/config/src/app_config.rs b/crates/config/src/app_config.rs index dd012cac79..149505ebe1 100644 --- a/crates/config/src/app_config.rs +++ b/crates/config/src/app_config.rs @@ -179,7 +179,7 @@ impl BBPath { } } - /// Check the environment variable and if found use that otherwisse use the given path + /// Check the environment variable and if found use that otherwise use the given path pub fn check(default_path: PathBuf) -> Result { let bb_path = if let Some(bb_path) = env::var("E3_CUSTOM_BB").ok() { BBPath::Custom(bb_path.try_into()?) From b77c9d20321fa0d119db0dcbdb0b9bce5b1cd045 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 6 Apr 2026 06:40:51 +0000 Subject: [PATCH 39/43] fix bad coderabbit merge --- crates/events/src/seed.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/events/src/seed.rs b/crates/events/src/seed.rs index 4567f0b093..e49934de73 100644 --- a/crates/events/src/seed.rs +++ b/crates/events/src/seed.rs @@ -41,7 +41,6 @@ impl AsBytesSerde for Seed { bytes.try_into().map_err(|_| "Seed requires 32 bytes")?, )) } - } } impl Display for Seed { From b33037331d6a05c0c675c3b3e3d6eeceb64af708 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 6 Apr 2026 06:41:38 +0000 Subject: [PATCH 40/43] update header --- crates/daemon-server/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/daemon-server/src/lib.rs b/crates/daemon-server/src/lib.rs index 57e21274a0..9905d70eae 100644 --- a/crates/daemon-server/src/lib.rs +++ b/crates/daemon-server/src/lib.rs @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.0-only +// SPDX-License-Identifier: LGPL-3.0-only // // This file is provided WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY From 3e6739d65818ac280fbe30a623de9b850d7ab0eb Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 6 Apr 2026 07:16:33 +0000 Subject: [PATCH 41/43] extract to be more testable --- crates/cli/src/events.rs | 22 +--- crates/events/src/cursor.rs | 79 +++++++++++++++ crates/events/src/eventstore.rs | 131 +++++++++++++++++++++++- crates/events/src/lib.rs | 2 + crates/net/src/net_event_batch.rs | 162 ++++++++++++++++++++++++++++++ 5 files changed, 377 insertions(+), 19 deletions(-) create mode 100644 crates/events/src/cursor.rs diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 50f3dbc3b6..2abcb7b0ca 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -10,11 +10,8 @@ use e3_ciphernode_builder::global_eventstore_cache::EventStoreReader; use e3_config::AppConfig; use e3_console::{log, Console}; use e3_entrypoint::helpers::datastore::get_eventstore_reader; -use e3_events::CorrelationId; -use e3_events::EnclaveEvent; -use e3_events::EventContextSeq; -use e3_events::EventStoreQueryResponse; -use e3_events::{AggregateId, EventStoreQueryBy, SeqAgg}; +use e3_events::{compute_seq_cursor, CorrelationId, EnclaveEvent, SeqCursor, SeqAgg}; +use e3_events::{AggregateId, EventStoreQueryBy, EventStoreQueryResponse}; use e3_utils::actix::channel as actix_toolbox; use std::collections::HashMap; @@ -46,12 +43,6 @@ pub async fn execute(out: Console, command: EventsCommands, config: &AppConfig) Ok(()) } -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] -pub enum BatchCursor { - Done, - Next(u64), -} - async fn query_events( out: Console, config: &AppConfig, @@ -71,7 +62,7 @@ async fn fetch_events( aggregate: Option, since: Option, limit: Option, -) -> Result<(Vec, BatchCursor)> { +) -> Result<(Vec, SeqCursor)> { let aggregate = aggregate.unwrap_or(0); let since = since.unwrap_or(0); let limit = limit.unwrap_or(10); @@ -86,12 +77,7 @@ async fn fetch_events( eventstore.seq().do_send(msg); let events = rx.await?.into_events(); - let next = if events.len() == limit as usize { - let last_event_seq = events.last().map(|e| e.seq()).unwrap_or(0); - BatchCursor::Next(last_event_seq) - } else { - BatchCursor::Done - }; + let next = compute_seq_cursor(&events, limit as usize); Ok((events, next)) } diff --git a/crates/events/src/cursor.rs b/crates/events/src/cursor.rs new file mode 100644 index 0000000000..153ffe02b1 --- /dev/null +++ b/crates/events/src/cursor.rs @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use crate::traits::EventContextSeq; + +#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)] +pub enum SeqCursor { + Done, + Next(u64), +} + +pub fn compute_seq_cursor(events: &[T], limit: usize) -> SeqCursor { + if events.len() == limit { + let last_seq = events.last().map(|e| e.seq()).unwrap_or(0); + SeqCursor::Next(last_seq) + } else { + SeqCursor::Done + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::traits::EventContextSeq; + + struct MockEvent(u64); + impl EventContextSeq for MockEvent { + fn seq(&self) -> u64 { + self.0 + } + } + + #[test] + fn test_seq_cursor_done_when_under_limit() { + let events = vec![MockEvent(1), MockEvent(2)]; + let cursor = compute_seq_cursor(&events, 10); + assert!(matches!(cursor, SeqCursor::Done)); + } + + #[test] + fn test_seq_cursor_next_when_at_limit() { + let events = vec![MockEvent(1), MockEvent(2)]; + let cursor = compute_seq_cursor(&events, 2); + match cursor { + SeqCursor::Next(seq) => assert_eq!(seq, 2), + SeqCursor::Done => panic!("Expected Next, got Done"), + } + } + + #[test] + fn test_seq_cursor_uses_last_event_seq() { + let events = vec![MockEvent(100), MockEvent(200), MockEvent(300)]; + let cursor = compute_seq_cursor(&events, 3); + match cursor { + SeqCursor::Next(seq) => assert_eq!(seq, 300), + SeqCursor::Done => panic!("Expected Next, got Done"), + } + } + + #[test] + fn test_seq_cursor_empty_returns_done() { + let events: Vec = vec![]; + let cursor = compute_seq_cursor(&events, 10); + assert!(matches!(cursor, SeqCursor::Done)); + } + + #[test] + fn test_seq_cursor_single_event_at_limit() { + let events = vec![MockEvent(42)]; + let cursor = compute_seq_cursor(&events, 1); + match cursor { + SeqCursor::Next(seq) => assert_eq!(seq, 42), + SeqCursor::Done => panic!("Expected Next, got Done"), + } + } +} diff --git a/crates/events/src/eventstore.rs b/crates/events/src/eventstore.rs index b4c999d3a9..1ad3bc3cde 100644 --- a/crates/events/src/eventstore.rs +++ b/crates/events/src/eventstore.rs @@ -160,7 +160,7 @@ impl Handler> for EventSto #[cfg(test)] mod tests { - use crate::{EventConstructorWithTimestamp, EventSource, TestEvent}; + use crate::{EventConstructorWithTimestamp, EventContextSeq, EventSource, TestEvent}; use super::*; use anyhow::Result; @@ -502,4 +502,133 @@ mod tests { assert_eq!(events.len(), 2); } + + // =========================================================================== + // Pagination / Cursor boundary tests + // =========================================================================== + + #[test] + fn ts_query_is_inclusive_at_boundary() { + let store = populated_store(&[ + make_local_event(100), + make_local_event(200), + make_local_event(300), + ]); + + let page1 = store.query_by_ts(100, None, Some(2)).unwrap(); + assert_eq!(page1.len(), 2); + assert_eq!(page1[0].get_ctx().ts(), 100); + assert_eq!(page1[1].get_ctx().ts(), 200); + + let page2 = store.query_by_ts(200, None, Some(2)).unwrap(); + assert_eq!(page2.len(), 2); + assert_eq!(page2[0].get_ctx().ts(), 200); + assert_eq!(page2[1].get_ctx().ts(), 300); + } + + #[test] + fn ts_query_cursor_off_by_one_causes_duplicates() { + let store = populated_store(&[ + make_local_event(100), + make_local_event(200), + make_local_event(300), + ]); + + let page1 = store.query_by_ts(100, None, Some(2)).unwrap(); + assert_eq!(page1.len(), 2); + + let cursor_ts = page1.last().unwrap().get_ctx().ts(); + assert_eq!(cursor_ts, 200); + + let page2 = store.query_by_ts(cursor_ts, None, None).unwrap(); + assert_eq!(page2.len(), 2); + + let total: Vec<_> = page1.iter().chain(page2.iter()).collect(); + let ts_values: Vec<_> = total.iter().map(|e| e.get_ctx().ts()).collect(); + let has_duplicates = ts_values.len() + != ts_values + .iter() + .collect::>() + .len(); + + assert!( + has_duplicates, + "BUG: ts=200 appears in both pages (inclusive query with cursor=last_ts)" + ); + } + + #[test] + fn ts_query_pagination_without_duplicates() { + let store = populated_store(&[ + make_local_event(100), + make_local_event(200), + make_local_event(300), + make_local_event(400), + ]); + + let page1 = store.query_by_ts(100, None, Some(2)).unwrap(); + assert_eq!(page1.len(), 2); + + let cursor_ts = page1.last().unwrap().get_ctx().ts() + 1; + let page2 = store.query_by_ts(cursor_ts, None, Some(2)).unwrap(); + + let all_ts: Vec<_> = page1 + .iter() + .chain(page2.iter()) + .map(|e| e.get_ctx().ts()) + .collect(); + + assert_eq!(all_ts.len(), 4); + assert_eq!(all_ts, vec![100, 200, 300, 400]); + } + + #[test] + fn seq_query_is_inclusive_at_boundary() { + let store = populated_store(&[ + make_local_event(100), + make_local_event(200), + make_local_event(300), + ]); + + let page1 = store.query_by_seq(0, None, Some(2)); + assert_eq!(page1.len(), 2); + assert_eq!(page1[0].seq(), 0); + assert_eq!(page1[1].seq(), 1); + + let page2 = store.query_by_seq(1, None, Some(2)); + assert_eq!(page2.len(), 2); + assert_eq!(page2[0].seq(), 1); + assert_eq!(page2[1].seq(), 2); + } + + #[test] + fn seq_query_cursor_off_by_one_causes_duplicates() { + let store = populated_store(&[ + make_local_event(100), + make_local_event(200), + make_local_event(300), + ]); + + let page1 = store.query_by_seq(0, None, Some(2)); + assert_eq!(page1.len(), 2); + + let cursor_seq = page1.last().unwrap().seq(); + assert_eq!(cursor_seq, 1); + + let page2 = store.query_by_seq(cursor_seq, None, None); + assert_eq!(page2.len(), 2); + + let total: Vec<_> = page1.iter().chain(page2.iter()).collect(); + let seq_values: Vec<_> = total.iter().map(|e| e.seq()).collect(); + let has_duplicates = seq_values.len() + != seq_values + .iter() + .collect::>() + .len(); + + assert!( + has_duplicates, + "BUG: seq=1 appears in both pages (inclusive query with cursor=last_seq)" + ); + } } diff --git a/crates/events/src/lib.rs b/crates/events/src/lib.rs index bd0fe091dc..a435677474 100644 --- a/crates/events/src/lib.rs +++ b/crates/events/src/lib.rs @@ -7,6 +7,7 @@ mod bus_handle; mod committee; mod correlation_id; +mod cursor; mod data_events; mod e3id; mod enclave_event; @@ -32,6 +33,7 @@ mod traits; pub use bus_handle::*; pub use committee::*; pub use correlation_id::*; +pub use cursor::*; pub use data_events::*; pub use e3id::*; pub use enclave_event::*; diff --git a/crates/net/src/net_event_batch.rs b/crates/net/src/net_event_batch.rs index b1b934c02c..eddf9db95f 100644 --- a/crates/net/src/net_event_batch.rs +++ b/crates/net/src/net_event_batch.rs @@ -194,4 +194,166 @@ mod tests { vec![b"event1".to_vec(), b"event2".to_vec(), b"event3".to_vec(),] ); } + + #[tokio::test] + async fn test_no_duplicate_events_across_batches() { + let (net_cmds_tx, net_cmds_rx) = mpsc::channel::(16); + let (net_events_tx, net_events_rx) = broadcast::channel::(16); + let net_events = Arc::new(net_events_rx); + + let requester = DirectRequester::builder(net_cmds_tx, net_events).build(); + + let batch1 = EventBatch { + events: vec![b"event1".to_vec(), b"event2".to_vec()], + next: BatchCursor::Next(2), + aggregate_id: AggregateId::new(1), + }; + let batch2 = EventBatch { + events: vec![b"event3".to_vec()], + next: BatchCursor::Done, + aggregate_id: AggregateId::new(1), + }; + + let handle = DirectRequesterTester::new(net_cmds_rx, net_events_tx) + .expect_request(FetchEventsSince::new(AggregateId::new(1), 0, 100)) + .respond_with(batch1) + .expect_request(FetchEventsSince::new(AggregateId::new(1), 2, 100)) + .respond_with(batch2) + .spawn(); + + let events: Vec> = + fetch_all_batched_events(requester, PeerTarget::Random, AggregateId::new(1), 0, 100) + .await + .unwrap(); + + handle.await.unwrap(); + + let unique: Vec<_> = events.iter().collect::>().into_iter().collect(); + assert_eq!( + events.len(), + unique.len(), + "Found duplicate events: total={}, unique={}", + events.len(), + unique.len() + ); + assert_eq!(events, vec![b"event1".to_vec(), b"event2".to_vec(), b"event3".to_vec()]); + } + + #[tokio::test] + async fn test_cursor_correctly_excludes_last_event_on_batch_boundary() { + let (net_cmds_tx, net_cmds_rx) = mpsc::channel::(16); + let (net_events_tx, net_events_rx) = broadcast::channel::(16); + let net_events = Arc::new(net_events_rx); + + let requester = DirectRequester::builder(net_cmds_tx, net_events).build(); + + let batch1 = EventBatch { + events: vec![b"event1".to_vec()], + next: BatchCursor::Next(100), + aggregate_id: AggregateId::new(1), + }; + let batch2 = EventBatch { + events: vec![b"event2".to_vec()], + next: BatchCursor::Done, + aggregate_id: AggregateId::new(1), + }; + + let handle = DirectRequesterTester::new(net_cmds_rx, net_events_tx) + .expect_request(FetchEventsSince::new(AggregateId::new(1), 0, 1)) + .respond_with(batch1) + .expect_request(FetchEventsSince::new(AggregateId::new(1), 100, 1)) + .respond_with(batch2) + .spawn(); + + let events: Vec> = + fetch_all_batched_events(requester, PeerTarget::Random, AggregateId::new(1), 0, 1) + .await + .unwrap(); + + handle.await.unwrap(); + + assert_eq!(events.len(), 2); + assert_eq!(events[0], b"event1"); + assert_eq!(events[1], b"event2"); + } + + #[tokio::test] + async fn test_single_batch_with_limit_exactly_matched_returns_done() { + let (net_cmds_tx, net_cmds_rx) = mpsc::channel::(16); + let (net_events_tx, net_events_rx) = broadcast::channel::(16); + let net_events = Arc::new(net_events_rx); + + let requester = DirectRequester::builder(net_cmds_tx, net_events).build(); + + let batch = EventBatch { + events: vec![b"event1".to_vec()], + next: BatchCursor::Done, + aggregate_id: AggregateId::new(1), + }; + + let handle = DirectRequesterTester::new(net_cmds_rx, net_events_tx) + .expect_request(FetchEventsSince::new(AggregateId::new(1), 0, 1)) + .respond_with(batch) + .spawn(); + + let events: Vec> = + fetch_all_batched_events(requester, PeerTarget::Random, AggregateId::new(1), 0, 1) + .await + .unwrap(); + + handle.await.unwrap(); + + assert_eq!(events, vec![b"event1".to_vec()]); + } + + #[tokio::test] + async fn test_three_batches_with_cursor_continuity() { + let (net_cmds_tx, net_cmds_rx) = mpsc::channel::(16); + let (net_events_tx, net_events_rx) = broadcast::channel::(16); + let net_events = Arc::new(net_events_rx); + + let requester = DirectRequester::builder(net_cmds_tx, net_events).build(); + + let batch1 = EventBatch { + events: vec![b"a".to_vec(), b"b".to_vec()], + next: BatchCursor::Next(200), + aggregate_id: AggregateId::new(1), + }; + let batch2 = EventBatch { + events: vec![b"c".to_vec(), b"d".to_vec()], + next: BatchCursor::Next(400), + aggregate_id: AggregateId::new(1), + }; + let batch3 = EventBatch { + events: vec![b"e".to_vec()], + next: BatchCursor::Done, + aggregate_id: AggregateId::new(1), + }; + + let handle = DirectRequesterTester::new(net_cmds_rx, net_events_tx) + .expect_request(FetchEventsSince::new(AggregateId::new(1), 0, 2)) + .respond_with(batch1) + .expect_request(FetchEventsSince::new(AggregateId::new(1), 200, 2)) + .respond_with(batch2) + .expect_request(FetchEventsSince::new(AggregateId::new(1), 400, 2)) + .respond_with(batch3) + .spawn(); + + let events: Vec> = + fetch_all_batched_events(requester, PeerTarget::Random, AggregateId::new(1), 0, 2) + .await + .unwrap(); + + handle.await.unwrap(); + + let expected = vec![ + b"a".to_vec(), + b"b".to_vec(), + b"c".to_vec(), + b"d".to_vec(), + b"e".to_vec(), + ]; + assert_eq!(events.len(), expected.len()); + assert_eq!(events, expected); + } } From eb60acd345a220ccad96645eb7eac844629f9f25 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 6 Apr 2026 07:19:52 +0000 Subject: [PATCH 42/43] formatting --- crates/cli/src/events.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/events.rs b/crates/cli/src/events.rs index 2abcb7b0ca..867cc30732 100644 --- a/crates/cli/src/events.rs +++ b/crates/cli/src/events.rs @@ -10,7 +10,7 @@ use e3_ciphernode_builder::global_eventstore_cache::EventStoreReader; use e3_config::AppConfig; use e3_console::{log, Console}; use e3_entrypoint::helpers::datastore::get_eventstore_reader; -use e3_events::{compute_seq_cursor, CorrelationId, EnclaveEvent, SeqCursor, SeqAgg}; +use e3_events::{compute_seq_cursor, CorrelationId, EnclaveEvent, SeqAgg, SeqCursor}; use e3_events::{AggregateId, EventStoreQueryBy, EventStoreQueryResponse}; use e3_utils::actix::channel as actix_toolbox; use std::collections::HashMap; From ca749b35536571268ecafb08522d388073ab4c04 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 6 Apr 2026 07:21:00 +0000 Subject: [PATCH 43/43] formatting --- crates/net/src/net_event_batch.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/net/src/net_event_batch.rs b/crates/net/src/net_event_batch.rs index eddf9db95f..cd0ab5d280 100644 --- a/crates/net/src/net_event_batch.rs +++ b/crates/net/src/net_event_batch.rs @@ -228,7 +228,11 @@ mod tests { handle.await.unwrap(); - let unique: Vec<_> = events.iter().collect::>().into_iter().collect(); + let unique: Vec<_> = events + .iter() + .collect::>() + .into_iter() + .collect(); assert_eq!( events.len(), unique.len(), @@ -236,7 +240,10 @@ mod tests { events.len(), unique.len() ); - assert_eq!(events, vec![b"event1".to_vec(), b"event2".to_vec(), b"event3".to_vec()]); + assert_eq!( + events, + vec![b"event1".to_vec(), b"event2".to_vec(), b"event3".to_vec()] + ); } #[tokio::test]