diff --git a/Cargo.lock b/Cargo.lock index eeb9e85..62cfa34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5082,6 +5082,7 @@ dependencies = [ "ed25519-dalek", "hex", "jmt", + "log", "prism-errors", "rand", "serde", diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index c86ffdd..e8dbcf7 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -17,6 +17,7 @@ hex.workspace = true sha2.workspace = true celestia-types.workspace = true bincode.workspace = true +log.workspace = true ed25519-dalek.workspace = true rand.workspace = true diff --git a/crates/common/src/hashchain.rs b/crates/common/src/hashchain.rs index 614fac8..8375324 100644 --- a/crates/common/src/hashchain.rs +++ b/crates/common/src/hashchain.rs @@ -128,7 +128,7 @@ impl Hashchain { signature: Vec, service_id: String, challenge: ServiceChallengeInput, - ) -> Result { + ) -> Result { let operation = Operation::CreateAccount(CreateAccountArgs { id: self.id.clone(), signature, @@ -143,7 +143,7 @@ impl Hashchain { &self.entries[idx] } - pub fn push(&mut self, operation: Operation) -> Result { + fn push(&mut self, operation: Operation) -> Result { if operation.id() != self.id { bail!("Operation ID does not match Hashchain ID"); } @@ -156,18 +156,10 @@ impl Hashchain { let entry = HashchainEntry::new(operation, previous_hash); self.entries.push(entry.clone()); - Ok(entry.hash) + Ok(entry) } - pub fn add(&mut self, operation: Operation) -> Result { - self.perform_operation(operation) - } - - pub fn revoke(&mut self, operation: Operation) -> Result { - self.perform_operation(operation) - } - - fn perform_operation(&mut self, operation: Operation) -> Result { + pub fn perform_operation(&mut self, operation: Operation) -> Result { self.validate_operation(&operation)?; self.push(operation) } @@ -185,7 +177,10 @@ impl Hashchain { self.verify_signature(&signing_key, &message, &args.signature.signature) } // TODO - Operation::CreateAccount(_) => unimplemented!(), + Operation::CreateAccount(_) => { + println!("oopsie"); + Ok(()) + } } } diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index c766706..dbd4516 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -2,5 +2,8 @@ pub mod hashchain; pub mod operation; pub mod tree; +#[macro_use] +extern crate log; + #[cfg(feature = "test_utils")] pub mod test_utils; diff --git a/crates/common/src/test_utils.rs b/crates/common/src/test_utils.rs index d3e1831..87eaf85 100644 --- a/crates/common/src/test_utils.rs +++ b/crates/common/src/test_utils.rs @@ -1,6 +1,9 @@ use crate::{ hashchain::{Hashchain, HashchainEntry}, - operation::{KeyOperationArgs, Operation, PublicKey, SignatureBundle}, + operation::{ + CreateAccountArgs, KeyOperationArgs, Operation, PublicKey, ServiceChallengeInput, + SignatureBundle, + }, tree::{Digest, InsertProof, KeyDirectoryTree, SnarkableTree, UpdateProof}, }; use anyhow::{anyhow, Result}; @@ -96,8 +99,7 @@ impl TestTreeState { signature, }); - account.hashchain.add(operation).unwrap(); - + account.hashchain.perform_operation(operation).unwrap(); Ok(()) } } @@ -173,7 +175,7 @@ pub fn create_random_update(state: &mut TestTreeState, rng: &mut StdRng) -> Upda }, }); - hc.add(final_operation) + hc.perform_operation(final_operation) .expect("Adding to hashchain should succeed"); println!("updated key: {key:?}"); @@ -197,13 +199,15 @@ pub fn create_mock_hashchain(id: &str, signing_key: &SigningKey) -> Hashchain { let public_key = PublicKey::Ed25519(signing_key.verifying_key().to_bytes().to_vec()); let signature = create_mock_signature(signing_key, id.as_bytes()); - let op = Operation::AddKey(KeyOperationArgs { + let op = Operation::CreateAccount(CreateAccountArgs { id: id.to_string(), value: public_key.clone(), - signature, + signature: signature.signature, + service_id: "test".to_string(), + challenge: ServiceChallengeInput::Signed(Vec::new()), }); - hc.push(op).unwrap(); + hc.perform_operation(op).unwrap(); hc } diff --git a/crates/common/src/tree.rs b/crates/common/src/tree.rs index 9892a74..9a123f7 100644 --- a/crates/common/src/tree.rs +++ b/crates/common/src/tree.rs @@ -6,10 +6,14 @@ use jmt::{ storage::{NodeBatch, TreeReader, TreeUpdateBatch, TreeWriter}, JellyfishMerkleTree, KeyHash, RootHash, SimpleHasher, }; +use prism_errors::DatabaseError; use serde::{ser::SerializeTupleStruct, Deserialize, Serialize}; use std::sync::Arc; -use crate::hashchain::Hashchain; +use crate::{ + hashchain::Hashchain, + operation::{CreateAccountArgs, KeyOperationArgs, Operation, ServiceChallengeInput}, +}; pub const SPARSE_MERKLE_PLACEHOLDER_HASH: Digest = Digest::new(*b"SPARSE_MERKLE_PLACEHOLDER_HASH__"); @@ -229,6 +233,7 @@ impl UpdateProof { } pub trait SnarkableTree { + fn process_operation(&mut self, operation: &Operation) -> Result; fn insert(&mut self, key: KeyHash, value: Hashchain) -> Result; fn update(&mut self, key: KeyHash, value: Hashchain) -> Result; fn get(&self, key: KeyHash) -> Result>; @@ -303,6 +308,63 @@ impl SnarkableTree for KeyDirectoryTree where S: TreeReader + TreeWriter, { + fn process_operation(&mut self, operation: &Operation) -> Result { + match operation { + Operation::AddKey(KeyOperationArgs { id, .. }) + | Operation::RevokeKey(KeyOperationArgs { id, .. }) => { + let hashed_id = hash(id.as_bytes()); + let key_hash = KeyHash::with::(hashed_id); + + let mut current_chain = self + .get(key_hash)? + .map_err(|_| anyhow!("Failed to get hashchain for ID {}", id))?; + + current_chain.perform_operation(operation.clone())?; + + debug!("updating hashchain for user id {}", id.clone()); + let proof = self.update(key_hash, current_chain.clone())?; + + Ok(Proof::Update(proof)) + } + Operation::CreateAccount(CreateAccountArgs { + id, + value, + signature, + service_id, + challenge, + }) => { + let hashed_id = hash(id.as_bytes()); + let key_hash = KeyHash::with::(hashed_id); + + match &challenge { + ServiceChallengeInput::Signed(_) => debug!("Signature verification for service challenge gate not yet implemented. Skipping verification.") + }; + + // hashchain should not already exist + if self.get(key_hash)?.is_ok() { + bail!(DatabaseError::NotFoundError(format!( + "empty slot for ID {}", + id + ))); + } + + debug!("creating new hashchain for user id {}", id); + let mut chain = Hashchain::new(id.clone()); + chain.create_account( + value.clone(), + signature.clone(), + service_id.clone(), + // TODO: Challenge is a placeholder rn + ServiceChallengeInput::Signed(Vec::new()), + )?; + + Ok(Proof::Insert( + self.insert(KeyHash::with::(hashed_id), chain)?, + )) + } + } + } + fn insert(&mut self, key: KeyHash, value: Hashchain) -> Result { let serialized_value = Self::serialize_value(&value)?; diff --git a/crates/prism/src/node_types/sequencer.rs b/crates/prism/src/node_types/sequencer.rs index cebb7d1..f878cdc 100644 --- a/crates/prism/src/node_types/sequencer.rs +++ b/crates/prism/src/node_types/sequencer.rs @@ -1,11 +1,13 @@ use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; use ed25519_dalek::SigningKey; -use jmt::KeyHash; +use jmt::KeyHash; use prism_common::{ - operation::{KeyOperationArgs, ServiceChallengeInput}, - tree::{hash, Batch, Digest, Hasher, KeyDirectoryTree, Proof, SnarkableTree}, + hashchain::Hashchain, + tree::{ + hash, Batch, Digest, Hasher, KeyDirectoryTree, NonMembershipProof, Proof, SnarkableTree, + }, }; use std::{self, collections::VecDeque, sync::Arc}; use tokio::sync::{broadcast, Mutex}; @@ -19,11 +21,7 @@ use crate::{ storage::Database, webserver::WebServer, }; -use prism_common::{ - hashchain::{Hashchain, HashchainEntry}, - operation::Operation, -}; -use prism_errors::DatabaseError; +use prism_common::operation::Operation; pub const PRISM_ELF: &[u8] = include_bytes!("../../../../elf/riscv32im-succinct-zkvm-elf"); @@ -78,7 +76,6 @@ impl Sequencer { let ws = cfg.webserver.context("Missing webserver configuration")?; let start_height = cfg.celestia_config.unwrap_or_default().start_height; - // Create the KeyDirectory let tree = Arc::new(Mutex::new(KeyDirectoryTree::new(db.clone()))); let prover_client = ProverClient::new(); @@ -214,8 +211,7 @@ impl Sequencer { buffered_operations: &mut VecDeque>, saved_epoch: u64, ) -> Result<()> { - let mut tree = self.tree.lock().await; - let prev_commitment = tree.get_commitment()?; + let prev_commitment = self.get_commitment().await?; debug!( "processing height {}, saved_epoch: {}, current_epoch: {}", @@ -229,14 +225,12 @@ impl Sequencer { if !buffered_operations.is_empty() && height > saved_epoch { let all_ops: Vec = buffered_operations.drain(..).flatten().collect(); *current_epoch = height; - self.finalize_new_epoch(*current_epoch, all_ops, &mut tree) - .await?; + self.finalize_new_epoch(*current_epoch, all_ops).await?; } else if let Some(epoch) = epoch_result { self.process_existing_epoch( epoch, current_epoch, buffered_operations, - &mut tree, prev_commitment, height, ) @@ -253,7 +247,6 @@ impl Sequencer { epoch: FinalizedEpoch, current_epoch: &mut u64, buffered_operations: &mut VecDeque>, - tree: &mut KeyDirectoryTree>, prev_commitment: Digest, height: u64, ) -> Result<()> { @@ -269,10 +262,10 @@ impl Sequencer { } while let Some(buffered_ops) = buffered_operations.pop_front() { - self.execute_block(buffered_ops, tree).await?; + self.execute_block(buffered_ops).await?; } - let new_commitment = tree.get_commitment()?; + let new_commitment = self.get_commitment().await?; if epoch.current_commitment != new_commitment { return Err(anyhow!("Commitment mismatch at epoch {}", current_epoch)); } @@ -285,17 +278,13 @@ impl Sequencer { Ok(()) } - async fn execute_block( - &self, - operations: Vec, - tree: &mut KeyDirectoryTree>, - ) -> Result> { + async fn execute_block(&self, operations: Vec) -> Result> { debug!("executing block with {} operations", operations.len()); let mut proofs = Vec::new(); for operation in operations { - match self.process_operation(&operation, tree).await { + match self.process_operation(&operation).await { Ok(proof) => proofs.push(proof), Err(e) => { // Log the error and continue with the next operation @@ -307,17 +296,12 @@ impl Sequencer { Ok(proofs) } - async fn finalize_new_epoch( - &self, - height: u64, - operations: Vec, - tree: &mut KeyDirectoryTree>, - ) -> Result<()> { - let prev_commitment = tree.get_commitment()?; + async fn finalize_new_epoch(&self, height: u64, operations: Vec) -> Result<()> { + let prev_commitment = self.get_commitment().await?; - let proofs = self.execute_block(operations, tree).await?; + let proofs = self.execute_block(operations).await?; - let new_commitment = tree.get_commitment()?; + let new_commitment = self.get_commitment().await?; let finalized_epoch = self .prove_epoch(height, prev_commitment, new_commitment, proofs) @@ -379,77 +363,21 @@ impl Sequencer { tree.get_commitment().context("Failed to get commitment") } - /// Updates the state from an already verified pending operation. - async fn process_operation( + pub async fn get_hashchain( &self, - operation: &Operation, - tree: &mut KeyDirectoryTree>, - ) -> Result { - match operation { - Operation::AddKey(KeyOperationArgs { id, .. }) - | Operation::RevokeKey(KeyOperationArgs { id, .. }) => { - // verify that the hashchain already exists - let mut current_chain = self - .db - .get_hashchain(id) - .context(format!("Failed to get hashchain for ID {}", id))?; - - let hashed_id = hash(id.as_bytes()); - - let previous_hash = current_chain.last().context("Hashchain is empty")?.hash; - - let new_chain_entry = HashchainEntry::new(operation.clone(), previous_hash); - current_chain.push(new_chain_entry.operation.clone())?; - - debug!("updating hashchain for user id {}", id.clone()); - let proof = - tree.update(KeyHash::with::(hashed_id), current_chain.clone())?; - self.db - .set_hashchain(operation, ¤t_chain) - .context(format!( - "Failed to update hashchain for operation {:?}", - operation - ))?; - - Ok(Proof::Update(proof)) - } - Operation::CreateAccount(args) => { - let id = args.id.clone(); - match &args.challenge { - ServiceChallengeInput::Signed(_) => debug!("Signature verification for service challenge gate not yet implemented. Skipping verification.") - }; - - let hashchain: Result = self.db.get_hashchain(id.as_str()); - if hashchain.is_ok() { - return Err(DatabaseError::NotFoundError(format!( - "empty slot for ID {}", - id.clone() - )) - .into()); - } + id: &String, + ) -> Result> { + let tree = self.tree.lock().await; + let hashed_id = hash(id.as_bytes()); + let key_hash = KeyHash::with::(hashed_id); - debug!("creating new hashchain for user id {}", args.id); - let mut chain = Hashchain::new(id); - chain.create_account( - args.value.clone(), - args.signature.clone(), - args.service_id.clone(), - // TODO: Challenge is a placeholder rn - ServiceChallengeInput::Signed(Vec::new()), - )?; - - self.db.set_hashchain(operation, &chain).context(format!( - "Failed to create hashchain for operation {:?}", - operation - ))?; - - let hashed_id = hash(args.id.as_bytes()); - - Ok(Proof::Insert( - tree.insert(KeyHash::with::(hashed_id), chain)?, - )) - } - } + tree.get(key_hash) + } + + /// Updates the state from an already verified pending operation. + async fn process_operation(&self, operation: &Operation) -> Result { + let mut tree = self.tree.lock().await; + tree.process_operation(operation) } /// Adds an operation to be posted to the DA layer and applied in the next epoch. @@ -476,7 +404,9 @@ mod tests { use ed25519_dalek::Signer; use keystore_rs::create_signing_key; use prism_common::{ - operation::{CreateAccountArgs, PublicKey, ServiceChallengeInput, SignatureBundle}, + operation::{ + CreateAccountArgs, KeyOperationArgs, PublicKey, ServiceChallengeInput, SignatureBundle, + }, test_utils::create_mock_signing_key, }; use serial_test::serial; @@ -601,14 +531,13 @@ mod tests { #[serial] async fn test_process_operation() { let sequencer = create_test_sequencer().await; - let mut tree = sequencer.tree.lock().await; let signing_key = create_mock_signing_key(); let original_pubkey = PublicKey::Ed25519(signing_key.verifying_key().to_bytes().to_vec()); let create_account_op = create_random_user("test@example.com", signing_key.clone()); let proof = sequencer - .process_operation(&create_account_op, &mut tree) + .process_operation(&create_account_op) .await .unwrap(); assert!(matches!(proof, Proof::Insert(_))); @@ -617,19 +546,13 @@ mod tests { let pubkey = PublicKey::Ed25519(new_key.verifying_key().to_bytes().to_vec()); let add_key_op = add_key("test@example.com", 0, pubkey, signing_key); - let proof = sequencer - .process_operation(&add_key_op, &mut tree) - .await - .unwrap(); + let proof = sequencer.process_operation(&add_key_op).await.unwrap(); assert!(matches!(proof, Proof::Update(_))); // Revoke original key let revoke_op = revoke_key("test@example.com", 1, original_pubkey, new_key); - let proof = sequencer - .process_operation(&revoke_op, &mut tree) - .await - .unwrap(); + let proof = sequencer.process_operation(&revoke_op).await.unwrap(); assert!(matches!(proof, Proof::Update(_))); teardown_db(sequencer.db.clone()); @@ -639,7 +562,6 @@ mod tests { #[serial] async fn test_execute_block() { let sequencer = create_test_sequencer().await; - let mut tree = sequencer.tree.lock().await; let signing_key_1 = create_mock_signing_key(); let signing_key_2 = create_mock_signing_key(); @@ -655,10 +577,7 @@ mod tests { add_key("user1@example.com", 0, new_key, signing_key_1), ]; - let proofs = sequencer - .execute_block(operations, &mut tree) - .await - .unwrap(); + let proofs = sequencer.execute_block(operations).await.unwrap(); assert_eq!(proofs.len(), 3); teardown_db(sequencer.db.clone()); @@ -668,7 +587,7 @@ mod tests { #[serial] async fn test_finalize_new_epoch() { let sequencer = create_test_sequencer().await; - let mut tree = sequencer.tree.lock().await; + let tree = sequencer.tree.lock().await; let signing_key_1 = create_mock_signing_key(); let signing_key_2 = create_mock_signing_key(); @@ -685,10 +604,7 @@ mod tests { ]; let prev_commitment = tree.get_commitment().unwrap(); - sequencer - .finalize_new_epoch(0, operations, &mut tree) - .await - .unwrap(); + sequencer.finalize_new_epoch(0, operations).await.unwrap(); let new_commitment = tree.get_commitment().unwrap(); assert_ne!(prev_commitment, new_commitment); diff --git a/crates/prism/src/storage.rs b/crates/prism/src/storage.rs index f649bbb..fde5c7d 100644 --- a/crates/prism/src/storage.rs +++ b/crates/prism/src/storage.rs @@ -15,12 +15,8 @@ use std::{ }; use crate::cfg::RedisConfig; -use prism_common::{ - hashchain::{Hashchain, HashchainEntry}, - operation::Operation, - tree::Digest, -}; -use prism_errors::{DatabaseError, GeneralError, PrismError}; +use prism_common::tree::Digest; +use prism_errors::{DatabaseError, PrismError}; // there are different key prefixes for the different tables in the database // app_state:key => app state (just epoch counter for now) @@ -31,10 +27,6 @@ pub struct RedisConnection { #[auto_impl(&, Box, Arc)] pub trait Database: Send + Sync + TreeReader + TreeWriter { - fn get_hashchain(&self, key: &str) -> Result; - fn set_hashchain(&self, incoming_operation: &Operation, value: &[HashchainEntry]) - -> Result<()>; - fn get_commitment(&self, epoch: &u64) -> Result; fn set_commitment(&self, epoch: &u64, commitment: &Digest) -> Result<()>; @@ -163,21 +155,6 @@ impl TreeWriter for RedisConnection { } impl Database for RedisConnection { - fn get_hashchain(&self, key: &str) -> Result { - let mut con = self.lock_connection()?; - let value: String = con - .get(format!("main:{}", key)) - .map_err(|_| DatabaseError::NotFoundError(format!("hashchain key {}", key)))?; - - let res: Vec = serde_json::from_str(&value) - .map_err(|e| anyhow!(GeneralError::ParsingError(format!("hashchain: {}", e))))?; - - Ok(Hashchain { - id: key.to_string(), - entries: res, - }) - } - fn get_commitment(&self, epoch: &u64) -> Result { let mut con = self.lock_connection()?; let value = con @@ -200,27 +177,6 @@ impl Database for RedisConnection { .map_err(|_| anyhow!(DatabaseError::WriteError(format!("epoch: {}", epoch)))) } - fn set_hashchain( - &self, - incoming_operation: &Operation, - value: &[HashchainEntry], - ) -> Result<()> { - let mut con = self.lock_connection()?; - let value = serde_json::to_string(&value).map_err(|_| { - PrismError::General(GeneralError::ParsingError( - "hashchain to string".to_string(), - )) - })?; - let id = incoming_operation.id(); - con.set::<&str, String, ()>(&format!("main:{}", id), value) - .map_err(|_| { - anyhow!(DatabaseError::WriteError(format!( - "hashchain update for key: {}", - id - ))) - }) - } - fn set_commitment(&self, epoch: &u64, commitment: &Digest) -> Result<()> { let mut con = self.lock_connection()?; con.set::<&String, &String, ()>( @@ -243,158 +199,3 @@ impl Database for RedisConnection { .map_err(|_| anyhow!(DatabaseError::DeleteError("all entries".to_string()))) } } - -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::storage::Database; -// use prism_common::{ -// operation::{KeyOperationArgs, Operation, PublicKey, SignatureBundle}, -// test_utils::{ -// create_add_key_operation_with_test_value, create_mock_chain_entry, -// create_mock_signature, create_mock_signing_key, -// }, -// tree::hash, -// }; -// use serde::{Deserialize, Serialize}; -// use serial_test::serial; - -// // Helper functions - -// // set up redis connection and flush database before each test -// fn setup() -> RedisConnection { -// let redis_connection = RedisConnection::new(&RedisConfig::default()).unwrap(); -// redis_connection.flush_database().unwrap(); -// redis_connection -// } - -// // flush database after each test -// fn teardown(redis_connections: &RedisConnection) { -// redis_connections.flush_database().unwrap(); -// } - -// #[test] -// #[serial] -// fn test_get_hashchain() { -// let redis_connections = setup(); -// let signing_key = create_mock_signing_key(); - -// let incoming_operation = -// create_add_key_operation_with_test_value("main:test_key", &signing_key); -// let chain_entry = create_mock_chain_entry(&signing_key); -// redis_connections -// .set_hashchain(&incoming_operation, &[chain_entry.clone()]) -// .unwrap(); - -// let hashchain = redis_connections -// .get_hashchain(&incoming_operation.id()) -// .unwrap(); - -// let first = hashchain.get(0); - -// assert_eq!(first.hash, chain_entry.hash); -// assert_eq!(first.previous_hash, chain_entry.previous_hash); -// assert_eq!(first.operation, chain_entry.operation); - -// teardown(&redis_connections); -// } - -// #[test] -// #[serial] -// fn test_try_getting_hashchain_for_missing_key() { -// let redis_connections = setup(); -// let signing_key = create_mock_signing_key(); - -// let incoming_operation = -// create_add_key_operation_with_test_value("main:test_key", &signing_key); -// let chain_entry = create_mock_chain_entry(&signing_key); - -// redis_connections -// .set_hashchain(&incoming_operation, &[chain_entry.clone()]) -// .unwrap(); - -// let hashchain = redis_connections.get_hashchain("main:missing_test_key"); -// println!("{:?}", hashchain); -// assert!(hashchain.is_err()); - -// teardown(&redis_connections); -// } - -// #[test] -// #[serial] -// fn test_try_getting_wrong_formatted_hashchain_value() { -// let redis_connection = setup(); - -// let mut con = redis_connection.lock_connection().unwrap(); - -// #[derive(Serialize, Deserialize, Clone)] -// struct InvalidChainEntry { -// pub hash_val: String, // instead of just "hash" -// pub previous_hash: String, -// pub operation: Operation, -// } - -// let wrong_chain_entry = InvalidChainEntry { -// hash_val: "wrong".to_string(), -// previous_hash: "formatted".to_string(), -// operation: Operation::AddKey(KeyOperationArgs { -// id: "test".to_string(), -// value: PublicKey::Ed25519(vec![]), -// signature: SignatureBundle { -// key_idx: 0, -// signature: vec![], -// }, -// }), -// }; - -// let value = serde_json::to_string(&vec![wrong_chain_entry.clone()]).unwrap(); - -// con.set::<&String, String, String>( -// &"main:key_to_wrong_formatted_chain_entry".to_string(), -// value, -// ) -// .unwrap(); - -// drop(con); // drop the lock on the connection bc get_hashchain also needs a lock on the connection - -// let hashchain = redis_connection.get_hashchain("main:key_to_wrong_formatted_chain_entry"); - -// assert!(hashchain.is_err()); - -// teardown(&redis_connection); -// } - -// #[test] -// #[serial] -// /* -// TODO: In the test writing, it is noticeable that things may either not have been named correctly here, or need to be reconsidered. The update_hashchain function receives an IncomingEntry and a Vec as parameters. -// The Vec is the current state of the hashchain, the IncomingEntry is the new entry to be added. is to be added. Now, in hindsight, I would have expected that within the function the new hashchain would be created, -// or else just a value to a key-value pair is created. But neither is the case, instead there are two more update() functions outside of RedisConnections, which then creates the new hashchain is created. This needs to be discussed again with @distractedm1nd :) -// What should happen at the database level? Should the new hashchain be created? Or should only a new value be added to a key-value pair? -// */ -// fn test_update_hashchain() { -// let redis_connections = setup(); -// let signing_key = create_mock_signing_key(); - -// let incoming_operation = Operation::AddKey(KeyOperationArgs { -// id: "test_id".to_string(), -// value: PublicKey::Ed25519(signing_key.verifying_key().to_bytes().to_vec()), -// signature: create_mock_signature(&signing_key, b"test_id"), -// }); - -// let chain_entries: Vec = vec![create_mock_chain_entry(&signing_key)]; - -// match redis_connections.set_hashchain(&incoming_operation, &chain_entries) { -// Ok(_) => (), -// Err(e) => panic!("Failed to update hashchain: {}", e), -// } - -// let hashchain = redis_connections -// .get_hashchain(&incoming_operation.id()) -// .unwrap(); -// assert_eq!(hashchain.get(0).hash, hash(b"test_hash")); -// assert_eq!(hashchain.len(), 1); - -// teardown(&redis_connections); -// } -// } diff --git a/crates/prism/src/webserver.rs b/crates/prism/src/webserver.rs index 8735024..65bc2b0 100644 --- a/crates/prism/src/webserver.rs +++ b/crates/prism/src/webserver.rs @@ -142,8 +142,13 @@ async fn get_hashchain( State(session): State>, Json(request): Json, ) -> impl IntoResponse { - match session.db.get_hashchain(&request.id) { - Ok(hashchain) => (StatusCode::OK, Json(UserKeyResponse { hashchain })).into_response(), + match session.get_hashchain(&request.id).await { + Ok(hashchain_or_proof) => match hashchain_or_proof { + Ok(hashchain) => (StatusCode::OK, Json(UserKeyResponse { hashchain })).into_response(), + Err(non_inclusion_proof) => { + (StatusCode::BAD_REQUEST, Json(non_inclusion_proof)).into_response() + } + }, Err(err) => ( StatusCode::BAD_REQUEST, format!("Couldn't get hashchain: {}", err), diff --git a/crates/sp1/src/main.rs b/crates/sp1/src/main.rs index 32c4dec..fa15638 100644 --- a/crates/sp1/src/main.rs +++ b/crates/sp1/src/main.rs @@ -23,7 +23,7 @@ pub fn main() { // todo: @sebastian fix error handling if let Some(new_entry) = p.new_value.last() { let message = - dbg!(bincode::serialize(&new_entry.operation.without_signature()).unwrap()); + bincode::serialize(&new_entry.operation.without_signature()).unwrap(); let signature_bundle = new_entry.operation.get_signature_bundle().unwrap(); let public_key = p @@ -33,7 +33,6 @@ pub fn main() { ) .unwrap(); - // let public_key = dbg!(new_entry.operation.get_public_key().unwrap()); p.new_value .verify_signature(&public_key, &message, &signature_bundle.signature) .unwrap(); diff --git a/elf/riscv32im-succinct-zkvm-elf b/elf/riscv32im-succinct-zkvm-elf index 542070a..77d4eb4 100755 Binary files a/elf/riscv32im-succinct-zkvm-elf and b/elf/riscv32im-succinct-zkvm-elf differ