Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
315b77b
chore: copy over contracts from tokenomics branch
hmzakhalid Sep 19, 2025
030e0ff
feat: policy can ban nodes
hmzakhalid Sep 24, 2025
03632d5
feat: ticket checkpoints
hmzakhalid Sep 25, 2025
7677604
feat: ticket usdc wrapper with votes:
hmzakhalid Sep 26, 2025
f777154
feat: rewards distribution
hmzakhalid Sep 26, 2025
4acd3a4
feat: add ignition modules
hmzakhalid Sep 29, 2025
7aace0b
feat: add bonding registry tests
hmzakhalid Sep 29, 2025
85cf66e
fix: stack too deep error
hmzakhalid Sep 29, 2025
c9cce4e
fix: enclave tests
hmzakhalid Sep 29, 2025
6089fa5
feat: deployment scripts
hmzakhalid Sep 30, 2025
10b36f5
feat: ciphernode add script
hmzakhalid Sep 30, 2025
f19e8a8
chore: fix linting errors
hmzakhalid Sep 30, 2025
58cfe9f
chore: refactor
hmzakhalid Sep 30, 2025
af8d7ac
fix: mint USDC when requesting committee:
hmzakhalid Sep 30, 2025
1c4cb16
fix: contract addresses
hmzakhalid Sep 30, 2025
8b1f9ee
fix: review fixes
hmzakhalid Oct 1, 2025
14711f3
chore: updates
hmzakhalid Oct 1, 2025
66b3ec4
fix: more review fixes
hmzakhalid Oct 2, 2025
0a3958d
fix: contract updates and TODO comments
hmzakhalid Oct 2, 2025
f4f73f0
chore: wip
hmzakhalid Oct 3, 2025
30dfad9
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 11, 2025
005dcf9
chore: review fixes
hmzakhalid Oct 11, 2025
498c9fd
chore: merge economics ciphernode integration
hmzakhalid Oct 14, 2025
bade2f7
fix: crisp cli request fix
hmzakhalid Oct 14, 2025
4005ae4
chore: lint
hmzakhalid Oct 14, 2025
6c95d1a
chore: lint
hmzakhalid Oct 14, 2025
97fe0db
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 14, 2025
ee767e0
chore: merge dev
hmzakhalid Oct 14, 2025
c083619
chore: add header
hmzakhalid Oct 14, 2025
d79b571
fix: remove bonding registry artifacts from gitignore
hmzakhalid Oct 15, 2025
59f64d5
fix: remove filter
hmzakhalid Oct 15, 2025
6cb50fc
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 15, 2025
9f85fa6
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 15, 2025
a2074e0
chore: fix test
hmzakhalid Oct 15, 2025
a4b219c
feat: onchain committee sortition
hmzakhalid Oct 23, 2025
2b78cc4
chore: header
hmzakhalid Oct 23, 2025
b63d6bb
chore: linter fix
hmzakhalid Oct 23, 2025
cc2fa56
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 23, 2025
d524e35
chore: merge dev to hmza/economics
hmzakhalid Oct 23, 2025
225e445
chore: add CommitteeSortition to gitigore
hmzakhalid Oct 23, 2025
6491252
fix: pass posideonT3 to Ciphernode deployment
hmzakhalid Oct 23, 2025
492bf7c
chore: remove old contracts from hardhat config
hmzakhalid Oct 23, 2025
f736216
chore: add contracts to hh config
hmzakhalid Oct 23, 2025
85a9a23
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 23, 2025
56eec15
chore: update deployment addresses
hmzakhalid Oct 23, 2025
367817b
fix: minor deployment errors
hmzakhalid Oct 24, 2025
b30eebc
chore: remove ignition (#887)
ctrlc03 Oct 24, 2025
0d3e17f
fix: interface fix
hmzakhalid Oct 24, 2025
f460597
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 24, 2025
b8fd610
fix: ciphernode builder contract registry writer
hmzakhalid Oct 24, 2025
005e803
chore: committee sorition
hmzakhalid Oct 26, 2025
8f41d25
chore: merge sortition to ciphernode contract
hmzakhalid Oct 26, 2025
21bc518
feat: ciphernode contract methods in crates
hmzakhalid Oct 26, 2025
fcd2bca
feat: integrate committee finalizer
hmzakhalid Oct 26, 2025
be717ba
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 26, 2025
ac2f7b2
chore: merge dev
hmzakhalid Oct 26, 2025
31764ca
chore: remove unused contracts
hmzakhalid Oct 26, 2025
5028edc
fix: coderabbit review fixes
hmzakhalid Oct 26, 2025
7d77897
fix: error handling for committee finalizer
hmzakhalid Oct 26, 2025
0805bd9
fix: update nodes addresses
hmzakhalid Oct 26, 2025
c5658c6
feat(sync): implement persistent node state, finalized committees, an…
hmzakhalid Oct 27, 2025
d15361a
fix: add score sorition to integration test
hmzakhalid Oct 27, 2025
c6c4437
fix: integration test
hmzakhalid Oct 27, 2025
96ef2ef
fix: dont call sortition on Committee Finalized
hmzakhalid Oct 27, 2025
77f81ff
fix: dont call sortition on Committee Finalized
hmzakhalid Oct 27, 2025
64b60e5
fix: integration test passing
hmzakhalid Oct 27, 2025
1b6e85c
chore(sdk): approve fee token for e3 request
hmzakhalid Oct 27, 2025
a0e9675
fix: fetch time from RPC
hmzakhalid Oct 27, 2025
a614dd8
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 27, 2025
80c5689
fix: trust committee finalized event for party ids
hmzakhalid Oct 27, 2025
7ef399d
fix: sdk test
hmzakhalid Oct 27, 2025
083c09f
feat(sortition): add sortition to ciphernode builder and make distanc…
hmzakhalid Oct 28, 2025
233bcd4
fix: contract addresses for crisp e2e test
hmzakhalid Oct 28, 2025
3c97583
feat: tests for new sortition changes
hmzakhalid Oct 28, 2025
0cec52a
chore: linter fixes
hmzakhalid Oct 28, 2025
9ff6c74
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 28, 2025
3a143de
fix: increase publish cound
hmzakhalid Oct 28, 2025
79efc75
fix: increase E3 window time
hmzakhalid Oct 28, 2025
b8208b0
fix: aggreagtor wallet setup
hmzakhalid Oct 28, 2025
5ebdd1b
fix: legacy integration tests
hmzakhalid Oct 28, 2025
065ea2b
fix: debug the correct timestamp
hmzakhalid Oct 28, 2025
088df6a
chore: documentation for score sortition flow
hmzakhalid Oct 28, 2025
424d42d
feat: remove node state manager actor and create a single sortition a…
hmzakhalid Oct 29, 2025
8ccc0b7
fix: a few little fixes
hmzakhalid Oct 29, 2025
cc97082
fix: chain setter error
hmzakhalid Oct 29, 2025
d1aaee3
fix: testing with a sleep fix
hmzakhalid Oct 29, 2025
9366fe6
fix: revert test
hmzakhalid Oct 29, 2025
d1385b2
Merge branch 'dev' into hmza/economics
hmzakhalid Oct 30, 2025
54e295b
fix: crisp version mismatch [skip ci]
hmzakhalid Oct 30, 2025
4fce862
fix: remove fee token from sdk
hmzakhalid Oct 30, 2025
ffdcf80
fix: trying out with workspace *
hmzakhalid Oct 30, 2025
b269b14
fix: fetch timestamp after feeQuote
hmzakhalid Oct 30, 2025
a11a8b3
fix: add feetoken to sdk and committee publish timeout to e2e test
hmzakhalid Oct 30, 2025
da1badc
fix: router scoping issue
hmzakhalid Oct 30, 2025
d3672d9
fix: use setup in integration test & remove recipient from committee …
hmzakhalid Oct 31, 2025
ea97768
fix: update package.json to include browser conditions
hmzakhalid Oct 31, 2025
de8ab47
fix: update package.json to include browser conditions
hmzakhalid Oct 31, 2025
0ace70b
fix: test out sdk version in crisp
hmzakhalid Oct 31, 2025
adfa7a9
fix: update pnpm lock
hmzakhalid Oct 31, 2025
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
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
url = https://github.com/risc0/risc0-ethereum
[submodule "templates/default/lib/risc0-ethereum"]
path = templates/default/lib/risc0-ethereum
url = https://github.com/gnosisguild/risc0-ethereum
url = https://github.com/gnosisguild/risc0-ethereum
2 changes: 2 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ sequenceDiagram
E3Program-->>Enclave: inputValidator
Enclave->>ComputeProvider: validate(computeProviderParams)
ComputeProvider-->>Enclave: decryptionVerifier
Enclave->>CiphernodeRegistry: requestCommittee(e3Id, filter, threshold)
Enclave->>CiphernodeRegistry: requestCommittee(e3Id, seed, threshold)
CiphernodeRegistry-->>Enclave: success
Enclave-->>Users: e3Id, E3 struct

Expand Down
1 change: 1 addition & 0 deletions crates/aggregator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ bincode = { workspace = true }
e3-config = { workspace = true }
e3-data = { workspace = true }
e3-events = { workspace = true }
e3-evm = { workspace = true }
Comment thread
ryardley marked this conversation as resolved.
e3-fhe = { workspace = true }
e3-multithread = { workspace = true }
e3-trbfv = { workspace = true }
Expand Down
148 changes: 148 additions & 0 deletions crates/aggregator/src/committee_finalizer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// 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::{
CommitteeFinalizeRequested, CommitteeRequested, EnclaveEvent, EventBus, Shutdown, Subscribe,
};
use std::collections::HashMap;
use std::time::Duration;
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<EventBus<EnclaveEvent>>,
pending_committees: HashMap<String, SpawnHandle>,
}

impl CommitteeFinalizer {
pub fn new(bus: &Addr<EventBus<EnclaveEvent>>) -> Self {
Self {
bus: bus.clone(),
pending_committees: HashMap::new(),
}
}

pub fn attach(bus: &Addr<EventBus<EnclaveEvent>>) -> Addr<Self> {
let addr = CommitteeFinalizer::new(bus).start();

bus.do_send(Subscribe::new(
"CommitteeRequested",
addr.clone().recipient(),
));
bus.do_send(Subscribe::new("Shutdown", addr.clone().recipient()));

addr
}
}

impl Actor for CommitteeFinalizer {
type Context = Context<Self>;
}

impl Handler<EnclaveEvent> 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),
_ => (),
}
}
}

impl Handler<CommitteeRequested> for CommitteeFinalizer {
type Result = ();

fn handle(&mut self, msg: CommitteeRequested, ctx: &mut Self::Context) -> Self::Result {
let e3_id = msg.e3_id.clone();
let submission_deadline = msg.submission_deadline;

const FINALIZATION_BUFFER_SECONDS: u64 = 1;

let e3_id_for_log = e3_id.clone();
let fut = async move {
match e3_evm::helpers::get_current_timestamp().await {
Ok(timestamp) => Some(timestamp),
Err(e) => {
error!(
e3_id = %e3_id_for_log,
error = %e,
"Failed to get current timestamp from RPC"
);
None
}
}
};

let e3_id_for_async = e3_id;
ctx.spawn(
fut.into_actor(self)
.then(move |current_timestamp, act, ctx| {
if let Some(current_timestamp) = current_timestamp {
let seconds_until_deadline = if submission_deadline > current_timestamp {
(submission_deadline - current_timestamp) + FINALIZATION_BUFFER_SECONDS
} else {
info!(
e3_id = %e3_id_for_async,
submission_deadline = submission_deadline,
current_timestamp = current_timestamp,
"Submission deadline already passed, finalizing with buffer"
);
FINALIZATION_BUFFER_SECONDS
};

info!(
e3_id = %e3_id_for_async,
submission_deadline = submission_deadline,
current_timestamp = current_timestamp,
seconds_to_wait = seconds_until_deadline,
"Scheduling committee finalization"
);

let bus = act.bus.clone();
let e3_id_clone = e3_id_for_async.clone();

let handle = ctx.run_later(
Duration::from_secs(seconds_until_deadline),
move |act, _ctx| {
info!(e3_id = %e3_id_clone, "Dispatching CommitteeFinalizeRequested event");

bus.do_send(EnclaveEvent::from(CommitteeFinalizeRequested {
e3_id: e3_id_clone.clone(),
}));

act.pending_committees.remove(&e3_id_clone.to_string());
},
);

act.pending_committees
.insert(e3_id_for_async.to_string(), handle);
} else {
error!(
e3_id = %e3_id_for_async,
"Skipping committee finalization due to timestamp fetch failure"
);
}
Comment thread
hmzakhalid marked this conversation as resolved.

async {}.into_actor(act)
}),
);
}
}

impl Handler<Shutdown> for CommitteeFinalizer {
type Result = ();
fn handle(&mut self, _msg: Shutdown, ctx: &mut Self::Context) -> Self::Result {
info!("Killing CommitteeFinalizer");
// Cancel all pending finalization tasks
for (_, handle) in self.pending_committees.drain() {
ctx.cancel_future(handle);
}
ctx.stop();
}
}
2 changes: 2 additions & 0 deletions crates/aggregator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
// without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.

mod committee_finalizer;
pub mod ext;
mod plaintext_aggregator;
mod publickey_aggregator;
mod repo;
mod threshold_plaintext_aggregator;
pub use committee_finalizer::CommitteeFinalizer;
pub use plaintext_aggregator::{
PlaintextAggregator, PlaintextAggregatorParams, PlaintextAggregatorState,
};
Expand Down
38 changes: 12 additions & 26 deletions crates/aggregator/src/publickey_aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use e3_events::{
Die, E3id, EnclaveEvent, EventBus, KeyshareCreated, OrderedSet, PublicKeyAggregated, Seed,
};
use e3_fhe::{Fhe, GetAggregatePublicKey};
use e3_sortition::{GetNodeIndex, GetNodes, Sortition};
use e3_sortition::{GetNodesForE3, Sortition};
use e3_utils::ArcBytes;
use std::sync::Arc;
use tracing::{error, trace};
Expand Down Expand Up @@ -148,47 +148,32 @@ impl Handler<KeyshareCreated> for PublicKeyAggregator {
type Result = ResponseActFuture<Self, Result<()>>;

fn handle(&mut self, event: KeyshareCreated, _: &mut Self::Context) -> Self::Result {
let Some(PublicKeyAggregatorState::Collecting {
threshold_n, seed, ..
}) = self.state.get()
else {
error!(state=?self.state, "Aggregator has been closed for collecting keyshares.");
return Box::pin(fut::ready(Ok(())));
};

let size = threshold_n;
let address = event.node;
let chain_id = event.e3_id.chain_id();
let address = event.node.clone();
let e3_id = event.e3_id.clone();
let pubkey = event.pubkey.clone();

Box::pin(
self.sortition
.send(GetNodeIndex {
chain_id,
address,
size,
seed,
.send(GetNodesForE3 {
e3_id: e3_id.clone(),
chain_id: e3_id.chain_id(),
})
.into_actor(self)
.map(move |res, act, ctx| {
// NOTE: Returning Ok(()) on errors as we probably dont need a result type here since
// we will not be doing a send
let maybe_found_index = res?;
let Some(_) = maybe_found_index else {
trace!("Node not found in committee");
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(());
}

// add the keyshare and
act.add_keyshare(pubkey)?;

// Check the state and if it has changed to the computing
if let Some(PublicKeyAggregatorState::Computing { keyshares }) =
&act.state.get()
{
Expand Down Expand Up @@ -228,7 +213,8 @@ impl Handler<NotifyNetwork> for PublicKeyAggregator {
fn handle(&mut self, msg: NotifyNetwork, _: &mut Self::Context) -> Self::Result {
Box::pin(
self.sortition
.send(GetNodes {
.send(GetNodesForE3 {
e3_id: msg.e3_id.clone(),
chain_id: msg.e3_id.chain_id(),
})
.into_actor(self)
Expand Down
45 changes: 11 additions & 34 deletions crates/aggregator/src/threshold_plaintext_aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ use e3_events::{
Seed,
};
use e3_multithread::Multithread;
use e3_sortition::{GetNodeIndex, Sortition};
use e3_sortition::{GetNodesForE3, Sortition};
use e3_trbfv::{
calculate_threshold_decryption::{
CalculateThresholdDecryptionRequest, CalculateThresholdDecryptionResponse,
},
TrBFVConfig, TrBFVRequest,
};
use e3_utils::utility_types::ArcBytes;
use tracing::{error, info};
use tracing::{error, info, trace};

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Collecting {
Expand Down Expand Up @@ -248,46 +248,23 @@ impl Handler<DecryptionshareCreated> for ThresholdPlaintextAggregator {

fn handle(&mut self, event: DecryptionshareCreated, _: &mut Self::Context) -> Self::Result {
info!(event=?event, "Processing DecryptionShareCreated...");
let Some(ThresholdPlaintextAggregatorState::Collecting(Collecting {
threshold_n,
seed,
..
})) = self.state.get()
else {
error!(state=?self.state, "Aggregator has been closed for collecting.");
return Box::pin(fut::ready(Ok(())));
};

let size = threshold_n as usize;
let address = event.node;
let address = event.node.clone();
let party_id = event.party_id;
let chain_id = event.e3_id.chain_id();
let e3_id = event.e3_id.clone();
let decryption_share = event.decryption_share.clone();

// Why do we need to get the node index when the event contains the party_id? I guess we
// don't trust the event. Maybe that is fine.
Box::pin(
self.sortition
.send(GetNodeIndex {
chain_id,
address: address.clone(),
size,
seed,
.send(GetNodesForE3 {
e3_id: e3_id.clone(),
chain_id: e3_id.chain_id(),
})
.into_actor(self)
.map(move |res, act, ctx| {
let maybe_found_index = res?;
let Some(party) = maybe_found_index else {
error!("Attempting to aggregate share but party not found in committee");
return Ok(());
};
let nodes = res?;

if party != party_id {
error!(
"Bad aggregation state! Address {} not found at index {} instead it was found at {}",
address, party_id, party
);
if !nodes.contains(&address) {
trace!("Node {} not found in finalized committee", address);
return Ok(());
}

Expand All @@ -296,10 +273,10 @@ impl Handler<DecryptionshareCreated> for ThresholdPlaintextAggregator {
return Ok(());
}

// add the keyshare and
// Trust the party_id from the event - it's based on CommitteeFinalized order
// which is the authoritative source of truth for party IDs
act.add_share(party_id, decryption_share)?;

// Check the state and if it has changed to the computing
if let Some(ThresholdPlaintextAggregatorState::Computing(Computing {
threshold_m,
threshold_n,
Expand Down
Loading
Loading