diff --git a/integration_tests/tests/account.rs b/integration_tests/tests/account.rs index 3d5854cf..3490b42b 100644 --- a/integration_tests/tests/account.rs +++ b/integration_tests/tests/account.rs @@ -156,7 +156,11 @@ async fn import_private_account() -> Result<()> { let mut ctx = TestContext::new().await?; let key_chain = KeyChain::new_os_random(); - let account_id = lee::AccountId::from((&key_chain.nullifier_public_key, 0)); + let account_id = lee::AccountId::from(( + &key_chain.nullifier_public_key, + &key_chain.viewing_public_key, + 0, + )); let account = lee::Account { program_owner: Program::authenticated_transfer_program().id(), balance: 777, @@ -213,7 +217,11 @@ async fn import_private_account_second_time_overrides_account_data() -> Result<( let mut ctx = TestContext::new().await?; let key_chain = KeyChain::new_os_random(); - let account_id = lee::AccountId::from((&key_chain.nullifier_public_key, 0)); + let account_id = lee::AccountId::from(( + &key_chain.nullifier_public_key, + &key_chain.viewing_public_key, + 0, + )); let key_chain_json = serde_json::to_string(&key_chain).context("Failed to serialize key chain")?; diff --git a/integration_tests/tests/auth_transfer/private.rs b/integration_tests/tests/auth_transfer/private.rs index 45a1b085..1e29cbb8 100644 --- a/integration_tests/tests/auth_transfer/private.rs +++ b/integration_tests/tests/auth_transfer/private.rs @@ -7,13 +7,12 @@ use integration_tests::{ public_mention, verify_commitment_is_in_state, }; use lee::{ - AccountId, SharedSecretKey, execute_and_prove, - privacy_preserving_transaction::circuit::ProgramWithDependencies, program::Program, + AccountId, execute_and_prove, privacy_preserving_transaction::circuit::ProgramWithDependencies, + program::Program, }; use lee_core::{ - EncryptedAccountData, InputAccountIdentity, NullifierPublicKey, - account::AccountWithMetadata, - encryption::{EphemeralPublicKey, ViewingPublicKey}, + InputAccountIdentity, NullifierPublicKey, account::AccountWithMetadata, + encryption::ViewingPublicKey, }; use log::info; use sequencer_service_rpc::RpcClient as _; @@ -600,14 +599,14 @@ async fn shielded_transfers_to_two_identifiers_same_npk() -> Result<()> { .await?; // Both accounts must be discovered with the correct balances. - let account_id_1 = AccountId::for_regular_private_account(&npk, identifier_1); + let account_id_1 = AccountId::for_regular_private_account(&npk, &vpk, identifier_1); let acc_1 = ctx .wallet() .get_account_private(account_id_1) .context("account for identifier 1 not found after sync")?; assert_eq!(acc_1.balance, 100); - let account_id_2 = AccountId::for_regular_private_account(&npk, identifier_2); + let account_id_2 = AccountId::for_regular_private_account(&npk, &vpk, identifier_2); let acc_2 = ctx .wallet() .get_account_private(account_id_2) @@ -666,11 +665,9 @@ async fn ppt_cant_chain_call_faucet() -> Result<()> { let nsk: lee_core::NullifierSecretKey = [3; 32]; let npk = NullifierPublicKey::from(&nsk); let vpk = ViewingPublicKey::from_bytes(vec![4_u8; 1184]).unwrap(); - let ssk = SharedSecretKey([55_u8; 32]); - let epk = EphemeralPublicKey(vec![55_u8; 1088]); let attacker_vault_id = { let seed = vault_core::compute_vault_seed(attacker_id); - AccountId::for_private_pda(&vault_program_id, &seed, &npk, 1337) + AccountId::for_private_pda(&vault_program_id, &seed, &npk, &vpk, 1337) }; let amount: u128 = 1; @@ -712,10 +709,9 @@ async fn ppt_cant_chain_call_faucet() -> Result<()> { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivatePdaInit { - epk, - view_tag: EncryptedAccountData::compute_view_tag(&npk, &vpk), + vpk, + esk: [0; 32], npk, - ssk, identifier: 1337, seed: None, }, diff --git a/integration_tests/tests/private_pda.rs b/integration_tests/tests/private_pda.rs index f96faa52..2cb8de88 100644 --- a/integration_tests/tests/private_pda.rs +++ b/integration_tests/tests/private_pda.rs @@ -12,7 +12,6 @@ use integration_tests::{ LEE_PROGRAM_FOR_TEST_PDA_SPEND_PROXY, TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, verify_commitment_is_in_state, }; -use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder; use lee::{ AccountId, PrivacyPreservingTransaction, ProgramId, privacy_preserving_transaction::{ @@ -23,7 +22,7 @@ use lee::{ program::Program, }; use lee_core::{ - EncryptedAccountData, InputAccountIdentity, NullifierPublicKey, + InputAccountIdentity, NullifierPublicKey, account::{Account, AccountWithMetadata}, encryption::ViewingPublicKey, program::PdaSeed, @@ -52,7 +51,8 @@ async fn fund_private_pda( amount: u128, auth_transfer: &ProgramWithDependencies, ) -> Result<()> { - let pda_account_id = AccountId::for_private_pda(&authority_program_id, &seed, &npk, identifier); + let pda_account_id = + AccountId::for_private_pda(&authority_program_id, &seed, &npk, &vpk, identifier); let sender_account = wallet .get_account_public(sender) .await @@ -64,20 +64,15 @@ async fn fund_private_pda( let sender_pre = AccountWithMetadata::new(sender_account.clone(), true, sender); let pda_pre = AccountWithMetadata::new(Account::default(), false, pda_account_id); - let eph_holder = EphemeralKeyHolder::new(&vpk); - let ssk = eph_holder.calculate_shared_secret_sender(); - let epk = eph_holder.ephemeral_public_key().clone(); - let instruction = Program::serialize_instruction(AuthTransferInstruction::Transfer { amount }) .context("failed to serialize auth_transfer instruction")?; let account_identities = vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivatePdaInit { - epk, - view_tag: EncryptedAccountData::compute_view_tag(&npk, &vpk), + vpk, + esk: [0; 32], npk, - ssk, identifier, seed: Some((seed, authority_program_id)), }, @@ -182,8 +177,8 @@ async fn private_pda_family_members_receive_and_spend() -> Result<()> { let spend_program = ProgramWithDependencies::new(proxy, [(auth_transfer_id, auth_transfer)].into()); - let alice_pda_0_id = AccountId::for_private_pda(&proxy_id, &seed, &alice_npk, 0); - let alice_pda_1_id = AccountId::for_private_pda(&proxy_id, &seed, &alice_npk, 1); + let alice_pda_0_id = AccountId::for_private_pda(&proxy_id, &seed, &alice_npk, &alice_vpk, 0); + let alice_pda_1_id = AccountId::for_private_pda(&proxy_id, &seed, &alice_npk, &alice_vpk, 1); // Use two different public senders to avoid nonce conflicts between the back-to-back txs. let senders = ctx.existing_public_accounts(); diff --git a/integration_tests/tests/tps.rs b/integration_tests/tests/tps.rs index 459f3d61..ae99896c 100644 --- a/integration_tests/tests/tps.rs +++ b/integration_tests/tests/tps.rs @@ -15,7 +15,6 @@ use anyhow::{Context as _, Result}; use bytesize::ByteSize; use common::transaction::LeeTransaction; use integration_tests::{TestContext, config::SequencerPartialConfig}; -use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder; use lee::{ Account, AccountId, PrivacyPreservingTransaction, PrivateKey, PublicKey, PublicTransaction, privacy_preserving_transaction::{self as pptx, circuit}, @@ -23,7 +22,7 @@ use lee::{ public_transaction as putx, }; use lee_core::{ - EncryptedAccountData, InputAccountIdentity, MembershipProof, NullifierPublicKey, + InputAccountIdentity, MembershipProof, NullifierPublicKey, account::{AccountWithMetadata, Nonce, data::Data}, encryption::ViewingPublicKey, }; @@ -266,7 +265,7 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction { data: Data::default(), }, true, - AccountId::for_regular_private_account(&sender_npk, 0), + AccountId::for_regular_private_account(&sender_npk, &sender_vpk, 0), ); let recipient_nsk = [2; 32]; let recipient_vpk = ViewingPublicKey::from_seed(&[101_u8; 32], &[102_u8; 32]); @@ -274,17 +273,9 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction { let recipient_pre = AccountWithMetadata::new( Account::default(), false, - AccountId::for_regular_private_account(&recipient_npk, 0), + AccountId::for_regular_private_account(&recipient_npk, &recipient_vpk, 0), ); - let eph_holder_from = EphemeralKeyHolder::new(&sender_vpk); - let sender_ss = eph_holder_from.calculate_shared_secret_sender(); - let sender_epk = eph_holder_from.ephemeral_public_key().clone(); - - let eph_holder_to = EphemeralKeyHolder::new(&recipient_vpk); - let recipient_ss = eph_holder_to.calculate_shared_secret_sender(); - let recipient_epk = eph_holder_to.ephemeral_public_key().clone(); - let balance_to_move: u128 = 1; let proof: MembershipProof = ( 1, @@ -301,18 +292,16 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction { .unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: sender_epk, - view_tag: EncryptedAccountData::compute_view_tag(&sender_npk, &sender_vpk), - ssk: sender_ss, + vpk: sender_vpk, + esk: [0; 32], nsk: sender_nsk, membership_proof: proof, identifier: 0, }, InputAccountIdentity::PrivateUnauthorized { - epk: recipient_epk, - view_tag: EncryptedAccountData::compute_view_tag(&recipient_npk, &recipient_vpk), + vpk: recipient_vpk, + esk: [0; 32], npk: recipient_npk, - ssk: recipient_ss, identifier: 0, }, ], diff --git a/integration_tests/tests/wallet_ffi.rs b/integration_tests/tests/wallet_ffi.rs index 24f2a9c8..a68a3db6 100644 --- a/integration_tests/tests/wallet_ffi.rs +++ b/integration_tests/tests/wallet_ffi.rs @@ -907,7 +907,11 @@ fn test_wallet_ffi_transfer_shielded() -> Result<()> { let (to, to_keys) = unsafe { let mut out_keys = FfiPrivateAccountKeys::default(); wallet_ffi_create_private_accounts_key(wallet_ffi_handle, &raw mut out_keys).unwrap(); - let account_id = lee::AccountId::for_regular_private_account(&out_keys.npk(), 0_u128); + let account_id = lee::AccountId::for_regular_private_account( + &out_keys.npk(), + &out_keys.vpk().unwrap(), + 0_u128, + ); let to: FfiBytes32 = account_id.into(); (to, out_keys) }; @@ -1044,7 +1048,11 @@ fn test_wallet_ffi_transfer_private() -> Result<()> { let (to, to_keys) = unsafe { let mut out_keys = FfiPrivateAccountKeys::default(); wallet_ffi_create_private_accounts_key(wallet_ffi_handle, &raw mut out_keys).unwrap(); - let account_id = lee::AccountId::for_regular_private_account(&out_keys.npk(), 0_u128); + let account_id = lee::AccountId::for_regular_private_account( + &out_keys.npk(), + &out_keys.vpk().unwrap(), + 0_u128, + ); let to: FfiBytes32 = account_id.into(); (to, out_keys) }; diff --git a/lee/key_protocol/src/key_management/group_key_holder.rs b/lee/key_protocol/src/key_management/group_key_holder.rs index 7fb24713..7bb94792 100644 --- a/lee/key_protocol/src/key_management/group_key_holder.rs +++ b/lee/key_protocol/src/key_management/group_key_holder.rs @@ -334,10 +334,10 @@ mod tests { let program_id: ProgramId = [9; 8]; let holder = GroupKeyHolder::from_gms(gms); - let npk = holder - .derive_keys_for_pda(&TEST_PROGRAM_ID, &seed) - .generate_nullifier_public_key(); - let account_id = AccountId::for_private_pda(&program_id, &seed, &npk, u128::MAX); + let keys = holder.derive_keys_for_pda(&TEST_PROGRAM_ID, &seed); + let npk = keys.generate_nullifier_public_key(); + let vpk = keys.generate_viewing_public_key(); + let account_id = AccountId::for_private_pda(&program_id, &seed, &npk, &vpk, u128::MAX); let expected_npk = NullifierPublicKey([ 136, 176, 234, 71, 208, 8, 143, 142, 126, 155, 132, 18, 71, 27, 88, 56, 100, 90, 79, @@ -346,7 +346,7 @@ mod tests { // AccountId is derived from (program_id, seed, npk), so it changes when npk changes. // We verify npk is pinned, and AccountId is deterministically derived from it. let expected_account_id = - AccountId::for_private_pda(&program_id, &seed, &expected_npk, u128::MAX); + AccountId::for_private_pda(&program_id, &seed, &expected_npk, &vpk, u128::MAX); assert_eq!(npk, expected_npk); assert_eq!(account_id, expected_account_id); @@ -543,13 +543,16 @@ mod tests { let bob_holder = GroupKeyHolder::unseal(&sealed, &bob_vsk).expect("Bob should unseal the GMS"); - let bob_npk = bob_holder - .derive_keys_for_pda(&TEST_PROGRAM_ID, &pda_seed) - .generate_nullifier_public_key(); + let bob_group_keys = bob_holder.derive_keys_for_pda(&TEST_PROGRAM_ID, &pda_seed); + let bob_npk = bob_group_keys.generate_nullifier_public_key(); assert_eq!(alice_npk, bob_npk); - let alice_account_id = AccountId::for_private_pda(&program_id, &pda_seed, &alice_npk, 0); - let bob_account_id = AccountId::for_private_pda(&program_id, &pda_seed, &bob_npk, 0); + let alice_vpk = alice_keys.generate_viewing_public_key(); + let bob_group_vpk = bob_group_keys.generate_viewing_public_key(); + let alice_account_id = + AccountId::for_private_pda(&program_id, &pda_seed, &alice_npk, &alice_vpk, 0); + let bob_account_id = + AccountId::for_private_pda(&program_id, &pda_seed, &bob_npk, &bob_group_vpk, 0); assert_eq!(alice_account_id, bob_account_id); } diff --git a/lee/key_protocol/src/key_management/key_tree/keys_private.rs b/lee/key_protocol/src/key_management/key_tree/keys_private.rs index 5a27be79..b33733fb 100644 --- a/lee/key_protocol/src/key_management/key_tree/keys_private.rs +++ b/lee/key_protocol/src/key_management/key_tree/keys_private.rs @@ -123,10 +123,11 @@ impl KeyTreeNode for ChildKeysPrivate { fn account_ids(&self) -> impl Iterator { let npk = self.value.0.nullifier_public_key; + let vpk = self.value.0.viewing_public_key.clone(); self.value .1 .keys() - .map(move |kind| lee::AccountId::for_private_account(&npk, kind)) + .map(move |kind| lee::AccountId::for_private_account(&npk, &vpk, kind)) } } diff --git a/lee/key_protocol/src/key_management/key_tree/mod.rs b/lee/key_protocol/src/key_management/key_tree/mod.rs index c15c09a5..e7d490d2 100644 --- a/lee/key_protocol/src/key_management/key_tree/mod.rs +++ b/lee/key_protocol/src/key_management/key_tree/mod.rs @@ -277,6 +277,7 @@ impl KeyTree { let node = self.key_map.get(cci)?; let account_id = lee::AccountId::for_regular_private_account( &node.value.0.nullifier_public_key, + &node.value.0.viewing_public_key, identifier, ); if self.account_id_map.contains_key(&account_id) { diff --git a/lee/state_machine/core/src/encryption/mod.rs b/lee/state_machine/core/src/encryption/mod.rs index 34c596af..d2d312fe 100644 --- a/lee/state_machine/core/src/encryption/mod.rs +++ b/lee/state_machine/core/src/encryption/mod.rs @@ -80,16 +80,6 @@ impl EncryptedAccountData { view_tag, } } - - /// Computes the tag as the first byte of SHA256("/LEE/v0.3/ViewTag/" || npk || vpk). - #[must_use] - pub fn compute_view_tag(npk: &crate::NullifierPublicKey, vpk: &ViewingPublicKey) -> ViewTag { - let mut bytes = Vec::new(); - bytes.extend_from_slice(b"/LEE/v0.3/ViewTag/"); - bytes.extend_from_slice(&npk.to_byte_array()); - bytes.extend_from_slice(vpk.to_bytes()); - Impl::hash_bytes(&bytes).as_bytes()[0] - } } impl EncryptionScheme { diff --git a/lee/state_machine/core/src/lib.rs b/lee/state_machine/core/src/lib.rs index 9ad2858e..c5d42ac9 100644 --- a/lee/state_machine/core/src/lib.rs +++ b/lee/state_machine/core/src/lib.rs @@ -11,7 +11,8 @@ pub use commitment::{ compute_digest_for_path, }; pub use encryption::{ - EncryptedAccountData, EncryptionScheme, EphemeralPublicKey, SharedSecretKey, ViewTag, + EncryptedAccountData, EncryptionScheme, EphemeralPublicKey, EphemeralSecretKey, + SharedSecretKey, ViewTag, }; pub use nullifier::{Identifier, Nullifier, NullifierPublicKey, NullifierSecretKey}; pub use program::PrivateAccountKind; diff --git a/lee/state_machine/src/privacy_preserving_transaction/circuit.rs b/lee/state_machine/src/privacy_preserving_transaction/circuit.rs index 87c7c5bb..ae666e61 100644 --- a/lee/state_machine/src/privacy_preserving_transaction/circuit.rs +++ b/lee/state_machine/src/privacy_preserving_transaction/circuit.rs @@ -178,8 +178,8 @@ mod tests { #![expect(clippy::shadow_unrelated, reason = "We don't care about it in tests")] use lee_core::{ - Commitment, DUMMY_COMMITMENT_HASH, EncryptedAccountData, EncryptionScheme, - EphemeralPublicKey, Nullifier, PrivacyPreservingCircuitOutput, SharedSecretKey, + Commitment, DUMMY_COMMITMENT_HASH, EncryptionScheme, Nullifier, + PrivacyPreservingCircuitOutput, SharedSecretKey, account::{Account, AccountId, AccountWithMetadata, Nonce, data::Data}, program::{PdaSeed, PrivateAccountKind}, }; @@ -235,7 +235,8 @@ mod tests { AccountId::new([0; 32]), ); - let recipient_account_id = AccountId::for_regular_private_account(&recipient_keys.npk(), 0); + let recipient_account_id = + AccountId::for_regular_private_account(&recipient_keys.npk(), &recipient_keys.vpk(), 0); let recipient = AccountWithMetadata::new(Account::default(), false, recipient_account_id); let balance_to_move: u128 = 37; @@ -268,13 +269,9 @@ mod tests { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: shared_secret, identifier: 0, }, ], @@ -317,12 +314,14 @@ mod tests { data: Data::default(), }, true, - AccountId::for_regular_private_account(&sender_keys.npk(), 0), + AccountId::for_regular_private_account(&sender_keys.npk(), &sender_keys.vpk(), 0), ); - let sender_account_id = AccountId::for_regular_private_account(&sender_keys.npk(), 0); + let sender_account_id = + AccountId::for_regular_private_account(&sender_keys.npk(), &sender_keys.vpk(), 0); let commitment_sender = Commitment::new(&sender_account_id, &sender_pre.account); - let recipient_account_id = AccountId::for_regular_private_account(&recipient_keys.npk(), 0); + let recipient_account_id = + AccountId::for_regular_private_account(&recipient_keys.npk(), &recipient_keys.vpk(), 0); let recipient = AccountWithMetadata::new(Account::default(), false, recipient_account_id); let balance_to_move: u128 = 37; @@ -372,12 +371,8 @@ mod tests { .unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: shared_secret_1, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: commitment_set .get_proof_for(&commitment_sender) @@ -385,13 +380,9 @@ mod tests { identifier: 0, }, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: shared_secret_2, identifier: 0, }, ], @@ -431,7 +422,7 @@ mod tests { let pre = AccountWithMetadata::new( Account::default(), false, - AccountId::for_regular_private_account(&account_keys.npk(), 0), + AccountId::for_regular_private_account(&account_keys.npk(), &account_keys.vpk(), 0), ); let validity_window_chain_caller = Program::validity_window_chain_caller(); @@ -446,9 +437,6 @@ mod tests { )) .unwrap(); - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&account_keys.vpk(), &[0_u8; 32], 0).0; - let program_with_deps = ProgramWithDependencies::new( validity_window_chain_caller, [(validity_window.id(), validity_window)].into(), @@ -458,13 +446,9 @@ mod tests { vec![pre], instruction, vec![InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &account_keys.npk(), - &account_keys.vpk(), - ), + vpk: account_keys.vpk(), + esk: [0; 32], npk: account_keys.npk(), - ssk: shared_secret, identifier: 0, }], &program_with_deps, @@ -485,17 +469,17 @@ mod tests { let shared_secret = SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; - let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk, identifier); + let account_id = + AccountId::for_private_pda(&program.id(), &seed, &npk, &keys.vpk(), identifier); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let (output, _proof) = execute_and_prove( vec![pre_state], Program::serialize_instruction(seed).unwrap(), vec![InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk, - ssk: shared_secret, identifier, seed: None, }], @@ -523,11 +507,9 @@ mod tests { let keys = test_private_account_keys_1(); let npk = keys.npk(); let seed = PdaSeed::new([42; 32]); - let shared_secret_pda = - SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; // PDA (new, private PDA) - let pda_id = AccountId::for_private_pda(&program.id(), &seed, &npk, 0); + let pda_id = AccountId::for_private_pda(&program.id(), &seed, &npk, &keys.vpk(), 0); let pda_pre = AccountWithMetadata::new(Account::default(), false, pda_id); let auth_id = auth_transfer.id(); @@ -541,10 +523,9 @@ mod tests { vec![pda_pre], instruction, vec![InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk, - ssk: shared_secret_pda, identifier: 0, seed: None, }], @@ -565,11 +546,9 @@ mod tests { let keys = test_private_account_keys_1(); let npk = keys.npk(); let seed = PdaSeed::new([42; 32]); - let shared_secret_pda = - SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; // PDA (new, private PDA) - let pda_id = AccountId::for_private_pda(&program.id(), &seed, &npk, 0); + let pda_id = AccountId::for_private_pda(&program.id(), &seed, &npk, &keys.vpk(), 0); let pda_pre = AccountWithMetadata::new(Account::default(), false, pda_id); // Recipient (public) @@ -596,10 +575,9 @@ mod tests { instruction, vec![ InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk, - ssk: shared_secret_pda, identifier: 0, seed: None, }, @@ -623,8 +601,6 @@ mod tests { let shared_keys = test_private_account_keys_1(); let shared_npk = shared_keys.npk(); let shared_identifier: u128 = 42; - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&shared_keys.vpk(), &[0_u8; 32], 0).0; // Sender: public account with balance, owned by auth-transfer let sender_id = AccountId::new([99; 32]); @@ -639,7 +615,8 @@ mod tests { ); // Recipient: shared private account (new, unauthorized) - let shared_account_id = AccountId::from((&shared_npk, shared_identifier)); + let shared_account_id = + AccountId::from((&shared_npk, &shared_keys.vpk(), shared_identifier)); let recipient = AccountWithMetadata::new(Account::default(), false, shared_account_id); let balance_to_move: u128 = 100; @@ -655,13 +632,9 @@ mod tests { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &shared_npk, - &shared_keys.vpk(), - ), + vpk: shared_keys.vpk(), + esk: [0; 32], npk: shared_npk, - ssk: shared_secret, identifier: shared_identifier, }, ], @@ -681,7 +654,8 @@ mod tests { let keys = test_private_account_keys_1(); let identifier: u128 = 99; let ssk = SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; - let account_id = AccountId::for_regular_private_account(&keys.npk(), identifier); + let account_id = + AccountId::for_regular_private_account(&keys.npk(), &keys.vpk(), identifier); let pre = AccountWithMetadata::new(Account::default(), true, account_id); let (output, _) = execute_and_prove( @@ -689,9 +663,8 @@ mod tests { Program::serialize_instruction(authenticated_transfer_core::Instruction::Initialize) .unwrap(), vec![InputAccountIdentity::PrivateAuthorizedInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&keys.npk(), &keys.vpk()), - ssk, + vpk: keys.vpk(), + esk: [0; 32], nsk: keys.nsk, identifier, }], @@ -723,7 +696,8 @@ mod tests { true, AccountId::new([0; 32]), ); - let recipient_id = AccountId::for_regular_private_account(&keys.npk(), identifier); + let recipient_id = + AccountId::for_regular_private_account(&keys.npk(), &keys.vpk(), identifier); let recipient = AccountWithMetadata::new(Account::default(), false, recipient_id); let (output, _) = execute_and_prove( @@ -735,10 +709,9 @@ mod tests { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&keys.npk(), &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk: keys.npk(), - ssk, identifier, }, ], @@ -760,7 +733,8 @@ mod tests { let keys = test_private_account_keys_1(); let identifier: u128 = 99; let ssk = SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; - let account_id = AccountId::for_regular_private_account(&keys.npk(), identifier); + let account_id = + AccountId::for_regular_private_account(&keys.npk(), &keys.vpk(), identifier); let account = Account { program_owner: program.id(), balance: 1, @@ -781,9 +755,8 @@ mod tests { .unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&keys.npk(), &keys.vpk()), - ssk, + vpk: keys.vpk(), + esk: [0; 32], nsk: keys.nsk, membership_proof: commitment_set.get_proof_for(&commitment).unwrap(), identifier, @@ -813,7 +786,8 @@ mod tests { let ssk = SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; let auth_transfer_id = auth_transfer.id(); - let pda_id = AccountId::for_private_pda(&program.id(), &seed, &npk, identifier); + let pda_id = + AccountId::for_private_pda(&program.id(), &seed, &npk, &keys.vpk(), identifier); let pda_account = Account { program_owner: auth_transfer_id, balance: 1, @@ -837,9 +811,8 @@ mod tests { Program::serialize_instruction((seed, 1_u128, auth_transfer_id, false)).unwrap(), vec![ InputAccountIdentity::PrivatePdaUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), - ssk, + vpk: keys.vpk(), + esk: [0; 32], nsk: keys.nsk, membership_proof: commitment_set.get_proof_for(&pda_commitment).unwrap(), identifier, @@ -867,20 +840,16 @@ mod tests { let keys = test_private_account_keys_1(); let npk = keys.npk(); let seed = PdaSeed::new([42; 32]); - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; - - let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk, 5); + let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk, &keys.vpk(), 5); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let result = execute_and_prove( vec![pre_state], Program::serialize_instruction(seed).unwrap(), vec![InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk, - ssk: shared_secret, identifier: 99, seed: None, }], @@ -897,10 +866,8 @@ mod tests { let keys = test_private_account_keys_1(); let npk = keys.npk(); let seed = PdaSeed::new([42; 32]); - let ssk = SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; - let auth_transfer_id = auth_transfer.id(); - let pda_id = AccountId::for_private_pda(&program.id(), &seed, &npk, 5); + let pda_id = AccountId::for_private_pda(&program.id(), &seed, &npk, &keys.vpk(), 5); let pda_account = Account { program_owner: auth_transfer_id, balance: 1, @@ -922,9 +889,8 @@ mod tests { Program::serialize_instruction((seed, 1_u128, auth_transfer_id, false)).unwrap(), vec![ InputAccountIdentity::PrivatePdaUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), - ssk, + vpk: keys.vpk(), + esk: [0; 32], nsk: keys.nsk, membership_proof: commitment_set.get_proof_for(&pda_commitment).unwrap(), identifier: 99, diff --git a/lee/state_machine/src/privacy_preserving_transaction/message.rs b/lee/state_machine/src/privacy_preserving_transaction/message.rs index b2594912..ae33b71c 100644 --- a/lee/state_machine/src/privacy_preserving_transaction/message.rs +++ b/lee/state_machine/src/privacy_preserving_transaction/message.rs @@ -109,6 +109,7 @@ pub mod tests { let npk1 = NullifierPublicKey::from(&nsk1); let npk2 = NullifierPublicKey::from(&nsk2); + let vpk = ViewingPublicKey::from_seed(&[7; 32], &[8; 32]); let public_account_ids = vec![AccountId::new([1; 32])]; @@ -118,10 +119,10 @@ pub mod tests { let encrypted_private_post_states = Vec::new(); - let account_id2 = lee_core::account::AccountId::for_regular_private_account(&npk2, 0); + let account_id2 = lee_core::account::AccountId::for_regular_private_account(&npk2, &vpk, 0); let new_commitments = vec![Commitment::new(&account_id2, &account2)]; - let account_id1 = lee_core::account::AccountId::for_regular_private_account(&npk1, 0); + let account_id1 = lee_core::account::AccountId::for_regular_private_account(&npk1, &vpk, 0); let old_commitment = Commitment::new(&account_id1, &account1); let new_nullifiers = vec![( Nullifier::for_account_update(&old_commitment, &nsk1), @@ -197,7 +198,7 @@ pub mod tests { let npk = NullifierPublicKey::from(&[1; 32]); let vpk = ViewingPublicKey::from_seed(&[2_u8; 32], &[3_u8; 32]); let account = Account::default(); - let account_id = lee_core::account::AccountId::for_regular_private_account(&npk, 0); + let account_id = lee_core::account::AccountId::for_regular_private_account(&npk, &vpk, 0); let commitment = Commitment::new(&account_id, &account); let (shared_secret, epk) = SharedSecretKey::encapsulate_deterministic(&vpk, &[0_u8; 32], 0); let ciphertext = EncryptionScheme::encrypt( diff --git a/lee/state_machine/src/state.rs b/lee/state_machine/src/state.rs index c7152917..4132b2ed 100644 --- a/lee/state_machine/src/state.rs +++ b/lee/state_machine/src/state.rs @@ -418,10 +418,10 @@ pub mod tests { use authenticated_transfer_core::Instruction as AuthTransferInstruction; use lee_core::{ - BlockId, Commitment, EncryptedAccountData, InputAccountIdentity, Nullifier, - NullifierPublicKey, NullifierSecretKey, SharedSecretKey, Timestamp, + BlockId, Commitment, InputAccountIdentity, Nullifier, NullifierPublicKey, + NullifierSecretKey, Timestamp, account::{Account, AccountId, AccountWithMetadata, Nonce, data::Data}, - encryption::{EphemeralPublicKey, ViewingPublicKey}, + encryption::ViewingPublicKey, program::{ BlockValidityWindow, ExecutionValidationError, PdaSeed, ProgramId, TimestampValidityWindow, WrappedBalanceSum, @@ -517,7 +517,7 @@ pub mod tests { #[must_use] pub fn with_private_account(mut self, keys: &TestPrivateKeys, account: &Account) -> Self { - let account_id = AccountId::for_regular_private_account(&keys.npk(), 0); + let account_id = AccountId::for_regular_private_account(&keys.npk(), &keys.vpk(), 0); let commitment = Commitment::new(&account_id, account); self.private_state.0.extend(&[commitment]); self @@ -729,8 +729,8 @@ pub mod tests { ..Account::default() }; - let account_id1 = AccountId::for_regular_private_account(&keys1.npk(), 0); - let account_id2 = AccountId::for_regular_private_account(&keys2.npk(), 0); + let account_id1 = AccountId::for_regular_private_account(&keys1.npk(), &keys1.vpk(), 0); + let account_id2 = AccountId::for_regular_private_account(&keys2.npk(), &keys2.vpk(), 0); let init_commitment1 = Commitment::new(&account_id1, &account); let init_commitment2 = Commitment::new(&account_id2, &account); @@ -1403,11 +1403,11 @@ pub mod tests { let sender_nonce = sender.account.nonce; - let recipient = - AccountWithMetadata::new(Account::default(), false, (&recipient_keys.npk(), 0)); - - let (shared_secret, epk) = - SharedSecretKey::encapsulate_deterministic(&recipient_keys.vpk(), &[0_u8; 32], 0); + let recipient = AccountWithMetadata::new( + Account::default(), + false, + (&recipient_keys.npk(), &recipient_keys.vpk(), 0), + ); let (output, proof) = circuit::execute_and_prove( vec![sender, recipient], @@ -1418,13 +1418,9 @@ pub mod tests { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivateUnauthorized { - epk, - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: shared_secret, identifier: 0, }, ], @@ -1451,21 +1447,19 @@ pub mod tests { state: &V03State, ) -> PrivacyPreservingTransaction { let program = Program::authenticated_transfer_program(); - let sender_account_id = AccountId::for_regular_private_account(&sender_keys.npk(), 0); + let sender_account_id = + AccountId::for_regular_private_account(&sender_keys.npk(), &sender_keys.vpk(), 0); let sender_commitment = Commitment::new(&sender_account_id, sender_private_account); let sender_pre = AccountWithMetadata::new( sender_private_account.clone(), true, - (&sender_keys.npk(), 0), + (&sender_keys.npk(), &sender_keys.vpk(), 0), + ); + let recipient_pre = AccountWithMetadata::new( + Account::default(), + false, + (&recipient_keys.npk(), &recipient_keys.vpk(), 0), ); - let recipient_pre = - AccountWithMetadata::new(Account::default(), false, (&recipient_keys.npk(), 0)); - - let (shared_secret_1, epk_1) = - SharedSecretKey::encapsulate_deterministic(&sender_keys.vpk(), &[0_u8; 32], 0); - - let (shared_secret_2, epk_2) = - SharedSecretKey::encapsulate_deterministic(&recipient_keys.vpk(), &[0_u8; 32], 1); let (output, proof) = circuit::execute_and_prove( vec![sender_pre, recipient_pre], @@ -1475,12 +1469,8 @@ pub mod tests { .unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: epk_1, - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: shared_secret_1, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: state .get_proof_for_commitment(&sender_commitment) @@ -1488,13 +1478,9 @@ pub mod tests { identifier: 0, }, InputAccountIdentity::PrivateUnauthorized { - epk: epk_2, - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: shared_secret_2, identifier: 0, }, ], @@ -1517,12 +1503,13 @@ pub mod tests { state: &V03State, ) -> PrivacyPreservingTransaction { let program = Program::authenticated_transfer_program(); - let sender_account_id = AccountId::for_regular_private_account(&sender_keys.npk(), 0); + let sender_account_id = + AccountId::for_regular_private_account(&sender_keys.npk(), &sender_keys.vpk(), 0); let sender_commitment = Commitment::new(&sender_account_id, sender_private_account); let sender_pre = AccountWithMetadata::new( sender_private_account.clone(), true, - (&sender_keys.npk(), 0), + (&sender_keys.npk(), &sender_keys.vpk(), 0), ); let recipient_pre = AccountWithMetadata::new( state.get_account_by_id(*recipient_account_id), @@ -1530,9 +1517,6 @@ pub mod tests { *recipient_account_id, ); - let (shared_secret, epk) = - SharedSecretKey::encapsulate_deterministic(&sender_keys.vpk(), &[0_u8; 32], 0); - let (output, proof) = circuit::execute_and_prove( vec![sender_pre, recipient_pre], Program::serialize_instruction(AuthTransferInstruction::Transfer { @@ -1541,12 +1525,8 @@ pub mod tests { .unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk, - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: shared_secret, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: state .get_proof_for_commitment(&sender_commitment) @@ -1634,8 +1614,10 @@ pub mod tests { &state, ); - let sender_account_id = AccountId::for_regular_private_account(&sender_keys.npk(), 0); - let recipient_account_id = AccountId::for_regular_private_account(&recipient_keys.npk(), 0); + let sender_account_id = + AccountId::for_regular_private_account(&sender_keys.npk(), &sender_keys.vpk(), 0); + let recipient_account_id = + AccountId::for_regular_private_account(&recipient_keys.npk(), &recipient_keys.vpk(), 0); let expected_new_commitment_1 = Commitment::new( &sender_account_id, &Account { @@ -1786,7 +1768,8 @@ pub mod tests { &state, ); - let sender_account_id = AccountId::for_regular_private_account(&sender_keys.npk(), 0); + let sender_account_id = + AccountId::for_regular_private_account(&sender_keys.npk(), &sender_keys.vpk(), 0); let expected_new_commitment = Commitment::new( &sender_account_id, &Account { @@ -2098,10 +2081,13 @@ pub mod tests { ..Account::default() }, true, - (&sender_keys.npk(), 0), + (&sender_keys.npk(), &sender_keys.vpk(), 0), + ); + let private_account_2 = AccountWithMetadata::new( + Account::default(), + false, + (&recipient_keys.npk(), &recipient_keys.vpk(), 0), ); - let private_account_2 = - AccountWithMetadata::new(Account::default(), false, (&recipient_keys.npk(), 0)); // Setting the recipient nsk to authorize the sender. // This should be set to the sender private account in a normal circumstance. @@ -2112,34 +2098,16 @@ pub mod tests { Program::serialize_instruction(10_u128).unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: SharedSecretKey::encapsulate_deterministic( - &sender_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: recipient_keys.nsk, membership_proof: (0, vec![]), identifier: 0, }, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: SharedSecretKey::encapsulate_deterministic( - &recipient_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, identifier: 0, }, ], @@ -2161,7 +2129,7 @@ pub mod tests { ..Account::default() }, true, - (&sender_keys.npk(), 0), + (&sender_keys.npk(), &sender_keys.vpk(), 0), ); let private_account_2 = AccountWithMetadata::new( Account { @@ -2170,7 +2138,7 @@ pub mod tests { ..Account::default() }, false, - (&recipient_keys.npk(), 0), + (&recipient_keys.npk(), &recipient_keys.vpk(), 0), ); let result = execute_and_prove( @@ -2178,34 +2146,16 @@ pub mod tests { Program::serialize_instruction(10_u128).unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: SharedSecretKey::encapsulate_deterministic( - &sender_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: (0, vec![]), identifier: 0, }, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: SharedSecretKey::encapsulate_deterministic( - &recipient_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, identifier: 0, }, ], @@ -2227,7 +2177,7 @@ pub mod tests { ..Account::default() }, true, - (&sender_keys.npk(), 0), + (&sender_keys.npk(), &sender_keys.vpk(), 0), ); let private_account_2 = AccountWithMetadata::new( Account { @@ -2236,7 +2186,7 @@ pub mod tests { ..Account::default() }, false, - (&recipient_keys.npk(), 0), + (&recipient_keys.npk(), &recipient_keys.vpk(), 0), ); let result = execute_and_prove( @@ -2244,34 +2194,16 @@ pub mod tests { Program::serialize_instruction(10_u128).unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: SharedSecretKey::encapsulate_deterministic( - &sender_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: (0, vec![]), identifier: 0, }, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: SharedSecretKey::encapsulate_deterministic( - &recipient_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, identifier: 0, }, ], @@ -2293,7 +2225,7 @@ pub mod tests { ..Account::default() }, true, - (&sender_keys.npk(), 0), + (&sender_keys.npk(), &sender_keys.vpk(), 0), ); let private_account_2 = AccountWithMetadata::new( Account { @@ -2302,7 +2234,7 @@ pub mod tests { ..Account::default() }, false, - (&recipient_keys.npk(), 0), + (&recipient_keys.npk(), &recipient_keys.vpk(), 0), ); let result = execute_and_prove( @@ -2310,34 +2242,16 @@ pub mod tests { Program::serialize_instruction(10_u128).unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: SharedSecretKey::encapsulate_deterministic( - &sender_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: (0, vec![]), identifier: 0, }, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: SharedSecretKey::encapsulate_deterministic( - &recipient_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, identifier: 0, }, ], @@ -2359,7 +2273,7 @@ pub mod tests { ..Account::default() }, true, - (&sender_keys.npk(), 0), + (&sender_keys.npk(), &sender_keys.vpk(), 0), ); let private_account_2 = AccountWithMetadata::new( Account { @@ -2368,7 +2282,7 @@ pub mod tests { ..Account::default() }, false, - (&recipient_keys.npk(), 0), + (&recipient_keys.npk(), &recipient_keys.vpk(), 0), ); let result = execute_and_prove( @@ -2376,34 +2290,16 @@ pub mod tests { Program::serialize_instruction(10_u128).unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: SharedSecretKey::encapsulate_deterministic( - &sender_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: (0, vec![]), identifier: 0, }, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: SharedSecretKey::encapsulate_deterministic( - &recipient_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, identifier: 0, }, ], @@ -2426,13 +2322,13 @@ pub mod tests { ..Account::default() }, true, - (&sender_keys.npk(), 0), + (&sender_keys.npk(), &sender_keys.vpk(), 0), ); let private_account_2 = AccountWithMetadata::new( Account::default(), // This should be set to false in normal circumstances true, - (&recipient_keys.npk(), 0), + (&recipient_keys.npk(), &recipient_keys.vpk(), 0), ); let result = execute_and_prove( @@ -2440,34 +2336,16 @@ pub mod tests { Program::serialize_instruction(10_u128).unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: SharedSecretKey::encapsulate_deterministic( - &sender_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: (0, vec![]), identifier: 0, }, InputAccountIdentity::PrivateUnauthorized { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), + vpk: recipient_keys.vpk(), + esk: [0; 32], npk: recipient_keys.npk(), - ssk: SharedSecretKey::encapsulate_deterministic( - &recipient_keys.vpk(), - &[0_u8; 32], - 0, - ) - .0, identifier: 0, }, ], @@ -2486,8 +2364,6 @@ pub mod tests { let program = Program::simple_balance_transfer(); let keys = test_private_account_keys_1(); let npk = keys.npk(); - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; let public_account_1 = AccountWithMetadata::new( Account { program_owner: program.id(), @@ -2506,10 +2382,9 @@ pub mod tests { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk, - ssk: shared_secret, identifier: u128::MAX, seed: None, }, @@ -2531,20 +2406,18 @@ pub mod tests { let keys = test_private_account_keys_1(); let npk = keys.npk(); let seed = PdaSeed::new([42; 32]); - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; - let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk, u128::MAX); + let account_id = + AccountId::for_private_pda(&program.id(), &seed, &npk, &keys.vpk(), u128::MAX); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let result = execute_and_prove( vec![pre_state], Program::serialize_instruction(seed).unwrap(), vec![InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk, - ssk: shared_secret, identifier: u128::MAX, seed: None, }], @@ -2571,23 +2444,21 @@ pub mod tests { let npk_a = keys_a.npk(); let npk_b = keys_b.npk(); let seed = PdaSeed::new([42; 32]); - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&keys_b.vpk(), &[0_u8; 32], 0).0; // `account_id` is derived from `npk_a`, but `npk_b` is supplied for this pre_state. // `AccountId::for_private_pda(program, seed, npk_b) != account_id`, so the claim check in // the circuit must reject. - let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk_a, u128::MAX); + let account_id = + AccountId::for_private_pda(&program.id(), &seed, &npk_a, &keys_a.vpk(), u128::MAX); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let result = execute_and_prove( vec![pre_state], Program::serialize_instruction(seed).unwrap(), vec![InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk_b, &keys_b.vpk()), + vpk: keys_b.vpk(), + esk: [0; 32], npk: npk_b, - ssk: shared_secret, identifier: u128::MAX, seed: None, }], @@ -2609,10 +2480,9 @@ pub mod tests { let keys = test_private_account_keys_1(); let npk = keys.npk(); let seed = PdaSeed::new([77; 32]); - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; - let account_id = AccountId::for_private_pda(&delegator.id(), &seed, &npk, u128::MAX); + let account_id = + AccountId::for_private_pda(&delegator.id(), &seed, &npk, &keys.vpk(), u128::MAX); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let callee_id = callee.id(); @@ -2623,10 +2493,9 @@ pub mod tests { vec![pre_state], Program::serialize_instruction((seed, seed, callee_id)).unwrap(), vec![InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk, - ssk: shared_secret, identifier: u128::MAX, seed: None, }], @@ -2651,10 +2520,9 @@ pub mod tests { let npk = keys.npk(); let claim_seed = PdaSeed::new([77; 32]); let wrong_delegated_seed = PdaSeed::new([88; 32]); - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; - let account_id = AccountId::for_private_pda(&delegator.id(), &claim_seed, &npk, u128::MAX); + let account_id = + AccountId::for_private_pda(&delegator.id(), &claim_seed, &npk, &keys.vpk(), u128::MAX); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let callee_id = callee.id(); @@ -2665,10 +2533,9 @@ pub mod tests { vec![pre_state], Program::serialize_instruction((claim_seed, wrong_delegated_seed, callee_id)).unwrap(), vec![InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk, - ssk: shared_secret, identifier: u128::MAX, seed: None, }], @@ -2692,11 +2559,21 @@ pub mod tests { let keys_a = test_private_account_keys_1(); let keys_b = test_private_account_keys_2(); let seed = PdaSeed::new([55; 32]); - let shared_a = SharedSecretKey::encapsulate_deterministic(&keys_a.vpk(), &[0_u8; 32], 0).0; - let shared_b = SharedSecretKey::encapsulate_deterministic(&keys_b.vpk(), &[0_u8; 32], 0).0; - let account_a = AccountId::for_private_pda(&program.id(), &seed, &keys_a.npk(), u128::MAX); - let account_b = AccountId::for_private_pda(&program.id(), &seed, &keys_b.npk(), u128::MAX); + let account_a = AccountId::for_private_pda( + &program.id(), + &seed, + &keys_a.npk(), + &keys_a.vpk(), + u128::MAX, + ); + let account_b = AccountId::for_private_pda( + &program.id(), + &seed, + &keys_b.npk(), + &keys_b.vpk(), + u128::MAX, + ); let pre_a = AccountWithMetadata::new(Account::default(), false, account_a); let pre_b = AccountWithMetadata::new(Account::default(), false, account_b); @@ -2706,18 +2583,16 @@ pub mod tests { Program::serialize_instruction(seed).unwrap(), vec![ InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&keys_a.npk(), &keys_a.vpk()), + vpk: keys_a.vpk(), + esk: [0; 32], npk: keys_a.npk(), - ssk: shared_a, identifier: u128::MAX, seed: None, }, InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&keys_b.npk(), &keys_b.vpk()), + vpk: keys_b.vpk(), + esk: [0; 32], npk: keys_b.npk(), - ssk: shared_b, identifier: u128::MAX, seed: None, }, @@ -2738,13 +2613,12 @@ pub mod tests { let program = Program::noop(); let keys = test_private_account_keys_1(); let npk = keys.npk(); - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&keys.vpk(), &[0_u8; 32], 0).0; let seed = PdaSeed::new([99; 32]); // Simulate a previously-claimed private PDA: program_owner != DEFAULT, is_authorized = // true, account_id derived via the private formula. - let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk, u128::MAX); + let account_id = + AccountId::for_private_pda(&program.id(), &seed, &npk, &keys.vpk(), u128::MAX); let owned_pre_state = AccountWithMetadata::new( Account { program_owner: program.id(), @@ -2758,10 +2632,9 @@ pub mod tests { vec![owned_pre_state], Program::serialize_instruction(()).unwrap(), vec![InputAccountIdentity::PrivatePdaInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag(&npk, &keys.vpk()), + vpk: keys.vpk(), + esk: [0; 32], npk, - ssk: shared_secret, identifier: u128::MAX, seed: None, }], @@ -2838,33 +2711,23 @@ pub mod tests { ..Account::default() }, true, - (&sender_keys.npk(), 0), + (&sender_keys.npk(), &sender_keys.vpk(), 0), ); - let shared_secret = - SharedSecretKey::encapsulate_deterministic(&sender_keys.vpk(), &[0_u8; 32], 0).0; let result = execute_and_prove( vec![private_account_1.clone(), private_account_1], Program::serialize_instruction(100_u128).unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: shared_secret, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: (1, vec![]), identifier: 0, }, InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: shared_secret, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: (1, vec![]), identifier: 0, @@ -3181,7 +3044,8 @@ pub mod tests { balance: 100, ..Account::default() }; - let sender_account_id = AccountId::for_regular_private_account(&sender_keys.npk(), 0); + let sender_account_id = + AccountId::for_regular_private_account(&sender_keys.npk(), &sender_keys.vpk(), 0); let sender_commitment = Commitment::new(&sender_account_id, &sender_private_account); let sender_init_nullifier = Nullifier::for_account_initialization(&sender_account_id); let mut state = V03State::new_with_genesis_accounts( @@ -3189,15 +3053,16 @@ pub mod tests { vec![(sender_commitment.clone(), sender_init_nullifier)], 0, ); - let sender_pre = - AccountWithMetadata::new(sender_private_account, true, (&sender_keys.npk(), 0)); + let sender_pre = AccountWithMetadata::new( + sender_private_account, + true, + (&sender_keys.npk(), &sender_keys.vpk(), 0), + ); let recipient_private_key = PrivateKey::try_new([2; 32]).unwrap(); let recipient_account_id = AccountId::from(&PublicKey::new_from_private_key(&recipient_private_key)); let recipient_pre = AccountWithMetadata::new(Account::default(), true, recipient_account_id); - let (shared_secret, epk) = - SharedSecretKey::encapsulate_deterministic(&sender_keys.vpk(), &[0_u8; 32], 0); let balance = 37; @@ -3209,12 +3074,8 @@ pub mod tests { .unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk, - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: shared_secret, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: state .get_proof_for_commitment(&sender_commitment) @@ -3268,7 +3129,7 @@ pub mod tests { ..Account::default() }, true, - (&from_keys.npk(), 0), + (&from_keys.npk(), &from_keys.vpk(), 0), ); let to_account = AccountWithMetadata::new( Account { @@ -3276,11 +3137,13 @@ pub mod tests { ..Account::default() }, true, - (&to_keys.npk(), 0), + (&to_keys.npk(), &to_keys.vpk(), 0), ); - let from_account_id = AccountId::for_regular_private_account(&from_keys.npk(), 0); - let to_account_id = AccountId::for_regular_private_account(&to_keys.npk(), 0); + let from_account_id = + AccountId::for_regular_private_account(&from_keys.npk(), &from_keys.vpk(), 0); + let to_account_id = + AccountId::for_regular_private_account(&to_keys.npk(), &to_keys.vpk(), 0); let from_commitment = Commitment::new(&from_account_id, &from_account.account); let to_commitment = Commitment::new(&to_account_id, &to_account.account); let from_init_nullifier = Nullifier::for_account_initialization(&from_account_id); @@ -3302,12 +3165,6 @@ pub mod tests { None, ); - let (from_ss, from_epk) = - SharedSecretKey::encapsulate_deterministic(&from_keys.vpk(), &[0_u8; 32], 0); - - let (to_ss, to_epk) = - SharedSecretKey::encapsulate_deterministic(&to_keys.vpk(), &[0_u8; 32], 1); - let mut dependencies = HashMap::new(); dependencies.insert(auth_transfers.id(), auth_transfers); @@ -3336,12 +3193,8 @@ pub mod tests { Program::serialize_instruction(instruction).unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: to_epk, - view_tag: EncryptedAccountData::compute_view_tag( - &to_keys.npk(), - &to_keys.vpk(), - ), - ssk: to_ss, + vpk: to_keys.vpk(), + esk: [0; 32], nsk: from_keys.nsk, membership_proof: state .get_proof_for_commitment(&from_commitment) @@ -3349,12 +3202,8 @@ pub mod tests { identifier: 0, }, InputAccountIdentity::PrivateAuthorizedUpdate { - epk: from_epk, - view_tag: EncryptedAccountData::compute_view_tag( - &from_keys.npk(), - &from_keys.vpk(), - ), - ssk: from_ss, + vpk: from_keys.vpk(), + esk: [0; 32], nsk: to_keys.nsk, membership_proof: state .get_proof_for_commitment(&to_commitment) @@ -3598,14 +3447,15 @@ pub mod tests { let private_keys = test_private_account_keys_1(); // Create an authorized private account with default values (new account being initialized) - let authorized_account = - AccountWithMetadata::new(Account::default(), true, (&private_keys.npk(), 0)); + let authorized_account = AccountWithMetadata::new( + Account::default(), + true, + (&private_keys.npk(), &private_keys.vpk(), 0), + ); let program = Program::authenticated_transfer_program(); // Set up parameters for the new account - let (shared_secret, epk) = - SharedSecretKey::encapsulate_deterministic(&private_keys.vpk(), &[0_u8; 32], 0); let instruction = authenticated_transfer_core::Instruction::Initialize; @@ -3614,12 +3464,8 @@ pub mod tests { vec![authorized_account], Program::serialize_instruction(instruction).unwrap(), vec![InputAccountIdentity::PrivateAuthorizedInit { - epk, - view_tag: EncryptedAccountData::compute_view_tag( - &private_keys.npk(), - &private_keys.vpk(), - ), - ssk: shared_secret, + vpk: private_keys.vpk(), + esk: [0; 32], nsk: private_keys.nsk, identifier: 0, }], @@ -3636,7 +3482,8 @@ pub mod tests { let result = state.transition_from_privacy_preserving_transaction(&tx, 1, 0); assert!(result.is_ok()); - let account_id = AccountId::for_regular_private_account(&private_keys.npk(), 0); + let account_id = + AccountId::for_regular_private_account(&private_keys.npk(), &private_keys.vpk(), 0); let nullifier = Nullifier::for_account_initialization(&account_id); assert!(state.private_state.1.contains(&nullifier)); } @@ -3650,24 +3497,21 @@ pub mod tests { // especially PDAs. Private PDAs are not useful in practice because there is no way to // operate them without the corresponding private keys, so unauthorized private claiming // remains allowed. - let unauthorized_account = - AccountWithMetadata::new(Account::default(), false, (&private_keys.npk(), 0)); + let unauthorized_account = AccountWithMetadata::new( + Account::default(), + false, + (&private_keys.npk(), &private_keys.vpk(), 0), + ); let program = Program::claimer(); - let (shared_secret, epk) = - SharedSecretKey::encapsulate_deterministic(&private_keys.vpk(), &[0_u8; 32], 0); let (output, proof) = execute_and_prove( vec![unauthorized_account], Program::serialize_instruction(0_u128).unwrap(), vec![InputAccountIdentity::PrivateUnauthorized { - epk, - view_tag: EncryptedAccountData::compute_view_tag( - &private_keys.npk(), - &private_keys.vpk(), - ), + vpk: private_keys.vpk(), + esk: [0; 32], npk: private_keys.npk(), - ssk: shared_secret, identifier: 0, }], &program.into(), @@ -3683,7 +3527,8 @@ pub mod tests { .transition_from_privacy_preserving_transaction(&tx, 1, 0) .unwrap(); - let account_id = AccountId::for_regular_private_account(&private_keys.npk(), 0); + let account_id = + AccountId::for_regular_private_account(&private_keys.npk(), &private_keys.vpk(), 0); let nullifier = Nullifier::for_account_initialization(&account_id); assert!(state.private_state.1.contains(&nullifier)); } @@ -3696,14 +3541,15 @@ pub mod tests { let private_keys = test_private_account_keys_1(); // Step 1: Create a new private account with authorization - let authorized_account = - AccountWithMetadata::new(Account::default(), true, (&private_keys.npk(), 0)); + let authorized_account = AccountWithMetadata::new( + Account::default(), + true, + (&private_keys.npk(), &private_keys.vpk(), 0), + ); let claimer_program = Program::claimer(); // Set up parameters for claiming the new account - let (shared_secret, epk) = - SharedSecretKey::encapsulate_deterministic(&private_keys.vpk(), &[0_u8; 32], 0); let instruction = authenticated_transfer_core::Instruction::Initialize; @@ -3712,12 +3558,8 @@ pub mod tests { vec![authorized_account.clone()], Program::serialize_instruction(instruction).unwrap(), vec![InputAccountIdentity::PrivateAuthorizedInit { - epk, - view_tag: EncryptedAccountData::compute_view_tag( - &private_keys.npk(), - &private_keys.vpk(), - ), - ssk: shared_secret, + vpk: private_keys.vpk(), + esk: [0; 32], nsk: private_keys.nsk, identifier: 0, }], @@ -3738,7 +3580,8 @@ pub mod tests { ); // Verify the account is now initialized (nullifier exists) - let account_id = AccountId::for_regular_private_account(&private_keys.npk(), 0); + let account_id = + AccountId::for_regular_private_account(&private_keys.npk(), &private_keys.vpk(), 0); let nullifier = Nullifier::for_account_initialization(&account_id); assert!(state.private_state.1.contains(&nullifier)); @@ -3750,20 +3593,14 @@ pub mod tests { }; let noop_program = Program::noop(); - let shared_secret2 = - SharedSecretKey::encapsulate_deterministic(&private_keys.vpk(), &[0_u8; 32], 0).0; // Step 3: Try to execute noop program with authentication but without initialization let res = execute_and_prove( vec![account_metadata], Program::serialize_instruction(()).unwrap(), vec![InputAccountIdentity::PrivateAuthorizedInit { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &private_keys.npk(), - &private_keys.vpk(), - ), - ssk: shared_secret2, + vpk: private_keys.vpk(), + esk: [0; 32], nsk: private_keys.nsk, identifier: 0, }], @@ -3831,8 +3668,11 @@ pub mod tests { fn private_changer_claimer_no_data_change_no_claim_succeeds() { let program = Program::changer_claimer(); let sender_keys = test_private_account_keys_1(); - let private_account = - AccountWithMetadata::new(Account::default(), true, (&sender_keys.npk(), 0)); + let private_account = AccountWithMetadata::new( + Account::default(), + true, + (&sender_keys.npk(), &sender_keys.vpk(), 0), + ); // Don't change data (None) and don't claim (false) let instruction: (Option>, bool) = (None, false); @@ -3840,13 +3680,8 @@ pub mod tests { vec![private_account], Program::serialize_instruction(instruction).unwrap(), vec![InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: SharedSecretKey::encapsulate_deterministic(&sender_keys.vpk(), &[0_u8; 32], 0) - .0, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: (0, vec![]), identifier: 0, @@ -3862,8 +3697,11 @@ pub mod tests { fn private_changer_claimer_data_change_no_claim_fails() { let program = Program::changer_claimer(); let sender_keys = test_private_account_keys_1(); - let private_account = - AccountWithMetadata::new(Account::default(), true, (&sender_keys.npk(), 0)); + let private_account = AccountWithMetadata::new( + Account::default(), + true, + (&sender_keys.npk(), &sender_keys.vpk(), 0), + ); // Change data but don't claim (false) - should fail let new_data = vec![1, 2, 3, 4, 5]; let instruction: (Option>, bool) = (Some(new_data), false); @@ -3872,13 +3710,8 @@ pub mod tests { vec![private_account], Program::serialize_instruction(instruction).unwrap(), vec![InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.npk(), - &sender_keys.vpk(), - ), - ssk: SharedSecretKey::encapsulate_deterministic(&sender_keys.vpk(), &[0_u8; 32], 0) - .0, + vpk: sender_keys.vpk(), + esk: [0; 32], nsk: sender_keys.nsk, membership_proof: (0, vec![]), identifier: 0, @@ -3907,10 +3740,14 @@ pub mod tests { false, sender_keys.account_id(), ); - let recipient_account = - AccountWithMetadata::new(Account::default(), true, (&recipient_keys.npk(), 0)); + let recipient_account = AccountWithMetadata::new( + Account::default(), + true, + (&recipient_keys.npk(), &recipient_keys.vpk(), 0), + ); - let recipient_account_id = AccountId::for_regular_private_account(&recipient_keys.npk(), 0); + let recipient_account_id = + AccountId::for_regular_private_account(&recipient_keys.npk(), &recipient_keys.vpk(), 0); let recipient_commitment = Commitment::new(&recipient_account_id, &recipient_account.account); let recipient_init_nullifier = Nullifier::for_account_initialization(&recipient_account_id); @@ -3924,9 +3761,6 @@ pub mod tests { let balance_to_transfer = 10_u128; let instruction = (balance_to_transfer, auth_transfers.id()); - let recipient = - SharedSecretKey::encapsulate_deterministic(&recipient_keys.vpk(), &[0_u8; 32], 0).0; - let mut dependencies = HashMap::new(); dependencies.insert(auth_transfers.id(), auth_transfers); let program_with_deps = ProgramWithDependencies::new(malicious_program, dependencies); @@ -3938,12 +3772,8 @@ pub mod tests { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(Vec::new()), - view_tag: EncryptedAccountData::compute_view_tag( - &recipient_keys.npk(), - &recipient_keys.vpk(), - ), - ssk: recipient, + vpk: recipient_keys.vpk(), + esk: [0; 32], nsk: recipient_keys.nsk, membership_proof: state .get_proof_for_commitment(&recipient_commitment) @@ -4083,12 +3913,13 @@ pub mod tests { let block_validity_window: BlockValidityWindow = 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(), 0)); + let pre = AccountWithMetadata::new( + Account::default(), + false, + (&account_keys.npk(), &account_keys.vpk(), 0), + ); let mut state = V03State::new_with_genesis_accounts(&[], vec![], 0).with_test_programs(); let tx = { - let (shared_secret, epk) = - SharedSecretKey::encapsulate_deterministic(&account_keys.vpk(), &[0_u8; 32], 0); - let instruction = ( block_validity_window, TimestampValidityWindow::new_unbounded(), @@ -4097,13 +3928,9 @@ pub mod tests { vec![pre], Program::serialize_instruction(instruction).unwrap(), vec![InputAccountIdentity::PrivateUnauthorized { - epk, - view_tag: EncryptedAccountData::compute_view_tag( - &account_keys.npk(), - &account_keys.vpk(), - ), + vpk: account_keys.vpk(), + esk: [0; 32], npk: account_keys.npk(), - ssk: shared_secret, identifier: 0, }], &validity_window_program.into(), @@ -4151,12 +3978,13 @@ pub mod tests { 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(), 0)); + let pre = AccountWithMetadata::new( + Account::default(), + false, + (&account_keys.npk(), &account_keys.vpk(), 0), + ); let mut state = V03State::new_with_genesis_accounts(&[], vec![], 0).with_test_programs(); let tx = { - let (shared_secret, epk) = - SharedSecretKey::encapsulate_deterministic(&account_keys.vpk(), &[0_u8; 32], 0); - let instruction = ( BlockValidityWindow::new_unbounded(), timestamp_validity_window, @@ -4165,13 +3993,9 @@ pub mod tests { vec![pre], Program::serialize_instruction(instruction).unwrap(), vec![InputAccountIdentity::PrivateUnauthorized { - epk, - view_tag: EncryptedAccountData::compute_view_tag( - &account_keys.npk(), - &account_keys.vpk(), - ), + vpk: account_keys.vpk(), + esk: [0; 32], npk: account_keys.npk(), - ssk: shared_secret, identifier: 0, }], &validity_window_program.into(), @@ -4688,8 +4512,10 @@ pub mod tests { ProgramWithDependencies::new(proxy, [(auth_transfer_id, auth_transfer.clone())].into()); let funder_id = funder_keys.account_id(); - let alice_pda_0_id = AccountId::for_private_pda(&proxy_id, &seed, &alice_npk, 0); - let alice_pda_1_id = AccountId::for_private_pda(&proxy_id, &seed, &alice_npk, 1); + let alice_pda_0_id = + AccountId::for_private_pda(&proxy_id, &seed, &alice_npk, &alice_keys.vpk(), 0); + let alice_pda_1_id = + AccountId::for_private_pda(&proxy_id, &seed, &alice_npk, &alice_keys.vpk(), 1); let recipient_id = test_public_account_keys_2().account_id(); let recipient_signing_key = test_public_account_keys_2().signing_key; @@ -4708,11 +4534,6 @@ pub mod tests { ..Account::default() }; - let (alice_shared_0, alice_epk_0) = - SharedSecretKey::encapsulate_deterministic(&alice_keys.vpk(), &[0_u8; 32], 0); - let (alice_shared_1, alice_epk_1) = - SharedSecretKey::encapsulate_deterministic(&alice_keys.vpk(), &[0_u8; 32], 1); - // Fund alice_pda_0 via authenticated_transfer directly. { let funder_account = state.get_account_by_id(funder_id); @@ -4727,13 +4548,9 @@ pub mod tests { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivatePdaInit { - epk: alice_epk_0.clone(), - view_tag: EncryptedAccountData::compute_view_tag( - &alice_npk, - &alice_keys.vpk(), - ), + vpk: alice_keys.vpk(), + esk: [0; 32], npk: alice_npk, - ssk: alice_shared_0, identifier: 0, seed: Some((seed, proxy_id)), }, @@ -4768,13 +4585,9 @@ pub mod tests { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivatePdaInit { - epk: alice_epk_1.clone(), - view_tag: EncryptedAccountData::compute_view_tag( - &alice_npk, - &alice_keys.vpk(), - ), + vpk: alice_keys.vpk(), + esk: [0; 32], npk: alice_npk, - ssk: alice_shared_1, identifier: 1, seed: Some((seed, proxy_id)), }, @@ -4812,12 +4625,8 @@ pub mod tests { Program::serialize_instruction((seed, amount, auth_transfer_id)).unwrap(), vec![ InputAccountIdentity::PrivatePdaUpdate { - epk: alice_epk_0, - view_tag: EncryptedAccountData::compute_view_tag( - &alice_npk, - &alice_keys.vpk(), - ), - ssk: alice_shared_0, + vpk: alice_keys.vpk(), + esk: [0; 32], nsk: alice_keys.nsk, membership_proof: state .get_proof_for_commitment(&commitment_pda_0) @@ -4854,12 +4663,8 @@ pub mod tests { Program::serialize_instruction((seed, amount, auth_transfer_id)).unwrap(), vec![ InputAccountIdentity::PrivatePdaUpdate { - epk: alice_epk_1, - view_tag: EncryptedAccountData::compute_view_tag( - &alice_npk, - &alice_keys.vpk(), - ), - ssk: alice_shared_1, + vpk: alice_keys.vpk(), + esk: [0; 32], nsk: alice_keys.nsk, membership_proof: state .get_proof_for_commitment(&commitment_pda_1) @@ -4898,7 +4703,6 @@ pub mod tests { }; let commitment_pda_1_after_spend = Commitment::new(&alice_pda_1_id, &alice_pda_1_account_after_spend); - let alice_shared_1_refund = SharedSecretKey([12; 32]); { let recipient_account = state.get_account_by_id(recipient_id); let recipient_nonce = recipient_account.nonce; @@ -4916,13 +4720,9 @@ pub mod tests { vec![ InputAccountIdentity::Public, InputAccountIdentity::PrivatePdaUpdate { - epk: EphemeralPublicKey(vec![12_u8; 1088]), - view_tag: EncryptedAccountData::compute_view_tag( - &alice_npk, - &alice_keys.vpk(), - ), + vpk: alice_keys.vpk(), + esk: [0; 32], nsk: alice_keys.nsk, - ssk: alice_shared_1_refund, membership_proof: state .get_proof_for_commitment(&commitment_pda_1_after_spend) .expect("pda_1 after spend must be in state"), diff --git a/lee/state_machine/src/validated_state_diff.rs b/lee/state_machine/src/validated_state_diff.rs index 0d71d485..80d9f4ad 100644 --- a/lee/state_machine/src/validated_state_diff.rs +++ b/lee/state_machine/src/validated_state_diff.rs @@ -575,7 +575,7 @@ mod tests { #[test] fn privacy_malicious_programs_cannot_drain_public_victim() { use lee_core::{ - Commitment, EncryptedAccountData, InputAccountIdentity, SharedSecretKey, + Commitment, InputAccountIdentity, account::{Account, AccountWithMetadata}, }; @@ -602,8 +602,8 @@ mod tests { // Attacker controls a private account. let attacker_keys = test_private_account_keys_1(); - let attacker_id = AccountId::for_regular_private_account(&attacker_keys.npk(), 0); - let (attacker_ssk, attacker_epk) = SharedSecretKey::encapsulate(&attacker_keys.vpk()); + let attacker_id = + AccountId::for_regular_private_account(&attacker_keys.npk(), &attacker_keys.vpk(), 0); let victim_id = AccountId::new([20_u8; 32]); let recipient_id = AccountId::new([42_u8; 32]); @@ -659,12 +659,8 @@ mod tests { // [2] recipient — first seen in authenticated_transfer's program_output.pre_states let account_identities = vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: attacker_epk, - view_tag: EncryptedAccountData::compute_view_tag( - &attacker_keys.npk(), - &attacker_keys.vpk(), - ), - ssk: attacker_ssk, + vpk: attacker_keys.vpk(), + esk: [0; 32], nsk: attacker_keys.nsk, membership_proof, identifier: 0, @@ -727,7 +723,7 @@ mod tests { #[test] fn privacy_malicious_programs_cannot_drain_private_victim() { use lee_core::{ - Commitment, EncryptedAccountData, InputAccountIdentity, SharedSecretKey, + Commitment, InputAccountIdentity, account::{Account, AccountWithMetadata}, }; @@ -757,12 +753,13 @@ mod tests { // Attacker controls a private account. let attacker_keys = test_private_account_keys_1(); - let attacker_id = AccountId::for_regular_private_account(&attacker_keys.npk(), 0); - let (attacker_ssk, attacker_epk) = SharedSecretKey::encapsulate(&attacker_keys.vpk()); + let attacker_id = + AccountId::for_regular_private_account(&attacker_keys.npk(), &attacker_keys.vpk(), 0); // Victim is a private account — not registered in public chain state. let victim_keys = test_private_account_keys_2(); - let victim_id = AccountId::for_regular_private_account(&victim_keys.npk(), 0); + let victim_id = + AccountId::for_regular_private_account(&victim_keys.npk(), &victim_keys.vpk(), 0); let victim_balance = 5_000_u128; let recipient_id = AccountId::new([42_u8; 32]); @@ -819,12 +816,8 @@ mod tests { // so PrivateAuthorizedUpdate is not an option. let account_identities = vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: attacker_epk, - view_tag: EncryptedAccountData::compute_view_tag( - &attacker_keys.npk(), - &attacker_keys.vpk(), - ), - ssk: attacker_ssk, + vpk: attacker_keys.vpk(), + esk: [0; 32], nsk: attacker_keys.nsk, membership_proof, identifier: 0, diff --git a/lez/sequencer/core/src/lib.rs b/lez/sequencer/core/src/lib.rs index 651951d2..e8cc6d37 100644 --- a/lez/sequencer/core/src/lib.rs +++ b/lez/sequencer/core/src/lib.rs @@ -819,8 +819,7 @@ mod tests { }; use key_protocol::key_management::KeyChain; use lee::{ - Account, AccountId, Data, EphemeralPublicKey, PrivacyPreservingTransaction, - SharedSecretKey, V03State, + Account, AccountId, Data, PrivacyPreservingTransaction, V03State, error::LeeError, execute_and_prove, privacy_preserving_transaction::{Message, circuit::ProgramWithDependencies}, @@ -828,7 +827,7 @@ mod tests { system_bridge_account_id, }; use lee_core::{ - Commitment, EncryptedAccountData, InputAccountIdentity, Nullifier, + Commitment, InputAccountIdentity, Nullifier, account::{AccountWithMetadata, Nonce}, }; use logos_blockchain_core::mantle::ops::channel::ChannelId; @@ -1605,8 +1604,11 @@ mod tests { #[test] fn private_bridge_withdraw_invocation_is_dropped() { let sender_keys = KeyChain::new_os_random(); - let sender_account_id = - AccountId::for_regular_private_account(&sender_keys.nullifier_public_key, 0); + let sender_account_id = AccountId::for_regular_private_account( + &sender_keys.nullifier_public_key, + &sender_keys.viewing_public_key, + 0, + ); let sender_private_account = Account { program_owner: Program::authenticated_transfer_program().id(), balance: 100, @@ -1629,7 +1631,11 @@ mod tests { let sender_pre = AccountWithMetadata::new( sender_private_account, true, - (&sender_keys.nullifier_public_key, 0), + ( + &sender_keys.nullifier_public_key, + &sender_keys.viewing_public_key, + 0, + ), ); let bridge_pre = AccountWithMetadata::new( state.get_account_by_id(bridge_account_id), @@ -1637,8 +1643,6 @@ mod tests { bridge_account_id, ); - let shared_secret = SharedSecretKey::encapsulate(&sender_keys.viewing_public_key).0; - let instruction = Program::serialize_instruction(bridge_core::Instruction::Withdraw { amount: 1, bedrock_account_pk: [0; 32], @@ -1659,12 +1663,8 @@ mod tests { instruction, vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - epk: EphemeralPublicKey(vec![12_u8; 1088]), - view_tag: EncryptedAccountData::compute_view_tag( - &sender_keys.nullifier_public_key, - &sender_keys.viewing_public_key, - ), - ssk: shared_secret, + vpk: sender_keys.viewing_public_key, + esk: [0; 32], nsk: sender_keys.private_key_holder.nullifier_secret_key, membership_proof: state .get_proof_for_commitment(&sender_commitment) diff --git a/lez/testnet_initial_state/src/lib.rs b/lez/testnet_initial_state/src/lib.rs index 5bb6e1b4..7d207d40 100644 --- a/lez/testnet_initial_state/src/lib.rs +++ b/lez/testnet_initial_state/src/lib.rs @@ -85,6 +85,7 @@ pub struct PublicAccountPublicInitialData { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct PrivateAccountPublicInitialData { pub npk: lee_core::NullifierPublicKey, + pub vpk: lee_core::encryption::ViewingPublicKey, pub account: lee_core::account::Account, } @@ -107,6 +108,7 @@ impl PrivateAccountPrivateInitialData { pub fn account_id(&self) -> lee::AccountId { lee::AccountId::for_regular_private_account( &self.key_chain.nullifier_public_key, + &self.key_chain.viewing_public_key, self.identifier, ) } @@ -184,6 +186,7 @@ pub fn initial_commitments() -> Vec { .into_iter() .map(|data| PrivateAccountPublicInitialData { npk: data.key_chain.nullifier_public_key, + vpk: data.key_chain.viewing_public_key.clone(), account: data.account, }) .collect() @@ -215,7 +218,8 @@ pub fn initial_state() -> V03State { .iter() .map(|init_comm_data| { let npk = &init_comm_data.npk; - let account_id = lee::AccountId::for_regular_private_account(npk, 0); + let account_id = + lee::AccountId::for_regular_private_account(npk, &init_comm_data.vpk, 0); let mut acc = init_comm_data.account.clone(); @@ -390,6 +394,10 @@ mod tests { init_comms[0], PrivateAccountPublicInitialData { npk: NullifierPublicKey(NPK_PRIV_ACC_A), + vpk: init_private_accs_keys[0] + .key_chain + .viewing_public_key + .clone(), account: Account { program_owner: DEFAULT_PROGRAM_OWNER, balance: PRIV_ACC_A_INITIAL_BALANCE, @@ -403,6 +411,10 @@ mod tests { init_comms[1], PrivateAccountPublicInitialData { npk: NullifierPublicKey(NPK_PRIV_ACC_B), + vpk: init_private_accs_keys[1] + .key_chain + .viewing_public_key + .clone(), account: Account { program_owner: DEFAULT_PROGRAM_OWNER, balance: PRIV_ACC_B_INITIAL_BALANCE, diff --git a/lez/wallet-ffi/src/types.rs b/lez/wallet-ffi/src/types.rs index ad366b91..f9d818ce 100644 --- a/lez/wallet-ffi/src/types.rs +++ b/lez/wallet-ffi/src/types.rs @@ -601,9 +601,10 @@ mod tests { let identifier = u128::from_le_bytes([45; 16]); let private_reg_acc_id = - AccountId::for_private_account(&npk, &PrivateAccountKind::Regular(identifier)); + AccountId::for_private_account(&npk, &vpk, &PrivateAccountKind::Regular(identifier)); let private_pda_acc_id = AccountId::for_private_account( &npk, + &vpk, &PrivateAccountKind::Pda { program_id: [46; 8], seed: PdaSeed::new([47; 32]), diff --git a/lez/wallet/src/account_manager.rs b/lez/wallet/src/account_manager.rs index ce9d1833..3cab5a23 100644 --- a/lez/wallet/src/account_manager.rs +++ b/lez/wallet/src/account_manager.rs @@ -1,15 +1,15 @@ use core::fmt; use anyhow::Result; -use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder; use keycard_wallet::{KeycardWallet, python_path}; use lee::{AccountId, PrivateKey, PublicKey, Signature}; use lee_core::{ - Identifier, InputAccountIdentity, MembershipProof, NullifierPublicKey, NullifierSecretKey, - SharedSecretKey, + EphemeralSecretKey, Identifier, InputAccountIdentity, MembershipProof, NullifierPublicKey, + NullifierSecretKey, SharedSecretKey, account::{AccountWithMetadata, Nonce}, - encryption::{EncryptedAccountData, EphemeralPublicKey, ViewingPublicKey}, + encryption::ViewingPublicKey, }; +use rand::{RngCore as _, rngs::OsRng}; use crate::{ExecutionFailureKind, WalletCore}; @@ -261,10 +261,9 @@ impl AccountManager { identifier, } => { let acc = lee_core::account::Account::default(); - let auth_acc = AccountWithMetadata::new(acc, false, (&npk, identifier)); - let eph_holder = EphemeralKeyHolder::new(&vpk); - let ssk = eph_holder.calculate_shared_secret_sender(); - let epk = eph_holder.ephemeral_public_key().clone(); + let auth_acc = AccountWithMetadata::new(acc, false, (&npk, &vpk, identifier)); + let mut esk: EphemeralSecretKey = [0; 32]; + OsRng.fill_bytes(&mut esk); let pre = AccountPreparedData { nsk: None, npk, @@ -272,8 +271,7 @@ impl AccountManager { vpk, pre_state: auth_acc, proof: None, - ssk, - epk, + esk, is_pda: false, }; @@ -291,9 +289,8 @@ impl AccountManager { } => { let acc = lee_core::account::Account::default(); let auth_acc = AccountWithMetadata::new(acc, false, account_id); - let eph_holder = EphemeralKeyHolder::new(&vpk); - let ssk = eph_holder.calculate_shared_secret_sender(); - let epk = eph_holder.ephemeral_public_key().clone(); + let mut esk: EphemeralSecretKey = [0; 32]; + OsRng.fill_bytes(&mut esk); let pre = AccountPreparedData { nsk: None, npk, @@ -301,8 +298,7 @@ impl AccountManager { vpk, pre_state: auth_acc, proof: None, - ssk, - epk, + esk, is_pda: true, }; State::Private(pre) @@ -313,7 +309,7 @@ impl AccountManager { vpk, identifier, } => { - let account_id = lee::AccountId::from((&npk, identifier)); + let account_id = lee::AccountId::from((&npk, &vpk, identifier)); let pre = private_shared_acc_preparation( wallet, account_id, nsk, npk, vpk, identifier, false, ) @@ -373,9 +369,18 @@ impl AccountManager { self.states .iter() .filter_map(|state| match state { - State::Private(pre) => Some(PrivateAccountKeys { ssk: pre.ssk }), + State::Private(pre) => Some(pre), State::Public { .. } | State::PublicKeycard { .. } => None, }) + .enumerate() + .map(|(output_index, pre)| PrivateAccountKeys { + ssk: SharedSecretKey::encapsulate_deterministic( + &pre.vpk, + &pre.esk, + u32::try_from(output_index).expect("private output index fits in u32"), + ) + .0, + }) .collect() } @@ -390,19 +395,17 @@ impl AccountManager { State::Public { .. } | State::PublicKeycard { .. } => InputAccountIdentity::Public, State::Private(pre) if pre.is_pda => match (pre.nsk, pre.proof.clone()) { (Some(nsk), Some(membership_proof)) => InputAccountIdentity::PrivatePdaUpdate { - epk: pre.epk.clone(), - view_tag: EncryptedAccountData::compute_view_tag(&pre.npk, &pre.vpk), - ssk: pre.ssk, + vpk: pre.vpk.clone(), + esk: pre.esk, nsk, membership_proof, identifier: pre.identifier, seed: None, }, _ => InputAccountIdentity::PrivatePdaInit { - epk: pre.epk.clone(), - view_tag: EncryptedAccountData::compute_view_tag(&pre.npk, &pre.vpk), + vpk: pre.vpk.clone(), + esk: pre.esk, npk: pre.npk, - ssk: pre.ssk, identifier: pre.identifier, seed: None, }, @@ -410,26 +413,23 @@ impl AccountManager { State::Private(pre) => match (pre.nsk, pre.proof.clone()) { (Some(nsk), Some(membership_proof)) => { InputAccountIdentity::PrivateAuthorizedUpdate { - epk: pre.epk.clone(), - view_tag: EncryptedAccountData::compute_view_tag(&pre.npk, &pre.vpk), - ssk: pre.ssk, + vpk: pre.vpk.clone(), + esk: pre.esk, nsk, membership_proof, identifier: pre.identifier, } } (Some(nsk), None) => InputAccountIdentity::PrivateAuthorizedInit { - epk: pre.epk.clone(), - view_tag: EncryptedAccountData::compute_view_tag(&pre.npk, &pre.vpk), - ssk: pre.ssk, + vpk: pre.vpk.clone(), + esk: pre.esk, nsk, identifier: pre.identifier, }, (None, _) => InputAccountIdentity::PrivateUnauthorized { - epk: pre.epk.clone(), - view_tag: EncryptedAccountData::compute_view_tag(&pre.npk, &pre.vpk), + vpk: pre.vpk.clone(), + esk: pre.esk, npk: pre.npk, - ssk: pre.ssk, identifier: pre.identifier, }, }, @@ -505,13 +505,7 @@ struct AccountPreparedData { vpk: ViewingPublicKey, pre_state: AccountWithMetadata, proof: Option, - /// Cached shared-secret key derived once at `AccountManager::new`. Reused for both the - /// circuit input variant (`account_identities()`) and the message ephemeral-key tuples - /// (`private_account_keys()`), so all consumers see the same key. The corresponding - /// `EphemeralKeyHolder` uses `OsRng` and would produce a different value on a second call. - ssk: SharedSecretKey, - /// Cached ephemeral public key, paired with `ssk`. - epk: EphemeralPublicKey, + esk: EphemeralSecretKey, /// True when this account is a private PDA (owned or foreign). Used by `account_identities()` /// to select `PrivatePdaInit`/`PrivatePdaUpdate` rather than the standalone private variants. is_pda: bool, @@ -542,9 +536,8 @@ async fn private_key_tree_acc_preparation( // support from that in the wallet. let sender_pre = AccountWithMetadata::new(from_acc.account.clone(), true, account_id); - let eph_holder = EphemeralKeyHolder::new(&from_vpk); - let ssk = eph_holder.calculate_shared_secret_sender(); - let epk = eph_holder.ephemeral_public_key().clone(); + let mut esk: EphemeralSecretKey = [0; 32]; + OsRng.fill_bytes(&mut esk); Ok(AccountPreparedData { nsk: Some(nsk), @@ -553,8 +546,7 @@ async fn private_key_tree_acc_preparation( vpk: from_vpk, pre_state: sender_pre, proof, - ssk, - epk, + esk, is_pda, }) } @@ -582,9 +574,8 @@ async fn private_shared_acc_preparation( .await .unwrap_or(None); - let eph_holder = EphemeralKeyHolder::new(&vpk); - let ssk = eph_holder.calculate_shared_secret_sender(); - let epk = eph_holder.ephemeral_public_key().clone(); + let mut esk: EphemeralSecretKey = [0; 32]; + OsRng.fill_bytes(&mut esk); Ok(AccountPreparedData { nsk: Some(nsk), @@ -593,8 +584,7 @@ async fn private_shared_acc_preparation( vpk, pre_state, proof, - ssk, - epk, + esk, is_pda, }) } diff --git a/lez/wallet/src/cli/account.rs b/lez/wallet/src/cli/account.rs index e0ec2d0f..2f3dfa9f 100644 --- a/lez/wallet/src/cli/account.rs +++ b/lez/wallet/src/cli/account.rs @@ -525,8 +525,11 @@ impl WalletSubcommand for ImportSubcommand { let key_chain: KeyChain = serde_json::from_str(&key_chain_json) .map_err(|err| anyhow::anyhow!("Invalid key chain JSON: {err}"))?; let account = lee::Account::from(account_state); - let account_id = - lee::AccountId::from((&key_chain.nullifier_public_key, identifier)); + let account_id = lee::AccountId::from(( + &key_chain.nullifier_public_key, + &key_chain.viewing_public_key, + identifier, + )); wallet_core .storage_mut() diff --git a/lez/wallet/src/lib.rs b/lez/wallet/src/lib.rs index 7dece16a..010e438e 100644 --- a/lez/wallet/src/lib.rs +++ b/lez/wallet/src/lib.rs @@ -377,7 +377,7 @@ impl WalletCore { let keys = holder.derive_keys_for_pda(&program_id, &pda_seed); let npk = keys.generate_nullifier_public_key(); let vpk = keys.generate_viewing_public_key(); - let account_id = AccountId::for_private_pda(&program_id, &pda_seed, &npk, identifier); + let account_id = AccountId::for_private_pda(&program_id, &pda_seed, &npk, &vpk, identifier); self.register_shared_account( account_id, @@ -419,7 +419,7 @@ impl WalletCore { let keys = holder.derive_keys_for_shared_account(&derivation_seed); let npk = keys.generate_nullifier_public_key(); let vpk = keys.generate_viewing_public_key(); - let account_id = AccountId::from((&npk, identifier)); + let account_id = AccountId::from((&npk, &vpk, identifier)); self.register_shared_account(account_id, group_name, identifier, None, None); @@ -763,7 +763,11 @@ impl WalletCore { ) .map(|(kind, res_acc)| { let npk = &key_chain.nullifier_public_key; - let account_id = lee::AccountId::for_private_account(npk, &kind); + let account_id = lee::AccountId::for_private_account( + npk, + &key_chain.viewing_public_key, + &kind, + ); (account_id, kind, res_acc) }) }) diff --git a/lez/wallet/src/storage/key_chain.rs b/lez/wallet/src/storage/key_chain.rs index f73833eb..5db90119 100644 --- a/lez/wallet/src/storage/key_chain.rs +++ b/lez/wallet/src/storage/key_chain.rs @@ -174,7 +174,8 @@ impl UserKeyChain { .1 .first_key_value() .expect("Newly created key chain node must have at least one account"); - let account_id = AccountId::for_private_account(&npk, kind); + let account_id = + AccountId::for_private_account(&npk, &node.value.0.viewing_public_key, kind); (account_id, chain_index) } @@ -240,6 +241,7 @@ impl UserKeyChain { .find_map(|found| { let expected_id = AccountId::for_private_account( &found.key_chain.nullifier_public_key, + &found.key_chain.viewing_public_key, found.kind, ); (expected_id == account_id).then_some(found) @@ -264,8 +266,11 @@ impl UserKeyChain { .iter() .flat_map(|(key, data)| { data.accounts.keys().map(|kind| { - let account_id = - AccountId::for_private_account(&key.key_chain.nullifier_public_key, kind); + let account_id = AccountId::for_private_account( + &key.key_chain.nullifier_public_key, + &key.key_chain.viewing_public_key, + kind, + ); (account_id, &key.key_chain, key.chain_index.as_ref()) }) }) @@ -340,8 +345,11 @@ impl UserKeyChain { // Then try to update imported account for (key, data) in &mut self.imported_private_accounts { for (kind, imported_account) in &mut data.accounts { - let expected_id = - AccountId::for_private_account(&key.key_chain.nullifier_public_key, kind); + let expected_id = AccountId::for_private_account( + &key.key_chain.nullifier_public_key, + &key.key_chain.viewing_public_key, + kind, + ); if expected_id == account_id { debug!("Updating imported private account {account_id}"); *imported_account = account; @@ -378,8 +386,11 @@ impl UserKeyChain { // Node not yet in account_id_map — find it by checking all nodes for (ci, node) in &mut self.private_key_tree.key_map { - let expected_id = - lee::AccountId::for_private_account(&node.value.0.nullifier_public_key, &kind); + let expected_id = lee::AccountId::for_private_account( + &node.value.0.nullifier_public_key, + &node.value.0.viewing_public_key, + &kind, + ); if expected_id == account_id { match node.value.1.entry(kind) { Entry::Occupied(mut occupied) => { @@ -429,8 +440,11 @@ impl UserKeyChain { .iter() .flat_map(|(key, data)| { data.accounts.keys().map(|kind| { - let account_id = - AccountId::for_private_account(&key.key_chain.nullifier_public_key, kind); + let account_id = AccountId::for_private_account( + &key.key_chain.nullifier_public_key, + &key.key_chain.viewing_public_key, + kind, + ); (account_id, key.chain_index.as_ref()) }) }) @@ -720,7 +734,11 @@ mod tests { let mut user_data = UserKeyChain::default(); let key_chain = KeyChain::new_os_random(); - let account_id = AccountId::from((&key_chain.nullifier_public_key, 0)); + let account_id = AccountId::from(( + &key_chain.nullifier_public_key, + &key_chain.viewing_public_key, + 0, + )); let account = lee_core::account::Account::default(); user_data.add_imported_private_account(key_chain, None, 0, account); @@ -735,7 +753,11 @@ mod tests { let mut user_data = UserKeyChain::default(); let key_chain = KeyChain::new_os_random(); - let account_id = AccountId::from((&key_chain.nullifier_public_key, 0)); + let account_id = AccountId::from(( + &key_chain.nullifier_public_key, + &key_chain.viewing_public_key, + 0, + )); let account = lee_core::account::Account::default(); user_data.add_imported_private_account(key_chain, None, 0, account.clone()); @@ -780,7 +802,11 @@ mod tests { let mut user_data = UserKeyChain::default(); let key_chain = KeyChain::new_os_random(); - let account_id = AccountId::from((&key_chain.nullifier_public_key, 0)); + let account_id = AccountId::from(( + &key_chain.nullifier_public_key, + &key_chain.viewing_public_key, + 0, + )); let new_account = lee_core::account::Account { balance: 100, @@ -801,7 +827,11 @@ mod tests { let mut user_data = UserKeyChain::default(); let key_chain = KeyChain::new_os_random(); - let account_id1 = AccountId::from((&key_chain.nullifier_public_key, 0)); + let account_id1 = AccountId::from(( + &key_chain.nullifier_public_key, + &key_chain.viewing_public_key, + 0, + )); let account = lee_core::account::Account::default(); user_data.add_imported_private_account(key_chain, None, 0, account); diff --git a/test_fixtures/src/config.rs b/test_fixtures/src/config.rs index 73cd775b..5dee5a4b 100644 --- a/test_fixtures/src/config.rs +++ b/test_fixtures/src/config.rs @@ -23,7 +23,11 @@ pub struct InitialPrivateAccountForWallet { impl InitialPrivateAccountForWallet { #[must_use] pub fn account_id(&self) -> AccountId { - AccountId::from((&self.key_chain.nullifier_public_key, self.identifier)) + AccountId::from(( + &self.key_chain.nullifier_public_key, + &self.key_chain.viewing_public_key, + self.identifier, + )) } } diff --git a/tools/crypto_primitives_bench/benches/primitives.rs b/tools/crypto_primitives_bench/benches/primitives.rs index 11c11d9b..9a42305c 100644 --- a/tools/crypto_primitives_bench/benches/primitives.rs +++ b/tools/crypto_primitives_bench/benches/primitives.rs @@ -48,7 +48,8 @@ fn bench_encryption(c: &mut Criterion) { let recipient_kc = KeyChain::new_os_random(); let npk = recipient_kc.nullifier_public_key; let account = Account::default(); - let account_id = AccountId::for_regular_private_account(&npk, 0); + let account_id = + AccountId::for_regular_private_account(&npk, &recipient_kc.viewing_public_key, 0); let commitment = Commitment::new(&account_id, &account); let (shared, _epk) = SharedSecretKey::encapsulate(&recipient_kc.viewing_public_key); let kind = PrivateAccountKind::Regular(0_u128);