Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
053cdda
feat: store merkle tree on program
ctrlc03 Nov 10, 2025
d81c37c
chore: update crisp indexer
ctrlc03 Nov 17, 2025
6acd9c0
chore: indexer updates
ctrlc03 Nov 18, 2025
e532900
chore: use e3crisp inputs
ctrlc03 Nov 18, 2025
ece09dd
chore: lint
ctrlc03 Nov 18, 2025
6bf276b
chore: cleanup
ctrlc03 Nov 18, 2025
8466ec0
chore: add missing dependency
ctrlc03 Nov 18, 2025
e052f8d
chore: remove poseidont3 from ignition development
ctrlc03 Nov 18, 2025
7709917
test: indexer integration
ctrlc03 Nov 18, 2025
2e16def
test: indexer remove redundant test
ctrlc03 Nov 18, 2025
069567a
chore: update mock crisp
ctrlc03 Nov 19, 2025
42c4130
chore: update template
ctrlc03 Nov 19, 2025
852573c
chore: prevent stack too deep error
ctrlc03 Nov 20, 2025
3fe8751
chore: add compile command before tests
ctrlc03 Nov 20, 2025
84d13a2
chore: add license
ctrlc03 Nov 20, 2025
f4c033d
chore: fix tests
ctrlc03 Nov 20, 2025
2cd4f32
chore: link library to program
ctrlc03 Nov 20, 2025
2207a51
chore: format
ctrlc03 Nov 20, 2025
b685788
fix: invert condition on validate
ctrlc03 Nov 20, 2025
df4eed7
chore: update validateInput logic
ctrlc03 Nov 20, 2025
a4005ea
chore: test with risc0
ctrlc03 Nov 20, 2025
0beb632
fix: set round data per e3
ctrlc03 Nov 20, 2025
ff02f58
chore: pr comments
ctrlc03 Nov 20, 2025
40332f1
chore: uppercase and remove script
ctrlc03 Nov 21, 2025
8ad3b77
chore: remove unused import
ctrlc03 Nov 21, 2025
cac79eb
chore: eslint
ctrlc03 Nov 21, 2025
f8d4dfa
fix: ci workflow
ctrlc03 Nov 22, 2025
7655996
feat: swap out leanimt for normal imt on compute provider
ctrlc03 Nov 22, 2025
aec0898
chore: lint rust code
ctrlc03 Nov 22, 2025
582eb20
chore: update cargo lock files
ctrlc03 Nov 22, 2025
694536a
refactor: rename merkle tree to merkle tree builder
cedoor Nov 24, 2025
12949d4
fix: make static default values for merkle tree
cedoor Nov 24, 2025
ba06e5b
chore: remove unused dependencies
cedoor Nov 24, 2025
4b30601
refactor: remove unused imports
cedoor Nov 24, 2025
ebab6bf
fix: use tree depth in merkle root calculation
cedoor Nov 24, 2025
a06ab83
chore: use a more recent poseidon deployment
cedoor Nov 24, 2025
731a82a
fix: update compute provider git rev and resolve dependency issues
hmzakhalid Nov 25, 2025
fe24227
fix: add tree depth to mock program
cedoor Nov 25, 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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,7 @@ jobs:
- name: Test Template
run: |
cd templates/default
pnpm compile
Comment thread
cedoor marked this conversation as resolved.
chmod 755 .enclave/generated/contracts tests
chmod 644 .enclave/generated/contracts/ImageID.sol
pnpm test:integration
Expand Down
11 changes: 11 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/compute-provider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ light-poseidon = "=0.2.0"
ark-ff = "=0.4.2"
ark-bn254 = "=0.4.0"
rayon = "=1.10.0"
zk-kit-imt = "0.0.7"
13 changes: 6 additions & 7 deletions crates/compute-provider/src/compute_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// or FITNESS FOR A PARTICULAR PURPOSE.

use crate::ciphertext_output::ComputeResult;
use crate::merkle_tree::MerkleTree;
use crate::merkle_tree_builder::MerkleTreeBuilder;
use sha3::{Digest, Keccak256};

pub type FHEProcessor = fn(&FHEInputs) -> Vec<u8>;
Expand Down Expand Up @@ -34,12 +34,11 @@ impl ComputeInput {
"Ciphertext hash mismatch"
);

let merkle_root = MerkleTree {
leaf_hashes: self.leaf_hashes.clone(),
}
.build_tree()
.root()
.unwrap();
let merkle_root = MerkleTreeBuilder::new()
.with_leaf_hashes(self.leaf_hashes.clone())
.build_tree()
.root()
.unwrap();

ComputeResult {
ciphertext_hash: processed_hash,
Expand Down
18 changes: 10 additions & 8 deletions crates/compute-provider/src/compute_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use crate::ciphertext_output::ComputeProvider;
use crate::compute_input::{ComputeInput, FHEInputs};
use crate::merkle_tree::MerkleTree;
use crate::merkle_tree_builder::MerkleTreeBuilder;
use crate::FHEProcessor;
use rayon::prelude::*;
use sha3::{Digest, Keccak256};
Expand Down Expand Up @@ -56,9 +56,10 @@ where
}

fn start_sequential(&mut self) -> (P::Output, Vec<u8>) {
let mut tree_handler = MerkleTree::new();
tree_handler.compute_leaf_hashes(&self.input.fhe_inputs.ciphertexts);
self.input.leaf_hashes = tree_handler.leaf_hashes.clone();
let mut tree_builder = MerkleTreeBuilder::new();

tree_builder.compute_leaf_hashes(&self.input.fhe_inputs.ciphertexts);
self.input.leaf_hashes = tree_builder.leaf_hashes.clone();

// Compute the ciphertext
let ciphertext = (self.processor)(&self.input.fhe_inputs);
Expand All @@ -83,9 +84,10 @@ where
let tally_results: Vec<(P::Output, Vec<u8>, String)> = chunks
.into_par_iter()
.map(|chunk| {
let mut tree_handler = MerkleTree::new();
tree_handler.compute_leaf_hashes(&chunk);
let merkle_root = tree_handler.build_tree().root().unwrap();
let mut tree_builder = MerkleTreeBuilder::new();

tree_builder.compute_leaf_hashes(&chunk);
let merkle_root = tree_builder.build_tree().root().unwrap();
Comment thread
cedoor marked this conversation as resolved.

let fhe_inputs = FHEInputs {
ciphertexts: chunk.clone(),
Expand All @@ -98,7 +100,7 @@ where
let input = ComputeInput {
fhe_inputs,
ciphertext_hash,
leaf_hashes: tree_handler.leaf_hashes.clone(),
leaf_hashes: tree_builder.leaf_hashes.clone(),
};

(self.provider.prove(&input), ciphertext, merkle_root)
Expand Down
2 changes: 1 addition & 1 deletion crates/compute-provider/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
mod ciphertext_output;
mod compute_input;
mod compute_manager;
mod merkle_tree;
mod merkle_tree_builder;

pub use ciphertext_output::*;
pub use compute_input::*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,35 @@

use ark_bn254::Fr;
use ark_ff::{BigInt, BigInteger};
use lean_imt::LeanIMT;
use light_poseidon::{Poseidon, PoseidonHasher};
use num_bigint::BigUint;
use num_traits::Num;
use sha3::{Digest, Keccak256};
use std::str::FromStr;
use zk_kit_imt::imt::IMT;

pub struct MerkleTree {
pub struct MerkleTreeBuilder {
pub leaf_hashes: Vec<String>,
pub arity: usize,
pub zero_value: String,
pub depth: usize,
}

impl MerkleTree {
impl MerkleTreeBuilder {
pub fn new() -> Self {
Self {
leaf_hashes: Vec::new(),
arity: 2,
zero_value: "0".to_string(),
depth: 20,
}
}

pub fn with_leaf_hashes(mut self, leaf_hashes: Vec<String>) -> Self {
self.leaf_hashes = leaf_hashes;
self
}

pub fn compute_leaf_hashes(&mut self, data: &[(Vec<u8>, u64)]) {
for item in data {
let hex_output = hex::encode(Keccak256::digest(&item.0));
Expand Down Expand Up @@ -60,9 +71,20 @@ impl MerkleTree {
hex::encode(result_hash.to_bytes_be())
}

pub fn build_tree(&self) -> LeanIMT {
let mut tree = LeanIMT::new(Self::poseidon_hash);
tree.insert_many(self.leaf_hashes.clone()).unwrap();
pub fn build_tree(&self) -> IMT {
let mut tree = IMT::new(
Self::poseidon_hash,
self.depth,
self.zero_value.clone(),
self.arity,
vec![],
)
.unwrap();

for leaf in &self.leaf_hashes {
tree.insert(leaf.clone()).unwrap();
}

tree
}
}
3 changes: 0 additions & 3 deletions crates/evm-helpers/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ sol! {
bytes plaintextOutput;
}

#[derive(Debug)]
event InputPublished(uint256 indexed e3Id, bytes data, uint256 inputHash, uint256 index);

#[derive(Debug)]
event CiphertextOutputPublished(uint256 indexed e3Id, bytes ciphertextOutput);

Expand Down
27 changes: 1 addition & 26 deletions crates/indexer/src/indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use alloy::sol_types::SolEvent;
use async_trait::async_trait;
use e3_evm_helpers::{
contracts::{EnclaveContract, EnclaveContractFactory, EnclaveRead, ReadOnly},
events::{CiphertextOutputPublished, E3Activated, InputPublished, PlaintextOutputPublished},
events::{CiphertextOutputPublished, E3Activated, PlaintextOutputPublished},
listener::EventListener,
};
use eyre::eyre;
Expand Down Expand Up @@ -276,30 +276,6 @@ impl<S: DataStore> EnclaveIndexer<S> {
Ok(())
}

async fn register_input_published(&mut self) -> Result<()> {
let store = self.store.clone();
self.listener
.add_event_handler(move |e: InputPublished| {
let store = SharedStore::new(store.clone());
async move {
println!(
"InputPublished: e3_id={}, index={}, data=0x{}...",
e.e3Id,
e.index,
hex::encode(&e.data[..8.min(e.data.len())])
);
let e3_id = u64_try_from(e.e3Id)?;

let mut repo = E3Repository::new(store, e3_id);
repo.insert_ciphertext_input(e.data.to_vec(), e.index.to::<u64>())
.await?;
Ok(())
}
})
.await;
Ok(())
}

async fn register_ciphertext_output_published(&mut self) -> Result<()> {
let store = self.store.clone();
self.listener
Expand Down Expand Up @@ -349,7 +325,6 @@ impl<S: DataStore> EnclaveIndexer<S> {

async fn setup_listeners(&mut self) -> Result<()> {
self.register_e3_activated().await?;
self.register_input_published().await?;
self.register_ciphertext_output_published().await?;
self.register_plaintext_output_published().await?;
Ok(())
Expand Down
53 changes: 0 additions & 53 deletions crates/indexer/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,56 +61,6 @@ async fn test_indexer() -> Result<()> {
.watch()
.await?;

// InputPublished
Comment thread
cedoor marked this conversation as resolved.
let data = "Random data that wont actually be a string".to_string();
contract
.emitInputPublished(
Uint::from(e3_id),
Bytes::from(data.clone().into_bytes()),
Uint::from(1111),
Uint::from(1),
)
.send()
.await?
.watch()
.await?;

contract
.emitInputPublished(
Uint::from(e3_id),
Bytes::from(data.clone().into_bytes()),
Uint::from(2222),
Uint::from(2),
)
.send()
.await?
.watch()
.await?;

contract
.emitInputPublished(
Uint::from(e3_id),
Bytes::from(data.clone().into_bytes()),
Uint::from(3333),
Uint::from(3),
)
.send()
.await?
.watch()
.await?;

sleep(Duration::from_millis(10)).await;

assert_eq!(indexer.get_e3(e3_id).await?.ciphertext_inputs.len(), 3);
assert_eq!(
indexer.get_e3(e3_id).await?.ciphertext_inputs,
vec![
(Bytes::from(data.clone().into_bytes()).to_vec(), 1),
(Bytes::from(data.clone().into_bytes()).to_vec(), 2),
(Bytes::from(data.clone().into_bytes()).to_vec(), 3),
]
);

let ciphertext_output = vec![9, 8, 7, 6, 5, 4, 3, 2, 1];
contract
.emitCiphertextOutputPublished(Uint::from(e3_id), Bytes::from(ciphertext_output.clone()))
Expand All @@ -125,8 +75,5 @@ async fn test_indexer() -> Result<()> {

assert_eq!(e3.ciphertext_output, ciphertext_output);

let store = indexer.get_store();
let val = store.get::<u64>("input_count").await?.unwrap();
assert_eq!(val, 3);
Ok(())
}
Loading
Loading