Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
441e41d
feat: prompt user to autogenerate net keypair when not specified
Feb 17, 2026
2520ef2
add config dir prompt
Feb 17, 2026
79b0fdb
fix up ordering in config-set
Feb 17, 2026
2c2ad82
refactor: consolidate config-set into ciphernode setup command
Feb 17, 2026
c1dbbd2
add ignore switch for address check
Feb 17, 2026
bcf851b
Update crates/cli/src/wallet_set.rs
ryardley Feb 17, 2026
d661b2f
Update crates/ciphernode-builder/src/ciphernode_builder.rs
ryardley Feb 17, 2026
5080799
Update docs/pages/ciphernode-operators/running.mdx
ryardley Feb 17, 2026
8237b76
fix parsers
Feb 17, 2026
3757c55
get test working in virtual environments
Feb 18, 2026
e4fbfe8
header
Feb 18, 2026
e366ba9
import get_tmpdir fn
Feb 18, 2026
b752dc7
fix bad imports
Feb 18, 2026
e3ae32d
make tmp folder if not exists
Feb 18, 2026
8cc413f
explain why we need to use get_tmpdir()
Feb 18, 2026
575b967
set address in config when changing wallet private key
Feb 18, 2026
fd24c17
headers
Feb 18, 2026
b9c34d1
add dependency diagram
Feb 19, 2026
879b687
update yaml
Feb 19, 2026
aa4b55f
remove redundant yaml manipulation
Feb 19, 2026
0260dfc
headers
Feb 19, 2026
c1011f2
remove net commands
Feb 19, 2026
5789681
add config location instructions
Feb 19, 2026
edb6ad7
Add wallet get command and improve setup output
Feb 19, 2026
f595da9
trigger
Feb 19, 2026
47832fc
add enclave net get-peer-id
Feb 19, 2026
958f637
tidy up output
Feb 19, 2026
7514f55
headers
Feb 19, 2026
16dace3
remove diagram
Feb 19, 2026
25d3692
zeroize validation
Feb 19, 2026
7d18fa7
remove address
Feb 19, 2026
6a50ae5
tidy up comments
Feb 19, 2026
2da767b
autogenerate net keypair
Feb 19, 2026
028ba5a
fix doc tests
Feb 19, 2026
4ec942f
add color to errors
Feb 19, 2026
fdb4ccf
stored data is bytes not string
Feb 19, 2026
b5200ba
fix using_custom_config param
Feb 19, 2026
bfebcf8
fix custom config
Feb 19, 2026
66b9e9b
update pnpm-lock
Feb 20, 2026
e5bb527
add build script to zk-prover
Feb 20, 2026
e697c9b
ensure circuits will exist if there are no artifacts
Feb 20, 2026
eedb657
if no nargo dont try to build circuits
Feb 20, 2026
8291ace
add comment
Feb 20, 2026
e7ca739
update tests to support custom_bb
Feb 20, 2026
e978330
add check for bb
Feb 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 17 additions & 34 deletions crates/ciphernode-builder/src/ciphernode_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use e3_sortition::{
NodeStateRepositoryFactory, Sortition, SortitionBackend, SortitionRepositoryFactory,
};
use e3_sync::sync;
use e3_utils::{rand_eth_addr, SharedRng};
use e3_utils::SharedRng;
use e3_zk_prover::{setup_zk_actors, ZkBackend};
use std::time::Duration;
use std::{collections::HashMap, path::PathBuf, sync::Arc};
Expand Down Expand Up @@ -61,7 +61,6 @@ pub struct CiphernodeBuilder {
multithread_cache: Option<Addr<Multithread>>,
multithread_concurrent_jobs: Option<usize>,
multithread_report: Option<Addr<MultithreadReport>>,
name: String,
pubkey_agg: bool,
rng: SharedRng,
sortition_backend: SortitionBackend,
Expand All @@ -74,7 +73,7 @@ pub struct CiphernodeBuilder {
threshold_plaintext_agg: bool,
zk_backend: Option<ZkBackend>,
net_config: Option<NetConfig>,
start_buffer: bool,
ignore_address_check: bool,
}

// Simple Net Configuration
Expand Down Expand Up @@ -115,7 +114,7 @@ impl CiphernodeBuilder {
/// - name - Unique name for the ciphernode
/// - rng - Arc Mutex wrapped random number generator
/// - cipher - Cipher for encryption and decryption of sensitive data
pub fn new(name: &str, rng: SharedRng, cipher: Arc<Cipher>) -> Self {
pub fn new(rng: SharedRng, cipher: Arc<Cipher>) -> Self {
Self {
address: None,
chains: vec![],
Expand All @@ -128,7 +127,6 @@ impl CiphernodeBuilder {
multithread_cache: None,
multithread_concurrent_jobs: None,
multithread_report: None,
name: name.to_owned(),
pubkey_agg: false,
rng,
sortition_backend: SortitionBackend::score(),
Expand All @@ -140,8 +138,8 @@ impl CiphernodeBuilder {
testmode_signer: None,
threshold_plaintext_agg: false,
net_config: None,
start_buffer: false,
zk_backend: None,
ignore_address_check: false,
}
}

Expand Down Expand Up @@ -193,12 +191,6 @@ impl CiphernodeBuilder {
self.testmode_errors = true;
self
}
/// Ensure SnapshotBuffer starts immediately instead of waiting for SyncEnded. This is important
/// for tests that don't specifically
pub fn testmode_start_buffer_immediately(mut self) -> Self {
self.start_buffer = true;
self
}

/// Use the node configuration on these specific chains. This will overwrite any previously
/// given chains.
Expand All @@ -207,12 +199,6 @@ impl CiphernodeBuilder {
self
}

/// Use the given Address to represent the node. This should be unique.
pub fn with_address(mut self, addr: &str) -> Self {
self.address = Some(addr.to_owned());
self
}

/// Log data actor events
pub fn with_logging(mut self) -> Self {
self.logging = true;
Expand Down Expand Up @@ -316,6 +302,11 @@ impl CiphernodeBuilder {
self
}

pub fn testmode_ignore_address_check(mut self) -> Self {
self.ignore_address_check = true;
self
}

fn create_local_bus() -> Addr<EventBus<EnclaveEvent>> {
EventBus::<EnclaveEvent>::new(EventBusConfig { deduplicate: true }).start()
}
Expand Down Expand Up @@ -368,15 +359,6 @@ impl CiphernodeBuilder {
None
};

let addr = if let Some(addr) = self.address.clone() {
info!("Using eth address = {}", addr);
addr
} else {
info!("Using random eth address");
// TODO: This is for testing and should not be used for production if we use this to create ciphernodes in production
rand_eth_addr(&self.rng)
};

// Create provider cache early to use for chain validation
let mut provider_cache = if let Some(signer) = self.testmode_signer.take() {
ProviderCache::new().with_signer(signer)
Expand All @@ -388,33 +370,34 @@ impl CiphernodeBuilder {
// Get an event system instance.
let event_system =
if let EventSystemType::Persisted { kv_path, log_path } = self.event_system.clone() {
EventSystem::persisted(&addr, log_path, kv_path)
EventSystem::persisted(log_path, kv_path)
.with_event_bus(local_bus)
.with_aggregate_config(aggregate_config.clone())
} else {
if let Some(ref store) = self.in_mem_store {
EventSystem::in_mem_from_store(&addr, store)
EventSystem::in_mem_from_store(store)
.with_event_bus(local_bus)
.with_aggregate_config(aggregate_config.clone())
} else {
EventSystem::in_mem(&addr)
EventSystem::in_mem()
.with_event_bus(local_bus)
.with_aggregate_config(aggregate_config.clone())
}
};

let bus = event_system.handle()?;
let store = event_system.store()?;
let eventstore_ts = event_system.eventstore_getter_ts()?;
let eventstore_seq = event_system.eventstore_getter_seq()?;
let cipher = &self.cipher;
let repositories = Arc::new(store.repositories());

// Now we add write support as store depends on event system
let mut provider_cache =
provider_cache.with_write_support(Arc::clone(cipher), Arc::clone(&repositories));

// Use the configured backend directly
// We need to supply the Hlc to the bus handle in order to enable it
let addr = provider_cache.ensure_signer().await?.address().to_string();
let bus = event_system.handle()?.enable(&addr);

// Use the configured sortition backend directly
let default_backend = self.sortition_backend.clone();

let ciphernode_selector =
Expand Down
71 changes: 19 additions & 52 deletions crates/ciphernode-builder/src/event_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,15 @@ use e3_data::{
CommitLogEventLog, DataStore, InMemEventLog, InMemSequenceIndex, InMemStore, SledSequenceIndex,
SledStore,
};
use e3_events::hlc::Hlc;
use e3_events::hlc_factory::HlcFactory;
use e3_events::{
AggregateConfig, BusHandle, EnclaveEvent, EventBus, EventBusConfig, EventStore,
AggregateConfig, BusHandle, Disabled, EnclaveEvent, EventBus, EventBusConfig, EventStore,
EventStoreQueryBy, EventStoreRouter, EventSubscriber, EventType, InsertBatch, SeqAgg,
Sequencer, SnapshotBuffer, StoreEventRequested, TsAgg, UpdateDestination,
};
use e3_utils::enumerate_path;
use once_cell::sync::OnceCell;
use std::collections::HashMap;
use std::hash::{DefaultHasher, Hash, Hasher};
use std::path::PathBuf;

struct InMemBackend {
Expand All @@ -45,7 +44,7 @@ struct PersistedBackend {
}

impl PersistedBackend {
fn get_or_init_store(&self, handle: &BusHandle) -> Result<Addr<SledStore>> {
fn get_or_init_store(&self, handle: &BusHandle<Disabled>) -> Result<Addr<SledStore>> {
self.store
.get_or_try_init(|| SledStore::new(handle, &self.sled_path))
.cloned()
Expand Down Expand Up @@ -74,8 +73,6 @@ pub enum EventStoreAddrs {
/// - **WriteBuffer** for batching inserts from actors into a snapshot
///
pub struct EventSystem {
/// A nodes id to be used as a tiebreaker in logical clock timestamp differentiation
node_id: u32,
/// EventSystem backend either persisted or in memory
backend: EventSystemBackend,
/// WriteBuffer for batching inserts from actors into a snapshot
Expand All @@ -85,9 +82,7 @@ pub struct EventSystem {
/// EventSystem eventbus
eventbus: OnceCell<Addr<EventBus<EnclaveEvent>>>,
/// EventSystem BusHandle
handle: OnceCell<BusHandle>,
/// Hlc override
hlc: OnceCell<Hlc>,
handle: OnceCell<BusHandle<Disabled>>,
/// Central configuration for aggregates, including delays and other settings
aggregate_config: OnceCell<AggregateConfig>,
/// Cached EventStoreAddrs for idempotency
Expand All @@ -96,14 +91,13 @@ pub struct EventSystem {

impl EventSystem {
/// Create a new in memory EventSystem with default settings
pub fn new(name: &str) -> Self {
EventSystem::in_mem(name)
pub fn new() -> Self {
EventSystem::in_mem()
}

/// Create an in memory EventSystem
pub fn in_mem(node_id: &str) -> Self {
pub fn in_mem() -> Self {
Self {
node_id: EventSystem::node_id(node_id),
backend: EventSystemBackend::InMem(InMemBackend {
eventstores: OnceCell::new(),
store: OnceCell::new(),
Expand All @@ -112,16 +106,14 @@ impl EventSystem {
sequencer: OnceCell::new(),
eventbus: OnceCell::new(),
handle: OnceCell::new(),
hlc: OnceCell::new(),
aggregate_config: OnceCell::new(),
eventstore_addrs: OnceCell::new(),
}
}

/// Create an in memory EventSystem with a given store
pub fn in_mem_from_store(node_id: &str, store: &Addr<InMemStore>) -> Self {
pub fn in_mem_from_store(store: &Addr<InMemStore>) -> Self {
Self {
node_id: EventSystem::node_id(node_id),
backend: EventSystemBackend::InMem(InMemBackend {
eventstores: OnceCell::new(),
store: OnceCell::from(store.to_owned()),
Expand All @@ -130,16 +122,14 @@ impl EventSystem {
sequencer: OnceCell::new(),
eventbus: OnceCell::new(),
handle: OnceCell::new(),
hlc: OnceCell::new(),
aggregate_config: OnceCell::new(),
eventstore_addrs: OnceCell::new(),
}
}

/// Create a persisted EventSystem with datafiles at the given paths
pub fn persisted(node_id: &str, log_path: PathBuf, sled_path: PathBuf) -> Self {
pub fn persisted(log_path: PathBuf, sled_path: PathBuf) -> Self {
Self {
node_id: EventSystem::node_id(node_id),
backend: EventSystemBackend::Persisted(PersistedBackend {
log_path,
sled_path,
Expand All @@ -150,7 +140,6 @@ impl EventSystem {
sequencer: OnceCell::new(),
eventbus: OnceCell::new(),
handle: OnceCell::new(),
hlc: OnceCell::new(),
aggregate_config: OnceCell::new(),
eventstore_addrs: OnceCell::new(),
}
Expand All @@ -170,12 +159,6 @@ impl EventSystem {
self
}

/// Add an injected hlc
pub fn with_hlc(self, hlc: Hlc) -> Self {
let _ = self.hlc.set(hlc);
self
}

/// Add aggregate configuration including delays and other settings
pub fn with_aggregate_config(self, config: AggregateConfig) -> Self {
let _ = self.aggregate_config.set(config);
Expand Down Expand Up @@ -320,18 +303,11 @@ impl EventSystem {
}
}

/// Get an instance of the Hlc
pub fn hlc(&self) -> Result<Hlc> {
self.hlc
.get_or_try_init(|| Ok(Hlc::new(self.node_id)))
.cloned()
}

/// Get the BusHandle
pub fn handle(&self) -> Result<BusHandle> {
pub fn handle(&self) -> Result<BusHandle<Disabled>> {
self.handle
.get_or_try_init(|| {
let handle = BusHandle::new(self.eventbus(), self.sequencer()?, self.hlc()?);
let handle = BusHandle::new(self.eventbus(), self.sequencer()?, HlcFactory::new());
// Buffer subscribes to all events first
// This is important so as to open up a batch for each sequence
handle.subscribe(EventType::All, self.buffer()?.recipient());
Expand Down Expand Up @@ -363,12 +339,6 @@ impl EventSystem {

Ok(store)
}

fn node_id(name: &str) -> u32 {
let mut hasher = DefaultHasher::new();
name.hash(&mut hasher);
hasher.finish() as u32
}
}

struct NoopBatchReceiver;
Expand Down Expand Up @@ -480,7 +450,7 @@ mod tests {
async fn test_persisted() -> Result<()> {
let _guard = with_tracing("debug");
let tmp = TempDir::new().unwrap();
let system = EventSystem::persisted("cn2", tmp.path().join("log"), tmp.path().join("sled"));
let system = EventSystem::persisted(tmp.path().join("log"), tmp.path().join("sled"));
let _handle = system.handle().expect("Failed to get handle");
system.store().expect("Failed to get store");
Ok(())
Expand All @@ -489,7 +459,7 @@ mod tests {
#[actix::test]
async fn test_in_mem() {
let eventbus = EventBus::<EnclaveEvent>::default().start();
let system = EventSystem::in_mem("cn1").with_event_bus(eventbus);
let system = EventSystem::in_mem().with_event_bus(eventbus);

let _handle = system.handle().expect("Failed to get handle");
system.store().expect("Failed to get store");
Expand All @@ -505,11 +475,11 @@ mod tests {
delays.insert(AggregateId::new(0), Duration::from_secs(1)); // Ag0 is default
let config = AggregateConfig::new(delays);

let system = EventSystem::in_mem("cn1")
let system = EventSystem::in_mem()
.with_fresh_bus()
.with_aggregate_config(config);

let handle = system.handle()?;
let handle = system.handle()?.enable("test");
let datastore = system.store()?;
let buffer = system.buffer()?;

Expand Down Expand Up @@ -661,7 +631,7 @@ mod tests {
let aggregate_config = AggregateConfig::new(delays);

// Test in-memory eventstores
let system = EventSystem::in_mem("test_multi").with_aggregate_config(aggregate_config);
let system = EventSystem::in_mem().with_aggregate_config(aggregate_config);
let Ok(EventStoreAddrs::InMem(addrs)) = system.eventstore_addrs() else {
panic!("Expected InMem event store addrs");
};
Expand All @@ -675,12 +645,9 @@ mod tests {

// Test persistent eventstores
let tmp = TempDir::new().unwrap();
let persisted_system = EventSystem::persisted(
"test_persisted",
tmp.path().join("log"),
tmp.path().join("sled"),
)
.with_aggregate_config(AggregateConfig::new(HashMap::new()));
let persisted_system =
EventSystem::persisted(tmp.path().join("log"), tmp.path().join("sled"))
.with_aggregate_config(AggregateConfig::new(HashMap::new()));

let Ok(EventStoreAddrs::Persisted(addrs)) = persisted_system.eventstore_addrs() else {
panic!("Expected Persisted event store addrs");
Expand Down
Loading
Loading