diff --git a/Cargo.lock b/Cargo.lock index fb98aa49e0..1e941168f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2867,6 +2867,7 @@ dependencies = [ "proptest", "serde", "sha2", + "strum", "thiserror 1.0.69", "tokio", "tracing", @@ -3118,6 +3119,7 @@ dependencies = [ "num-bigint", "rand 0.8.5", "serde", + "tokio", "tracing", ] diff --git a/crates/aggregator/src/committee_finalizer.rs b/crates/aggregator/src/committee_finalizer.rs index 587c8311ea..aef3847ea2 100644 --- a/crates/aggregator/src/committee_finalizer.rs +++ b/crates/aggregator/src/committee_finalizer.rs @@ -6,7 +6,8 @@ use actix::prelude::*; use e3_events::{ - CommitteeFinalizeRequested, CommitteeRequested, EnclaveEvent, EventBus, Shutdown, Subscribe, + prelude::*, BusHandle, CommitteeFinalizeRequested, CommitteeRequested, EnclaveEvent, + EnclaveEventData, Shutdown, }; use std::collections::HashMap; use std::time::Duration; @@ -15,26 +16,25 @@ use tracing::{error, info}; /// CommitteeFinalizer is an actor that listens to CommitteeRequested events and dispatches /// CommitteeFinalizeRequested events after the submission deadline has passed. pub struct CommitteeFinalizer { - bus: Addr>, + bus: BusHandle, pending_committees: HashMap, } impl CommitteeFinalizer { - pub fn new(bus: &Addr>) -> Self { + pub fn new(bus: &BusHandle) -> Self { Self { bus: bus.clone(), pending_committees: HashMap::new(), } } - pub fn attach(bus: &Addr>) -> Addr { + pub fn attach(bus: &BusHandle) -> Addr { let addr = CommitteeFinalizer::new(bus).start(); - bus.do_send(Subscribe::new( - "CommitteeRequested", + bus.subscribe_all( + &["CommitteeRequested", "Shutdown"], addr.clone().recipient(), - )); - bus.do_send(Subscribe::new("Shutdown", addr.clone().recipient())); + ); addr } @@ -47,9 +47,9 @@ impl Actor for CommitteeFinalizer { impl Handler for CommitteeFinalizer { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::CommitteeRequested { data, .. } => ctx.notify(data), - EnclaveEvent::Shutdown { data, .. } => ctx.notify(data), + match msg.into_data() { + EnclaveEventData::CommitteeRequested(data) => ctx.notify(data), + EnclaveEventData::Shutdown(data) => ctx.notify(data), _ => (), } } @@ -112,9 +112,9 @@ impl Handler for CommitteeFinalizer { move |act, _ctx| { info!(e3_id = %e3_id_clone, "Dispatching CommitteeFinalizeRequested event"); - bus.do_send(EnclaveEvent::from(CommitteeFinalizeRequested { + bus.publish(CommitteeFinalizeRequested { e3_id: e3_id_clone.clone(), - })); + }); act.pending_committees.remove(&e3_id_clone.to_string()); }, diff --git a/crates/aggregator/src/ext.rs b/crates/aggregator/src/ext.rs index 703566af9a..abdbbdf489 100644 --- a/crates/aggregator/src/ext.rs +++ b/crates/aggregator/src/ext.rs @@ -4,6 +4,9 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +use std::sync::Arc; + +use crate::keyshare_created_filter_buffer::KeyshareCreatedFilterBuffer; use crate::{ PlaintextAggregator, PlaintextAggregatorParams, PlaintextAggregatorState, PlaintextRepositoryFactory, PublicKeyAggregator, PublicKeyAggregatorParams, @@ -11,24 +14,26 @@ use crate::{ ThresholdPlaintextAggregatorParams, ThresholdPlaintextAggregatorState, TrBfvPlaintextRepositoryFactory, }; -use actix::{Actor, Addr}; +use actix::{Actor, Addr, Recipient}; use anyhow::{anyhow, Result}; use async_trait::async_trait; -use e3_data::{AutoPersist, RepositoriesFactory}; -use e3_events::{BusError, EnclaveErrorType, EnclaveEvent, EventBus}; +use e3_data::{AutoPersist, Persistable, RepositoriesFactory}; +use e3_events::{prelude::*, E3id}; +use e3_events::{BusHandle, EnclaveErrorType, EnclaveEvent, EnclaveEventData}; use e3_fhe::ext::FHE_KEY; +use e3_fhe::Fhe; use e3_multithread::Multithread; use e3_request::{E3Context, E3ContextSnapshot, E3Extension, META_KEY}; use e3_sortition::Sortition; #[deprecated = "In favour of ThresholdPlaintextAggregatorExtension"] pub struct PlaintextAggregatorExtension { - bus: Addr>, + bus: BusHandle, sortition: Addr, } impl PlaintextAggregatorExtension { - pub fn create(bus: &Addr>, sortition: &Addr) -> Box { + pub fn create(bus: &BusHandle, sortition: &Addr) -> Box { Box::new(Self { bus: bus.clone(), sortition: sortition.clone(), @@ -43,7 +48,7 @@ const ERROR_PLAINTEXT_META_MISSING:&str = "Could not create PlaintextAggregator impl E3Extension for PlaintextAggregatorExtension { fn on_event(&self, ctx: &mut E3Context, evt: &EnclaveEvent) { // Save plaintext aggregator - let EnclaveEvent::CiphertextOutputPublished { data, .. } = evt else { + let EnclaveEventData::CiphertextOutputPublished(data) = evt.get_data() else { return; }; @@ -143,16 +148,12 @@ impl E3Extension for PlaintextAggregatorExtension { } pub struct PublicKeyAggregatorExtension { - bus: Addr>, - sortition: Addr, + bus: BusHandle, } impl PublicKeyAggregatorExtension { - pub fn create(bus: &Addr>, sortition: &Addr) -> Box { - Box::new(Self { - bus: bus.clone(), - sortition: sortition.clone(), - }) + pub fn create(bus: &BusHandle) -> Box { + Box::new(Self { bus: bus.clone() }) } } @@ -163,7 +164,7 @@ const ERROR_PUBKEY_META_MISSING:&str = "Could not create PublicKeyAggregator bec impl E3Extension for PublicKeyAggregatorExtension { fn on_event(&self, ctx: &mut E3Context, evt: &EnclaveEvent) { // Saving the publickey aggregator with deps on E3Requested - let EnclaveEvent::E3Requested { data, .. } = evt else { + let EnclaveEventData::E3Requested(data) = evt.get_data() else { return; }; @@ -187,22 +188,10 @@ impl E3Extension for PublicKeyAggregatorExtension { meta.threshold_n, meta.seed, ))); - ctx.set_event_recipient( - "publickey", - Some( - PublicKeyAggregator::new( - PublicKeyAggregatorParams { - fhe: fhe.clone(), - bus: self.bus.clone(), - sortition: self.sortition.clone(), - e3_id, - }, - sync_state, - ) - .start() - .into(), - ), - ); + + let value = create_publickey_aggregator(fhe.clone(), self.bus.clone(), e3_id, sync_state); + + ctx.set_event_recipient("publickey", Some(value)); } async fn hydrate(&self, ctx: &mut E3Context, snapshot: &E3ContextSnapshot) -> Result<()> { @@ -228,18 +217,12 @@ impl E3Extension for PublicKeyAggregatorExtension { return Ok(()); }; - - let value = PublicKeyAggregator::new( - PublicKeyAggregatorParams { - fhe: fhe.clone(), - bus: self.bus.clone(), - sortition: self.sortition.clone(), - e3_id: ctx.e3_id.clone(), - }, + let value = create_publickey_aggregator( + fhe.clone(), + self.bus.clone(), + ctx.e3_id.clone(), sync_state, - ) - .start() - .into(); + ); // send to context ctx.set_event_recipient("publickey", Some(value)); @@ -248,15 +231,30 @@ impl E3Extension for PublicKeyAggregatorExtension { } } +fn create_publickey_aggregator( + fhe: Arc, + bus: BusHandle, + e3_id: E3id, + sync_state: Persistable, +) -> Recipient { + KeyshareCreatedFilterBuffer::new( + PublicKeyAggregator::new(PublicKeyAggregatorParams { fhe, bus, e3_id }, sync_state) + .start() + .into(), + ) + .start() + .into() +} + pub struct ThresholdPlaintextAggregatorExtension { - bus: Addr>, + bus: BusHandle, sortition: Addr, multithread: Addr, } impl ThresholdPlaintextAggregatorExtension { pub fn create( - bus: &Addr>, + bus: &BusHandle, sortition: &Addr, multithread: &Addr, ) -> Box { @@ -274,7 +272,7 @@ const ERROR_TRBFV_PLAINTEXT_META_MISSING:&str = "Could not create ThresholdPlain impl E3Extension for ThresholdPlaintextAggregatorExtension { fn on_event(&self, ctx: &mut E3Context, evt: &EnclaveEvent) { // Save plaintext aggregator - let EnclaveEvent::CiphertextOutputPublished { data, .. } = evt else { + let EnclaveEventData::CiphertextOutputPublished(data) = evt.get_data() else { return; }; diff --git a/crates/aggregator/src/keyshare_created_filter_buffer.rs b/crates/aggregator/src/keyshare_created_filter_buffer.rs new file mode 100644 index 0000000000..43fc32b111 --- /dev/null +++ b/crates/aggregator/src/keyshare_created_filter_buffer.rs @@ -0,0 +1,74 @@ +// 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 actix::prelude::*; + +use e3_events::{prelude::*, EnclaveEvent, EnclaveEventData}; +use std::collections::HashSet; + +use crate::PublicKeyAggregator; + +/// Buffer KeyshareCreated events until CommitteeFinalized has been published +pub struct KeyshareCreatedFilterBuffer { + dest: Addr, + committee: Option>, + buffer: Vec, +} + +impl KeyshareCreatedFilterBuffer { + pub fn new(dest: Addr) -> Self { + Self { + dest, + committee: None, + buffer: Vec::new(), + } + } + + fn process_buffered_events(&mut self) { + if let Some(ref committee) = self.committee { + for event in self.buffer.drain(..) { + if let EnclaveEventData::KeyshareCreated(data) = event.get_data() { + if committee.contains(&data.node) { + self.dest.do_send(event); + } + } + } + } + } +} + +impl Actor for KeyshareCreatedFilterBuffer { + type Context = Context; +} + +impl Handler for KeyshareCreatedFilterBuffer { + type Result = (); + + fn handle(&mut self, msg: EnclaveEvent, _ctx: &mut Self::Context) -> Self::Result { + match msg.get_data() { + EnclaveEventData::KeyshareCreated(data) => match &self.committee { + Some(committee) if committee.contains(&data.node) => { + // if the committee is ready then process + self.dest.do_send(msg); + } + None => { + // if not buffer + self.buffer.push(msg); + } + _ => {} + }, + EnclaveEventData::CommitteeFinalized(data) => { + self.dest.do_send(msg.clone()); // forward committee first + self.committee = Some(data.committee.iter().cloned().collect()); + self.process_buffered_events(); + } + _ => { + // forward all other events + self.dest.do_send(msg); + } + } + } +} diff --git a/crates/aggregator/src/lib.rs b/crates/aggregator/src/lib.rs index 1b25bee22c..f335f2c737 100644 --- a/crates/aggregator/src/lib.rs +++ b/crates/aggregator/src/lib.rs @@ -6,6 +6,7 @@ mod committee_finalizer; pub mod ext; +mod keyshare_created_filter_buffer; mod plaintext_aggregator; mod publickey_aggregator; mod repo; diff --git a/crates/aggregator/src/plaintext_aggregator.rs b/crates/aggregator/src/plaintext_aggregator.rs index 9b6dae9ff3..afc416255b 100644 --- a/crates/aggregator/src/plaintext_aggregator.rs +++ b/crates/aggregator/src/plaintext_aggregator.rs @@ -8,8 +8,8 @@ use actix::prelude::*; use anyhow::Result; use e3_data::Persistable; use e3_events::{ - DecryptionshareCreated, Die, E3id, EnclaveEvent, EventBus, OrderedSet, PlaintextAggregated, - Seed, + prelude::*, BusHandle, DecryptionshareCreated, Die, E3id, EnclaveEvent, EnclaveEventData, + OrderedSet, PlaintextAggregated, Seed, }; use e3_fhe::{Fhe, GetAggregatePlaintext}; use e3_sortition::{GetNodeIndex, Sortition}; @@ -72,7 +72,7 @@ struct ComputeAggregate { #[deprecated = "To be replaced by ThresholdPlaintextAggregator"] pub struct PlaintextAggregator { fhe: Arc, - bus: Addr>, + bus: BusHandle, sortition: Addr, e3_id: E3id, state: Persistable, @@ -80,7 +80,7 @@ pub struct PlaintextAggregator { pub struct PlaintextAggregatorParams { pub fhe: Arc, - pub bus: Addr>, + pub bus: BusHandle, pub sortition: Addr, pub e3_id: E3id, } @@ -145,9 +145,9 @@ impl Actor for PlaintextAggregator { impl Handler for PlaintextAggregator { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::DecryptionshareCreated { data, .. } => ctx.notify(data), - EnclaveEvent::E3RequestComplete { .. } => ctx.notify(Die), + match msg.into_data() { + EnclaveEventData::DecryptionshareCreated(data) => ctx.notify(data), + EnclaveEventData::E3RequestComplete(_) => ctx.notify(Die), _ => (), } } @@ -234,12 +234,12 @@ impl Handler for PlaintextAggregator { self.set_decryption(decrypted_output.clone())?; // Dispatch the PlaintextAggregated event - let event = EnclaveEvent::from(PlaintextAggregated { + let event = PlaintextAggregated { decrypted_output: vec![ArcBytes::from_bytes(&decrypted_output)], e3_id: self.e3_id.clone(), - }); + }; - self.bus.do_send(event); + self.bus.publish(event); Ok(()) } diff --git a/crates/aggregator/src/publickey_aggregator.rs b/crates/aggregator/src/publickey_aggregator.rs index af7664c5f4..4c66dbd129 100644 --- a/crates/aggregator/src/publickey_aggregator.rs +++ b/crates/aggregator/src/publickey_aggregator.rs @@ -8,13 +8,14 @@ use actix::prelude::*; use anyhow::Result; use e3_data::Persistable; use e3_events::{ - Die, E3id, EnclaveEvent, EventBus, KeyshareCreated, OrderedSet, PublicKeyAggregated, Seed, + prelude::*, BusHandle, Die, E3id, EnclaveEvent, EnclaveEventData, KeyshareCreated, OrderedSet, + PublicKeyAggregated, Seed, }; use e3_fhe::{Fhe, GetAggregatePublicKey}; -use e3_sortition::{GetNodesForE3, Sortition}; +use e3_sortition::Sortition; use e3_utils::ArcBytes; use std::sync::Arc; -use tracing::{error, trace}; +use tracing::{error, info}; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub enum PublicKeyAggregatorState { @@ -22,13 +23,16 @@ pub enum PublicKeyAggregatorState { threshold_n: usize, keyshares: OrderedSet, seed: Seed, + nodes: OrderedSet, }, Computing { keyshares: OrderedSet, + nodes: OrderedSet, }, Complete { public_key: Vec, keyshares: OrderedSet, + nodes: OrderedSet, }, } @@ -38,6 +42,7 @@ impl PublicKeyAggregatorState { threshold_n, keyshares: OrderedSet::new(), seed, + nodes: OrderedSet::new(), } } } @@ -49,25 +54,16 @@ struct ComputeAggregate { pub e3_id: E3id, } -#[derive(Message)] -#[rtype(result = "anyhow::Result<()>")] -struct NotifyNetwork { - pub pubkey: Vec, - pub e3_id: E3id, -} - pub struct PublicKeyAggregator { fhe: Arc, - bus: Addr>, - sortition: Addr, + bus: BusHandle, e3_id: E3id, state: Persistable, } pub struct PublicKeyAggregatorParams { pub fhe: Arc, - pub bus: Addr>, - pub sortition: Addr, + pub bus: BusHandle, pub e3_id: E3id, } @@ -85,17 +81,17 @@ impl PublicKeyAggregator { PublicKeyAggregator { fhe: params.fhe, bus: params.bus, - sortition: params.sortition, e3_id: params.e3_id, state, } } - pub fn add_keyshare(&mut self, keyshare: ArcBytes) -> Result<()> { + pub fn add_keyshare(&mut self, keyshare: ArcBytes, node: String) -> Result<()> { self.state.try_mutate(|mut state| { let PublicKeyAggregatorState::Collecting { threshold_n, keyshares, + nodes, .. } = &mut state else { @@ -103,9 +99,17 @@ impl PublicKeyAggregator { }; keyshares.insert(keyshare); + nodes.insert(node); + info!( + "PublicKeyAggregator got keyshares {}/{}", + keyshares.len(), + threshold_n + ); if keyshares.len() == *threshold_n { + info!("Computing aggregate public key..."); return Ok(PublicKeyAggregatorState::Computing { - keyshares: keyshares.clone(), + keyshares: std::mem::take(keyshares), + nodes: std::mem::take(nodes), }); } @@ -115,15 +119,14 @@ impl PublicKeyAggregator { pub fn set_pubkey(&mut self, pubkey: Vec) -> Result<()> { self.state.try_mutate(|mut state| { - let PublicKeyAggregatorState::Computing { keyshares } = &mut state else { + let PublicKeyAggregatorState::Computing { keyshares, nodes } = &mut state else { return Ok(state); }; - let keyshares = keyshares.to_owned(); - Ok(PublicKeyAggregatorState::Complete { public_key: pubkey, - keyshares, + keyshares: std::mem::take(keyshares), + nodes: std::mem::take(nodes), }) }) } @@ -136,56 +139,37 @@ impl Actor for PublicKeyAggregator { impl Handler for PublicKeyAggregator { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::KeyshareCreated { data, .. } => ctx.notify(data), - EnclaveEvent::E3RequestComplete { .. } => ctx.notify(Die), + match msg.into_data() { + EnclaveEventData::KeyshareCreated(data) => ctx.notify(data), + EnclaveEventData::E3RequestComplete(_) => ctx.notify(Die), _ => (), } } } impl Handler for PublicKeyAggregator { - type Result = ResponseActFuture>; + type Result = Result<()>; - fn handle(&mut self, event: KeyshareCreated, _: &mut Self::Context) -> Self::Result { - let address = event.node.clone(); + fn handle(&mut self, event: KeyshareCreated, ctx: &mut Self::Context) -> Self::Result { let e3_id = event.e3_id.clone(); let pubkey = event.pubkey.clone(); + let node = event.node.clone(); + + if e3_id != self.e3_id { + error!("Wrong e3_id sent to aggregator. This should not happen."); + return Ok(()); + } + + self.add_keyshare(pubkey, node)?; - Box::pin( - self.sortition - .send(GetNodesForE3 { - e3_id: e3_id.clone(), - chain_id: e3_id.chain_id(), - }) - .into_actor(self) - .map(move |res, act, ctx| { - let nodes = res?; - - if !nodes.contains(&address) { - trace!("Node {} not found in finalized committee", address); - return Ok(()); - } - - if e3_id != act.e3_id { - error!("Wrong e3_id sent to aggregator. This should not happen."); - return Ok(()); - } - - act.add_keyshare(pubkey)?; - - if let Some(PublicKeyAggregatorState::Computing { keyshares }) = - &act.state.get() - { - ctx.notify(ComputeAggregate { - keyshares: keyshares.clone(), - e3_id, - }) - } - - Ok(()) - }), - ) + if let Some(PublicKeyAggregatorState::Computing { keyshares, .. }) = &self.state.get() { + ctx.notify(ComputeAggregate { + keyshares: keyshares.clone(), + e3_id, + }) + } + + Ok(()) } } @@ -193,48 +177,33 @@ impl Handler for PublicKeyAggregator { type Result = Result<()>; fn handle(&mut self, msg: ComputeAggregate, ctx: &mut Self::Context) -> Self::Result { + info!("Computing Aggregate PublicKey..."); let pubkey = self.fhe.get_aggregate_public_key(GetAggregatePublicKey { - keyshares: msg.keyshares.clone(), + keyshares: msg.keyshares, })?; // Update the local state - self.set_pubkey(pubkey.clone())?; - - ctx.notify(NotifyNetwork { - pubkey, - e3_id: msg.e3_id, - }); + self.set_pubkey(pubkey)?; + + if let Some(PublicKeyAggregatorState::Complete { + public_key: pubkey, + nodes, + .. + }) = self.state.get() + { + info!("Notifying network of PublicKey"); + info!("Sending PublicKeyAggregated..."); + let event = PublicKeyAggregated { + pubkey, + e3_id: msg.e3_id, + nodes, + }; + self.bus.publish(event); + } Ok(()) } } -impl Handler for PublicKeyAggregator { - type Result = ResponseActFuture>; - fn handle(&mut self, msg: NotifyNetwork, _: &mut Self::Context) -> Self::Result { - Box::pin( - self.sortition - .send(GetNodesForE3 { - e3_id: msg.e3_id.clone(), - chain_id: msg.e3_id.chain_id(), - }) - .into_actor(self) - .map(move |res, act, _| { - let nodes = res?; - - let pubkey = msg.pubkey.clone(); - - let event = EnclaveEvent::from(PublicKeyAggregated { - pubkey, - e3_id: msg.e3_id.clone(), - nodes: OrderedSet::from(nodes), - }); - act.bus.do_send(event); - Ok(()) - }), - ) - } -} - impl Handler for PublicKeyAggregator { type Result = (); fn handle(&mut self, _: Die, ctx: &mut Self::Context) -> Self::Result { diff --git a/crates/aggregator/src/threshold_plaintext_aggregator.rs b/crates/aggregator/src/threshold_plaintext_aggregator.rs index 092b438b84..4471338185 100644 --- a/crates/aggregator/src/threshold_plaintext_aggregator.rs +++ b/crates/aggregator/src/threshold_plaintext_aggregator.rs @@ -10,8 +10,8 @@ use actix::prelude::*; use anyhow::{anyhow, bail, Result}; use e3_data::Persistable; use e3_events::{ - ComputeRequest, DecryptionshareCreated, Die, E3id, EnclaveEvent, EventBus, PlaintextAggregated, - Seed, + prelude::*, BusHandle, ComputeRequest, DecryptionshareCreated, Die, E3id, EnclaveEvent, + EnclaveEventData, PlaintextAggregated, Seed, }; use e3_multithread::Multithread; use e3_sortition::{GetNodesForE3, Sortition}; @@ -122,7 +122,7 @@ pub struct ComputeAggregate { pub struct ThresholdPlaintextAggregator { multithread: Addr, - bus: Addr>, + bus: BusHandle, sortition: Addr, e3_id: E3id, state: Persistable, @@ -130,7 +130,7 @@ pub struct ThresholdPlaintextAggregator { pub struct ThresholdPlaintextAggregatorParams { pub multithread: Addr, - pub bus: Addr>, + pub bus: BusHandle, pub sortition: Addr, pub e3_id: E3id, } @@ -235,9 +235,9 @@ impl Actor for ThresholdPlaintextAggregator { impl Handler for ThresholdPlaintextAggregator { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::DecryptionshareCreated { data, .. } => ctx.notify(data), - EnclaveEvent::E3RequestComplete { .. } => ctx.notify(Die), + match msg.into_data() { + EnclaveEventData::DecryptionshareCreated(data) => ctx.notify(data), + EnclaveEventData::E3RequestComplete(_) => ctx.notify(Die), _ => (), } } @@ -336,13 +336,13 @@ impl Handler for ThresholdPlaintextAggregator { act.set_decryption(plaintext.clone())?; // Dispatch the PlaintextAggregated event - let event = EnclaveEvent::from(PlaintextAggregated { + let event = PlaintextAggregated { decrypted_output: plaintext, // Extracting here for now e3_id: act.e3_id.clone(), - }); + }; info!("Dispatching plaintext event {:?}", event); - act.bus.do_send(event); + act.bus.publish(event); Ok(()) }), ) diff --git a/crates/ciphernode-builder/src/ciphernode.rs b/crates/ciphernode-builder/src/ciphernode.rs index f56e32b117..6bf9775d47 100644 --- a/crates/ciphernode-builder/src/ciphernode.rs +++ b/crates/ciphernode-builder/src/ciphernode.rs @@ -6,13 +6,13 @@ use actix::Addr; use e3_data::{DataStore, InMemStore, StoreAddr}; -use e3_events::{EnclaveEvent, EventBus, HistoryCollector}; +use e3_events::{BusHandle, EnclaveEvent, EventBus, HistoryCollector}; #[derive(Clone, Debug)] pub struct CiphernodeHandle { pub address: String, pub store: DataStore, - pub bus: Addr>, + pub bus: BusHandle, pub history: Option>>, pub errors: Option>>, } @@ -21,7 +21,7 @@ impl CiphernodeHandle { pub fn new( address: String, store: DataStore, - bus: Addr>, + bus: BusHandle, history: Option>>, errors: Option>>, ) -> Self { @@ -35,7 +35,7 @@ impl CiphernodeHandle { } pub fn bus(&self) -> Addr> { - self.bus.clone() + self.bus.bus() } pub fn history(&self) -> Option>> { diff --git a/crates/ciphernode-builder/src/ciphernode_builder.rs b/crates/ciphernode-builder/src/ciphernode_builder.rs index c871a68f78..861b567a31 100644 --- a/crates/ciphernode-builder/src/ciphernode_builder.rs +++ b/crates/ciphernode-builder/src/ciphernode_builder.rs @@ -298,6 +298,9 @@ impl CiphernodeBuilder { None }; + // Get a handle from the event bus + let bus = local_bus.into(); + let addr = if let Some(addr) = self.address.clone() { info!("Using eth address = {}", addr); addr @@ -318,7 +321,7 @@ impl CiphernodeBuilder { let default_backend = self.sortition_backend.clone(); let sortition = Sortition::attach( - &local_bus, + &bus, repositories.sortition(), repositories.node_state(), repositories.finalized_committees(), @@ -326,12 +329,12 @@ impl CiphernodeBuilder { ) .await?; - CiphernodeSelector::attach(&local_bus, &sortition, &addr, &store); + CiphernodeSelector::attach(&bus, &sortition, &addr, &store); let mut provider_cache = ProviderCaches::new(); let cipher = &self.cipher; - let coordinator = HistoricalEventCoordinator::setup(local_bus.clone()); + let coordinator = HistoricalEventCoordinator::setup(bus.clone()); let processor = coordinator.clone().recipient(); // TODO: gather an async handle from the event readers that closes when they shutdown and @@ -348,7 +351,7 @@ impl CiphernodeBuilder { .await?; EnclaveSol::attach( &processor, - &local_bus, + &bus, read_provider.clone(), write_provider.clone(), &chain.contracts.enclave.address(), @@ -363,7 +366,7 @@ impl CiphernodeBuilder { let read_provider = provider_cache.ensure_read_provider(chain).await?; EnclaveSolReader::attach( &processor, - &local_bus, + &bus, read_provider.clone(), &chain.contracts.enclave.address(), &repositories.enclave_sol_reader(read_provider.chain_id()), @@ -377,7 +380,7 @@ impl CiphernodeBuilder { let read_provider = provider_cache.ensure_read_provider(chain).await?; BondingRegistrySol::attach( &processor, - &local_bus, + &bus, read_provider.clone(), &chain.contracts.bonding_registry.address(), &repositories.bonding_registry_reader(read_provider.chain_id()), @@ -391,7 +394,7 @@ impl CiphernodeBuilder { let read_provider = provider_cache.ensure_read_provider(chain).await?; CiphernodeRegistrySol::attach( &processor, - &local_bus, + &bus, read_provider.clone(), &chain.contracts.ciphernode_registry.address(), &repositories.ciphernode_registry_reader(read_provider.chain_id()), @@ -406,7 +409,7 @@ impl CiphernodeBuilder { { Ok(write_provider) => { let _writer = CiphernodeRegistrySol::attach_writer( - &local_bus, + &bus, write_provider.clone(), &chain.contracts.ciphernode_registry.address(), self.pubkey_agg, @@ -416,7 +419,7 @@ impl CiphernodeBuilder { if self.pubkey_agg && matches!(self.sortition_backend, SortitionBackend::Score(_)) { info!("Attaching CommitteeFinalizer for score sortition"); - e3_aggregator::CommitteeFinalizer::attach(&local_bus); + e3_aggregator::CommitteeFinalizer::attach(&bus); } } Err(e) => error!( @@ -431,13 +434,13 @@ impl CiphernodeBuilder { coordinator.do_send(CoordinatorStart); // E3 specific setup - let mut e3_builder = E3Router::builder(&local_bus, store.clone()); + let mut e3_builder = E3Router::builder(&bus, store.clone()); if let Some(KeyshareKind::Threshold) = self.keyshare { let multithread = self.ensure_multithread(); info!("Setting up ThresholdKeyshareExtension"); e3_builder = e3_builder.with(ThresholdKeyshareExtension::create( - &local_bus, + &bus, &self.cipher, &multithread, &addr, @@ -449,26 +452,24 @@ impl CiphernodeBuilder { || self.plaintext_agg { info!("Setting up FheExtension"); - e3_builder = e3_builder.with(FheExtension::create(&local_bus, &self.rng)) + e3_builder = e3_builder.with(FheExtension::create(&bus, &self.rng)) } if self.pubkey_agg { info!("Setting up PublicKeyAggregationExtension"); - e3_builder = - e3_builder.with(PublicKeyAggregatorExtension::create(&local_bus, &sortition)) + e3_builder = e3_builder.with(PublicKeyAggregatorExtension::create(&bus)) } if self.plaintext_agg { info!("Setting up PlaintextAggregationExtension (legacy)"); - e3_builder = - e3_builder.with(PlaintextAggregatorExtension::create(&local_bus, &sortition)) + e3_builder = e3_builder.with(PlaintextAggregatorExtension::create(&bus, &sortition)) } if self.threshold_plaintext_agg { info!("Setting up ThresholdPlaintextAggregatorExtension NEW!"); let multithread = self.ensure_multithread(); e3_builder = e3_builder.with(ThresholdPlaintextAggregatorExtension::create( - &local_bus, + &bus, &sortition, &multithread, )) @@ -476,7 +477,7 @@ impl CiphernodeBuilder { if matches!(self.keyshare, Some(KeyshareKind::NonThreshold)) { info!("Setting up KeyshareExtension (legacy)!"); - e3_builder = e3_builder.with(KeyshareExtension::create(&local_bus, &addr, &self.cipher)) + e3_builder = e3_builder.with(KeyshareExtension::create(&bus, &addr, &self.cipher)) } info!("building..."); e3_builder.build().await?; @@ -484,7 +485,7 @@ impl CiphernodeBuilder { Ok(CiphernodeHandle::new( addr.to_owned(), store, - local_bus, + bus, history, errors, )) diff --git a/crates/cli/src/start.rs b/crates/cli/src/start.rs index df3897e6f3..e74fbb324f 100644 --- a/crates/cli/src/start.rs +++ b/crates/cli/src/start.rs @@ -53,7 +53,7 @@ pub async fn execute( peer_id ); - tokio::spawn(listen_for_shutdown(bus.into(), handle)).await?; + tokio::spawn(listen_for_shutdown(bus, handle)).await?; Ok(()) } diff --git a/crates/config/src/load_config.rs b/crates/config/src/load_config.rs index 27466e0b84..9cffd09065 100644 --- a/crates/config/src/load_config.rs +++ b/crates/config/src/load_config.rs @@ -61,7 +61,7 @@ pub fn resolve_config_path>( mod tests { use super::resolve_config_path; use anyhow::Result; - use std::path::{Path, PathBuf}; + use std::path::PathBuf; #[test] fn test_resolve_cli() -> Result<()> { diff --git a/crates/data/src/sled_store.rs b/crates/data/src/sled_store.rs index c45ac70463..87f3d87c79 100644 --- a/crates/data/src/sled_store.rs +++ b/crates/data/src/sled_store.rs @@ -8,7 +8,7 @@ use crate::{Get, Insert, InsertSync, Remove}; use actix::{Actor, ActorContext, Addr, Handler}; use anyhow::{Context, Result}; use e3_events::{ - get_enclave_event_bus, BusError, EnclaveErrorType, EnclaveEvent, EventBus, Subscribe, + get_enclave_bus_handle, prelude::*, BusHandle, EnclaveErrorType, EnclaveEvent, EnclaveEventData, }; use once_cell::sync::Lazy; use sled::Db; @@ -21,7 +21,7 @@ use tracing::{error, info}; pub struct SledStore { db: Option, - bus: Addr>, + bus: BusHandle, } impl Actor for SledStore { @@ -29,7 +29,7 @@ impl Actor for SledStore { } impl SledStore { - pub fn new(bus: &Addr>, path: &PathBuf) -> Result> { + pub fn new(bus: &BusHandle, path: &PathBuf) -> Result> { info!("Starting SledStore with {:?}", path); let db = SledDb::new(PathBuf::from(path))?; @@ -39,7 +39,7 @@ impl SledStore { } .start(); - bus.do_send(Subscribe::new("Shutdown", store.clone().into())); + bus.subscribe("Shutdown", store.clone().into()); Ok(store) } @@ -47,7 +47,7 @@ impl SledStore { pub fn from_db(db: SledDb) -> Result { Ok(Self { db: Some(db), - bus: get_enclave_event_bus(), + bus: get_enclave_bus_handle(), }) } } @@ -112,7 +112,7 @@ impl Handler for SledStore { impl Handler for SledStore { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - if let EnclaveEvent::Shutdown { .. } = msg { + if let EnclaveEventData::Shutdown(_) = msg.get_data() { let _db = self.db.take(); // db will be dropped ctx.stop() } diff --git a/crates/entrypoint/src/helpers/datastore.rs b/crates/entrypoint/src/helpers/datastore.rs index 166ea9d92c..39fc5129d0 100644 --- a/crates/entrypoint/src/helpers/datastore.rs +++ b/crates/entrypoint/src/helpers/datastore.rs @@ -6,14 +6,14 @@ use std::path::PathBuf; -use actix::{Actor, Addr}; +use actix::Actor; use anyhow::Result; use e3_config::AppConfig; use e3_data::{DataStore, InMemStore, SledDb, SledStore}; use e3_data::{Repositories, RepositoriesFactory}; -use e3_events::{get_enclave_event_bus, EnclaveEvent, EventBus}; +use e3_events::{get_enclave_bus_handle, BusHandle, EnclaveEvent}; -pub fn get_sled_store(bus: &Addr>, db_file: &PathBuf) -> Result { +pub fn get_sled_store(bus: &BusHandle, db_file: &PathBuf) -> Result { Ok((&SledStore::new(bus, db_file)?).into()) } @@ -21,10 +21,7 @@ pub fn get_in_mem_store() -> DataStore { (&InMemStore::new(true).start()).into() } -pub fn setup_datastore( - config: &AppConfig, - bus: &Addr>, -) -> Result { +pub fn setup_datastore(config: &AppConfig, bus: &BusHandle) -> Result { let store: DataStore = if !config.use_in_mem_store() { get_sled_store(&bus, &config.db_file())? } else { @@ -34,7 +31,7 @@ pub fn setup_datastore( } pub fn get_repositories(config: &AppConfig) -> Result { - let bus = get_enclave_event_bus(); + let bus = get_enclave_bus_handle(); let store = setup_datastore(config, &bus)?; Ok(store.repositories()) } diff --git a/crates/entrypoint/src/helpers/shutdown.rs b/crates/entrypoint/src/helpers/shutdown.rs index 851381f6af..ae4e6123b2 100644 --- a/crates/entrypoint/src/helpers/shutdown.rs +++ b/crates/entrypoint/src/helpers/shutdown.rs @@ -4,9 +4,8 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use actix::Recipient; use anyhow::Result; -use e3_events::{EnclaveEvent, Shutdown}; +use e3_events::{prelude::*, BusHandle, EnclaveEvent, Shutdown}; use std::time::Duration; use tokio::{ select, @@ -15,7 +14,7 @@ use tokio::{ }; use tracing::{error, info}; -pub async fn listen_for_shutdown(bus: Recipient, mut handle: JoinHandle>) { +pub async fn listen_for_shutdown(bus: BusHandle, mut handle: JoinHandle>) { let mut sigterm = signal(SignalKind::terminate()).expect("Failed to create SIGTERM signal stream"); select! { @@ -23,7 +22,10 @@ pub async fn listen_for_shutdown(bus: Recipient, mut handle: JoinH info!("SIGTERM received, initiating graceful shutdown..."); // Stop the actor system - let _ = bus.send(EnclaveEvent::from(Shutdown)).await; + bus.publish(Shutdown); + + // Wait for all events to propagate + tokio::time::sleep(Duration::from_secs(2)).await; // Abort the spawned task handle.abort(); diff --git a/crates/entrypoint/src/start/aggregator_start.rs b/crates/entrypoint/src/start/aggregator_start.rs index c9a93f386a..3789ba2f1b 100644 --- a/crates/entrypoint/src/start/aggregator_start.rs +++ b/crates/entrypoint/src/start/aggregator_start.rs @@ -4,13 +4,12 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use actix::Addr; use anyhow::Result; use e3_ciphernode_builder::CiphernodeBuilder; use e3_config::AppConfig; use e3_crypto::Cipher; use e3_data::RepositoriesFactory; -use e3_events::{get_enclave_event_bus, EnclaveEvent, EventBus}; +use e3_events::{get_enclave_bus_handle, BusHandle, EnclaveEvent}; use e3_net::{NetEventTranslator, NetRepositoryFactory}; use e3_test_helpers::{PlaintextWriter, PublicKeyWriter}; use rand::SeedableRng; @@ -28,15 +27,15 @@ pub async fn execute( pubkey_write_path: Option, plaintext_write_path: Option, experimental_trbfv: bool, -) -> Result<(Addr>, JoinHandle>, String)> { - let bus = get_enclave_event_bus(); +) -> Result<(BusHandle, JoinHandle>, String)> { + let bus = get_enclave_bus_handle(); let rng = Arc::new(Mutex::new(ChaCha20Rng::from_rng(OsRng)?)); let store = setup_datastore(config, &bus)?; let repositories = store.repositories(); let cipher = Arc::new(Cipher::from_file(config.key_file()).await?); let mut builder = CiphernodeBuilder::new(rng.clone(), cipher.clone()) - .with_source_bus(&bus) + .with_source_bus(&bus.bus()) .with_datastore(store) .with_chains(&config.chains()) .with_sortition_score() diff --git a/crates/entrypoint/src/start/start.rs b/crates/entrypoint/src/start/start.rs index 1cc8bec79a..9ba3e3ab35 100644 --- a/crates/entrypoint/src/start/start.rs +++ b/crates/entrypoint/src/start/start.rs @@ -4,15 +4,14 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use actix::Addr; use alloy::primitives::Address; use anyhow::Result; use e3_ciphernode_builder::CiphernodeBuilder; use e3_config::AppConfig; use e3_crypto::Cipher; use e3_data::RepositoriesFactory; -use e3_events::get_enclave_event_bus; -use e3_events::{EnclaveEvent, EventBus}; +use e3_events::BusHandle; +use e3_events::{get_enclave_bus_handle, EnclaveEvent}; use e3_net::{NetEventTranslator, NetRepositoryFactory}; use rand::SeedableRng; use rand_chacha::rand_core::OsRng; @@ -27,17 +26,17 @@ pub async fn execute( config: &AppConfig, address: Address, experimental_trbfv: bool, -) -> Result<(Addr>, JoinHandle>, String)> { +) -> Result<(BusHandle, JoinHandle>, String)> { let rng = Arc::new(Mutex::new(rand_chacha::ChaCha20Rng::from_rng(OsRng)?)); - let bus = get_enclave_event_bus(); + let bus = get_enclave_bus_handle(); let cipher = Arc::new(Cipher::from_file(&config.key_file()).await?); let store = setup_datastore(&config, &bus)?; let repositories = store.repositories(); let mut builder = CiphernodeBuilder::new(rng.clone(), cipher.clone()) .with_address(&address.to_string()) - .with_source_bus(&bus) + .with_source_bus(&bus.bus()) .with_datastore(store) .with_sortition_score() .with_chains(&config.chains()) diff --git a/crates/events/Cargo.toml b/crates/events/Cargo.toml index 9363256125..bbdb604ae7 100644 --- a/crates/events/Cargo.toml +++ b/crates/events/Cargo.toml @@ -21,6 +21,7 @@ futures-util = { workspace = true } once_cell = { workspace = true } serde = { workspace = true } sha2 = { workspace = true } +strum = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } tokio = { workspace = true } diff --git a/crates/events/src/bus_handle.rs b/crates/events/src/bus_handle.rs new file mode 100644 index 0000000000..b0e2e3135c --- /dev/null +++ b/crates/events/src/bus_handle.rs @@ -0,0 +1,87 @@ +// 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 actix::{Addr, Recipient}; + +use crate::{ + traits::{ + CompositeEvent, ErrorDispatcher, ErrorFactory, Event, EventConstructorWithTimestamp, + EventFactory, EventPublisher, EventSubscriber, + }, + ErrorEvent, EventBus, Subscribe, +}; + +#[derive(Clone, Debug)] +pub struct BusHandle { + bus: Addr>, +} + +impl BusHandle { + pub fn new(bus: Addr>) -> Self { + Self { bus } + } + + pub fn bus(&self) -> Addr> { + self.bus.clone() + } +} + +impl EventPublisher for BusHandle { + fn publish(&self, data: impl Into) { + let evt = self.event_from(data); + self.bus.do_send(evt); + } + + fn publish_from_remote(&self, data: impl Into, ts: u128) { + let evt = self.event_from_remote_source(data, ts); + self.bus.do_send(evt) + } + + fn naked_dispatch(&self, event: E) { + self.bus.do_send(event); + } +} + +impl ErrorDispatcher for BusHandle +where + E: CompositeEvent, +{ + fn err(&self, err_type: E::ErrType, error: impl Into) { + let evt = self.event_from_error(err_type, error); + self.bus.do_send(evt); + } +} + +impl EventFactory for BusHandle { + fn event_from(&self, data: impl Into) -> E { + // TODO: add self.hcl.tick() + E::new_with_timestamp(data.into(), 0) + } + + fn event_from_remote_source(&self, data: impl Into, ts: u128) -> E { + // TODO: add self.hcl.receive(ts) + E::new_with_timestamp(data.into(), ts) + } +} + +impl ErrorFactory for BusHandle { + fn event_from_error(&self, err_type: E::ErrType, error: impl Into) -> E { + E::from_error(err_type, error) + } +} + +impl EventSubscriber for BusHandle { + fn subscribe(&self, event_type: &str, recipient: Recipient) { + self.bus.do_send(Subscribe::new(event_type, recipient)) + } + + fn subscribe_all(&self, event_types: &[&str], recipient: Recipient) { + for event_type in event_types.into_iter() { + self.bus + .do_send(Subscribe::new(*event_type, recipient.clone())); + } + } +} diff --git a/crates/events/src/enclave_event/enclave_error.rs b/crates/events/src/enclave_event/enclave_error.rs index 35ab08fc94..1487cc7836 100644 --- a/crates/events/src/enclave_event/enclave_error.rs +++ b/crates/events/src/enclave_event/enclave_error.rs @@ -9,8 +9,7 @@ use serde::{Deserialize, Serialize}; use std::fmt::{self, Display}; pub trait FromError { - type Error; - fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> Self; + fn from_error(err_type: EnclaveErrorType, error: impl Into) -> Self; } #[derive(Message, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -39,20 +38,19 @@ pub enum EnclaveErrorType { } impl EnclaveError { - pub fn new(err_type: EnclaveErrorType, message: &str) -> Self { + pub fn new(err_type: EnclaveErrorType, message: impl Into) -> Self { Self { err_type, - message: message.to_string(), + message: message.into().to_string(), } } } impl FromError for EnclaveError { - type Error = anyhow::Error; - fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> Self { + fn from_error(err_type: EnclaveErrorType, error: impl Into) -> Self { Self { err_type, - message: error.to_string(), + message: error.into(), } } } diff --git a/crates/events/src/enclave_event/mod.rs b/crates/events/src/enclave_event/mod.rs index 4c6cb2cf39..0048b85890 100644 --- a/crates/events/src/enclave_event/mod.rs +++ b/crates/events/src/enclave_event/mod.rs @@ -54,13 +54,17 @@ pub use plaintext_output_published::*; pub use publickey_aggregated::*; pub use publish_document::*; pub use shutdown::*; +use strum::IntoStaticStr; pub use test_event::*; pub use threshold_share_created::*; pub use ticket_balance_updated::*; pub use ticket_generated::*; pub use ticket_submitted::*; -use crate::{E3id, ErrorEvent, Event, EventId}; +use crate::{ + traits::{ErrorEvent, Event, EventConstructorWithTimestamp}, + E3id, EventId, +}; use actix::Message; use serde::{Deserialize, Serialize}; use std::{ @@ -68,130 +72,62 @@ use std::{ hash::Hash, }; -/// Macro to help define From traits for EnclaveEvent -macro_rules! impl_from_event { +/// Macro to help define From traits for EnclaveEventData +macro_rules! impl_into_event_data { ($($variant:ident),*) => { $( - impl From<$variant> for EnclaveEvent { - fn from(data: $variant) -> Self { - EnclaveEvent::$variant { - id: EventId::hash(data.clone()), - data: data.clone(), - } + impl From<$variant> for EnclaveEventData { + fn from(data:$variant) -> Self { + EnclaveEventData::$variant(data) } } )* }; } +#[derive(Clone, Debug, PartialEq, Eq, Hash, IntoStaticStr, Serialize, Deserialize)] +pub enum EnclaveEventData { + KeyshareCreated(KeyshareCreated), + E3Requested(E3Requested), + PublicKeyAggregated(PublicKeyAggregated), + CiphertextOutputPublished(CiphertextOutputPublished), + DecryptionshareCreated(DecryptionshareCreated), + PlaintextAggregated(PlaintextAggregated), + PublishDocumentRequested(PublishDocumentRequested), + CiphernodeSelected(CiphernodeSelected), + CiphernodeAdded(CiphernodeAdded), + CiphernodeRemoved(CiphernodeRemoved), + TicketBalanceUpdated(TicketBalanceUpdated), + ConfigurationUpdated(ConfigurationUpdated), + OperatorActivationChanged(OperatorActivationChanged), + CommitteePublished(CommitteePublished), + CommitteeRequested(CommitteeRequested), + CommitteeFinalizeRequested(CommitteeFinalizeRequested), + CommitteeFinalized(CommitteeFinalized), + TicketGenerated(TicketGenerated), + TicketSubmitted(TicketSubmitted), + PlaintextOutputPublished(PlaintextOutputPublished), + EnclaveError(EnclaveError), + E3RequestComplete(E3RequestComplete), + Shutdown(Shutdown), + DocumentReceived(DocumentReceived), + ThresholdShareCreated(ThresholdShareCreated), + /// This is a test event to use in testing + TestEvent(TestEvent), +} + +impl EnclaveEventData { + pub fn event_type(&self) -> String { + let name: &'static str = self.into(); + name.to_string() + } +} + #[derive(Message, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[rtype(result = "()")] -pub enum EnclaveEvent { - KeyshareCreated { - id: EventId, - data: KeyshareCreated, - }, - E3Requested { - id: EventId, - data: E3Requested, - }, - PublicKeyAggregated { - id: EventId, - data: PublicKeyAggregated, - }, - CiphertextOutputPublished { - id: EventId, - data: CiphertextOutputPublished, - }, - DecryptionshareCreated { - id: EventId, - data: DecryptionshareCreated, - }, - PlaintextAggregated { - id: EventId, - data: PlaintextAggregated, - }, - PublishDocumentRequested { - id: EventId, - data: PublishDocumentRequested, - }, - CiphernodeSelected { - id: EventId, - data: CiphernodeSelected, - }, - CiphernodeAdded { - id: EventId, - data: CiphernodeAdded, - }, - CiphernodeRemoved { - id: EventId, - data: CiphernodeRemoved, - }, - TicketBalanceUpdated { - id: EventId, - data: TicketBalanceUpdated, - }, - ConfigurationUpdated { - id: EventId, - data: ConfigurationUpdated, - }, - OperatorActivationChanged { - id: EventId, - data: OperatorActivationChanged, - }, - CommitteePublished { - id: EventId, - data: CommitteePublished, - }, - CommitteeRequested { - id: EventId, - data: CommitteeRequested, - }, - CommitteeFinalizeRequested { - id: EventId, - data: CommitteeFinalizeRequested, - }, - CommitteeFinalized { - id: EventId, - data: CommitteeFinalized, - }, - TicketGenerated { - id: EventId, - data: TicketGenerated, - }, - TicketSubmitted { - id: EventId, - data: TicketSubmitted, - }, - PlaintextOutputPublished { - id: EventId, - data: PlaintextOutputPublished, - }, - EnclaveError { - id: EventId, - data: EnclaveError, - }, - E3RequestComplete { - id: EventId, - data: E3RequestComplete, - }, - Shutdown { - id: EventId, - data: Shutdown, - }, - DocumentReceived { - id: EventId, - data: DocumentReceived, - }, - ThresholdShareCreated { - id: EventId, - data: ThresholdShareCreated, - }, - /// This is a test event to use in testing - TestEvent { - id: EventId, - data: TestEvent, - }, +pub struct EnclaveEvent { + id: EventId, + payload: EnclaveEventData, } impl EnclaveEvent { @@ -210,120 +146,70 @@ impl EnclaveEvent { impl Event for EnclaveEvent { type Id = EventId; + type Data = EnclaveEventData; + // type FromError = anyhow::Error; + // type ErrType = EnclaveErrorType; fn event_type(&self) -> String { - let s = format!("{:?}", self); - extract_enclave_event_name(&s).to_string() + self.payload.event_type() } fn event_id(&self) -> Self::Id { self.get_id() } + + fn get_data(&self) -> &EnclaveEventData { + &self.payload + } + fn into_data(self) -> EnclaveEventData { + self.payload + } } impl ErrorEvent for EnclaveEvent { - type Error = EnclaveError; - type ErrorType = EnclaveErrorType; - fn as_error(&self) -> Option<&Self::Error> { - match self { - EnclaveEvent::EnclaveError { data, .. } => Some(data), - _ => None, - } - } + type ErrType = EnclaveErrorType; + type FromError = anyhow::Error; - fn from_error(err_type: Self::ErrorType, error: anyhow::Error) -> Self { - EnclaveEvent::from(EnclaveError::new(err_type, error.to_string().as_str())) + fn from_error(err_type: Self::ErrType, msg: impl Into) -> Self { + let payload = EnclaveError::new(err_type, msg); + let id = EventId::hash(&payload); + EnclaveEvent { + payload: payload.into(), + id, + } } } impl From for EventId { fn from(value: EnclaveEvent) -> Self { - match value { - EnclaveEvent::KeyshareCreated { id, .. } => id, - EnclaveEvent::E3Requested { id, .. } => id, - EnclaveEvent::PublicKeyAggregated { id, .. } => id, - EnclaveEvent::CiphertextOutputPublished { id, .. } => id, - EnclaveEvent::DecryptionshareCreated { id, .. } => id, - EnclaveEvent::PlaintextAggregated { id, .. } => id, - EnclaveEvent::PublishDocumentRequested { id, .. } => id, - EnclaveEvent::CiphernodeSelected { id, .. } => id, - EnclaveEvent::CiphernodeAdded { id, .. } => id, - EnclaveEvent::CiphernodeRemoved { id, .. } => id, - EnclaveEvent::TicketBalanceUpdated { id, .. } => id, - EnclaveEvent::ConfigurationUpdated { id, .. } => id, - EnclaveEvent::OperatorActivationChanged { id, .. } => id, - EnclaveEvent::CommitteePublished { id, .. } => id, - EnclaveEvent::CommitteeRequested { id, .. } => id, - EnclaveEvent::CommitteeFinalizeRequested { id, .. } => id, - EnclaveEvent::PlaintextOutputPublished { id, .. } => id, - EnclaveEvent::EnclaveError { id, .. } => id, - EnclaveEvent::E3RequestComplete { id, .. } => id, - EnclaveEvent::Shutdown { id, .. } => id, - EnclaveEvent::TestEvent { id, .. } => id, - EnclaveEvent::DocumentReceived { id, .. } => id, - EnclaveEvent::ThresholdShareCreated { id, .. } => id, - EnclaveEvent::CommitteeFinalized { id, .. } => id, - EnclaveEvent::TicketGenerated { id, .. } => id, - EnclaveEvent::TicketSubmitted { id, .. } => id, - } + value.id } } impl EnclaveEvent { pub fn get_e3_id(&self) -> Option { - match self.clone() { - EnclaveEvent::KeyshareCreated { data, .. } => Some(data.e3_id), - EnclaveEvent::E3Requested { data, .. } => Some(data.e3_id), - EnclaveEvent::PublicKeyAggregated { data, .. } => Some(data.e3_id), - EnclaveEvent::CiphertextOutputPublished { data, .. } => Some(data.e3_id), - EnclaveEvent::DecryptionshareCreated { data, .. } => Some(data.e3_id), - EnclaveEvent::PlaintextAggregated { data, .. } => Some(data.e3_id), - EnclaveEvent::CiphernodeSelected { data, .. } => Some(data.e3_id), - EnclaveEvent::ThresholdShareCreated { data, .. } => Some(data.e3_id), - EnclaveEvent::CommitteePublished { data, .. } => Some(data.e3_id), - EnclaveEvent::CommitteeRequested { data, .. } => Some(data.e3_id), - EnclaveEvent::CommitteeFinalizeRequested { data, .. } => Some(data.e3_id), - EnclaveEvent::PlaintextOutputPublished { data, .. } => Some(data.e3_id), - EnclaveEvent::CommitteeFinalized { data, .. } => Some(data.e3_id), - EnclaveEvent::TicketGenerated { data, .. } => Some(data.e3_id), - EnclaveEvent::TicketSubmitted { data, .. } => Some(data.e3_id), + match self.payload { + EnclaveEventData::KeyshareCreated(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::E3Requested(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::PublicKeyAggregated(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::CiphertextOutputPublished(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::DecryptionshareCreated(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::PlaintextAggregated(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::CiphernodeSelected(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::ThresholdShareCreated(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::CommitteePublished(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::CommitteeRequested(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::CommitteeFinalizeRequested(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::PlaintextOutputPublished(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::CommitteeFinalized(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::TicketGenerated(ref data) => Some(data.e3_id.clone()), + EnclaveEventData::TicketSubmitted(ref data) => Some(data.e3_id.clone()), _ => None, } } - pub fn get_data(&self) -> String { - match self.clone() { - EnclaveEvent::KeyshareCreated { data, .. } => format!("{}", data), - EnclaveEvent::E3Requested { data, .. } => format!("{}", data), - EnclaveEvent::PublicKeyAggregated { data, .. } => format!("{}", data), - EnclaveEvent::CiphertextOutputPublished { data, .. } => format!("{}", data), - EnclaveEvent::DecryptionshareCreated { data, .. } => format!("{}", data), - EnclaveEvent::PlaintextAggregated { data, .. } => format!("{}", data), - EnclaveEvent::PublishDocumentRequested { data, .. } => format!("{}", data), - EnclaveEvent::CiphernodeSelected { data, .. } => format!("{}", data), - EnclaveEvent::CiphernodeAdded { data, .. } => format!("{}", data), - EnclaveEvent::CiphernodeRemoved { data, .. } => format!("{}", data), - EnclaveEvent::TicketBalanceUpdated { data, .. } => format!("{:?}", data), - EnclaveEvent::ConfigurationUpdated { data, .. } => format!("{:?}", data), - EnclaveEvent::OperatorActivationChanged { data, .. } => format!("{:?}", data), - EnclaveEvent::CommitteePublished { data, .. } => format!("{:?}", data), - EnclaveEvent::CommitteeRequested { data, .. } => format!("{:?}", data), - EnclaveEvent::CommitteeFinalizeRequested { data, .. } => format!("{:?}", data), - EnclaveEvent::PlaintextOutputPublished { data, .. } => format!("{:?}", data), - EnclaveEvent::E3RequestComplete { data, .. } => format!("{}", data), - EnclaveEvent::EnclaveError { data, .. } => format!("{:?}", data), - EnclaveEvent::Shutdown { data, .. } => format!("{:?}", data), - EnclaveEvent::ThresholdShareCreated { data, .. } => format!("{:?}", data), - EnclaveEvent::TestEvent { data, .. } => format!("{:?}", data), - EnclaveEvent::DocumentReceived { data, .. } => format!("{:?}", data), - EnclaveEvent::CommitteeFinalized { data, .. } => format!("{:?}", data), - EnclaveEvent::TicketGenerated { data, .. } => format!("{:?}", data), - EnclaveEvent::TicketSubmitted { data, .. } => format!("{:?}", data), - // _ => "".to_string(), - } - } } -impl_from_event!( +impl_into_event_data!( KeyshareCreated, E3Requested, PublicKeyAggregated, @@ -352,14 +238,6 @@ impl_from_event!( ThresholdShareCreated ); -impl FromError for EnclaveEvent { - type Error = anyhow::Error; - fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> Self { - let error_event = EnclaveError::from_error(err_type, error); - EnclaveEvent::from(error_event) - } -} - impl TryFrom<&EnclaveEvent> for EnclaveError { type Error = anyhow::Error; fn try_from(value: &EnclaveEvent) -> Result { @@ -370,7 +248,7 @@ impl TryFrom<&EnclaveEvent> for EnclaveError { impl TryFrom for EnclaveError { type Error = anyhow::Error; fn try_from(value: EnclaveEvent) -> Result { - if let EnclaveEvent::EnclaveError { data, .. } = value.clone() { + if let EnclaveEventData::EnclaveError(data) = value.payload.clone() { Ok(data) } else { return Err(anyhow::anyhow!("Not an enclave error {:?}", value)); @@ -380,23 +258,15 @@ impl TryFrom for EnclaveError { impl fmt::Display for EnclaveEvent { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&format!("{}({})", self.event_type(), self.get_data())) + f.write_str(&format!("{:?}", self)) } } -fn extract_enclave_event_name(s: &str) -> &str { - let bytes = s.as_bytes(); - for (i, &item) in bytes.iter().enumerate() { - if item == b' ' || item == b'(' { - return &s[..i]; - } - } - s -} - -impl EnclaveEvent { - pub fn event_type(&self) -> String { - let s = format!("{:?}", self); - extract_enclave_event_name(&s).to_string() +impl EventConstructorWithTimestamp for EnclaveEvent { + fn new_with_timestamp(data: Self::Data, _ts: u128) -> Self { + let payload = data.into(); + let id = EventId::hash(&payload); + // hcl.receive(remote_ts)?; + EnclaveEvent { id, payload } } } diff --git a/crates/events/src/eventbus.rs b/crates/events/src/eventbus.rs index 09fd3ee027..883663d9fb 100644 --- a/crates/events/src/eventbus.rs +++ b/crates/events/src/eventbus.rs @@ -4,34 +4,14 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +use crate::traits::{ErrorEvent, Event}; +use crate::{prelude::*, BusHandle, CompositeEvent}; use actix::prelude::*; use bloom::{BloomFilter, ASMS}; use std::collections::{HashMap, VecDeque}; -use std::fmt::Display; -use std::hash::Hash; use std::marker::PhantomData; use tracing::info; -////////////////////////////////////////////////////////////////////////////// -// Core Traits -////////////////////////////////////////////////////////////////////////////// - -/// Trait that must be implemented by events used with EventBus -pub trait Event: Message + Clone + Display + Send + Sync + Unpin + 'static { - type Id: Hash + Eq + Clone + Unpin + Send + Sync + Display; - fn event_type(&self) -> String; - fn event_id(&self) -> Self::Id; -} - -/// Trait for events that contain an error -pub trait ErrorEvent: Event { - type Error: Clone; - type ErrorType; - - fn as_error(&self) -> Option<&Self::Error>; - fn from_error(err_type: Self::ErrorType, error: anyhow::Error) -> Self; -} - ////////////////////////////////////////////////////////////////////////////// // Configuration ////////////////////////////////////////////////////////////////////////////// @@ -89,6 +69,7 @@ impl EventBus { source.do_send(Subscribe::new("*", addr.clone().recipient())); addr } + pub fn error(source: &Addr>) -> Addr> { let addr = HistoryCollector::::new().start(); source.do_send(Subscribe::new("EnclaveError", addr.clone().recipient())); @@ -152,6 +133,12 @@ impl Handler for EventBus { } } +impl From>> for BusHandle { + fn from(value: Addr>) -> Self { + BusHandle::new(value) + } +} + ////////////////////////////////////////////////////////////////////////////// // Subscribe Message ////////////////////////////////////////////////////////////////////////////// @@ -295,7 +282,7 @@ impl Handler for HistoryCollector { } #[derive(Message)] -#[rtype(result = "Vec")] +#[rtype(result = "Vec")] pub struct GetErrors(PhantomData); impl GetErrors { @@ -304,27 +291,6 @@ impl GetErrors { } } -////////////////////////////////////////////////////////////////////////////// -// Error Bus Trait -////////////////////////////////////////////////////////////////////////////// - -/// Trait to send errors directly to the bus -pub trait BusError { - fn err(&self, err_type: E::ErrorType, err: anyhow::Error); -} - -impl BusError for Addr> { - fn err(&self, err_type: E::ErrorType, err: anyhow::Error) { - self.do_send(E::from_error(err_type, err)) - } -} - -impl BusError for Recipient { - fn err(&self, err_type: E::ErrorType, err: anyhow::Error) { - self.do_send(E::from_error(err_type, err)) - } -} - ////////////////////////////////////////////////////////////////////////////// // History Collector ////////////////////////////////////////////////////////////////////////////// @@ -451,11 +417,11 @@ impl Handler for HistoryCollector { ////////////////////////////////////////////////////////////////////////////// /// Function to help with testing when we want to maintain a vec of events -pub fn new_event_bus_with_history() -> (Addr>, Addr>) { - let bus = EventBus::::default().start(); +pub fn new_event_bus_with_history() -> (BusHandle, Addr>) +{ + let bus: BusHandle = EventBus::::default().start().into(); let history = HistoryCollector::new().start(); - - bus.do_send(Subscribe::new("*", history.clone().recipient())); + bus.subscribe("*", history.clone().recipient()); (bus, history) } diff --git a/crates/events/src/eventbus_factory.rs b/crates/events/src/eventbus_factory.rs index 6049b8115a..f7312d6f71 100644 --- a/crates/events/src/eventbus_factory.rs +++ b/crates/events/src/eventbus_factory.rs @@ -12,9 +12,9 @@ use std::any::TypeId; use std::collections::HashMap; use std::sync::Mutex; +use crate::traits::Event; +use crate::BusHandle; use crate::EnclaveEvent; -use crate::ErrorEvent; -use crate::Event; use crate::EventBus; use crate::HistoryCollector; use crate::Subscribe; @@ -60,7 +60,7 @@ impl EventBusFactory { event_bus } - pub fn get_error_collector(&self) -> Addr> { + pub fn get_error_collector(&self) -> Addr> { let type_id = TypeId::of::(); let mut error_collector_cache = self.error_collector_cache.lock().unwrap(); @@ -91,3 +91,7 @@ pub fn get_enclave_event_bus() -> Addr> { pub fn get_error_collector() -> Addr> { EventBusFactory::instance().get_error_collector() } + +pub fn get_enclave_bus_handle() -> BusHandle { + get_enclave_event_bus().into() +} diff --git a/crates/events/src/lib.rs b/crates/events/src/lib.rs index 61c3d987f0..1f356b3a47 100644 --- a/crates/events/src/lib.rs +++ b/crates/events/src/lib.rs @@ -4,6 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +mod bus_handle; mod correlation_id; mod e3id; mod enclave_event; @@ -12,8 +13,11 @@ mod eventbus; mod eventbus_factory; pub mod hlc; mod ordered_set; +pub mod prelude; mod seed; +mod traits; +pub use bus_handle::*; pub use correlation_id::*; pub use e3id::*; pub use enclave_event::*; @@ -22,3 +26,4 @@ pub use eventbus::*; pub use eventbus_factory::*; pub use ordered_set::*; pub use seed::*; +pub use traits::*; diff --git a/crates/events/src/ordered_set.rs b/crates/events/src/ordered_set.rs index 976f42467b..13f08295aa 100644 --- a/crates/events/src/ordered_set.rs +++ b/crates/events/src/ordered_set.rs @@ -9,7 +9,7 @@ use std::collections::BTreeSet; use std::fmt; use std::hash::{Hash, Hasher}; -#[derive(Clone, Serialize, Deserialize)] +#[derive(Clone, Default, Serialize, Deserialize)] pub struct OrderedSet(BTreeSet); impl OrderedSet { diff --git a/crates/events/src/prelude.rs b/crates/events/src/prelude.rs new file mode 100644 index 0000000000..e039b5f298 --- /dev/null +++ b/crates/events/src/prelude.rs @@ -0,0 +1,8 @@ +// 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. + +// Export a prelude to ensure all traits are available +pub use crate::traits::*; diff --git a/crates/events/src/traits.rs b/crates/events/src/traits.rs new file mode 100644 index 0000000000..ba98fda9da --- /dev/null +++ b/crates/events/src/traits.rs @@ -0,0 +1,92 @@ +// 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 actix::{Message, Recipient}; +use std::fmt::Display; +use std::hash::Hash; + +/// Trait that must be implemented by events used with EventBus +pub trait Event: + Message + Clone + Display + Send + Sync + Unpin + Sized + 'static +{ + type Id: Hash + Eq + Clone + Unpin + Send + Sync + Display; + + /// Payload for the Event + type Data; + + fn event_type(&self) -> String; + fn event_id(&self) -> Self::Id; + fn get_data(&self) -> &Self::Data; + fn into_data(self) -> Self::Data; +} + +/// Trait for events that contain an error +pub trait ErrorEvent: Event { + /// Error type associated with this event + type ErrType; + type FromError; + + fn from_error(err_type: Self::ErrType, error: impl Into) -> Self; +} + +/// An EventFactory creates events +pub trait EventFactory { + /// Create a new event from the given event data, apply a local HLC timestamp. + /// + /// This method should be used for events that have originated locally. + fn event_from(&self, data: impl Into) -> E; + /// Create a new event from the given event data, apply the given remote HLC time to ensure correct + /// event ordering. + /// + /// This method should be used for events that originated from remote sources. + fn event_from_remote_source(&self, data: impl Into, ts: u128) -> E; +} + +/// An ErrorFactory creates errors. +pub trait ErrorFactory { + /// Create an error event from the given error. + fn event_from_error(&self, err_type: E::ErrType, error: impl Into) -> E; +} + +/// An EventPublisher publishes events on it's internal EventBus +pub trait EventPublisher { + /// Create a new event from the given event data, apply a local HLC timestamp and publish it + /// to the event bus. + /// + /// This method should be used for events that have originated locally. + fn publish(&self, data: impl Into); + /// Create a new event from the given event data, apply the given remote HLC time to ensure correct + /// event ordering and publish it. + /// + /// This method should be used for events that originated from remote sources. + fn publish_from_remote(&self, data: impl Into, ts: u128); + /// Dispatch the given event without applying any HLC transformation. + fn naked_dispatch(&self, event: E); +} + +/// Trait for dispatching errors to an inner event bus +pub trait ErrorDispatcher { + /// Dispatch the error to the event bus. + fn err(&self, err_type: E::ErrType, error: impl Into); +} + +/// Trait to subscribe to events +pub trait EventSubscriber { + /// Subscribe the recipient to events matching the given event type + fn subscribe(&self, event_type: &str, recipient: Recipient); + /// Subscribe the recipient to events matching any of the given event types + fn subscribe_all(&self, event_types: &[&str], recipient: Recipient); +} + +/// Trait to create an event with a timestamp from its associated type data +pub trait EventConstructorWithTimestamp: Event + Sized { + /// Create an event passing attaching a specific timestamp. + fn new_with_timestamp(data: Self::Data, ts: u128) -> Self; +} + +pub trait CompositeEvent: ErrorEvent + EventConstructorWithTimestamp {} + +impl CompositeEvent for E where E: Sized + Event + ErrorEvent + EventConstructorWithTimestamp {} diff --git a/crates/evm-helpers/tests/helpers.rs b/crates/evm-helpers/tests/helpers.rs index 4fd3d3f9a9..1757f8b9dc 100644 --- a/crates/evm-helpers/tests/helpers.rs +++ b/crates/evm-helpers/tests/helpers.rs @@ -6,7 +6,6 @@ // helpers.rs use alloy::{ - network::Ethereum, node_bindings::{Anvil, AnvilInstance}, providers::{Provider, ProviderBuilder, WsConnect}, signers::local::PrivateKeySigner, @@ -14,7 +13,6 @@ use alloy::{ }; use eyre::Result; use EmitLogs::EmitLogsInstance; -use Enclave::EnclaveInstance; sol!( #[sol(rpc)] diff --git a/crates/evm-helpers/tests/integration.rs b/crates/evm-helpers/tests/integration.rs index 48a15de85a..746490ea56 100644 --- a/crates/evm-helpers/tests/integration.rs +++ b/crates/evm-helpers/tests/integration.rs @@ -8,7 +8,6 @@ mod helpers; use alloy::consensus::BlockHeader; use alloy::providers::ext::AnvilApi; use alloy::{node_bindings::Anvil, providers::ProviderBuilder, sol}; -use e3_evm_helpers::block_listener; use e3_evm_helpers::{block_listener::BlockListener, event_listener::EventListener}; use eyre::Result; use helpers::setup_logs_contract; diff --git a/crates/evm/src/bonding_registry_sol.rs b/crates/evm/src/bonding_registry_sol.rs index b89e5a2bb6..af199634ae 100644 --- a/crates/evm/src/bonding_registry_sol.rs +++ b/crates/evm/src/bonding_registry_sol.rs @@ -16,7 +16,7 @@ use alloy::{ }; use anyhow::Result; use e3_data::Repository; -use e3_events::{EnclaveEvent, EventBus}; +use e3_events::{BusHandle, EnclaveEvent, EnclaveEventData}; use tracing::{error, info, trace}; sol!( @@ -40,10 +40,10 @@ impl From for e3_events::TicketBalanceUpdated { } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: TicketBalanceUpdatedWithChainId) -> Self { let payload: e3_events::TicketBalanceUpdated = value.into(); - EnclaveEvent::from(payload) + Self::from(payload) } } @@ -85,28 +85,28 @@ impl From for e3_events::OperatorActivatio } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: OperatorActivationChangedWithChainId) -> Self { let payload: e3_events::OperatorActivationChanged = value.into(); - EnclaveEvent::from(payload) + Self::from(payload) } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: ConfigurationUpdatedWithChainId) -> Self { let payload: e3_events::ConfigurationUpdated = value.into(); - EnclaveEvent::from(payload) + Self::from(payload) } } -pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option { +pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option { match topic { Some(&IBondingRegistry::TicketBalanceUpdated::SIGNATURE_HASH) => { let Ok(event) = IBondingRegistry::TicketBalanceUpdated::decode_log_data(data) else { error!("Error parsing event TicketBalanceUpdated after topic was matched!"); return None; }; - Some(EnclaveEvent::from(TicketBalanceUpdatedWithChainId( + Some(EnclaveEventData::from(TicketBalanceUpdatedWithChainId( event, chain_id, ))) } @@ -116,16 +116,16 @@ pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option< error!("Error parsing event OperatorActivationChanged after topic was matched!"); return None; }; - Some(EnclaveEvent::from(OperatorActivationChangedWithChainId( - event, chain_id, - ))) + Some(EnclaveEventData::from( + OperatorActivationChangedWithChainId(event, chain_id), + )) } Some(&IBondingRegistry::ConfigurationUpdated::SIGNATURE_HASH) => { let Ok(event) = IBondingRegistry::ConfigurationUpdated::decode_log_data(data) else { error!("Error parsing event ConfigurationUpdated after topic was matched!"); return None; }; - Some(EnclaveEvent::from(ConfigurationUpdatedWithChainId( + Some(EnclaveEventData::from(ConfigurationUpdatedWithChainId( event, chain_id, ))) } @@ -145,7 +145,7 @@ pub struct BondingRegistrySolReader; impl BondingRegistrySolReader { pub async fn attach

( processor: &Recipient, - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: &str, repository: &Repository, @@ -179,7 +179,7 @@ pub struct BondingRegistrySol; impl BondingRegistrySol { pub async fn attach

( processor: &Recipient, - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: &str, repository: &Repository, diff --git a/crates/evm/src/ciphernode_registry_sol.rs b/crates/evm/src/ciphernode_registry_sol.rs index 2e12c08c08..a6cf0918f4 100644 --- a/crates/evm/src/ciphernode_registry_sol.rs +++ b/crates/evm/src/ciphernode_registry_sol.rs @@ -18,9 +18,9 @@ use alloy::{ use anyhow::Result; use e3_data::Repository; use e3_events::{ - BusError, CommitteeFinalizeRequested, CommitteeFinalized, E3id, EnclaveErrorType, EnclaveEvent, - EventBus, OrderedSet, PublicKeyAggregated, Seed, Shutdown, Subscribe, TicketGenerated, - TicketId, + prelude::*, BusHandle, CommitteeFinalizeRequested, CommitteeFinalized, E3id, EnclaveErrorType, + EnclaveEvent, EnclaveEventData, EventSubscriber, OrderedSet, PublicKeyAggregated, Seed, + Shutdown, TicketGenerated, TicketId, }; use tracing::{error, info, trace}; @@ -53,10 +53,10 @@ impl From for e3_events::CiphernodeAdded { } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: CiphernodeAddedWithChainId) -> Self { let payload: e3_events::CiphernodeAdded = value.into(); - EnclaveEvent::from(payload) + EnclaveEventData::from(payload) } } @@ -81,10 +81,10 @@ impl From for e3_events::CiphernodeRemoved { } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: CiphernodeRemovedWithChainId) -> Self { let payload: e3_events::CiphernodeRemoved = value.into(); - EnclaveEvent::from(payload) + EnclaveEventData::from(payload) } } @@ -103,10 +103,10 @@ impl From for e3_events::CommitteeRequested { } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: CommitteeRequestedWithChainId) -> Self { let payload: e3_events::CommitteeRequested = value.into(); - EnclaveEvent::from(payload) + EnclaveEventData::from(payload) } } @@ -127,10 +127,10 @@ impl From for CommitteeFinalized { } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: CommitteeFinalizedWithChainId) -> Self { let payload: e3_events::CommitteeFinalized = value.into(); - EnclaveEvent::from(payload) + EnclaveEventData::from(payload) } } @@ -148,21 +148,21 @@ impl From for e3_events::TicketSubmitted { } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: TicketSubmittedWithChainId) -> Self { let payload: e3_events::TicketSubmitted = value.into(); - EnclaveEvent::from(payload) + EnclaveEventData::from(payload) } } -pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option { +pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option { match topic { Some(&ICiphernodeRegistry::CiphernodeAdded::SIGNATURE_HASH) => { let Ok(event) = ICiphernodeRegistry::CiphernodeAdded::decode_log_data(data) else { error!("Error parsing event CiphernodeAdded after topic was matched!"); return None; }; - Some(EnclaveEvent::from(CiphernodeAddedWithChainId( + Some(EnclaveEventData::from(CiphernodeAddedWithChainId( event, chain_id, ))) } @@ -171,7 +171,7 @@ pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option< error!("Error parsing event CiphernodeRemoved after topic was matched!"); return None; }; - Some(EnclaveEvent::from(CiphernodeRemovedWithChainId( + Some(EnclaveEventData::from(CiphernodeRemovedWithChainId( event, chain_id, ))) } @@ -180,7 +180,7 @@ pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option< error!("Error parsing event CommitteeRequested after topic was matched!"); return None; }; - Some(EnclaveEvent::from(CommitteeRequestedWithChainId( + Some(EnclaveEventData::from(CommitteeRequestedWithChainId( event, chain_id, ))) } @@ -189,7 +189,7 @@ pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option< error!("Error parsing event CommitteeFinalized after topic was matched!"); return None; }; - Some(EnclaveEvent::from(CommitteeFinalizedWithChainId( + Some(EnclaveEventData::from(CommitteeFinalizedWithChainId( event, chain_id, ))) } @@ -198,7 +198,7 @@ pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option< error!("Error parsing event TicketSubmitted after topic was matched!"); return None; }; - Some(EnclaveEvent::from(TicketSubmittedWithChainId( + Some(EnclaveEventData::from(TicketSubmittedWithChainId( event, chain_id, ))) } @@ -218,7 +218,7 @@ pub struct CiphernodeRegistrySolReader; impl CiphernodeRegistrySolReader { pub async fn attach

( processor: &Recipient, - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: &str, repository: &Repository, @@ -250,12 +250,12 @@ impl CiphernodeRegistrySolReader { pub struct CiphernodeRegistrySolWriter

{ provider: EthProvider

, contract_address: Address, - bus: Addr>, + bus: BusHandle, } impl CiphernodeRegistrySolWriter

{ pub async fn new( - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: Address, ) -> Result { @@ -267,7 +267,7 @@ impl CiphernodeRegistrySolWriter } pub async fn attach( - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: &str, is_aggregator: bool, @@ -277,26 +277,21 @@ impl CiphernodeRegistrySolWriter .start(); if is_aggregator { - let _ = bus - .send(Subscribe::new("PublicKeyAggregated", addr.clone().into())) - .await; - let _ = bus - .send(Subscribe::new( - "CommitteeFinalizeRequested", - addr.clone().into(), - )) - .await; + bus.subscribe_all( + &["PublicKeyAggregated", "CommitteeFinalizeRequested"], + addr.clone().into(), + ) } - // Subscribe to TicketGenerated for ticket submission - let _ = bus - .send(Subscribe::new("TicketGenerated", addr.clone().into())) - .await; - - // Stop gracefully on shutdown - let _ = bus - .send(Subscribe::new("Shutdown", addr.clone().into())) - .await; + bus.subscribe_all( + &[ + // Subscribe to TicketGenerated for ticket submission + "TicketGenerated", + // Stop gracefully on shutdown + "Shutdown", + ], + addr.clone().into(), + ); Ok(addr) } @@ -312,25 +307,25 @@ impl Handler type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::PublicKeyAggregated { data, .. } => { + match msg.into_data() { + EnclaveEventData::PublicKeyAggregated(data) => { // Only publish if the src and destination chains match if self.provider.chain_id() == data.e3_id.chain_id() { ctx.notify(data); } } - EnclaveEvent::CommitteeFinalizeRequested { data, .. } => { + EnclaveEventData::CommitteeFinalizeRequested(data) => { if self.provider.chain_id() == data.e3_id.chain_id() { ctx.notify(data); } } - EnclaveEvent::TicketGenerated { data, .. } => { + EnclaveEventData::TicketGenerated(data) => { // Submit ticket if chain matches if self.provider.chain_id() == data.e3_id.chain_id() { ctx.notify(data); } } - EnclaveEvent::Shutdown { data, .. } => ctx.notify(data), + EnclaveEventData::Shutdown(data) => ctx.notify(data), _ => (), } } @@ -446,6 +441,7 @@ pub async fn submit_ticket_to_registry( e3_id: E3id, ticket_number: u64, ) -> Result { + info!("Calling: contract.submitTicket(..)"); let e3_id: U256 = e3_id.try_into()?; let ticket_number = U256::from(ticket_number); let from_address = provider.provider().default_signer_address(); @@ -467,6 +463,7 @@ pub async fn finalize_committee_on_registry Result { + info!("Calling: contract.finalizeCommittee(..)"); let e3_id: U256 = e3_id.try_into()?; let from_address = provider.provider().default_signer_address(); let current_nonce = provider @@ -487,6 +484,7 @@ pub async fn publish_committee_to_registry nodes: OrderedSet, public_key: Vec, ) -> Result { + info!("Calling: contract.publishCommittee(..)"); let e3_id: U256 = e3_id.try_into()?; let public_key = Bytes::from(public_key); let nodes_vec: Vec

= nodes @@ -513,7 +511,7 @@ pub struct CiphernodeRegistrySol; impl CiphernodeRegistrySol { pub async fn attach

( processor: &Recipient, - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: &str, repository: &Repository, @@ -537,7 +535,7 @@ impl CiphernodeRegistrySol { } pub async fn attach_writer

( - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: &str, is_aggregator: bool, diff --git a/crates/evm/src/enclave_sol.rs b/crates/evm/src/enclave_sol.rs index a0ec11695a..387116f92c 100644 --- a/crates/evm/src/enclave_sol.rs +++ b/crates/evm/src/enclave_sol.rs @@ -8,18 +8,18 @@ use crate::{ enclave_sol_reader::EnclaveSolReader, enclave_sol_writer::EnclaveSolWriter, event_reader::EvmEventReaderState, helpers::EthProvider, EnclaveEvmEvent, }; -use actix::{Addr, Recipient}; +use actix::Recipient; use alloy::providers::{Provider, WalletProvider}; use anyhow::Result; use e3_data::Repository; -use e3_events::{EnclaveEvent, EventBus}; +use e3_events::{BusHandle, EnclaveEvent}; pub struct EnclaveSol; impl EnclaveSol { pub async fn attach( processor: &Recipient, - bus: &Addr>, + bus: &BusHandle, read_provider: EthProvider, write_provider: EthProvider, contract_address: &str, diff --git a/crates/evm/src/enclave_sol_reader.rs b/crates/evm/src/enclave_sol_reader.rs index c06eff602a..3a2a938005 100644 --- a/crates/evm/src/enclave_sol_reader.rs +++ b/crates/evm/src/enclave_sol_reader.rs @@ -13,7 +13,7 @@ use alloy::providers::Provider; use alloy::{sol, sol_types::SolEvent}; use anyhow::Result; use e3_data::Repository; -use e3_events::{E3id, EnclaveEvent, EventBus}; +use e3_events::{BusHandle, E3id, EnclaveEvent, EnclaveEventData}; use e3_utils::utility_types::ArcBytes; use num_bigint::BigUint; use tracing::{error, info, trace}; @@ -44,10 +44,10 @@ impl From for e3_events::E3Requested { } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: E3RequestedWithChainId) -> Self { let payload: e3_events::E3Requested = value.into(); - EnclaveEvent::from(payload) + payload.into() } } @@ -64,30 +64,32 @@ impl From for e3_events::CiphertextOutputP } } -impl From for EnclaveEvent { +impl From for EnclaveEventData { fn from(value: CiphertextOutputPublishedWithChainId) -> Self { let payload: e3_events::CiphertextOutputPublished = value.into(); - EnclaveEvent::from(payload) + payload.into() } } -pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option { +pub fn extractor(data: &LogData, topic: Option<&B256>, chain_id: u64) -> Option { match topic { Some(&IEnclave::E3Requested::SIGNATURE_HASH) => { let Ok(event) = IEnclave::E3Requested::decode_log_data(data) else { error!("Error parsing event E3Requested after topic matched!"); return None; }; - Some(EnclaveEvent::from(E3RequestedWithChainId(event, chain_id))) + Some(EnclaveEventData::from(E3RequestedWithChainId( + event, chain_id, + ))) } Some(&IEnclave::CiphertextOutputPublished::SIGNATURE_HASH) => { let Ok(event) = IEnclave::CiphertextOutputPublished::decode_log_data(data) else { error!("Error parsing event CiphertextOutputPublished after topic matched!"); return None; }; - Some(EnclaveEvent::from(CiphertextOutputPublishedWithChainId( - event, chain_id, - ))) + Some(EnclaveEventData::from( + CiphertextOutputPublishedWithChainId(event, chain_id), + )) } _topic => { trace!( @@ -105,7 +107,7 @@ pub struct EnclaveSolReader; impl EnclaveSolReader { pub async fn attach

( processor: &Recipient, - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: &str, repository: &Repository, diff --git a/crates/evm/src/enclave_sol_writer.rs b/crates/evm/src/enclave_sol_writer.rs index 66b6b3816c..35aade7e7f 100644 --- a/crates/evm/src/enclave_sol_writer.rs +++ b/crates/evm/src/enclave_sol_writer.rs @@ -17,9 +17,12 @@ use alloy::{ rpc::types::TransactionReceipt, }; use anyhow::Result; +use e3_events::prelude::*; +use e3_events::BusHandle; +use e3_events::EnclaveEvent; +use e3_events::EnclaveEventData; use e3_events::Shutdown; -use e3_events::{BusError, E3id, EnclaveErrorType, PlaintextAggregated, Subscribe}; -use e3_events::{EnclaveEvent, EventBus}; +use e3_events::{E3id, EnclaveErrorType, PlaintextAggregated}; use tracing::info; sol!( @@ -32,12 +35,12 @@ sol!( pub struct EnclaveSolWriter

{ provider: EthProvider

, contract_address: Address, - bus: Addr>, + bus: BusHandle, } impl EnclaveSolWriter

{ pub fn new( - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: Address, ) -> Result { @@ -49,18 +52,12 @@ impl EnclaveSolWriter

{ } pub async fn attach( - bus: &Addr>, + bus: &BusHandle, provider: EthProvider

, contract_address: &str, ) -> Result>> { let addr = EnclaveSolWriter::new(bus, provider, contract_address.parse()?)?.start(); - - bus.send(Subscribe::new("PlaintextAggregated", addr.clone().into())) - .await?; - - bus.send(Subscribe::new("Shutdown", addr.clone().into())) - .await?; - + bus.subscribe_all(&["PlaintextAggregated", "Shutdown"], addr.clone().into()); Ok(addr) } } @@ -73,14 +70,14 @@ impl Handler for E type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::PlaintextAggregated { data, .. } => { + match msg.into_data() { + EnclaveEventData::PlaintextAggregated(data) => { // Only publish if the src and destination chains match if self.provider.chain_id() == data.e3_id.chain_id() { ctx.notify(data); } } - EnclaveEvent::Shutdown { data, .. } => ctx.notify(data), + EnclaveEventData::Shutdown(data) => ctx.notify(data), _ => (), } } diff --git a/crates/evm/src/event_reader.rs b/crates/evm/src/event_reader.rs index b206b1568e..eec8f1e463 100644 --- a/crates/evm/src/event_reader.rs +++ b/crates/evm/src/event_reader.rs @@ -14,7 +14,8 @@ use alloy::providers::Provider; use alloy::rpc::types::Filter; use anyhow::{anyhow, Result}; use e3_data::{AutoPersist, Persistable, Repository}; -use e3_events::{BusError, EnclaveErrorType, EnclaveEvent, EventBus, EventId, Subscribe}; +use e3_events::{prelude::*, EnclaveErrorType, EnclaveEvent, EnclaveEventData, EventId}; +use e3_events::{BusHandle, Event}; use futures_util::stream::StreamExt; use std::collections::HashSet; use tokio::select; @@ -30,13 +31,13 @@ pub enum EnclaveEvmEvent { HistoricalSyncComplete, /// An actual event from the blockchain Event { - event: EnclaveEvent, + event: EnclaveEventData, block: Option, }, } impl EnclaveEvmEvent { - pub fn new(event: EnclaveEvent, block: Option) -> Self { + pub fn new(event: EnclaveEventData, block: Option) -> Self { Self::Event { event, block } } @@ -49,11 +50,11 @@ pub type ExtractorFn = fn(&LogData, Option<&B256>, u64) -> Option; pub struct EvmEventReaderParams

{ provider: EthProvider

, - extractor: ExtractorFn, + extractor: ExtractorFn, contract_address: Address, start_block: Option, processor: Recipient, - bus: Addr>, + bus: BusHandle, state: Persistable, rpc_url: String, } @@ -71,7 +72,7 @@ pub struct EvmEventReader

{ /// The contract address contract_address: Address, /// The Extractor function to determine which events to extract and convert to EnclaveEvents - extractor: ExtractorFn, + extractor: ExtractorFn, /// A shutdown receiver to listen to for shutdown signals sent to the loop this is only used /// internally. You should send the Shutdown signal to the reader directly or via the EventBus shutdown_rx: Option>, @@ -82,7 +83,7 @@ pub struct EvmEventReader

{ /// Processor to forward events an actor processor: Recipient, /// Event bus for error propagation only - bus: Addr>, + bus: BusHandle, /// The auto persistable state of the event reader state: Persistable, /// The RPC URL for the provider @@ -108,11 +109,11 @@ impl EvmEventReader

{ pub async fn attach( provider: EthProvider

, - extractor: ExtractorFn, + extractor: ExtractorFn, contract_address: &str, start_block: Option, processor: &Recipient, - bus: &Addr>, + bus: &BusHandle, repository: &Repository, rpc_url: String, ) -> Result> { @@ -136,7 +137,7 @@ impl EvmEventReader

{ processor.do_send(EnclaveEvmEvent::RegisterReader); - bus.do_send(Subscribe::new("Shutdown", addr.clone().into())); + bus.subscribe("Shutdown", addr.clone().into()); Ok(addr) } } @@ -187,10 +188,10 @@ async fn stream_from_evm( provider: EthProvider

, contract_address: &Address, reader_addr: Addr>, - extractor: fn(&LogData, Option<&B256>, u64) -> Option, + extractor: fn(&LogData, Option<&B256>, u64) -> Option, mut shutdown: oneshot::Receiver<()>, start_block: Option, - bus: &Addr>, + bus: &BusHandle, rpc_url: String, ) { let chain_id = provider.chain_id(); @@ -258,7 +259,7 @@ async fn stream_from_evm( continue; }; - trace!("Extracted EVM Event: {}", event); + trace!("Extracted EVM Event: {:?}", event); reader_addr.do_send(EnclaveEvmEvent::new(event, block_number)); } None => break, // Stream ended @@ -291,7 +292,7 @@ impl Handler for EvmEventReader

type Result = (); fn handle(&mut self, msg: EnclaveEvent, _: &mut Self::Context) -> Self::Result { - if let EnclaveEvent::Shutdown { .. } = msg { + if let EnclaveEventData::Shutdown(_) = msg.into_data() { if let Some(shutdown) = self.shutdown_tx.take() { let _ = shutdown.send(()); } diff --git a/crates/evm/src/historical_event_coordinator.rs b/crates/evm/src/historical_event_coordinator.rs index 6b6317494f..12f1b9e466 100644 --- a/crates/evm/src/historical_event_coordinator.rs +++ b/crates/evm/src/historical_event_coordinator.rs @@ -6,13 +6,13 @@ use crate::EnclaveEvmEvent; use actix::prelude::*; -use e3_events::{EnclaveEvent, EventBus}; +use e3_events::{prelude::*, BusHandle, EnclaveEvent, EnclaveEventData}; use tracing::info; #[derive(Clone)] struct BufferedEvent { block: u64, - event: EnclaveEvent, + event: EnclaveEventData, } /// Message to start forwarding buffered events after all readers have registered @@ -30,13 +30,13 @@ pub struct HistoricalEventCoordinator { /// Buffered events during historical sync buffered_events: Vec, /// Target to forward events to (typically EventBus) - target: Addr>, + target: BusHandle, /// Whether we've started forwarding (after Start message) started: bool, } impl HistoricalEventCoordinator { - pub fn new(target: Addr>) -> Self { + pub fn new(target: BusHandle) -> Self { Self { registered_count: 0, completed_count: 0, @@ -46,7 +46,7 @@ impl HistoricalEventCoordinator { } } - pub fn setup(target: Addr>) -> Addr { + pub fn setup(target: BusHandle) -> Addr { Self::new(target).start() } @@ -60,7 +60,7 @@ impl HistoricalEventCoordinator { let count = self.buffered_events.len(); for BufferedEvent { event, .. } in self.buffered_events.drain(..) { - self.target.do_send(event); + self.target.publish(event); } info!( @@ -108,13 +108,10 @@ impl Handler for HistoricalEventCoordinator { EnclaveEvmEvent::Event { event, block } => { if !self.started || !self.all_readers_complete() { if let Some(block) = block { - self.buffered_events.push(BufferedEvent { - block, - event: event.clone(), - }); + self.buffered_events.push(BufferedEvent { block, event }); } } else { - self.target.do_send(event); + self.target.publish(event); } } } diff --git a/crates/evm/tests/integration.rs b/crates/evm/tests/integration.rs index 799a254eb3..a315276c2a 100644 --- a/crates/evm/tests/integration.rs +++ b/crates/evm/tests/integration.rs @@ -17,7 +17,8 @@ use anyhow::Result; use e3_data::Repository; use e3_entrypoint::helpers::datastore::get_in_mem_store; use e3_events::{ - new_event_bus_with_history, EnclaveEvent, GetEvents, HistoryCollector, Shutdown, TestEvent, + new_event_bus_with_history, prelude::*, EnclaveEvent, EnclaveEventData, GetEvents, + HistoryCollector, Shutdown, TestEvent, }; use e3_evm::{helpers::EthProvider, CoordinatorStart, EvmEventReader, HistoricalEventCoordinator}; use std::time::Duration; @@ -33,16 +34,19 @@ fn test_event_extractor( data: &LogData, topic: Option<&FixedBytes<32>>, _chain_id: u64, -) -> Option { +) -> Option { match topic { Some(&EmitLogs::ValueChanged::SIGNATURE_HASH) => { let Ok(event) = EmitLogs::ValueChanged::decode_log_data(data) else { return None; }; - Some(EnclaveEvent::from(TestEvent { - msg: event.value, - entropy: event.count.try_into().unwrap(), // This prevents de-duplication in tests - })) + Some( + TestEvent { + msg: event.value, + entropy: event.count.try_into().unwrap(), // This prevents de-duplication in tests + } + .into(), + ) } _ => None, } @@ -54,8 +58,8 @@ async fn get_msgs(history_collector: &Addr>) -> R .await?; let msgs: Vec = history .into_iter() - .filter_map(|evt| match evt { - EnclaveEvent::TestEvent { data, .. } => Some(data.msg), + .filter_map(|evt| match evt.into_data() { + EnclaveEventData::TestEvent(data) => Some(data.msg), _ => None, }) .collect(); @@ -121,8 +125,8 @@ async fn evm_reader() -> Result<()> { let msgs: Vec<_> = history .into_iter() - .filter_map(|evt| match evt { - EnclaveEvent::TestEvent { data, .. } => Some(data.msg), + .filter_map(|evt| match evt.into_data() { + EnclaveEventData::TestEvent(data) => Some(data.msg), _ => None, }) .collect(); @@ -200,8 +204,8 @@ async fn ensure_historical_events() -> Result<()> { let msgs: Vec<_> = history .into_iter() - .filter_map(|evt| match evt { - EnclaveEvent::TestEvent { data, .. } => Some(data.msg), + .filter_map(|evt| match evt.into_data() { + EnclaveEventData::TestEvent(data) => Some(data.msg), _ => None, }) .collect(); @@ -265,7 +269,7 @@ async fn ensure_resume_after_shutdown() -> Result<()> { // Ensure shutdown doesn't cause event to be lost. sleep(Duration::from_millis(10)).await; - addr1.send(EnclaveEvent::from(Shutdown)).await?; + addr1.send(bus.event_from(Shutdown)).await?; for msg in ["these", "are", "not", "lost"] { contract diff --git a/crates/fhe/src/ext.rs b/crates/fhe/src/ext.rs index d51a4ac9a0..8c568f34f8 100644 --- a/crates/fhe/src/ext.rs +++ b/crates/fhe/src/ext.rs @@ -5,11 +5,12 @@ // or FITNESS FOR A PARTICULAR PURPOSE. use crate::{Fhe, FheRepositoryFactory}; -use actix::Addr; use anyhow::{anyhow, Result}; use async_trait::async_trait; use e3_data::{FromSnapshotWithParams, RepositoriesFactory, Snapshot}; -use e3_events::{BusError, E3Requested, EnclaveErrorType, EnclaveEvent, EventBus}; +use e3_events::{ + prelude::*, BusHandle, E3Requested, EnclaveErrorType, EnclaveEvent, EnclaveEventData, +}; use e3_request::{E3Context, E3ContextSnapshot, E3Extension, TypedKey}; use e3_utils::SharedRng; use std::sync::Arc; @@ -19,11 +20,11 @@ pub const FHE_KEY: TypedKey> = TypedKey::new("fhe"); /// TODO: move these to each package with access on MyStruct::launcher() pub struct FheExtension { rng: SharedRng, - bus: Addr>, + bus: BusHandle, } impl FheExtension { - pub fn create(bus: &Addr>, rng: &SharedRng) -> Box { + pub fn create(bus: &BusHandle, rng: &SharedRng) -> Box { Box::new(Self { rng: rng.clone(), bus: bus.clone(), @@ -37,7 +38,7 @@ const ERROR_FHE_FAILED_TO_DECODE: &str = "Failed to decode encoded FHE params"; impl E3Extension for FheExtension { fn on_event(&self, ctx: &mut E3Context, evt: &EnclaveEvent) { // Saving the fhe on Committee Requested - let EnclaveEvent::E3Requested { data, .. } = evt else { + let EnclaveEventData::E3Requested(data) = evt.get_data() else { return; }; diff --git a/crates/fhe/src/fhe.rs b/crates/fhe/src/fhe.rs index 8e6171d8a1..cd2b3507c2 100644 --- a/crates/fhe/src/fhe.rs +++ b/crates/fhe/src/fhe.rs @@ -15,10 +15,10 @@ use e3_data::{FromSnapshotWithParams, Snapshot}; use e3_events::{OrderedSet, Seed}; use e3_utils::{ArcBytes, SharedRng}; use fhe::{ - bfv::{BfvParameters, Ciphertext, Encoding, Plaintext, PublicKey, SecretKey}, + bfv::{BfvParameters, Ciphertext, Plaintext, PublicKey, SecretKey}, mbfv::{AggregateIter, CommonRandomPoly, DecryptionShare, PublicKeyShare}, }; -use fhe_traits::{Deserialize, DeserializeParametrized, FheDecoder, Serialize}; +use fhe_traits::{Deserialize, DeserializeParametrized, Serialize}; use rand::SeedableRng; use rand_chacha::ChaCha20Rng; use std::sync::{Arc, Mutex}; diff --git a/crates/indexer/src/callback_queue.rs b/crates/indexer/src/callback_queue.rs index 4a5694a152..75d7dd99ba 100644 --- a/crates/indexer/src/callback_queue.rs +++ b/crates/indexer/src/callback_queue.rs @@ -82,9 +82,10 @@ impl CallbackQueue { /// Execute all pending callbacks up to and including the given time pub async fn execute_until_including(&self, time: u64) -> Result<()> { - info!("execute_until_including..."); let handlers = self.inner.take_until_including(time); - info!("found {} handlers", handlers.len()); + if handlers.len() > 0 { + info!("found {} handlers", handlers.len()); + } for callback in handlers { callback().await?; } @@ -99,7 +100,7 @@ mod tests { #[tokio::test] async fn test_single_callback_executes() { - let mut queue = CallbackQueue::new(); + let queue = CallbackQueue::new(); let called = Arc::new(Mutex::new(false)); let called_clone = called.clone(); @@ -117,7 +118,7 @@ mod tests { #[tokio::test] async fn test_callback_not_executed_before_threshold() { - let mut queue = CallbackQueue::new(); + let queue = CallbackQueue::new(); let called = Arc::new(Mutex::new(false)); let called_clone = called.clone(); @@ -135,7 +136,7 @@ mod tests { #[tokio::test] async fn test_multiple_callbacks_execute() { - let mut queue = CallbackQueue::new(); + let queue = CallbackQueue::new(); let counter = Arc::new(Mutex::new(0)); let c1 = counter.clone(); @@ -171,7 +172,7 @@ mod tests { #[tokio::test] async fn test_error_propagation() { - let mut queue = CallbackQueue::new(); + let queue = CallbackQueue::new(); queue.push(100, || async { Err(eyre::eyre!("test error")) }); diff --git a/crates/indexer/tests/helpers.rs b/crates/indexer/tests/helpers.rs index 43dfdb1d7b..bc9f8a0b2e 100644 --- a/crates/indexer/tests/helpers.rs +++ b/crates/indexer/tests/helpers.rs @@ -8,7 +8,6 @@ use std::sync::Arc; // helpers.rs use alloy::{ - network::Ethereum, node_bindings::{Anvil, AnvilInstance}, providers::{Provider, ProviderBuilder, WsConnect}, signers::local::PrivateKeySigner, @@ -30,18 +29,6 @@ sol!( "tests/fixtures/emit_logs.json" ); -pub async fn setup_fake_enclave() -> Result<( - EnclaveInstance, - String, - String, - AnvilInstance, -)> { - let (provider, endpoint, anvil) = setup_provider().await?; - let contract = Enclave::deploy(provider).await?; - let address = contract.address().to_string(); - Ok((contract, address, endpoint, anvil)) -} - pub async fn setup_two_contracts() -> Result<( EnclaveInstance, String, diff --git a/crates/keyshare/src/ext.rs b/crates/keyshare/src/ext.rs index 134c664e23..c7bb8c95f4 100644 --- a/crates/keyshare/src/ext.rs +++ b/crates/keyshare/src/ext.rs @@ -13,24 +13,20 @@ use anyhow::{anyhow, Result}; use async_trait::async_trait; use e3_crypto::Cipher; use e3_data::{AutoPersist, RepositoriesFactory}; -use e3_events::{BusError, EnclaveErrorType, EnclaveEvent, EventBus}; +use e3_events::{prelude::*, BusHandle, EnclaveErrorType, EnclaveEvent, EnclaveEventData}; use e3_fhe::ext::FHE_KEY; use e3_multithread::Multithread; use e3_request::{E3Context, E3ContextSnapshot, E3Extension, META_KEY}; use std::sync::Arc; pub struct KeyshareExtension { - bus: Addr>, + bus: BusHandle, address: String, cipher: Arc, } impl KeyshareExtension { - pub fn create( - bus: &Addr>, - address: &str, - cipher: &Arc, - ) -> Box { + pub fn create(bus: &BusHandle, address: &str, cipher: &Arc) -> Box { Box::new(Self { bus: bus.clone(), address: address.to_owned(), @@ -46,7 +42,7 @@ const ERROR_KEYSHARE_FHE_MISSING: &str = impl E3Extension for KeyshareExtension { fn on_event(&self, ctx: &mut E3Context, evt: &EnclaveEvent) { // if this is NOT a CiphernodeSelected event then ignore - let EnclaveEvent::CiphernodeSelected { data, .. } = evt else { + let EnclaveEventData::CiphernodeSelected(data) = evt.get_data() else { return; }; @@ -121,7 +117,7 @@ impl E3Extension for KeyshareExtension { } pub struct ThresholdKeyshareExtension { - bus: Addr>, + bus: BusHandle, cipher: Arc, address: String, multithread: Addr, @@ -129,7 +125,7 @@ pub struct ThresholdKeyshareExtension { impl ThresholdKeyshareExtension { pub fn create( - bus: &Addr>, + bus: &BusHandle, cipher: &Arc, multithread: &Addr, address: &str, @@ -147,7 +143,7 @@ impl ThresholdKeyshareExtension { impl E3Extension for ThresholdKeyshareExtension { fn on_event(&self, ctx: &mut E3Context, evt: &EnclaveEvent) { // if this is NOT a CiphernodeSelected event then ignore - let EnclaveEvent::CiphernodeSelected { data, .. } = evt else { + let EnclaveEventData::CiphernodeSelected(data) = evt.get_data() else { return; }; diff --git a/crates/keyshare/src/keyshare.rs b/crates/keyshare/src/keyshare.rs index 57e3840617..065009e39e 100644 --- a/crates/keyshare/src/keyshare.rs +++ b/crates/keyshare/src/keyshare.rs @@ -9,8 +9,8 @@ use anyhow::{anyhow, Result}; use e3_crypto::Cipher; use e3_data::Persistable; use e3_events::{ - BusError, CiphernodeSelected, CiphertextOutputPublished, DecryptionshareCreated, Die, - E3RequestComplete, EnclaveErrorType, EnclaveEvent, EventBus, FromError, KeyshareCreated, + prelude::*, BusHandle, CiphernodeSelected, CiphertextOutputPublished, DecryptionshareCreated, + Die, E3RequestComplete, EnclaveErrorType, EnclaveEvent, EnclaveEventData, KeyshareCreated, }; use e3_fhe::{DecryptCiphertext, Fhe}; use e3_utils::utility_types::ArcBytes; @@ -19,7 +19,7 @@ use tracing::warn; pub struct Keyshare { fhe: Arc, - bus: Addr>, + bus: BusHandle, secret: Persistable>, address: String, cipher: Arc, @@ -30,7 +30,7 @@ impl Actor for Keyshare { } pub struct KeyshareParams { - pub bus: Addr>, + pub bus: BusHandle, pub secret: Persistable>, pub fhe: Arc, pub address: String, @@ -76,11 +76,11 @@ impl Handler for Keyshare { type Result = (); fn handle(&mut self, event: EnclaveEvent, ctx: &mut actix::Context) -> Self::Result { - match event { - EnclaveEvent::CiphernodeSelected { data, .. } => ctx.notify(data), - EnclaveEvent::CiphertextOutputPublished { data, .. } => ctx.notify(data), - EnclaveEvent::E3RequestComplete { data, .. } => ctx.notify(data), - EnclaveEvent::Shutdown { .. } => ctx.notify(Die), + match event.into_data() { + EnclaveEventData::CiphernodeSelected(data) => ctx.notify(data), + EnclaveEventData::CiphertextOutputPublished(data) => ctx.notify(data), + EnclaveEventData::E3RequestComplete(data) => ctx.notify(data), + EnclaveEventData::Shutdown(_) => ctx.notify(Die), _ => (), } } @@ -94,27 +94,24 @@ impl Handler for Keyshare { // generate keyshare let Ok((secret, pubkey)) = self.fhe.generate_keyshare() else { - self.bus.do_send(EnclaveEvent::from_error( + self.bus.err( EnclaveErrorType::KeyGeneration, anyhow!("Error creating Keyshare for {e3_id}"), - )); + ); return; }; // Save secret on state if let Err(err) = self.set_secret(secret) { - self.bus.do_send(EnclaveEvent::from_error( - EnclaveErrorType::KeyGeneration, - err, - )) + self.bus.err(EnclaveErrorType::KeyGeneration, err) }; // Broadcast the KeyshareCreated message - self.bus.do_send(EnclaveEvent::from(KeyshareCreated { + self.bus.publish(KeyshareCreated { pubkey, e3_id, node: self.address.clone(), - })); + }); } } @@ -158,12 +155,12 @@ impl Handler for Keyshare { return; }; - self.bus.do_send(EnclaveEvent::from(DecryptionshareCreated { + self.bus.publish(DecryptionshareCreated { party_id: 0, // Not used e3_id, decryption_share: vec![ArcBytes::from_bytes(&decryption_share)], node: self.address.clone(), - })); + }); } } diff --git a/crates/keyshare/src/threshold_keyshare.rs b/crates/keyshare/src/threshold_keyshare.rs index 8d8a5b5918..ccea059247 100644 --- a/crates/keyshare/src/threshold_keyshare.rs +++ b/crates/keyshare/src/threshold_keyshare.rs @@ -9,9 +9,9 @@ use anyhow::{anyhow, bail, Result}; use e3_crypto::{Cipher, SensitiveBytes}; use e3_data::Persistable; use e3_events::{ - CiphernodeSelected, CiphertextOutputPublished, ComputeRequest, ComputeResponse, - DecryptionshareCreated, E3id, EnclaveEvent, EventBus, KeyshareCreated, PartyId, ThresholdShare, - ThresholdShareCreated, + prelude::*, BusHandle, CiphernodeSelected, CiphertextOutputPublished, ComputeRequest, + ComputeResponse, DecryptionshareCreated, E3id, EnclaveEvent, EnclaveEventData, KeyshareCreated, + PartyId, ThresholdShare, ThresholdShareCreated, }; use e3_fhe::create_crp; use e3_multithread::Multithread; @@ -269,14 +269,14 @@ impl TryInto for ThresholdKeyshareState { } pub struct ThresholdKeyshareParams { - pub bus: Addr>, + pub bus: BusHandle, pub cipher: Arc, pub multithread: Addr, pub state: Persistable, } pub struct ThresholdKeyshare { - bus: Addr>, + bus: BusHandle, cipher: Arc, decryption_key_collector: Option>, multithread: Addr, @@ -526,7 +526,7 @@ impl ThresholdKeyshare { .map(|s| PvwEncrypted::new(s.decrypt(&self.cipher)?)) .collect::>()?; - self.bus.do_send(EnclaveEvent::from(ThresholdShareCreated { + self.bus.publish(ThresholdShareCreated { e3_id, share: Arc::new(ThresholdShare { party_id, @@ -535,7 +535,7 @@ impl ThresholdKeyshare { sk_sss, }), external: false, - })); + }); Ok(()) } @@ -630,11 +630,11 @@ impl ThresholdKeyshare { let address = state.get_address().to_owned(); let current: ReadyForDecryption = state.clone().try_into()?; - self.bus.do_send(EnclaveEvent::from(KeyshareCreated { + self.bus.publish(KeyshareCreated { pubkey: current.pk_share, e3_id, node: address, - })); + }); Ok(()) } @@ -689,15 +689,15 @@ impl ThresholdKeyshare { let e3_id = state.e3_id; let decryption_share = msg.d_share_poly; - let event = EnclaveEvent::from(DecryptionshareCreated { + let event = DecryptionshareCreated { party_id, node, e3_id, decryption_share, - }); + }; // send the decryption share - self.bus.do_send(event); + self.bus.publish(event); // mark as complete self.state.try_mutate(|s| { @@ -754,10 +754,10 @@ impl ThresholdKeyshare { impl Handler for ThresholdKeyshare { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::CiphernodeSelected { data, .. } => ctx.notify(data), - EnclaveEvent::CiphertextOutputPublished { data, .. } => ctx.notify(data), - EnclaveEvent::ThresholdShareCreated { data, .. } => { + match msg.into_data() { + EnclaveEventData::CiphernodeSelected(data) => ctx.notify(data), + EnclaveEventData::CiphertextOutputPublished(data) => ctx.notify(data), + EnclaveEventData::ThresholdShareCreated(data) => { let _ = self.handle_threshold_share_created(data, ctx.address()); } _ => (), diff --git a/crates/logger/src/logger.rs b/crates/logger/src/logger.rs index 1cc2270337..ea222bbe4f 100644 --- a/crates/logger/src/logger.rs +++ b/crates/logger/src/logger.rs @@ -5,7 +5,7 @@ // or FITNESS FOR A PARTICULAR PURPOSE. use actix::{Actor, Addr, Context, Handler}; -use e3_events::{EnclaveEvent, Event, EventBus, Subscribe}; +use e3_events::{prelude::Event, EnclaveEvent, EnclaveEventData, EventBus, Subscribe}; use std::marker::PhantomData; use tracing::{error, info}; @@ -48,8 +48,8 @@ impl Handler for SimpleLogger { impl EventLogging for EnclaveEvent { fn log(&self, logger_name: &str) { - match self { - EnclaveEvent::EnclaveError { .. } => error!(event=%self, "ERROR!"), + match self.get_data() { + EnclaveEventData::EnclaveError(_) => error!(event=%self, "ERROR!"), _ => match self.get_e3_id() { Some(e3_id) => { println!("{logger_name}: {e3_id} Event Broadcasted"); diff --git a/crates/net/src/bin/p2p_test.rs b/crates/net/src/bin/p2p_test.rs index 874ccf25b2..e5865f97b8 100644 --- a/crates/net/src/bin/p2p_test.rs +++ b/crates/net/src/bin/p2p_test.rs @@ -14,7 +14,6 @@ use std::sync::atomic::{AtomicU8, Ordering}; use std::time::Duration; use std::{env, process}; use tokio::sync::{broadcast, mpsc}; -use tokio::task::JoinHandle; use tokio::time::{sleep, timeout}; use tracing::info; use tracing_subscriber::{prelude::*, EnvFilter}; diff --git a/crates/net/src/document_publisher.rs b/crates/net/src/document_publisher.rs index 9f03994b72..d5be42ec57 100644 --- a/crates/net/src/document_publisher.rs +++ b/crates/net/src/document_publisher.rs @@ -14,9 +14,9 @@ use actix::prelude::*; use anyhow::Result; use chrono::{DateTime, Utc}; use e3_events::{ - BusError, CiphernodeSelected, CorrelationId, DocumentKind, DocumentMeta, DocumentReceived, - E3RequestComplete, E3id, EnclaveErrorType, EnclaveEvent, EventBus, PartyId, - PublishDocumentRequested, Subscribe, ThresholdShareCreated, + prelude::*, BusHandle, CiphernodeSelected, CorrelationId, DocumentKind, DocumentMeta, + DocumentReceived, E3RequestComplete, E3id, EnclaveErrorType, EnclaveEvent, EnclaveEventData, + Event, PartyId, PublishDocumentRequested, ThresholdShareCreated, }; use e3_utils::retry::{retry_with_backoff, to_retry}; use e3_utils::ArcBytes; @@ -40,7 +40,7 @@ const KADEMLIA_BROADCAST_TIMEOUT: Duration = Duration::from_secs(30); /// bus pub struct DocumentPublisher { /// Enclave EventBus - bus: Addr>, + bus: BusHandle, /// NetCommand sender to forward commands to the NetInterface tx: mpsc::Sender, /// NetEvent receiver to resubscribe for events from the NetInterface. This is in an Arc so @@ -55,7 +55,7 @@ pub struct DocumentPublisher { impl DocumentPublisher { /// Create a new NetEventTranslator actor pub fn new( - bus: &Addr>, + bus: &BusHandle, tx: &mpsc::Sender, rx: &Arc>, topic: impl Into, @@ -72,16 +72,16 @@ impl DocumentPublisher { /// This is needed to create simulation libp2p event routers pub fn is_document_publisher_event(event: &EnclaveEvent) -> bool { // Add a list of events with paylods for the DHT - match event { - EnclaveEvent::PublishDocumentRequested { .. } => true, - EnclaveEvent::ThresholdShareCreated { .. } => true, + match event.get_data() { + EnclaveEventData::PublishDocumentRequested(_) => true, + EnclaveEventData::ThresholdShareCreated(_) => true, _ => false, } } /// Setup the DocumentPublisher and start listening for GossipEvents pub fn setup( - bus: &Addr>, + bus: &BusHandle, tx: &mpsc::Sender, rx: &Arc>, topic: impl Into, @@ -90,7 +90,7 @@ impl DocumentPublisher { let addr = Self::new(bus, tx, rx, topic).start(); EventConverter::setup(bus); // Listen on all events - bus.do_send(Subscribe::new("*", addr.clone().recipient())); + bus.subscribe("*", addr.clone().recipient()); // Forward gossip data from NetEvent tokio::spawn({ @@ -133,10 +133,10 @@ impl Actor for DocumentPublisher { impl Handler for DocumentPublisher { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::PublishDocumentRequested { data, .. } => ctx.notify(data), - EnclaveEvent::CiphernodeSelected { data, .. } => ctx.notify(data), - EnclaveEvent::E3RequestComplete { data, .. } => ctx.notify(data), + match msg.into_data() { + EnclaveEventData::PublishDocumentRequested(data) => ctx.notify(data), + EnclaveEventData::CiphernodeSelected(data) => ctx.notify(data), + EnclaveEventData::E3RequestComplete(data) => ctx.notify(data), _ => (), } } @@ -253,7 +253,7 @@ pub async fn handle_publish_document_requested( pub async fn handle_document_published_notification( net_cmds: mpsc::Sender, net_events: Arc>, - bus: Addr>, + bus: BusHandle, ids: HashMap, event: DocumentPublishedNotification, ) -> Result<()> { @@ -280,10 +280,10 @@ pub async fn handle_document_published_notification( .await?; debug!("Sending received event..."); - bus.do_send(EnclaveEvent::from(DocumentReceived { + bus.publish(DocumentReceived { meta: event.meta, value, - })); + }); Ok(()) } @@ -374,7 +374,7 @@ async fn broadcast_document_published_notification( /// Convert between ThresholdShareCreated and DocumentPublished events pub struct EventConverter { - bus: Addr>, + bus: BusHandle, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -399,13 +399,13 @@ impl ReceivableDocument { } impl EventConverter { - pub fn new(bus: &Addr>) -> Self { + pub fn new(bus: &BusHandle) -> Self { Self { bus: bus.clone() } } - pub fn setup(bus: &Addr>) -> Addr { + pub fn setup(bus: &BusHandle) -> Addr { let addr = Self::new(bus).start(); - bus.do_send(Subscribe::new("ThresholdShareCreated", addr.clone().into())); - bus.do_send(Subscribe::new("DocumentReceived", addr.clone().into())); + bus.subscribe("ThresholdShareCreated", addr.clone().into()); + bus.subscribe("DocumentReceived", addr.clone().into()); addr } /// Local node created a threshold share. Send it as a published document @@ -422,25 +422,22 @@ impl EventConverter { vec![], None, ); - self.bus - .do_send(EnclaveEvent::from(PublishDocumentRequested::new( - meta, value, - ))); + self.bus.publish(PublishDocumentRequested::new(meta, value)); Ok(()) } /// Received document externally pub fn handle_document_received(&self, msg: DocumentReceived) -> Result<()> { warn!("Converting DocumentReceived..."); let receivable = ReceivableDocument::from_bytes(&msg.value.extract_bytes())?; - let event = EnclaveEvent::from(match receivable { + let event = match receivable { ReceivableDocument::ThresholdShareCreated(evt) => ThresholdShareCreated { external: true, e3_id: evt.e3_id, share: evt.share, }, - }); + }; - self.bus.do_send(event); + self.bus.publish(event); Ok(()) } } @@ -452,9 +449,9 @@ impl Actor for EventConverter { impl Handler for EventConverter { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::ThresholdShareCreated { data, .. } => ctx.notify(data), - EnclaveEvent::DocumentReceived { data, .. } => ctx.notify(data), + match msg.into_data() { + EnclaveEventData::ThresholdShareCreated(data) => ctx.notify(data), + EnclaveEventData::DocumentReceived(data) => ctx.notify(data), _ => (), } } @@ -462,7 +459,7 @@ impl Handler for EventConverter { impl Handler for EventConverter { type Result = (); - fn handle(&mut self, msg: ThresholdShareCreated, ctx: &mut Self::Context) -> Self::Result { + fn handle(&mut self, msg: ThresholdShareCreated, _ctx: &mut Self::Context) -> Self::Result { match self.handle_threshold_share_created(msg) { Ok(_) => (), Err(err) => error!("{err}"), @@ -472,7 +469,7 @@ impl Handler for EventConverter { impl Handler for EventConverter { type Result = (); - fn handle(&mut self, msg: DocumentReceived, ctx: &mut Self::Context) -> Self::Result { + fn handle(&mut self, msg: DocumentReceived, _ctx: &mut Self::Context) -> Self::Result { match self.handle_document_received(msg) { Ok(_) => (), Err(err) => error!("{err}"), @@ -489,8 +486,9 @@ mod tests { use actix::Addr; use anyhow::{bail, Result}; use e3_events::{ - CiphernodeSelected, DocumentKind, DocumentMeta, E3id, EnclaveError, EnclaveEvent, EventBus, - EventBusConfig, GetEvents, HistoryCollector, PublishDocumentRequested, TakeEvents, + BusHandle, CiphernodeSelected, DocumentKind, DocumentMeta, E3id, EnclaveError, + EnclaveEvent, EventBus, EventBusConfig, GetEvents, HistoryCollector, + PublishDocumentRequested, TakeEvents, }; use libp2p::kad::{GetRecordError, PutRecordError, RecordKey}; use tokio::{ @@ -501,7 +499,7 @@ mod tests { fn setup_test() -> ( DefaultGuard, - Addr>, + BusHandle, mpsc::Sender, mpsc::Receiver, broadcast::Sender, @@ -519,15 +517,17 @@ mod tests { let guard = tracing::subscriber::set_default(subscriber); - let bus = EventBus::::new(EventBusConfig { deduplicate: true }).start(); + let bus: BusHandle = + EventBus::::new(EventBusConfig { deduplicate: true }) + .start() + .into(); let (net_cmd_tx, net_cmd_rx) = mpsc::channel(100); let (net_evt_tx, net_evt_rx) = broadcast::channel(100); let net_evt_rx = Arc::new(net_evt_rx); let history = HistoryCollector::::new().start(); let error = HistoryCollector::::new().start(); - bus.do_send(Subscribe::new("*", history.clone().recipient())); - bus.do_send(Subscribe::new("EnclaveError", error.clone().recipient())); - + bus.subscribe("*", history.clone().recipient()); + bus.subscribe("EnclaveError", error.clone().recipient()); let publisher = DocumentPublisher::setup(&bus, &net_cmd_tx, &net_evt_rx, "topic"); ( @@ -544,10 +544,10 @@ mod tests { let e3_id = E3id::new("1243", 1); // 1. Send a request to publish - bus.do_send(EnclaveEvent::from(PublishDocumentRequested { + bus.publish(PublishDocumentRequested { meta: DocumentMeta::new(e3_id, DocumentKind::TrBFV, vec![], expires_at), value: value.clone(), - })); + }); // 2. Document publisher should have asked the NetInterface to put the doc on Kademlia let Some(NetCommand::DhtPutRecord { @@ -618,12 +618,12 @@ mod tests { let cid = Cid::from_content(&value); // 1. Ensure the publisher is interested in the id by receiving CiphernodeSelected - bus.do_send(EnclaveEvent::from(CiphernodeSelected { + bus.publish(CiphernodeSelected { e3_id: e3_id.clone(), threshold_m: 3, threshold_n: 5, ..CiphernodeSelected::default() - })); + }); net_evt_tx.send(NetEvent::GossipData( GossipData::DocumentPublishedNotification(DocumentPublishedNotification { @@ -680,10 +680,10 @@ mod tests { let e3_id = E3id::new("1243", 1); // Send a request to publish - bus.do_send(EnclaveEvent::from(PublishDocumentRequested { + bus.publish(PublishDocumentRequested { meta: DocumentMeta::new(e3_id, DocumentKind::TrBFV, vec![], expires_at), value: value.clone(), - })); + }); for _ in 0..4 { // Expect retry @@ -730,12 +730,12 @@ mod tests { let cid = Cid::from_content(&value); // 1. Ensure the publisher is interested in the id by receiving CiphernodeSelected - bus.do_send(EnclaveEvent::from(CiphernodeSelected { + bus.publish(CiphernodeSelected { e3_id: e3_id.clone(), threshold_m: 3, threshold_n: 5, ..CiphernodeSelected::default() - })); + }); // 2. Dispatch a NetEvent from the NetInterface signaling that a document was published net_evt_tx.send(NetEvent::GossipData( @@ -788,10 +788,8 @@ mod tests { // Check event was dispatched let events = history.send(GetEvents::new()).await?; - let Some(EnclaveEvent::DocumentReceived { - data: DocumentReceived { value: doc, .. }, - .. - }) = events.last() + let Some(EnclaveEventData::DocumentReceived(DocumentReceived { value: doc, .. })) = + events.last().map(|e| e.get_data()) else { bail!("No event sent"); }; diff --git a/crates/net/src/events.rs b/crates/net/src/events.rs index 0dedd10769..010e7130be 100644 --- a/crates/net/src/events.rs +++ b/crates/net/src/events.rs @@ -21,7 +21,6 @@ use std::{ time::{Duration, Instant}, }; use tokio::sync::{broadcast, mpsc}; -use tracing::{info, warn}; /// Incoming/Outgoing GossipData. We disambiguate on concerns relative to the net package. #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] diff --git a/crates/net/src/net_event_translator.rs b/crates/net/src/net_event_translator.rs index 18aa0cbb4a..f23905184f 100644 --- a/crates/net/src/net_event_translator.rs +++ b/crates/net/src/net_event_translator.rs @@ -15,7 +15,11 @@ use actix::prelude::*; use anyhow::{bail, Result}; use e3_crypto::Cipher; use e3_data::Repository; -use e3_events::{CorrelationId, EnclaveEvent, EventBus, EventId, Subscribe}; +use e3_events::prelude::*; +use e3_events::BusHandle; +use e3_events::EnclaveEventData; +use e3_events::Event; +use e3_events::{CorrelationId, EnclaveEvent, EventId}; use libp2p::identity::ed25519; use std::collections::HashSet; use std::sync::Arc; @@ -30,7 +34,7 @@ use tracing::{error, info, instrument, trace}; /// NetEventTranslator Actor converts between EventBus events and Libp2p events forwarding them to a /// NetInterface for propagation over the p2p network pub struct NetEventTranslator { - bus: Addr>, + bus: BusHandle, tx: mpsc::Sender, sent_events: HashSet, topic: String, @@ -47,13 +51,9 @@ struct LibP2pEvent(pub Vec); impl NetEventTranslator { /// Create a new NetEventTranslator actor - pub fn new( - bus: Addr>, - tx: &mpsc::Sender, - topic: &str, - ) -> Self { + pub fn new(bus: &BusHandle, tx: &mpsc::Sender, topic: &str) -> Self { Self { - bus, + bus: bus.clone(), tx: tx.clone(), sent_events: HashSet::new(), topic: topic.to_string(), @@ -61,19 +61,16 @@ impl NetEventTranslator { } pub fn setup( - bus: &Addr>, + bus: &BusHandle, tx: &mpsc::Sender, rx: &Arc>, topic: &str, ) -> Addr { let mut rx = rx.resubscribe(); - let addr = NetEventTranslator::new(bus.clone(), tx, topic).start(); + let addr = NetEventTranslator::new(&bus, tx, topic).start(); // Listen on all events - bus.do_send(Subscribe { - event_type: String::from("*"), - listener: addr.clone().recipient(), - }); + bus.subscribe("*", addr.clone().recipient()); tokio::spawn({ let addr = addr.clone(); @@ -99,11 +96,11 @@ impl NetEventTranslator { /// as static means we can keep this maintained here but use this rule elsewhere pub fn is_forwardable_event(event: &EnclaveEvent) -> bool { // Add a list of events allowed to be forwarded to libp2p - match event { - EnclaveEvent::DecryptionshareCreated { .. } => true, - EnclaveEvent::KeyshareCreated { .. } => true, - EnclaveEvent::PlaintextAggregated { .. } => true, - EnclaveEvent::PublicKeyAggregated { .. } => true, + match event.get_data() { + EnclaveEventData::DecryptionshareCreated(_) => true, + EnclaveEventData::KeyshareCreated(_) => true, + EnclaveEventData::PlaintextAggregated(_) => true, + EnclaveEventData::PublicKeyAggregated(_) => true, _ => false, } } @@ -111,7 +108,7 @@ impl NetEventTranslator { /// Spawn a Libp2p interface and hook it up to this actor #[instrument(name = "libp2p", skip_all)] pub async fn setup_with_interface( - bus: Addr>, + bus: BusHandle, peers: Vec, cipher: &Arc, quic_port: u16, @@ -165,7 +162,7 @@ impl Handler for NetEventTranslator { let LibP2pEvent(bytes) = msg; match EnclaveEvent::from_bytes(&bytes) { Ok(event) => { - self.bus.do_send(event.clone()); + self.bus.naked_dispatch(event.clone()); // TODO: convert to receive self.sent_events.insert(event.into()); } Err(err) => error!(error=?err, "Could not create EnclaveEvent from Libp2p Bytes!"), diff --git a/crates/program-server/src/types.rs b/crates/program-server/src/types.rs index 81996753c7..8fcdafb071 100644 --- a/crates/program-server/src/types.rs +++ b/crates/program-server/src/types.rs @@ -181,6 +181,6 @@ mod tests { "#; // Just dont crash - let payload: ComputeRequest = serde_json::from_str(json).unwrap(); + let _payload: ComputeRequest = serde_json::from_str(json).unwrap(); } } diff --git a/crates/request/src/meta.rs b/crates/request/src/meta.rs index 209ad63da2..25c4551999 100644 --- a/crates/request/src/meta.rs +++ b/crates/request/src/meta.rs @@ -8,7 +8,7 @@ use crate::{E3Context, E3ContextSnapshot, E3Extension, MetaRepositoryFactory, Ty use anyhow::*; use async_trait::async_trait; use e3_data::RepositoriesFactory; -use e3_events::{E3Requested, EnclaveEvent, Seed}; +use e3_events::{E3Requested, EnclaveEvent, EnclaveEventData, Event, Seed}; use e3_utils::utility_types::ArcBytes; pub const META_KEY: TypedKey = TypedKey::new("meta"); @@ -34,7 +34,7 @@ impl E3MetaExtension { #[async_trait] impl E3Extension for E3MetaExtension { fn on_event(&self, ctx: &mut crate::E3Context, event: &EnclaveEvent) { - let EnclaveEvent::E3Requested { data, .. } = event else { + let EnclaveEventData::E3Requested(data) = event.get_data() else { return; }; let E3Requested { diff --git a/crates/request/src/router.rs b/crates/request/src/router.rs index 33246db5fe..a3edf20f48 100644 --- a/crates/request/src/router.rs +++ b/crates/request/src/router.rs @@ -20,9 +20,12 @@ use e3_data::FromSnapshotWithParams; use e3_data::RepositoriesFactory; use e3_data::Repository; use e3_data::Snapshot; +use e3_events::prelude::*; +use e3_events::BusHandle; use e3_events::E3RequestComplete; +use e3_events::EnclaveEventData; use e3_events::Shutdown; -use e3_events::{E3id, EnclaveEvent, EventBus, Subscribe}; +use e3_events::{E3id, EnclaveEvent, Event}; use serde::Deserialize; use serde::Serialize; use std::collections::HashSet; @@ -102,19 +105,19 @@ pub struct E3Router { /// A buffer for events to send to the buffer: EventBuffer, /// The EventBus - bus: Addr>, + bus: BusHandle, /// A repository for storing snapshots store: Repository, } pub struct E3RouterParams { extensions: Arc>>, - bus: Addr>, + bus: BusHandle, store: Repository, } impl E3Router { - pub fn builder(bus: &Addr>, store: DataStore) -> E3RouterBuilder { + pub fn builder(bus: &BusHandle, store: DataStore) -> E3RouterBuilder { let repositories = store.repositories(); let builder = E3RouterBuilder { bus: bus.clone(), @@ -147,9 +150,9 @@ impl Actor for E3Router { impl Handler for E3Router { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - // If we are shuttomg down then bail on anything else - if let EnclaveEvent::Shutdown { data, .. } = msg { - ctx.notify(data); + // If we are shutting down then bail on anything else + if let EnclaveEventData::Shutdown(data) = msg.get_data() { + ctx.notify(data.clone()); return; } @@ -179,19 +182,19 @@ impl Handler for E3Router { context.forward_message(&msg, &mut self.buffer); - match &msg { - EnclaveEvent::PlaintextAggregated { .. } => { + match msg.into_data() { + EnclaveEventData::PlaintextAggregated(_) => { // Here we are detemining that by receiving the PlaintextAggregated event our request is // complete and we can notify everyone. This might change as we consider other factors // when determining if the request is complete - let event = EnclaveEvent::from(E3RequestComplete { + let event = E3RequestComplete { e3_id: e3_id.clone(), - }); + }; // Send to bus so all other actors can react to a request being complete. - self.bus.do_send(event); + self.bus.publish(event); } - EnclaveEvent::E3RequestComplete { .. } => { + EnclaveEventData::E3RequestComplete(_) => { // Note this will be sent above to the children who can kill themselves based on // the event self.contexts.remove(&e3_id); @@ -207,7 +210,7 @@ impl Handler for E3Router { impl Handler for E3Router { type Result = (); fn handle(&mut self, msg: Shutdown, _ctx: &mut Self::Context) -> Self::Result { - let shutdown_evt = EnclaveEvent::from(msg); + let shutdown_evt = self.bus.event_from(msg); for (_, ctx) in self.contexts.iter() { ctx.forward_message_now(&shutdown_evt) } @@ -279,7 +282,7 @@ impl FromSnapshotWithParams for E3Router { /// Builder for E3Router pub struct E3RouterBuilder { - pub bus: Addr>, + pub bus: BusHandle, pub extensions: Vec>, pub store: Repository, } @@ -304,8 +307,7 @@ impl E3RouterBuilder { }; let addr = e3r.start(); - self.bus - .do_send(Subscribe::new("*", addr.clone().recipient())); + self.bus.subscribe("*", addr.clone().recipient()); Ok(addr) } } diff --git a/crates/sortition/Cargo.toml b/crates/sortition/Cargo.toml index 096f450ec1..d38cd3bf30 100644 --- a/crates/sortition/Cargo.toml +++ b/crates/sortition/Cargo.toml @@ -21,4 +21,5 @@ num = { workspace = true } rand = { workspace = true } serde = { workspace = true } tracing = { workspace = true } -num-bigint = { workspace = true } \ No newline at end of file +tokio = { workspace = true } +num-bigint = { workspace = true } diff --git a/crates/sortition/src/ciphernode_selector.rs b/crates/sortition/src/ciphernode_selector.rs index d89b09cba2..0d2d278a57 100644 --- a/crates/sortition/src/ciphernode_selector.rs +++ b/crates/sortition/src/ciphernode_selector.rs @@ -11,14 +11,14 @@ use actix::prelude::*; use e3_config::StoreKeys; use e3_data::{DataStore, RepositoriesFactory}; use e3_events::{ - CiphernodeSelected, CommitteeFinalized, E3Requested, EnclaveEvent, EventBus, Shutdown, - Subscribe, TicketGenerated, TicketId, + prelude::*, BusHandle, CiphernodeSelected, CommitteeFinalized, E3Requested, EnclaveEvent, + EnclaveEventData, Shutdown, TicketGenerated, TicketId, }; use e3_request::MetaRepositoryFactory; use tracing::info; pub struct CiphernodeSelector { - bus: Addr>, + bus: BusHandle, sortition: Addr, address: String, data_store: DataStore, @@ -30,7 +30,7 @@ impl Actor for CiphernodeSelector { impl CiphernodeSelector { pub fn new( - bus: &Addr>, + bus: &BusHandle, sortition: &Addr, address: &str, data_store: &DataStore, @@ -44,19 +44,16 @@ impl CiphernodeSelector { } pub fn attach( - bus: &Addr>, + bus: &BusHandle, sortition: &Addr, address: &str, data_store: &DataStore, ) -> Addr { let addr = CiphernodeSelector::new(bus, sortition, address, data_store).start(); - bus.do_send(Subscribe::new("E3Requested", addr.clone().recipient())); - bus.do_send(Subscribe::new( - "CommitteeFinalized", - addr.clone().recipient(), - )); - bus.do_send(Subscribe::new("Shutdown", addr.clone().recipient())); + bus.subscribe("E3Requested", addr.clone().recipient()); + bus.subscribe("CommitteeFinalized", addr.clone().recipient()); + bus.subscribe("Shutdown", addr.clone().recipient()); addr } @@ -65,10 +62,10 @@ impl CiphernodeSelector { impl Handler for CiphernodeSelector { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::E3Requested { data, .. } => ctx.notify(data), - EnclaveEvent::CommitteeFinalized { data, .. } => ctx.notify(data), - EnclaveEvent::Shutdown { data, .. } => ctx.notify(data), + match msg.into_data() { + EnclaveEventData::E3Requested(data) => ctx.notify(data), + EnclaveEventData::CommitteeFinalized(data) => ctx.notify(data), + EnclaveEventData::Shutdown(data) => ctx.notify(data), _ => (), } } @@ -112,11 +109,11 @@ impl Handler for CiphernodeSelector { ticket_id = tid, "Ticket generated for score sortition" ); - bus.do_send(EnclaveEvent::from(TicketGenerated { + bus.publish(TicketGenerated { e3_id: data.e3_id.clone(), ticket_id: TicketId::Score(tid), node: address.clone(), - })); + }); } } else { info!("This node is not selected"); @@ -168,7 +165,7 @@ impl Handler for CiphernodeSelector { party_id = party_id, "Node is in finalized committee, emitting CiphernodeSelected" ); - bus.do_send(EnclaveEvent::from(CiphernodeSelected { + bus.publish(CiphernodeSelected { party_id: party_id as u64, e3_id, threshold_m: e3_meta.threshold_m, @@ -177,7 +174,7 @@ impl Handler for CiphernodeSelector { error_size: e3_meta.error_size, params: e3_meta.params, seed: e3_meta.seed, - })); + }); }) } } diff --git a/crates/sortition/src/sortition.rs b/crates/sortition/src/sortition.rs index ac9bad7d9e..09ecc5beb9 100644 --- a/crates/sortition/src/sortition.rs +++ b/crates/sortition/src/sortition.rs @@ -10,10 +10,11 @@ use alloy::primitives::U256; use anyhow::Result; use e3_data::{AutoPersist, Persistable, Repository}; use e3_events::{ - BusError, CiphernodeAdded, CiphernodeRemoved, CommitteeFinalized, CommitteePublished, - ConfigurationUpdated, EnclaveErrorType, EnclaveEvent, EventBus, OperatorActivationChanged, - PlaintextOutputPublished, Seed, Subscribe, TicketBalanceUpdated, + prelude::*, CiphernodeAdded, CiphernodeRemoved, CommitteeFinalized, CommitteePublished, + ConfigurationUpdated, EnclaveErrorType, EnclaveEvent, OperatorActivationChanged, + PlaintextOutputPublished, Seed, TicketBalanceUpdated, }; +use e3_events::{BusHandle, EnclaveEventData}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use tracing::info; @@ -138,7 +139,7 @@ pub struct Sortition { /// Persistent map of `chain_id -> NodeStateStore`. node_state: Persistable>, /// Event bus for error reporting and enclave event subscription. - bus: Addr>, + bus: BusHandle, /// Persistent map of finalized committees per E3 finalized_committees: Persistable>>, } @@ -147,7 +148,7 @@ pub struct Sortition { #[derive(Debug)] pub struct SortitionParams { /// Event bus address. - pub bus: Addr>, + pub bus: BusHandle, /// Persisted per-chain backend map. pub backends: Persistable>, /// Node state store per chain @@ -168,7 +169,7 @@ impl Sortition { #[instrument(name = "sortition_attach", skip_all)] pub async fn attach( - bus: &Addr>, + bus: &BusHandle, backends_store: Repository>, node_state_store: Repository>, committees_store: Repository>>, @@ -192,20 +193,19 @@ impl Sortition { .start(); // Subscribe to all relevant events - bus.do_send(Subscribe::new("CiphernodeAdded", addr.clone().into())); - bus.do_send(Subscribe::new("CiphernodeRemoved", addr.clone().into())); - bus.do_send(Subscribe::new("TicketBalanceUpdated", addr.clone().into())); - bus.do_send(Subscribe::new( - "OperatorActivationChanged", + bus.subscribe_all( + &[ + "CiphernodeAdded", + "CiphernodeRemoved", + "TicketBalanceUpdated", + "OperatorActivationChanged", + "ConfigurationUpdated", + "CommitteePublished", + "PlaintextOutputPublished", + "CommitteeFinalized", + ], addr.clone().into(), - )); - bus.do_send(Subscribe::new("ConfigurationUpdated", addr.clone().into())); - bus.do_send(Subscribe::new("CommitteePublished", addr.clone().into())); - bus.do_send(Subscribe::new( - "PlaintextOutputPublished", - addr.clone().into(), - )); - bus.do_send(Subscribe::new("CommitteeFinalized", addr.clone().into())); + ); info!("Sortition actor started"); Ok(addr) @@ -231,15 +231,15 @@ impl Handler for Sortition { type Result = (); fn handle(&mut self, msg: EnclaveEvent, ctx: &mut Self::Context) -> Self::Result { - match msg { - EnclaveEvent::CiphernodeAdded { data, .. } => ctx.notify(data.clone()), - EnclaveEvent::CiphernodeRemoved { data, .. } => ctx.notify(data.clone()), - EnclaveEvent::TicketBalanceUpdated { data, .. } => ctx.notify(data.clone()), - EnclaveEvent::OperatorActivationChanged { data, .. } => ctx.notify(data.clone()), - EnclaveEvent::ConfigurationUpdated { data, .. } => ctx.notify(data.clone()), - EnclaveEvent::CommitteePublished { data, .. } => ctx.notify(data.clone()), - EnclaveEvent::PlaintextOutputPublished { data, .. } => ctx.notify(data.clone()), - EnclaveEvent::CommitteeFinalized { data, .. } => ctx.notify(data.clone()), + match msg.into_data() { + EnclaveEventData::CiphernodeAdded(data) => ctx.notify(data.clone()), + EnclaveEventData::CiphernodeRemoved(data) => ctx.notify(data.clone()), + EnclaveEventData::TicketBalanceUpdated(data) => ctx.notify(data.clone()), + EnclaveEventData::OperatorActivationChanged(data) => ctx.notify(data.clone()), + EnclaveEventData::ConfigurationUpdated(data) => ctx.notify(data.clone()), + EnclaveEventData::CommitteePublished(data) => ctx.notify(data.clone()), + EnclaveEventData::PlaintextOutputPublished(data) => ctx.notify(data.clone()), + EnclaveEventData::CommitteeFinalized(data) => ctx.notify(data.clone()), _ => (), } } diff --git a/crates/test-helpers/src/ciphernode_system.rs b/crates/test-helpers/src/ciphernode_system.rs index eef4586b2d..dd62af9ca5 100644 --- a/crates/test-helpers/src/ciphernode_system.rs +++ b/crates/test-helpers/src/ciphernode_system.rs @@ -4,14 +4,13 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +use crate::simulate_libp2p_net; use anyhow::*; use e3_ciphernode_builder::CiphernodeHandle; +use e3_events::Event; use e3_events::{EnclaveEvent, GetEvents, ResetHistory, TakeEvents}; -use tokio::time::timeout; - use std::{future::Future, ops::Deref, pin::Pin, time::Duration}; - -use crate::simulate_libp2p_net; +use tokio::time::timeout; // This type allows us to store various dynamic async callbacks type SetupFn<'a> = @@ -198,7 +197,7 @@ mod tests { use super::*; use actix::prelude::*; use e3_data::InMemStore; - use e3_events::{EventBus, EventBusConfig}; + use e3_events::{BusHandle, EventBus, EventBusConfig}; async fn mock_setup_node(address: String) -> Result { // Create mock actors for the test @@ -206,6 +205,7 @@ mod tests { let bus = EventBus::::new(EventBusConfig { deduplicate: true }).start(); let history = EventBus::::history(&bus); let errors = EventBus::::error(&bus); + let bus = BusHandle::new(bus); Ok(CiphernodeHandle { address, diff --git a/crates/test-helpers/src/lib.rs b/crates/test-helpers/src/lib.rs index 51a40ac77d..2057b52416 100644 --- a/crates/test-helpers/src/lib.rs +++ b/crates/test-helpers/src/lib.rs @@ -15,7 +15,8 @@ use alloy::primitives::Address; use anyhow::*; use e3_ciphernode_builder::CiphernodeHandle; use e3_events::{ - CiphernodeAdded, EnclaveEvent, EventBus, EventBusConfig, HistoryCollector, Seed, Subscribe, + BusHandle, CiphernodeAdded, EnclaveEvent, EnclaveEventData, EventBus, EventBusConfig, + EventPublisher, HistoryCollector, Seed, Subscribe, }; use e3_fhe::{create_crp, setup_crp_params, ParamsWithCrp}; use e3_net::{DocumentPublisher, NetEventTranslator}; @@ -71,7 +72,7 @@ pub fn create_crp_bytes_params( pub fn get_common_setup( param_set: Option, ) -> Result<( - Addr>, + BusHandle, SharedRng, Seed, Arc, @@ -94,7 +95,7 @@ pub fn get_common_setup( let (crp_bytes, params) = create_crp_bytes_params(moduli, degree, plaintext_modulus, &seed); let crpoly = CommonRandomPoly::deserialize(&crp_bytes.clone(), ¶ms)?; - Ok((bus, rng, seed, params, crpoly, errors, history)) + Ok((bus.into(), rng, seed, params, crpoly, errors, history)) } /// Simulate libp2p by taking output events on each local bus and filter for !is_local_only() and forward remaining events back to the event bus @@ -158,32 +159,32 @@ pub fn create_random_eth_addrs(how_many: u32) -> Vec { /// Test helper to add addresses to the committee by creating events on the event bus #[derive(Clone, Debug)] pub struct AddToCommittee { - bus: Addr>, + bus: BusHandle, count: usize, chain_id: u64, } impl AddToCommittee { - pub fn new(bus: &Addr>, chain_id: u64) -> Self { + pub fn new(bus: &BusHandle, chain_id: u64) -> Self { Self { bus: bus.clone(), chain_id, count: 0, } } - pub async fn add(&mut self, address: &str) -> Result { - let evt = EnclaveEvent::from(CiphernodeAdded { + pub async fn add(&mut self, address: &str) -> Result { + let evt = CiphernodeAdded { chain_id: self.chain_id, address: address.to_owned(), index: self.count, num_nodes: self.count + 1, - }); + }; self.count += 1; - self.bus.send(evt.clone()).await?; + self.bus.publish(evt.clone()); - Ok(evt) + Ok(evt.into()) } } @@ -208,10 +209,3 @@ pub fn encrypt_ciphertext( .collect::>>()?; Ok((ciphertext, plaintext)) } - -fn pad_end(input: &[u64], pad: u64, total: usize) -> Vec { - let len = input.len(); - let mut cop = input.to_vec(); - cop.extend(std::iter::repeat(pad).take(total - len)); - cop -} diff --git a/crates/test-helpers/src/plaintext_writer.rs b/crates/test-helpers/src/plaintext_writer.rs index b2a5911bbb..5e77a12a4e 100644 --- a/crates/test-helpers/src/plaintext_writer.rs +++ b/crates/test-helpers/src/plaintext_writer.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; use super::write_file_with_dirs; use actix::{Actor, Addr, Context, Handler}; -use e3_events::{EnclaveEvent, EventBus, Subscribe}; +use e3_events::{prelude::*, BusHandle, EnclaveEvent, EnclaveEventData}; use e3_sdk::bfv_helpers::decode_bytes_to_vec_u64; use tracing::{error, info}; @@ -17,15 +17,12 @@ pub struct PlaintextWriter { } impl PlaintextWriter { - pub fn attach(path: &PathBuf, bus: Addr>) -> Addr { + pub fn attach(path: &PathBuf, bus: BusHandle) -> Addr { let addr = Self { path: path.to_owned(), } .start(); - bus.do_send(Subscribe { - listener: addr.clone().recipient(), - event_type: "PlaintextAggregated".to_string(), - }); + bus.subscribe("PlaintextAggregated", addr.clone().recipient()); addr } } @@ -37,7 +34,7 @@ impl Actor for PlaintextWriter { impl Handler for PlaintextWriter { type Result = (); fn handle(&mut self, msg: EnclaveEvent, _: &mut Self::Context) -> Self::Result { - if let EnclaveEvent::PlaintextAggregated { data, .. } = msg.clone() { + if let EnclaveEventData::PlaintextAggregated(data) = msg.into_data() { let Some(decrypted) = data.decrypted_output.first() else { error!("Decrypted output must not be empty!"); return; diff --git a/crates/test-helpers/src/public_key_writer.rs b/crates/test-helpers/src/public_key_writer.rs index db64b1b00b..bdd2523725 100644 --- a/crates/test-helpers/src/public_key_writer.rs +++ b/crates/test-helpers/src/public_key_writer.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; use super::write_file_with_dirs; use actix::{Actor, Addr, Context, Handler}; -use e3_events::{EnclaveEvent, EventBus, Subscribe}; +use e3_events::{prelude::*, BusHandle, EnclaveEvent, EnclaveEventData, EventSubscriber}; use tracing::info; pub struct PublicKeyWriter { @@ -16,15 +16,12 @@ pub struct PublicKeyWriter { } impl PublicKeyWriter { - pub fn attach(path: &PathBuf, bus: Addr>) -> Addr { + pub fn attach(path: &PathBuf, bus: BusHandle) -> Addr { let addr = Self { path: path.to_owned(), } .start(); - bus.do_send(Subscribe { - listener: addr.clone().recipient(), - event_type: "PublicKeyAggregated".to_string(), - }); + bus.subscribe("PublicKeyAggregated", addr.clone().recipient()); addr } } @@ -36,7 +33,7 @@ impl Actor for PublicKeyWriter { impl Handler for PublicKeyWriter { type Result = (); fn handle(&mut self, msg: EnclaveEvent, _: &mut Self::Context) -> Self::Result { - if let EnclaveEvent::PublicKeyAggregated { data, .. } = msg.clone() { + if let EnclaveEventData::PublicKeyAggregated(data) = msg.into_data() { info!(path = ?&self.path, "Writing Pubkey To Path"); write_file_with_dirs(&self.path, &data.pubkey).unwrap(); } diff --git a/crates/tests/tests/integration.rs b/crates/tests/tests/integration.rs index 0e5728b6cd..4a5f1ede59 100644 --- a/crates/tests/tests/integration.rs +++ b/crates/tests/tests/integration.rs @@ -10,9 +10,9 @@ use anyhow::{bail, Result}; use e3_ciphernode_builder::CiphernodeBuilder; use e3_crypto::Cipher; use e3_events::{ - CiphertextOutputPublished, CommitteeFinalized, ConfigurationUpdated, E3Requested, E3id, - EnclaveEvent, EventBus, EventBusConfig, OperatorActivationChanged, PlaintextAggregated, - TicketBalanceUpdated, + prelude::*, BusHandle, CiphertextOutputPublished, CommitteeFinalized, ConfigurationUpdated, + E3Requested, E3id, EnclaveEvent, EnclaveEventData, EventBus, EventBusConfig, + OperatorActivationChanged, PlaintextAggregated, TicketBalanceUpdated, }; use e3_multithread::{GetReport, Multithread}; use e3_sdk::bfv_helpers::{build_bfv_params_arc, decode_bytes_to_vec_u64, encode_bfv_params}; @@ -33,37 +33,34 @@ pub fn save_snapshot(file_name: &str, bytes: &[u8]) { } async fn setup_score_sortition_environment( - bus: &actix::Addr>, + bus: &BusHandle, eth_addrs: &Vec, chain_id: u64, ) -> Result<()> { - bus.send(EnclaveEvent::from(ConfigurationUpdated { + bus.publish(ConfigurationUpdated { parameter: "ticketPrice".to_string(), old_value: U256::ZERO, new_value: U256::from(10_000_000u64), chain_id, - })) - .await?; + }); let mut adder = AddToCommittee::new(bus, chain_id); for addr in eth_addrs { adder.add(addr).await?; - bus.send(EnclaveEvent::from(TicketBalanceUpdated { + bus.publish(TicketBalanceUpdated { operator: addr.clone(), delta: I256::try_from(1_000_000_000u64).unwrap(), new_balance: U256::from(1_000_000_000u64), reason: FixedBytes::ZERO, chain_id, - })) - .await?; + }); - bus.send(EnclaveEvent::from(OperatorActivationChanged { + bus.publish(OperatorActivationChanged { operator: addr.clone(), active: true, chain_id, - })) - .await?; + }); } Ok(()) @@ -121,7 +118,10 @@ async fn test_trbfv_actor() -> Result<()> { let rng = create_shared_rng_from_u64(42); // Create "trigger" bus - let bus = EventBus::::new(EventBusConfig { deduplicate: true }).start(); + let bus: BusHandle = + EventBus::::new(EventBusConfig { deduplicate: true }) + .start() + .into(); // Parameters (128bits of security) let (degree, plaintext_modulus, moduli) = ( @@ -181,7 +181,7 @@ async fn test_trbfv_actor() -> Result<()> { .with_pubkey_aggregation() .with_sortition_score() .with_threshold_plaintext_aggregation() - .testmode_with_forked_bus(&bus) + .testmode_with_forked_bus(&bus.bus()) .with_logging() .build() .await @@ -194,7 +194,7 @@ async fn test_trbfv_actor() -> Result<()> { .with_injected_multithread(multithread.clone()) .with_trbfv() .with_sortition_score() - .testmode_with_forked_bus(&bus) + .testmode_with_forked_bus(&bus.bus()) .with_logging() .build() .await @@ -238,9 +238,7 @@ async fn test_trbfv_actor() -> Result<()> { params, }; - let event = EnclaveEvent::from(e3_requested); - - bus.do_send(event); + bus.publish(e3_requested); // For score sortition, we need to wait for nodes to process E3Requested and run sortition // Since TicketGenerated is a local-only event (not shared across network), we can't collect it @@ -262,12 +260,11 @@ async fn test_trbfv_actor() -> Result<()> { println!("Emitting CommitteeFinalized with {} nodes", committee.len()); - bus.send(EnclaveEvent::from(CommitteeFinalized { + bus.publish(CommitteeFinalized { e3_id: e3_id.clone(), committee, chain_id, - })) - .await?; + }); let committee_finalized_timer = Instant::now(); @@ -322,9 +319,7 @@ async fn test_trbfv_actor() -> Result<()> { // First we get the public key println!("Getting public key"); - let Some(EnclaveEvent::PublicKeyAggregated { - data: pubkey_event, .. - }) = h.last().clone() + let Some(EnclaveEventData::PublicKeyAggregated(pubkey_event)) = h.last().map(|e| e.get_data()) else { panic!("Was expecting event to be PublicKeyAggregated"); }; @@ -361,12 +356,12 @@ async fn test_trbfv_actor() -> Result<()> { // Created the event println!("Publishing CiphertextOutputPublished..."); - let ciphertext_published_event = EnclaveEvent::from(CiphertextOutputPublished { + let ciphertext_published_event = CiphertextOutputPublished { ciphertext_output: ciphertexts, e3_id: e3_id.clone(), - }); + }; - bus.send(ciphertext_published_event.clone()).await?; + bus.publish(ciphertext_published_event.clone()); println!("CiphertextOutputPublished event has been dispatched!"); @@ -391,14 +386,10 @@ async fn test_trbfv_actor() -> Result<()> { publishing_ct_timer.elapsed(), )); - let Some(EnclaveEvent::PlaintextAggregated { - data: - PlaintextAggregated { - decrypted_output: plaintext, - .. - }, + let Some(EnclaveEventData::PlaintextAggregated(PlaintextAggregated { + decrypted_output: plaintext, .. - }) = h.last() + })) = h.last().map(|e| e.get_data()) else { bail!("bad event") }; diff --git a/crates/tests/tests/integration_legacy.rs b/crates/tests/tests/integration_legacy.rs index e07dcb2de2..0c0ba861c3 100644 --- a/crates/tests/tests/integration_legacy.rs +++ b/crates/tests/tests/integration_legacy.rs @@ -13,12 +13,14 @@ use e3_ciphernode_builder::CiphernodeHandle; use e3_crypto::Cipher; use e3_data::GetDump; use e3_data::InMemStore; +use e3_events::BusHandle; +use e3_events::EnclaveEventData; use e3_events::GetEvents; use e3_events::{ - CiphernodeSelected, CiphertextOutputPublished, CommitteeFinalized, ConfigurationUpdated, - E3Requested, E3id, EnclaveEvent, EventBus, EventBusConfig, HistoryCollector, - OperatorActivationChanged, OrderedSet, PlaintextAggregated, PublicKeyAggregated, Seed, - Shutdown, Subscribe, TakeEvents, TicketBalanceUpdated, + prelude::*, CiphernodeSelected, CiphertextOutputPublished, CommitteeFinalized, + ConfigurationUpdated, E3Requested, E3id, EnclaveEvent, EventBus, EventBusConfig, + HistoryCollector, OperatorActivationChanged, OrderedSet, PlaintextAggregated, + PublicKeyAggregated, Seed, Shutdown, TakeEvents, TicketBalanceUpdated, }; use e3_net::events::GossipData; use e3_net::{events::NetEvent, NetEventTranslator}; @@ -32,12 +34,11 @@ use e3_test_helpers::{ }; use e3_utils::utility_types::ArcBytes; use e3_utils::SharedRng; -use fhe::bfv::Encoding; use fhe::{ bfv::{BfvParameters, PublicKey, SecretKey}, mbfv::{AggregateIter, CommonRandomPoly, PublicKeyShare}, }; -use fhe_traits::{FheDecoder, Serialize}; +use fhe_traits::Serialize; use rand::SeedableRng; use rand_chacha::ChaCha20Rng; use std::{sync::Arc, time::Duration}; @@ -46,7 +47,7 @@ use tokio::sync::{broadcast, Mutex}; use tokio::time::sleep; async fn setup_local_ciphernode( - bus: &Addr>, + bus: &BusHandle, rng: &SharedRng, logging: bool, addr: &str, @@ -56,7 +57,7 @@ async fn setup_local_ciphernode( let mut builder = CiphernodeBuilder::new(rng.clone(), cipher.clone()) .with_keyshare() .with_address(addr) - .testmode_with_forked_bus(bus) + .testmode_with_forked_bus(&bus.bus()) .testmode_with_history() .testmode_with_errors() .with_pubkey_aggregation() @@ -101,7 +102,7 @@ fn generate_pk_shares( } async fn create_local_ciphernodes( - bus: &Addr>, + bus: &BusHandle, rng: &SharedRng, count: u32, cipher: &Arc, @@ -119,37 +120,34 @@ async fn create_local_ciphernodes( } async fn setup_score_sortition_environment( - bus: &Addr>, + bus: &BusHandle, eth_addrs: &Vec, chain_id: u64, ) -> Result<()> { - bus.send(EnclaveEvent::from(ConfigurationUpdated { + bus.publish(ConfigurationUpdated { parameter: "ticketPrice".to_string(), old_value: U256::ZERO, new_value: U256::from(10_000_000u64), chain_id, - })) - .await?; + }); let mut adder = AddToCommittee::new(bus, chain_id); for addr in eth_addrs { adder.add(addr).await?; - bus.send(EnclaveEvent::from(TicketBalanceUpdated { + bus.publish(TicketBalanceUpdated { operator: addr.clone(), delta: I256::try_from(1_000_000_000u64).unwrap(), new_balance: U256::from(1_000_000_000u64), reason: FixedBytes::ZERO, chain_id, - })) - .await?; + }); - bus.send(EnclaveEvent::from(OperatorActivationChanged { + bus.publish(OperatorActivationChanged { operator: addr.clone(), active: true, chain_id, - })) - .await?; + }); } Ok(()) @@ -193,29 +191,28 @@ async fn test_public_key_aggregation_and_decryption() -> Result<()> { setup_score_sortition_environment(&bus, ð_addrs, 1).await?; - let e3_request_event = EnclaveEvent::from(E3Requested { + let e3_request_event = E3Requested { e3_id: e3_id.clone(), params: ArcBytes::from_bytes(&encode_bfv_params(¶ms)), seed: seed.clone(), threshold_m: 3, threshold_n: 3, // Need to use n now to suggest committee size ..E3Requested::default() - }); + }; println!("Sending E3 event..."); // Send the computation requested event - bus.send(e3_request_event.clone()).await?; + bus.publish(e3_request_event.clone()); // Test that we cannot send the same event twice - bus.send(e3_request_event.clone()).await?; + bus.publish(e3_request_event.clone()); // Finalize committee with all available nodes - bus.send(EnclaveEvent::from(CommitteeFinalized { + bus.publish(CommitteeFinalized { e3_id: e3_id.clone(), committee: eth_addrs.clone(), chain_id: 1, - })) - .await?; + }); // Generate the test shares and pubkey let rng_test = create_shared_rng_from_u64(42); @@ -235,8 +232,8 @@ async fn test_public_key_aggregation_and_decryption() -> Result<()> { let aggregated_event: Vec<_> = history .into_iter() - .filter_map(|e| match e { - EnclaveEvent::PublicKeyAggregated { data, .. } => Some(data), + .filter_map(|e| match e.into_data() { + EnclaveEventData::PublicKeyAggregated(data) => Some(data), _ => None, }) .collect(); @@ -253,15 +250,15 @@ async fn test_public_key_aggregation_and_decryption() -> Result<()> { let (ciphertext, expected) = encrypt_ciphertext(¶ms, test_pubkey, raw_plaintext)?; // Setup Ciphertext Published Event - let ciphertext_published_event = EnclaveEvent::from(CiphertextOutputPublished { + let ciphertext_published_event = CiphertextOutputPublished { ciphertext_output: ciphertext .iter() .map(|ct| ArcBytes::from_bytes(&ct.to_bytes())) .collect(), e3_id: e3_id.clone(), - }); + }; - bus.send(ciphertext_published_event.clone()).await?; + bus.publish(ciphertext_published_event.clone()); let history = history_collector .send(TakeEvents::::new(6)) @@ -269,8 +266,8 @@ async fn test_public_key_aggregation_and_decryption() -> Result<()> { let actual = history .into_iter() - .filter_map(|e| match e { - EnclaveEvent::PlaintextAggregated { data, .. } => Some(data), + .filter_map(|e| match e.into_data() { + EnclaveEventData::PlaintextAggregated(data) => Some(data), _ => None, }) .collect::>() @@ -309,25 +306,20 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { }; // Send e3request - bus.send( - EnclaveEvent::from(E3Requested { - e3_id: e3_id.clone(), - threshold_m: 2, - threshold_n: 2, - seed: seed.clone(), - params: ArcBytes::from_bytes(&encode_bfv_params(¶ms)), - ..E3Requested::default() - }) - .clone(), - ) - .await?; - - bus.send(EnclaveEvent::from(CommitteeFinalized { + bus.publish(E3Requested { + e3_id: e3_id.clone(), + threshold_m: 2, + threshold_n: 2, + seed: seed.clone(), + params: ArcBytes::from_bytes(&encode_bfv_params(¶ms)), + ..E3Requested::default() + }); + + bus.publish(CommitteeFinalized { e3_id: e3_id.clone(), committee: eth_addrs.clone(), chain_id: 1, - })) - .await?; + }); let history_collector = cn1.history().unwrap(); let error_collector = cn1.errors().unwrap(); @@ -339,7 +331,7 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { assert_eq!(errors.len(), 0); // SEND SHUTDOWN! - bus.send(EnclaveEvent::from(Shutdown)).await?; + bus.publish(Shutdown); // This is probably overkill but required to ensure that all the data is written sleep(Duration::from_secs(1)).await; @@ -368,7 +360,9 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { // Apply the address and data node to two new actors // Here we test that hydration occurred sucessfully - let bus = EventBus::::new(EventBusConfig { deduplicate: true }).start(); + let bus = EventBus::::new(EventBusConfig { deduplicate: true }) + .start() + .into(); let cn1 = setup_local_ciphernode( &bus, &rng, @@ -395,8 +389,8 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { // get the public key from history. let pubkey: PublicKey = history .iter() - .filter_map(|evt| match evt { - EnclaveEvent::KeyshareCreated { data, .. } => { + .filter_map(|evt| match evt.get_data() { + EnclaveEventData::KeyshareCreated(data) => { PublicKeyShare::deserialize(&data.pubkey, ¶ms, crpoly.clone()).ok() } _ => None, @@ -406,17 +400,13 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { // Publish the ciphertext let raw_plaintext = vec![vec![1234, 567890]]; let (ciphertext, expected) = encrypt_ciphertext(¶ms, pubkey, raw_plaintext)?; - bus.send( - EnclaveEvent::from(CiphertextOutputPublished { - ciphertext_output: ciphertext - .iter() - .map(|ct| ArcBytes::from_bytes(&ct.to_bytes())) - .collect(), - e3_id: e3_id.clone(), - }) - .clone(), - ) - .await?; + bus.publish(CiphertextOutputPublished { + ciphertext_output: ciphertext + .iter() + .map(|ct| ArcBytes::from_bytes(&ct.to_bytes())) + .collect(), + e3_id: e3_id.clone(), + }); let history = history_collector .send(TakeEvents::::new(5)) @@ -424,8 +414,8 @@ async fn test_stopped_keyshares_retain_state() -> Result<()> { let actual = history .into_iter() - .filter_map(|e| match e { - EnclaveEvent::PlaintextAggregated { data, .. } => Some(data), + .filter_map(|e| match e.into_data() { + EnclaveEventData::PlaintextAggregated(data) => Some(data), _ => None, }) .collect::>() @@ -453,9 +443,12 @@ async fn test_p2p_actor_forwards_events_to_network() -> Result<()> { // Setup elements in test let (cmd_tx, mut cmd_rx) = mpsc::channel(100); // Transmit byte events to the network let (event_tx, _) = broadcast::channel(100); // Receive byte events from the network - let bus = EventBus::::new(EventBusConfig { deduplicate: true }).start(); + let bus: BusHandle = + EventBus::::new(EventBusConfig { deduplicate: true }) + .start() + .into(); let history_collector = HistoryCollector::::new().start(); - bus.do_send(Subscribe::new("*", history_collector.clone().recipient())); + bus.subscribe("*", history_collector.clone().recipient()); let event_rx = Arc::new(event_tx.subscribe()); // Pas cmd and event channels to NetEventTranslator NetEventTranslator::setup(&bus, &cmd_tx, &event_rx, "my-topic"); @@ -485,26 +478,26 @@ async fn test_p2p_actor_forwards_events_to_network() -> Result<()> { anyhow::Ok(()) }); - let evt_1 = EnclaveEvent::from(PlaintextAggregated { + let evt_1 = PlaintextAggregated { e3_id: E3id::new("1235", 1), decrypted_output: vec![ArcBytes::from_bytes(&[1, 2, 3, 4])], - }); + }; - let evt_2 = EnclaveEvent::from(PlaintextAggregated { + let evt_2 = PlaintextAggregated { e3_id: E3id::new("1236", 1), decrypted_output: vec![ArcBytes::from_bytes(&[1, 2, 3, 4])], - }); + }; - let local_evt_3 = EnclaveEvent::from(CiphernodeSelected { + let local_evt_3 = CiphernodeSelected { e3_id: E3id::new("1235", 1), threshold_m: 3, threshold_n: 3, ..CiphernodeSelected::default() - }); + }; - bus.do_send(evt_1.clone()); - bus.do_send(evt_2.clone()); - bus.do_send(local_evt_3.clone()); // This is a local event which should not be broadcast to the network + bus.publish(evt_1.clone()); + bus.publish(evt_2.clone()); + bus.publish(local_evt_3.clone()); // This is a local event which should not be broadcast to the network // check the history of the event bus let history = history_collector @@ -514,15 +507,18 @@ async fn test_p2p_actor_forwards_events_to_network() -> Result<()> { assert_eq!( *msgs.lock().await, vec![ - GossipData::GossipBytes(evt_1.to_bytes()?), - GossipData::GossipBytes(evt_2.to_bytes()?) + GossipData::GossipBytes(bus.event_from(evt_1.clone()).to_bytes()?), + GossipData::GossipBytes(bus.event_from(evt_2.clone()).to_bytes()?) ], // notice no local events "NetEventTranslator did not transmit correct events to the network" ); assert_eq!( - history, - vec![evt_1, evt_2, local_evt_3], // all local events that have been broadcast but no + history + .into_iter() + .map(|e| e.into_data()) + .collect::>(), + vec![evt_1.into(), evt_2.into(), local_evt_3.into()], // all local events that have been broadcast but no // events from the loopback "NetEventTranslator must not retransmit forwarded event to event bus" ); @@ -544,22 +540,21 @@ async fn test_duplicate_e3_id_with_different_chain_id() -> Result<()> { setup_score_sortition_environment(&bus, ð_addrs, 2).await?; // Send the computation requested event - bus.send(EnclaveEvent::from(E3Requested { + bus.publish(E3Requested { e3_id: E3id::new("1234", 1), threshold_m: 3, threshold_n: 3, seed: seed.clone(), params: ArcBytes::from_bytes(&encode_bfv_params(¶ms)), ..E3Requested::default() - })) - .await?; + }); - bus.send(EnclaveEvent::from(CommitteeFinalized { + bus.publish(CommitteeFinalized { e3_id: E3id::new("1234", 1), committee: eth_addrs.clone(), chain_id: 1, - })) - .await?; + }); + // Generate the test shares and pubkey let rng_test = create_shared_rng_from_u64(42); let test_pubkey = aggregate_public_key(&generate_pk_shares( @@ -572,31 +567,30 @@ async fn test_duplicate_e3_id_with_different_chain_id() -> Result<()> { .await?; assert_eq!( - history.last().unwrap(), - &EnclaveEvent::from(PublicKeyAggregated { + history.last().cloned().unwrap().into_data(), + PublicKeyAggregated { pubkey: test_pubkey.to_bytes(), e3_id: E3id::new("1234", 1), nodes: OrderedSet::from(eth_addrs.clone()), - }) + } + .into() ); // Send the computation requested event - bus.send(EnclaveEvent::from(E3Requested { + bus.publish(E3Requested { e3_id: E3id::new("1234", 2), threshold_m: 3, threshold_n: 3, seed: seed.clone(), params: ArcBytes::from_bytes(&encode_bfv_params(¶ms)), ..E3Requested::default() - })) - .await?; + }); - bus.send(EnclaveEvent::from(CommitteeFinalized { + bus.publish(CommitteeFinalized { e3_id: E3id::new("1234", 2), committee: eth_addrs.clone(), chain_id: 2, - })) - .await?; + }); let test_pubkey = aggregate_public_key(&generate_pk_shares( ¶ms, &crpoly, &rng_test, ð_addrs, @@ -607,12 +601,13 @@ async fn test_duplicate_e3_id_with_different_chain_id() -> Result<()> { .await?; assert_eq!( - history.last().unwrap(), - &EnclaveEvent::from(PublicKeyAggregated { + history.last().cloned().unwrap().into_data(), + PublicKeyAggregated { pubkey: test_pubkey.to_bytes(), e3_id: E3id::new("1234", 2), nodes: OrderedSet::from(eth_addrs.clone()), - }) + } + .into() ); Ok(()) @@ -625,25 +620,28 @@ async fn test_p2p_actor_forwards_events_to_bus() -> Result<()> { // Setup elements in test let (cmd_tx, _) = mpsc::channel(100); // Transmit byte events to the network let (event_tx, event_rx) = broadcast::channel(100); // Receive byte events from the network - let bus = EventBus::::new(EventBusConfig { deduplicate: true }).start(); + let bus: BusHandle = + EventBus::::new(EventBusConfig { deduplicate: true }) + .start() + .into(); let history_collector = HistoryCollector::::new().start(); - bus.do_send(Subscribe::new("*", history_collector.clone().recipient())); + bus.subscribe("*", history_collector.clone().recipient()); NetEventTranslator::setup(&bus, &cmd_tx, &Arc::new(event_rx), "mytopic"); // Capture messages from output on msgs vec - let event = EnclaveEvent::from(E3Requested { + let event = E3Requested { e3_id: E3id::new("1235", 1), threshold_m: 3, threshold_n: 3, seed: seed.clone(), params: ArcBytes::from_bytes(&[1, 2, 3, 4]), ..E3Requested::default() - }); + }; // lets send an event from the network let _ = event_tx.send(NetEvent::GossipData(GossipData::GossipBytes( - event.to_bytes()?, + bus.event_from(event.clone()).to_bytes()?, ))); // check the history of the event bus @@ -651,7 +649,13 @@ async fn test_p2p_actor_forwards_events_to_bus() -> Result<()> { .send(TakeEvents::::new(1)) .await?; - assert_eq!(history, vec![event]); + assert_eq!( + history + .into_iter() + .map(|e| e.into_data()) + .collect::>(), + vec![event.into()] + ); Ok(()) } diff --git a/crates/trbfv/src/calculate_threshold_decryption.rs b/crates/trbfv/src/calculate_threshold_decryption.rs index 31ed8355ad..8bd4831a7b 100644 --- a/crates/trbfv/src/calculate_threshold_decryption.rs +++ b/crates/trbfv/src/calculate_threshold_decryption.rs @@ -11,11 +11,10 @@ use crate::{helpers::try_poly_from_bytes, PartyId, TrBFVConfig}; use anyhow::*; use e3_bfv_helpers::{decode_plaintext_to_vec_u64, encode_vec_u64_to_bytes}; use e3_utils::utility_types::ArcBytes; -use fhe::bfv::{Encoding, Plaintext}; +use fhe::bfv::Plaintext; use fhe::{bfv::Ciphertext, trbfv::ShareManager}; use fhe_math::rq::Poly; use fhe_traits::DeserializeParametrized; -use fhe_traits::FheDecoder; use tracing::info; /// Shamir shares for a single party to decrypt a batch of ciphertexts. diff --git a/crates/utils/src/utility_types.rs b/crates/utils/src/utility_types.rs index bb71734dd6..59b2fedd8e 100644 --- a/crates/utils/src/utility_types.rs +++ b/crates/utils/src/utility_types.rs @@ -18,7 +18,7 @@ use crate::formatters::hexf; pub type SharedRng = Arc>; -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, Default, PartialEq, Eq, Hash)] pub struct ArcBytes(Arc>); impl ArcBytes { diff --git a/examples/CRISP/enclave.config.yaml b/examples/CRISP/enclave.config.yaml index 92bb4b9d16..2104bf53ad 100644 --- a/examples/CRISP/enclave.config.yaml +++ b/examples/CRISP/enclave.config.yaml @@ -3,7 +3,7 @@ chains: rpc_url: ws://localhost:8545 contracts: e3_program: - address: "0xc5a5C42992dECbae36851359345FE25997F5C42d" + address: "0x67d269191c92Caf3cD7723F116c85e6E9bf55933" deploy_block: 1 enclave: address: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0" @@ -61,4 +61,3 @@ nodes: autopassword: true role: type: aggregator - diff --git a/packages/enclave-contracts/scripts/deployAndSave/poseidonT3.ts b/packages/enclave-contracts/scripts/deployAndSave/poseidonT3.ts index f3220ceb82..b301480e28 100644 --- a/packages/enclave-contracts/scripts/deployAndSave/poseidonT3.ts +++ b/packages/enclave-contracts/scripts/deployAndSave/poseidonT3.ts @@ -27,23 +27,26 @@ export const deployAndSavePoseidonT3 = async ({ // probably on the hardhat network // fund the keyless account const [sender] = await ethers.getSigners(); - await sender.sendTransaction({ + let tx = await sender.sendTransaction({ to: poseidon.proxy.from, value: poseidon.proxy.gas, }); + await tx.wait(); // then send the presigned transaction deploying the proxy - await ethers.provider.broadcastTransaction(poseidon.proxy.tx); + tx = await ethers.provider.broadcastTransaction(poseidon.proxy.tx); + await tx.wait(); console.log(`Proxy deployed to: ${poseidon.proxy.address}`); } // Then deploy the hasher, if needed if ((await ethers.provider.getCode(poseidon.PoseidonT3.address)) === "0x") { const [sender] = await ethers.getSigners(); - await sender.sendTransaction({ + let tx = await sender.sendTransaction({ to: poseidon.proxy.address, data: poseidon.PoseidonT3.data, }); + await tx.wait(); console.log(`PoseidonT3 deployed to: ${poseidon.PoseidonT3.address}`); }