fmt and clippy

This commit is contained in:
Sergio Chouhy 2025-08-27 16:24:20 -03:00
parent 66b5efaacb
commit 0a3f093d60
19 changed files with 90 additions and 130 deletions

View File

@ -6,7 +6,7 @@ edition = "2024"
[dependencies]
thiserror = "2.0.12"
risc0-zkvm = "2.3.1"
nssa-core = { path = "core", features=["host"]}
nssa-core = { path = "core", features = ["host"] }
program-methods = { path = "program_methods" }
serde = "1.0.219"
sha2 = "0.10.9"

View File

@ -4,12 +4,12 @@ version = "0.1.0"
edition = "2024"
[dependencies]
risc0-zkvm = { version = "2.3.1"}
risc0-zkvm = { version = "2.3.1" }
serde = { version = "1.0", default-features = false }
thiserror = { version = "2.0.12", optional = true }
bytemuck = { version = "1.13", optional = true }
chacha20 = { version = "0.9", default-features = false }
k256 = { version = "0.13.3", optional = true}
k256 = { version = "0.13.3", optional = true }
[features]
default = []

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::program::ProgramId;
use serde::{Deserialize, Serialize};
pub type Nonce = u128;
type Data = Vec<u8>;

View File

@ -35,6 +35,7 @@ impl PrivacyPreservingCircuitOutput {
}
}
#[cfg(feature = "host")]
#[cfg(test)]
mod tests {
use super::*;

View File

@ -1,7 +1,7 @@
use risc0_zkvm::sha::{Impl, Sha256};
use serde::{Deserialize, Serialize};
use crate::{account::Account, NullifierPublicKey};
use crate::{NullifierPublicKey, account::Account};
#[derive(Serialize, Deserialize)]
#[cfg_attr(any(feature = "host", test), derive(Debug, Clone, PartialEq, Eq, Hash))]

View File

@ -171,6 +171,7 @@ mod tests {
assert_eq!(expected_bytes, bytes);
}
#[cfg(feature = "host")]
#[test]
fn test_nullifier_to_bytes() {
let nullifier = Nullifier((0..32).collect::<Vec<u8>>().try_into().unwrap());

View File

@ -11,7 +11,7 @@ pub(crate) mod shared_key_derivation;
#[cfg(feature = "host")]
pub use shared_key_derivation::{EphemeralPublicKey, EphemeralSecretKey, IncomingViewingPublicKey};
use crate::{Commitment, NullifierPublicKey, account::Account};
use crate::{Commitment, account::Account};
#[derive(Serialize, Deserialize, Clone)]
pub struct SharedSecretKey([u8; 32]);

View File

@ -62,7 +62,7 @@ mod tests {
202, 120, 42, 189, 194, 218, 78, 244, 31, 6, 108, 169, 29, 61, 22, 221, 69, 138, 197,
161, 241, 39, 142, 242, 242, 50, 188, 201, 99, 28, 176, 238,
]);
let Npk = NullifierPublicKey::from(&nsk);
assert_eq!(Npk, expected_npk);
let npk = NullifierPublicKey::from(&nsk);
assert_eq!(npk, expected_npk);
}
}

View File

@ -8,4 +8,3 @@ risc0-build = { version = "2.3.1" }
[package.metadata.risc0]
methods = ["guest"]

View File

@ -1,16 +1,18 @@
pub mod address;
pub mod error;
mod merkle_tree;
mod privacy_preserving_transaction;
pub mod program;
pub mod public_transaction;
mod signature;
mod state;
mod merkle_tree;
pub use address::Address;
pub use privacy_preserving_transaction::{
PrivacyPreservingTransaction, circuit::execute_and_prove,
};
pub use public_transaction::PublicTransaction;
pub use signature::PrivateKey;
pub use signature::PublicKey;
pub use signature::Signature;
pub use state::V01State;

View File

@ -1,5 +1,3 @@
use std::collections::{HashMap, HashSet};
use sha2::{Digest, Sha256};
mod default_values;
@ -47,8 +45,7 @@ impl MerkleTree {
/// Number of levels required to hold all values
fn depth(&self) -> usize {
let result = self.length.next_power_of_two().trailing_zeros() as usize;
result
self.length.next_power_of_two().trailing_zeros() as usize
}
fn get_node(&self, index: usize) -> &Node {
@ -108,7 +105,6 @@ impl MerkleTree {
self.set_node(node_index, node_hash);
self.length += 1;
let root_index = self.root_index();
for _ in 0..self.depth() {
let parent_index = (node_index - 1) >> 1;
let left_child = self.get_node((parent_index << 1) + 1);
@ -121,14 +117,6 @@ impl MerkleTree {
new_index
}
pub fn new(values: &[Value]) -> Self {
let mut this = Self::with_capacity(values.len());
for value in values.iter().cloned() {
this.insert(value);
}
this
}
pub fn get_authentication_path_for(&self, index: usize) -> Option<Vec<Node>> {
if index >= self.length {
return None;
@ -155,22 +143,6 @@ impl MerkleTree {
}
}
// Reference implementation
fn verify_authentication_path(value: &Value, index: usize, path: &[Node], root: &Node) -> bool {
let mut result = hash_value(value);
let mut level_index = index;
for node in path {
let is_left_child = level_index & 1 == 0;
if is_left_child {
result = hash_two(&result, node);
} else {
result = hash_two(node, &result);
}
level_index >>= 1;
}
&result == root
}
fn prev_power_of_two(x: usize) -> usize {
if x == 0 {
return 0;
@ -180,10 +152,19 @@ fn prev_power_of_two(x: usize) -> usize {
#[cfg(test)]
mod tests {
impl MerkleTree {
pub fn new(values: &[Value]) -> Self {
let mut this = Self::with_capacity(values.len());
for value in values.iter().cloned() {
this.insert(value);
}
this
}
}
use hex_literal::hex;
use super::*;
#[test]
fn test_empty_merkle_tree() {
let tree = MerkleTree::with_capacity(4);
@ -398,6 +379,22 @@ mod tests {
assert_eq!(expected_tree, tree);
}
// Reference implementation
fn verify_authentication_path(value: &Value, index: usize, path: &[Node], root: &Node) -> bool {
let mut result = hash_value(value);
let mut level_index = index;
for node in path {
let is_left_child = level_index & 1 == 0;
if is_left_child {
result = hash_two(&result, node);
} else {
result = hash_two(node, &result);
}
level_index >>= 1;
}
&result == root
}
#[test]
fn test_authentication_path_1() {
let values = [[1; 32], [2; 32], [3; 32], [4; 32]];

View File

@ -1,8 +1,8 @@
use nssa_core::{
CommitmentSetDigest, MembershipProof, NullifierPublicKey, NullifierSecretKey,
PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput, SharedSecretKey,
account::{Account, AccountWithMetadata, Nonce},
program::{InstructionData, ProgramId, ProgramOutput},
MembershipProof, NullifierPublicKey, NullifierSecretKey, PrivacyPreservingCircuitInput,
PrivacyPreservingCircuitOutput, SharedSecretKey,
account::AccountWithMetadata,
program::{InstructionData, ProgramOutput},
};
use risc0_zkvm::{ExecutorEnv, InnerReceipt, Receipt, default_prover};
@ -91,19 +91,12 @@ fn execute_and_prove_program(
#[cfg(test)]
mod tests {
use nssa_core::{
Commitment, EncryptionScheme, Nullifier, NullifierPublicKey, NullifierSecretKey,
Commitment, EncryptionScheme, Nullifier,
account::{Account, AccountWithMetadata},
encryption::EphemeralPublicKey,
};
use risc0_zkvm::{InnerReceipt, Journal, Receipt};
use crate::{
Address, V01State,
merkle_tree::MerkleTree,
privacy_preserving_transaction::{
circuit::{Proof, execute_and_prove},
message::EncryptedAccountData,
},
privacy_preserving_transaction::circuit::execute_and_prove,
program::Program,
state::{
CommitmentSet,
@ -111,8 +104,6 @@ mod tests {
},
};
use rand::{Rng, RngCore, rngs::OsRng};
use super::*;
#[test]
@ -152,7 +143,6 @@ mod tests {
let esk = [3; 32];
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
let epk = EphemeralPublicKey::from_scalar(esk);
let (output, proof) = execute_and_prove(
&[sender, recipient],
@ -206,7 +196,7 @@ mod tests {
let balance_to_move: u128 = 37;
let mut commitment_set = CommitmentSet::with_capacity(2);
commitment_set.extend(&[commitment_sender.clone()]);
commitment_set.extend(std::slice::from_ref(&commitment_sender));
let expected_new_nullifiers = vec![(
Nullifier::new(&commitment_sender, &sender_keys.nsk),
@ -234,11 +224,9 @@ mod tests {
let esk_1 = [3; 32];
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.ivk());
let epk_1 = EphemeralPublicKey::from_scalar(esk_1);
let esk_2 = [5; 32];
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
let epk_2 = EphemeralPublicKey::from_scalar(esk_2);
let (output, proof) = execute_and_prove(
&[sender_pre.clone(), recipient],

View File

@ -88,6 +88,7 @@ impl Message {
bytes
}
#[allow(unused)]
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
let prefix = {
let mut this = [0u8; MESSAGE_ENCODING_PREFIX_LEN];
@ -115,7 +116,7 @@ impl Message {
// Nonces
cursor.read_exact(&mut len_bytes)?;
let nonces_len = u32::from_le_bytes(len_bytes) as usize;
let mut nonces = Vec::with_capacity(nonces_len as usize);
let mut nonces = Vec::with_capacity(nonces_len);
for _ in 0..nonces_len {
let mut buf = [0u8; 16];
cursor.read_exact(&mut buf)?;
@ -153,7 +154,7 @@ impl Message {
for _ in 0..new_nullifiers_len {
let nullifier = Nullifier::from_cursor(cursor)?;
let mut commitment_set_digest = [0; 32];
cursor.read_exact(&mut commitment_set_digest);
cursor.read_exact(&mut commitment_set_digest)?;
new_nullifiers.push((nullifier, commitment_set_digest));
}

View File

@ -1,11 +1,8 @@
use std::io::Cursor;
use nssa_core::{
Commitment, CommitmentSetDigest, Nullifier, PrivacyPreservingCircuitOutput,
account::{Account, Nonce},
encryption::{Ciphertext, EphemeralPublicKey},
};
use serde::{Deserialize, Serialize};
use crate::{Address, error::NssaError};
@ -64,7 +61,7 @@ impl Message {
pub mod tests {
use std::io::Cursor;
use nssa_core::{account::Account, Commitment, Nullifier, NullifierPublicKey};
use nssa_core::{Commitment, Nullifier, NullifierPublicKey, account::Account};
use crate::{Address, privacy_preserving_transaction::message::Message};
@ -75,8 +72,8 @@ pub mod tests {
let nsk1 = [11; 32];
let nsk2 = [12; 32];
let Npk1 = NullifierPublicKey::from(&nsk1);
let Npk2 = NullifierPublicKey::from(&nsk2);
let npk1 = NullifierPublicKey::from(&nsk1);
let npk2 = NullifierPublicKey::from(&nsk2);
let public_addresses = vec![Address::new([1; 32])];
@ -86,9 +83,9 @@ pub mod tests {
let encrypted_private_post_states = Vec::new();
let new_commitments = vec![Commitment::new(&Npk2, &account2)];
let new_commitments = vec![Commitment::new(&npk2, &account2)];
let old_commitment = Commitment::new(&Npk1, &account1);
let old_commitment = Commitment::new(&npk1, &account1);
let new_nullifiers = vec![(Nullifier::new(&old_commitment, &nsk1), [0; 32])];
Message {

View File

@ -1,10 +1,8 @@
mod encoding;
mod message;
mod transaction;
mod witness_set;
pub mod message;
pub mod transaction;
pub mod witness_set;
pub mod circuit;
pub use message::{Message, EncryptedAccountData};
pub use transaction::PrivacyPreservingTransaction;
pub use witness_set::WitnessSet;

View File

@ -3,7 +3,6 @@ use std::collections::{HashMap, HashSet};
use nssa_core::{
Commitment, CommitmentSetDigest, Nullifier, PrivacyPreservingCircuitOutput,
account::{Account, AccountWithMetadata},
encryption::Ciphertext,
};
use crate::error::NssaError;

View File

@ -1,11 +1,10 @@
use borsh::{BorshDeserialize, BorshSerialize};
use nssa_core::{
account::{Account, AccountWithMetadata},
program::{DEFAULT_PROGRAM_ID, InstructionData, ProgramId, ProgramOutput},
program::{InstructionData, ProgramId, ProgramOutput},
};
use program_methods::{AUTHENTICATED_TRANSFER_ELF, AUTHENTICATED_TRANSFER_ID};
use risc0_zkvm::{
ExecutorEnv, ExecutorEnvBuilder, Journal, Receipt, default_executor, default_prover,
ExecutorEnv, ExecutorEnvBuilder, default_executor,
serde::to_vec,
};
use serde::Serialize;
@ -51,7 +50,7 @@ impl Program {
// Get outputs
let ProgramOutput {
mut post_states, ..
post_states, ..
} = session_info
.journal
.decode()
@ -83,11 +82,8 @@ impl Program {
#[cfg(test)]
mod tests {
use nssa_core::{
account::{Account, AccountWithMetadata},
program::ProgramOutput,
};
use risc0_zkvm::{InnerReceipt, Receipt, serde::to_vec};
use nssa_core::account::{Account, AccountWithMetadata};
use crate::program::Program;

View File

@ -11,8 +11,7 @@ use crate::{
};
const MESSAGE_ENCODING_PREFIX_LEN: usize = 22;
const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] =
b"\x00/NSSA/v0.1/TxMessage/";
const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] = b"\x00/NSSA/v0.1/TxMessage/";
impl Message {
/// Serializes a `Message` into bytes in the following layout:

View File

@ -4,14 +4,16 @@ use crate::{
public_transaction::PublicTransaction,
};
use nssa_core::{
account::Account, program::{ProgramId, DEFAULT_PROGRAM_ID}, Commitment, CommitmentSetDigest, MembershipProof, Nullifier
Commitment, CommitmentSetDigest, MembershipProof, Nullifier,
account::Account,
program::{DEFAULT_PROGRAM_ID, ProgramId},
};
use std::collections::{HashMap, HashSet};
pub(crate) struct CommitmentSet {
merkle_tree: MerkleTree,
commitments: HashMap<Commitment, usize>,
pub root_history: HashSet<CommitmentSetDigest>,
root_history: HashSet<CommitmentSetDigest>,
}
impl CommitmentSet {
@ -19,13 +21,12 @@ impl CommitmentSet {
self.merkle_tree.root()
}
pub(crate) fn get_proof_for(&self, commitment: &Commitment) -> Option<MembershipProof> {
pub fn get_proof_for(&self, commitment: &Commitment) -> Option<MembershipProof> {
let index = *self.commitments.get(commitment)?;
let proof = self
.merkle_tree
self.merkle_tree
.get_authentication_path_for(index)
.map(|path| (index, path));
proof
.map(|path| (index, path))
}
pub(crate) fn extend(&mut self, commitments: &[Commitment]) {
@ -53,7 +54,7 @@ type NullifierSet = HashSet<Nullifier>;
pub struct V01State {
public_state: HashMap<Address, Account>,
pub private_state: (CommitmentSet, NullifierSet),
private_state: (CommitmentSet, NullifierSet),
builtin_programs: HashMap<ProgramId, Program>,
}
@ -159,6 +160,10 @@ impl V01State {
.unwrap_or(Account::default())
}
pub fn get_proof_for_commitment(&self, commitment: &Commitment) -> Option<MembershipProof> {
self.private_state.0.get_proof_for(commitment)
}
pub(crate) fn builtin_programs(&self) -> &HashMap<ProgramId, Program> {
&self.builtin_programs
}
@ -199,16 +204,6 @@ impl V01State {
}
Ok(())
}
pub(crate) fn check_commitment_set_digest_is_valid(
&self,
commitment_set_digest: &CommitmentSetDigest,
) -> bool {
self.private_state
.0
.root_history
.contains(commitment_set_digest)
}
}
#[cfg(test)]
@ -220,7 +215,7 @@ pub mod tests {
Address, PublicKey, PublicTransaction, V01State,
error::NssaError,
privacy_preserving_transaction::{
EncryptedAccountData, Message, PrivacyPreservingTransaction, WitnessSet, circuit,
PrivacyPreservingTransaction, circuit, message::Message, witness_set::WitnessSet,
},
program::Program,
public_transaction,
@ -228,11 +223,10 @@ pub mod tests {
};
use nssa_core::{
account::{
Account, AccountWithMetadata, Nonce,
}, encryption::{EphemeralPublicKey, IncomingViewingPublicKey}, Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey
Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
account::{Account, AccountWithMetadata, Nonce},
encryption::{EphemeralPublicKey, IncomingViewingPublicKey},
};
use program_methods::AUTHENTICATED_TRANSFER_ID;
fn transfer_transaction(
from: Address,
@ -482,7 +476,7 @@ pub mod tests {
}
pub fn with_private_account(mut self, keys: &TestPrivateKeys, account: &Account) -> Self {
let commitment = Commitment::new(&keys.npk(), &account);
let commitment = Commitment::new(&keys.npk(), account);
self.private_state.0.extend(&[commitment]);
self
}
@ -825,7 +819,7 @@ pub mod tests {
state: &V01State,
) -> PrivacyPreservingTransaction {
let program = Program::authenticated_transfer_program();
let sender_commitment = Commitment::new(&sender_keys.npk(), &sender_private_account);
let sender_commitment = Commitment::new(&sender_keys.npk(), sender_private_account);
let sender_pre = AccountWithMetadata {
account: sender_private_account.clone(),
is_authorized: true,
@ -854,11 +848,7 @@ pub mod tests {
],
&[(
sender_keys.nsk,
state
.private_state
.0
.get_proof_for(&sender_commitment)
.unwrap(),
state.get_proof_for_commitment(&sender_commitment).unwrap(),
)],
&program,
)
@ -881,7 +871,7 @@ pub mod tests {
state: &V01State,
) -> PrivacyPreservingTransaction {
let program = Program::authenticated_transfer_program();
let sender_commitment = Commitment::new(&sender_keys.npk(), &sender_private_account);
let sender_commitment = Commitment::new(&sender_keys.npk(), sender_private_account);
let sender_pre = AccountWithMetadata {
account: sender_private_account.clone(),
is_authorized: true,
@ -903,23 +893,15 @@ pub mod tests {
&[(sender_keys.npk(), shared_secret)],
&[(
sender_keys.nsk,
state
.private_state
.0
.get_proof_for(&sender_commitment)
.unwrap(),
state.get_proof_for_commitment(&sender_commitment).unwrap(),
)],
&program,
)
.unwrap();
let message = Message::try_from_circuit_output(
vec![recipient_address.clone()],
vec![],
vec![epk],
output,
)
.unwrap();
let message =
Message::try_from_circuit_output(vec![*recipient_address], vec![], vec![epk], output)
.unwrap();
let witness_set = WitnessSet::for_message(&message, proof, &[]);