diff --git a/nssa/core/src/account/commitment.rs b/nssa/core/src/account/commitment.rs index 8f1b072..a288c0a 100644 --- a/nssa/core/src/account/commitment.rs +++ b/nssa/core/src/account/commitment.rs @@ -1,13 +1,19 @@ +use risc0_zkvm::{ + serde::to_vec, + sha::{Impl, Sha256}, +}; use serde::{Deserialize, Serialize}; use crate::account::{Account, NullifierPublicKey}; - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] pub struct Commitment([u8; 32]); impl Commitment { pub fn new(Npk: &NullifierPublicKey, account: &Account) -> Self { - todo!() + let mut bytes = Vec::new(); + bytes.extend_from_slice(&Npk.to_bytes()); + bytes.extend_from_slice(&account.to_bytes()); + Self(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap()) } } diff --git a/nssa/core/src/account/encoding.rs b/nssa/core/src/account/encoding.rs new file mode 100644 index 0000000..c560a9d --- /dev/null +++ b/nssa/core/src/account/encoding.rs @@ -0,0 +1,47 @@ +use risc0_zkvm::{ + serde::to_vec, + sha::{Impl, Sha256}, +}; + +use crate::account::Account; + +impl Account { + pub fn to_bytes(&self) -> Vec { + let mut bytes = Vec::new(); + for word in &self.program_owner { + bytes.extend_from_slice(&word.to_le_bytes()); + } + bytes.extend_from_slice(&self.balance.to_le_bytes()); + bytes.extend_from_slice(&self.nonce.to_le_bytes()); + let hashed_data: [u8; 32] = Impl::hash_bytes(&self.data).as_bytes().try_into().unwrap(); + bytes.extend_from_slice(&hashed_data); + bytes + } +} + +#[cfg(test)] +mod tests { + use crate::account::Account; + + #[test] + fn test_enconding() { + let account = Account { + program_owner: [1, 2, 3, 4, 5, 6, 7, 8], + balance: 123456789012345678901234567890123456, + nonce: 42, + data: b"hola mundo".to_vec(), + }; + + // program owner || balance || nonce || hash(data) + let expected_bytes = [ + 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, + 0, 0, 0, 192, 186, 220, 114, 113, 65, 236, 234, 222, 15, 215, 191, 227, 198, 23, 0, 42, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 137, 65, 102, 211, 51, 100, 53, 200, + 0, 190, 163, 111, 242, 27, 41, 234, 168, 1, 165, 47, 88, 76, 0, 108, 73, 40, 154, 13, + 207, 110, 47, + ]; + + let bytes = account.to_bytes(); + assert_eq!(bytes, expected_bytes); + } +} diff --git a/nssa/core/src/account/mod.rs b/nssa/core/src/account/mod.rs index 722a4fb..1358eb1 100644 --- a/nssa/core/src/account/mod.rs +++ b/nssa/core/src/account/mod.rs @@ -4,11 +4,13 @@ use crate::program::ProgramId; mod commitment; mod nullifier; +mod encoding; pub use commitment::Commitment; pub use nullifier::{Nullifier, NullifierPublicKey, NullifierSecretKey}; pub type Nonce = u128; +// TODO: Consider changing `Data` to `Vec` for r0 friendlinenss type Data = Vec; /// Account to be used both in public and private contexts diff --git a/nssa/core/src/account/nullifier.rs b/nssa/core/src/account/nullifier.rs index 600093c..155afe2 100644 --- a/nssa/core/src/account/nullifier.rs +++ b/nssa/core/src/account/nullifier.rs @@ -5,6 +5,12 @@ use crate::account::Commitment; #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct NullifierPublicKey([u8; 32]); +impl NullifierPublicKey { + pub(crate) fn to_bytes(&self) -> [u8; 32] { + self.0 + } +} + impl From<&NullifierSecretKey> for NullifierPublicKey { fn from(_value: &NullifierSecretKey) -> Self { todo!() diff --git a/nssa/src/privacy_preserving_transaction/message.rs b/nssa/src/privacy_preserving_transaction/message.rs index 08cad42..b2461c1 100644 --- a/nssa/src/privacy_preserving_transaction/message.rs +++ b/nssa/src/privacy_preserving_transaction/message.rs @@ -10,7 +10,81 @@ pub struct Message { pub(crate) public_addresses: Vec
, pub(crate) nonces: Vec, pub(crate) public_post_states: Vec, - pub(crate) encrypted_private_post_states: EncryptedAccountData, + pub(crate) encrypted_private_post_states: Vec, pub(crate) new_commitments: Vec, pub(crate) new_nullifiers: Vec, } + +impl Message { + pub fn new( + public_addresses: Vec
, + nonces: Vec, + public_post_states: Vec, + encrypted_private_post_states: Vec, + new_commitments: Vec, + new_nullifiers: Vec, + ) -> Self { + Self { + public_addresses, + nonces, + public_post_states, + encrypted_private_post_states, + new_commitments, + new_nullifiers, + } + } +} + +#[cfg(test)] +mod tests { + use nssa_core::account::{ + Account, Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, + }; + + use crate::{Address, privacy_preserving_transaction::message::Message}; + + #[test] + fn test_constructor() { + let account1 = Account::default(); + let account2 = Account::default(); + + let nsk1 = [11; 32]; + let nsk2 = [12; 32]; + + let Npk1 = NullifierPublicKey::from(&nsk1); + let Npk2 = NullifierPublicKey::from(&nsk2); + + let public_addresses = vec![Address::new([1; 32])]; + + let nonces = vec![1, 2, 3]; + + let public_post_states = vec![Account::default()]; + + let encrypted_private_post_states = Vec::new(); + + let new_commitments = vec![Commitment::new(&Npk2, &account2)]; + + let old_commitment = Commitment::new(&Npk1, &account1); + let new_nullifiers = vec![Nullifier::new(&old_commitment, &nsk1)]; + + let expected_message = Message { + public_addresses: public_addresses.clone(), + nonces: nonces.clone(), + public_post_states: public_post_states.clone(), + encrypted_private_post_states: encrypted_private_post_states.clone(), + new_commitments: new_commitments.clone(), + new_nullifiers: new_nullifiers.clone(), + }; + + let message = Message::new( + public_addresses, + nonces, + public_post_states, + encrypted_private_post_states, + new_commitments, + new_nullifiers, + ); + + assert_eq!(message, expected_message); + } +} diff --git a/nssa/src/privacy_preserving_transaction/transaction.rs b/nssa/src/privacy_preserving_transaction/transaction.rs index 33b1aa5..055cc02 100644 --- a/nssa/src/privacy_preserving_transaction/transaction.rs +++ b/nssa/src/privacy_preserving_transaction/transaction.rs @@ -133,7 +133,7 @@ fn check_privacy_preserving_circuit_proof_is_valid( proof: (), public_pre_states: &[AccountWithMetadata], public_post_states: &[Account], - encrypted_private_post_states: &EncryptedAccountData, + encrypted_private_post_states: &[EncryptedAccountData], new_commitments: &[nssa_core::account::Commitment], new_nullifiers: &[nssa_core::account::Nullifier], commitment_set_digest: CommitmentSetDigest, diff --git a/nssa/src/privacy_preserving_transaction/witness_set.rs b/nssa/src/privacy_preserving_transaction/witness_set.rs index 190099d..1405601 100644 --- a/nssa/src/privacy_preserving_transaction/witness_set.rs +++ b/nssa/src/privacy_preserving_transaction/witness_set.rs @@ -1,21 +1,26 @@ -use crate::{privacy_preserving_transaction::message::Message, PrivateKey, PublicKey, Signature}; - +use crate::{PrivateKey, PublicKey, Signature, privacy_preserving_transaction::message::Message}; type Proof = (); #[derive(Debug, Clone, PartialEq, Eq)] pub struct WitnessSet { pub(super) signatures_and_public_keys: Vec<(Signature, PublicKey)>, - pub(super) proof: Proof + pub(super) proof: Proof, } - impl WitnessSet { pub fn for_message(message: &Message, private_keys: &[&PrivateKey]) -> Self { todo!() } pub fn signatures_are_valid_for(&self, message: &Message) -> bool { + // let message_bytes = message.to_bytes(); + // for (signature, public_key) in self.signatures_and_public_keys() { + // if !signature.is_valid_for(&message_bytes, public_key) { + // return false; + // } + // } + // true todo!() }