diff --git a/integration_tests/tests/tps.rs b/integration_tests/tests/tps.rs index 204c21d5..95d69097 100644 --- a/integration_tests/tests/tps.rs +++ b/integration_tests/tests/tps.rs @@ -212,6 +212,7 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction { let sender_vsk = [99; 32]; let sender_vpk = ViewingPublicKey::from_scalar(sender_vsk); let sender_npk = NullifierPublicKey::from(&sender_nsk); + let sender_id = AccountId::account_id_without_identifier(&sender_npk); let sender_pre = AccountWithMetadata::new( Account { balance: 100, @@ -226,6 +227,7 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction { let recipient_vsk = [99; 32]; let recipient_vpk = ViewingPublicKey::from_scalar(recipient_vsk); let recipient_npk = NullifierPublicKey::from(&recipient_nsk); + let recipient_id = AccountId::account_id_without_identifier(&recipient_npk); let recipient_pre = AccountWithMetadata::new(Account::default(), false, AccountId::account_id_without_identifier(&recipient_npk)); @@ -250,8 +252,8 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction { Program::serialize_instruction(balance_to_move).unwrap(), vec![1, 2], vec![ - (sender_npk.clone(), sender_ss), - (recipient_npk.clone(), recipient_ss), + (sender_npk, sender_ss), + (recipient_npk, recipient_ss), ], vec![sender_nsk], vec![Some(proof)], @@ -262,8 +264,8 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction { vec![], vec![], vec![ - (sender_npk, sender_vpk, sender_epk), - (recipient_npk, recipient_vpk, recipient_epk), + (sender_id, sender_vpk, sender_epk), + (recipient_id, recipient_vpk, recipient_epk), ], output, ) diff --git a/key_protocol/src/key_management/secret_holders.rs b/key_protocol/src/key_management/secret_holders.rs index 1057bb55..02890631 100644 --- a/key_protocol/src/key_management/secret_holders.rs +++ b/key_protocol/src/key_management/secret_holders.rs @@ -27,7 +27,6 @@ pub type ViewingSecretKey = Scalar; #[derive(Serialize, Deserialize, Debug, Clone)] /// Private key holder. Produces public keys. Can produce `account_id`. Can produce shared secret /// for recepient. -#[expect(clippy::partial_pub_fields, reason = "TODO: fix later")] pub struct PrivateKeyHolder { pub nullifier_secret_key: NullifierSecretKey, pub viewing_secret_key: ViewingSecretKey, diff --git a/nssa/core/src/nullifier.rs b/nssa/core/src/nullifier.rs index 1825b286..997ef644 100644 --- a/nssa/core/src/nullifier.rs +++ b/nssa/core/src/nullifier.rs @@ -2,7 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use risc0_zkvm::sha::{Impl, Sha256 as _}; use serde::{Deserialize, Serialize}; -use crate::{Commitment}; +use crate::{Commitment, account::AccountId}; #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] #[cfg_attr(any(feature = "host", test), derive(Clone, Hash))] @@ -68,10 +68,10 @@ impl Nullifier { /// Computes a nullifier for an account initialization. #[must_use] - pub fn for_account_initialization(npk: &NullifierPublicKey) -> Self { + pub fn for_account_initialization(account_id: &AccountId) -> Self { const INIT_PREFIX: &[u8; 32] = b"/LEE/v0.3/Nullifier/Initialize/\x00"; let mut bytes = INIT_PREFIX.to_vec(); - bytes.extend_from_slice(&npk.to_byte_array()); + bytes.extend_from_slice(account_id.value()); Self(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap()) } } @@ -98,11 +98,11 @@ mod tests { 112, 188, 193, 129, 150, 55, 228, 67, 88, 168, 29, 151, 5, 92, 23, 190, 17, 162, 164, 255, 29, 105, 42, 186, 43, 11, 157, 168, 132, 225, 17, 163, ]); - let expected_nullifier = Nullifier([ - 149, 59, 95, 181, 2, 194, 20, 143, 72, 233, 104, 243, 59, 70, 67, 243, 110, 77, 109, - 132, 139, 111, 51, 125, 128, 92, 107, 46, 252, 4, 20, 149, - ]); - let nullifier = Nullifier::for_account_initialization(&npk); + + let account_id = AccountId::account_id_with_identifier(&npk, 0_u128); + + let expected_nullifier = Nullifier([63, 58, 51, 159, 15, 100, 240, 243, 60, 143, 151, 108, 116, 144, 101, 6, 134, 72, 198, 249, 108, 80, 237, 194, 143, 66, 225, 191, 111, 49, 66, 54]); + let nullifier = Nullifier::for_account_initialization(&account_id); assert_eq!(nullifier, expected_nullifier); } diff --git a/nssa/src/privacy_preserving_transaction/circuit.rs b/nssa/src/privacy_preserving_transaction/circuit.rs index a1ba35d9..c8b410e4 100644 --- a/nssa/src/privacy_preserving_transaction/circuit.rs +++ b/nssa/src/privacy_preserving_transaction/circuit.rs @@ -266,6 +266,7 @@ mod tests { let program = Program::authenticated_transfer_program(); let sender_keys = test_private_account_keys_1(); let recipient_keys = test_private_account_keys_2(); + let recipient_id = AccountId::account_id_without_identifier(&test_private_account_keys_2().npk()); let sender_nonce = Nonce(0xdead_beef); let sender_pre = AccountWithMetadata::new( @@ -296,7 +297,7 @@ mod tests { commitment_set.digest(), ), ( - Nullifier::for_account_initialization(&recipient_keys.npk()), + Nullifier::for_account_initialization(&recipient_id), DUMMY_COMMITMENT_HASH, ), ]; diff --git a/nssa/src/privacy_preserving_transaction/message.rs b/nssa/src/privacy_preserving_transaction/message.rs index fba8d107..1f615946 100644 --- a/nssa/src/privacy_preserving_transaction/message.rs +++ b/nssa/src/privacy_preserving_transaction/message.rs @@ -1,6 +1,6 @@ use borsh::{BorshDeserialize, BorshSerialize}; use nssa_core::{ - Commitment, CommitmentSetDigest, Nullifier, NullifierPublicKey, PrivacyPreservingCircuitOutput, + Commitment, CommitmentSetDigest, Nullifier, PrivacyPreservingCircuitOutput, account::{Account, Nonce}, encryption::{Ciphertext, EphemeralPublicKey, ViewingPublicKey}, program::ValidityWindow, @@ -21,11 +21,11 @@ pub struct EncryptedAccountData { impl EncryptedAccountData { fn new( ciphertext: Ciphertext, - npk: &NullifierPublicKey, + account_id: &AccountId, vpk: &ViewingPublicKey, epk: EphemeralPublicKey, ) -> Self { - let view_tag = Self::compute_view_tag(npk, vpk); + let view_tag = Self::compute_view_tag(account_id, vpk); Self { ciphertext, epk, @@ -35,10 +35,13 @@ impl EncryptedAccountData { /// Computes the tag as the first byte of SHA256("/LEE/v0.3/ViewTag/" || Npk || vpk). #[must_use] - pub fn compute_view_tag(npk: &NullifierPublicKey, vpk: &ViewingPublicKey) -> ViewTag { + pub fn compute_view_tag(account_id: &AccountId, vpk: &ViewingPublicKey) -> ViewTag { + const VIEWTAG_PREFIX: &[u8; 32] = + b"/LEE/v0.3/ViewTag\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; + let mut hasher = Sha256::new(); - hasher.update(b"/LEE/v0.3/ViewTag/"); - hasher.update(npk.to_byte_array()); + hasher.update(VIEWTAG_PREFIX); + hasher.update(account_id.to_bytes()); hasher.update(vpk.to_bytes()); let digest: [u8; 32] = hasher.finalize().into(); digest[0] @@ -88,7 +91,7 @@ impl Message { pub fn try_from_circuit_output( public_account_ids: Vec, nonces: Vec, - public_keys: Vec<(NullifierPublicKey, ViewingPublicKey, EphemeralPublicKey)>, + public_keys: Vec<(AccountId, ViewingPublicKey, EphemeralPublicKey)>, //TODO: Rename `public_keys` to account for `account_id`. output: PrivacyPreservingCircuitOutput, ) -> Result { if public_keys.len() != output.ciphertexts.len() { @@ -101,8 +104,8 @@ impl Message { .ciphertexts .into_iter() .zip(public_keys) - .map(|(ciphertext, (npk, vpk, epk))| { - EncryptedAccountData::new(ciphertext, &npk, &vpk, epk) + .map(|(ciphertext, (account_id, vpk, epk))| { + EncryptedAccountData::new(ciphertext, &account_id, &vpk, epk) }) .collect(); Ok(Self { @@ -183,7 +186,7 @@ pub mod tests { let epk = EphemeralPublicKey::from_scalar(esk); let ciphertext = EncryptionScheme::encrypt(&account, &shared_secret, &commitment, 2); let encrypted_account_data = - EncryptedAccountData::new(ciphertext.clone(), &npk, &vpk, epk.clone()); + EncryptedAccountData::new(ciphertext.clone(), &account_id, &vpk, epk.clone()); let expected_view_tag = { let mut hasher = Sha256::new(); @@ -198,7 +201,7 @@ pub mod tests { assert_eq!(encrypted_account_data.epk, epk); assert_eq!( encrypted_account_data.view_tag, - EncryptedAccountData::compute_view_tag(&npk, &vpk) + EncryptedAccountData::compute_view_tag(&account_id, &vpk) ); assert_eq!(encrypted_account_data.view_tag, expected_view_tag); } diff --git a/nssa/src/state.rs b/nssa/src/state.rs index 9f7c75b0..021a522e 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -953,7 +953,7 @@ pub mod tests { let message = Message::try_from_circuit_output( vec![sender_keys.account_id()], vec![sender_nonce], - vec![(recipient_keys.npk(), recipient_keys.vpk(), epk)], + vec![(recipient_id, recipient_keys.vpk(), epk)], output, ) .unwrap(); @@ -1004,8 +1004,8 @@ pub mod tests { vec![], vec![], vec![ - (sender_keys.npk(), sender_keys.vpk(), epk_1), - (recipient_keys.npk(), recipient_keys.vpk(), epk_2), + (sender_id, sender_keys.vpk(), epk_1), + (recipient_id, recipient_keys.vpk(), epk_2), ], output, ) @@ -1052,7 +1052,7 @@ pub mod tests { let message = Message::try_from_circuit_output( vec![*recipient_account_id], vec![], - vec![(sender_keys.npk(), sender_keys.vpk(), epk)], + vec![(sender_id, sender_keys.vpk(), epk)], output, ) .unwrap(); @@ -2557,8 +2557,8 @@ pub mod tests { vec![], vec![], vec![ - (to_keys.npk(), to_keys.vpk(), to_epk), - (from_keys.npk(), from_keys.vpk(), from_epk), + (to_account_id, to_keys.vpk(), to_epk), + (from_account_id, from_keys.vpk(), from_epk), ], output, ) @@ -2791,7 +2791,7 @@ pub mod tests { let message = Message::try_from_circuit_output( vec![], vec![], - vec![(private_keys.npk(), private_keys.vpk(), epk)], + vec![(account_id, private_keys.vpk(), epk)], output, ) .unwrap(); @@ -2802,7 +2802,7 @@ pub mod tests { let result = state.transition_from_privacy_preserving_transaction(&tx, 1); assert!(result.is_ok()); - let nullifier = Nullifier::for_account_initialization(&private_keys.npk()); + let nullifier = Nullifier::for_account_initialization(&account_id); assert!(state.private_state.1.contains(&nullifier)); } @@ -2842,7 +2842,7 @@ pub mod tests { let message = Message::try_from_circuit_output( vec![], vec![], - vec![(private_keys.npk(), private_keys.vpk(), epk)], + vec![(account_id, private_keys.vpk(), epk)], output, ) .unwrap(); @@ -2858,7 +2858,7 @@ pub mod tests { ); // Verify the account is now initialized (nullifier exists) - let nullifier = Nullifier::for_account_initialization(&private_keys.npk()); + let nullifier = Nullifier::for_account_initialization(&account_id); assert!(state.private_state.1.contains(&nullifier)); // Prepare new state of account @@ -3111,7 +3111,8 @@ pub mod tests { let validity_window: ValidityWindow = validity_window.try_into().unwrap(); let validity_window_program = Program::validity_window(); let account_keys = test_private_account_keys_1(); - let pre = AccountWithMetadata::new(Account::default(), false, &account_keys.npk()); + let account_id = AccountId::account_id_without_identifier(&account_keys.npk()); + let pre = AccountWithMetadata::new(Account::default(), false, account_id); let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); let tx = { let esk = [3; 32]; @@ -3132,7 +3133,7 @@ pub mod tests { let message = Message::try_from_circuit_output( vec![], vec![], - vec![(account_keys.npk(), account_keys.vpk(), epk)], + vec![(account_id, account_keys.vpk(), epk)], output, ) .unwrap(); diff --git a/program_methods/guest/src/bin/privacy_preserving_circuit.rs b/program_methods/guest/src/bin/privacy_preserving_circuit.rs index f217d01c..c6edec0c 100644 --- a/program_methods/guest/src/bin/privacy_preserving_circuit.rs +++ b/program_methods/guest/src/bin/privacy_preserving_circuit.rs @@ -317,7 +317,8 @@ fn compute_circuit_output( "Membership proof must be None for unauthorized accounts" ); - let nullifier = Nullifier::for_account_initialization(npk); + let account_id = AccountId::account_id_without_identifier(npk); + let nullifier = Nullifier::for_account_initialization(&account_id); let new_nonce = Nonce::private_account_nonce_init(npk); @@ -386,7 +387,7 @@ fn compute_nullifier_and_set_digest( ); // Compute initialization nullifier - let nullifier = Nullifier::for_account_initialization(npk); + let nullifier = Nullifier::for_account_initialization(&account_id); (nullifier, DUMMY_COMMITMENT_HASH) }, |membership_proof| { diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 7834140e..0c46fea8 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -393,7 +393,7 @@ impl WalletCore { Vec::from_iter(acc_manager.public_account_nonces()), private_account_keys .iter() - .map(|keys| (keys.npk.clone(), keys.vpk.clone(), keys.epk.clone())) + .map(|keys| (AccountId::account_id_without_identifier(&keys.npk.clone()), keys.vpk.clone(), keys.epk.clone())) .collect(), output, ) @@ -484,7 +484,7 @@ impl WalletCore { let affected_accounts = private_account_key_chains .flat_map(|(acc_account_id, key_chain, index)| { let view_tag = EncryptedAccountData::compute_view_tag( - &key_chain.nullifier_public_key, + &AccountId::account_id_without_identifier(&key_chain.nullifier_public_key), &key_chain.viewing_public_key, );