diff --git a/artifacts/program_methods/amm.bin b/artifacts/program_methods/amm.bin index b3f45bb8..026b6786 100644 Binary files a/artifacts/program_methods/amm.bin and b/artifacts/program_methods/amm.bin differ diff --git a/artifacts/program_methods/associated_token_account.bin b/artifacts/program_methods/associated_token_account.bin index b7df725e..206eee2e 100644 Binary files a/artifacts/program_methods/associated_token_account.bin and b/artifacts/program_methods/associated_token_account.bin differ diff --git a/artifacts/program_methods/authenticated_transfer.bin b/artifacts/program_methods/authenticated_transfer.bin index faf0b9b6..6d7f70de 100644 Binary files a/artifacts/program_methods/authenticated_transfer.bin and b/artifacts/program_methods/authenticated_transfer.bin differ diff --git a/artifacts/program_methods/clock.bin b/artifacts/program_methods/clock.bin index 3e31ce96..bc276a00 100644 Binary files a/artifacts/program_methods/clock.bin and b/artifacts/program_methods/clock.bin differ diff --git a/artifacts/program_methods/pinata.bin b/artifacts/program_methods/pinata.bin index 3cd4e775..83b6590f 100644 Binary files a/artifacts/program_methods/pinata.bin and b/artifacts/program_methods/pinata.bin differ diff --git a/artifacts/program_methods/pinata_token.bin b/artifacts/program_methods/pinata_token.bin index 53d01729..16783c28 100644 Binary files a/artifacts/program_methods/pinata_token.bin and b/artifacts/program_methods/pinata_token.bin differ diff --git a/artifacts/program_methods/privacy_preserving_circuit.bin b/artifacts/program_methods/privacy_preserving_circuit.bin index bae8f89f..c0ae0d75 100644 Binary files a/artifacts/program_methods/privacy_preserving_circuit.bin and b/artifacts/program_methods/privacy_preserving_circuit.bin differ diff --git a/artifacts/program_methods/token.bin b/artifacts/program_methods/token.bin index 33cb3836..18d098b1 100644 Binary files a/artifacts/program_methods/token.bin and b/artifacts/program_methods/token.bin differ diff --git a/artifacts/test_program_methods/burner.bin b/artifacts/test_program_methods/burner.bin index 20e8510c..f00bc824 100644 Binary files a/artifacts/test_program_methods/burner.bin and b/artifacts/test_program_methods/burner.bin differ diff --git a/artifacts/test_program_methods/chain_caller.bin b/artifacts/test_program_methods/chain_caller.bin index b5aea81f..876d90ba 100644 Binary files a/artifacts/test_program_methods/chain_caller.bin and b/artifacts/test_program_methods/chain_caller.bin differ diff --git a/artifacts/test_program_methods/changer_claimer.bin b/artifacts/test_program_methods/changer_claimer.bin index 1287d385..fcf62b00 100644 Binary files a/artifacts/test_program_methods/changer_claimer.bin and b/artifacts/test_program_methods/changer_claimer.bin differ diff --git a/artifacts/test_program_methods/claimer.bin b/artifacts/test_program_methods/claimer.bin index 43ed5f4f..b4615136 100644 Binary files a/artifacts/test_program_methods/claimer.bin and b/artifacts/test_program_methods/claimer.bin differ diff --git a/artifacts/test_program_methods/clock_chain_caller.bin b/artifacts/test_program_methods/clock_chain_caller.bin index c99cd0ce..0ab6e829 100644 Binary files a/artifacts/test_program_methods/clock_chain_caller.bin and b/artifacts/test_program_methods/clock_chain_caller.bin differ diff --git a/artifacts/test_program_methods/data_changer.bin b/artifacts/test_program_methods/data_changer.bin index a5e415d2..3bf39469 100644 Binary files a/artifacts/test_program_methods/data_changer.bin and b/artifacts/test_program_methods/data_changer.bin differ diff --git a/artifacts/test_program_methods/extra_output.bin b/artifacts/test_program_methods/extra_output.bin index 2c5ddb72..becee722 100644 Binary files a/artifacts/test_program_methods/extra_output.bin and b/artifacts/test_program_methods/extra_output.bin differ diff --git a/artifacts/test_program_methods/flash_swap_callback.bin b/artifacts/test_program_methods/flash_swap_callback.bin index c366bb35..80f0ac47 100644 Binary files a/artifacts/test_program_methods/flash_swap_callback.bin and b/artifacts/test_program_methods/flash_swap_callback.bin differ diff --git a/artifacts/test_program_methods/flash_swap_initiator.bin b/artifacts/test_program_methods/flash_swap_initiator.bin index c1d7af8c..5adcea84 100644 Binary files a/artifacts/test_program_methods/flash_swap_initiator.bin and b/artifacts/test_program_methods/flash_swap_initiator.bin differ diff --git a/artifacts/test_program_methods/malicious_authorization_changer.bin b/artifacts/test_program_methods/malicious_authorization_changer.bin index 1d7fa13e..323687b3 100644 Binary files a/artifacts/test_program_methods/malicious_authorization_changer.bin and b/artifacts/test_program_methods/malicious_authorization_changer.bin differ diff --git a/artifacts/test_program_methods/malicious_caller_program_id.bin b/artifacts/test_program_methods/malicious_caller_program_id.bin index e2eeb9d2..846906c2 100644 Binary files a/artifacts/test_program_methods/malicious_caller_program_id.bin and b/artifacts/test_program_methods/malicious_caller_program_id.bin differ diff --git a/artifacts/test_program_methods/malicious_self_program_id.bin b/artifacts/test_program_methods/malicious_self_program_id.bin index a745e6f8..8f974af7 100644 Binary files a/artifacts/test_program_methods/malicious_self_program_id.bin and b/artifacts/test_program_methods/malicious_self_program_id.bin differ diff --git a/artifacts/test_program_methods/minter.bin b/artifacts/test_program_methods/minter.bin index c6a2f5ec..3d77888f 100644 Binary files a/artifacts/test_program_methods/minter.bin and b/artifacts/test_program_methods/minter.bin differ diff --git a/artifacts/test_program_methods/missing_output.bin b/artifacts/test_program_methods/missing_output.bin index 77b3b0dd..8d3a5096 100644 Binary files a/artifacts/test_program_methods/missing_output.bin and b/artifacts/test_program_methods/missing_output.bin differ diff --git a/artifacts/test_program_methods/modified_transfer.bin b/artifacts/test_program_methods/modified_transfer.bin index a370d528..c1815d82 100644 Binary files a/artifacts/test_program_methods/modified_transfer.bin and b/artifacts/test_program_methods/modified_transfer.bin differ diff --git a/artifacts/test_program_methods/nonce_changer.bin b/artifacts/test_program_methods/nonce_changer.bin index 5f95e69b..e11516ce 100644 Binary files a/artifacts/test_program_methods/nonce_changer.bin and b/artifacts/test_program_methods/nonce_changer.bin differ diff --git a/artifacts/test_program_methods/noop.bin b/artifacts/test_program_methods/noop.bin index 4e5d29bd..03569011 100644 Binary files a/artifacts/test_program_methods/noop.bin and b/artifacts/test_program_methods/noop.bin differ diff --git a/artifacts/test_program_methods/pinata_cooldown.bin b/artifacts/test_program_methods/pinata_cooldown.bin index ae1e3971..4786739b 100644 Binary files a/artifacts/test_program_methods/pinata_cooldown.bin and b/artifacts/test_program_methods/pinata_cooldown.bin differ diff --git a/artifacts/test_program_methods/program_owner_changer.bin b/artifacts/test_program_methods/program_owner_changer.bin index e36a7c10..98843f5d 100644 Binary files a/artifacts/test_program_methods/program_owner_changer.bin and b/artifacts/test_program_methods/program_owner_changer.bin differ diff --git a/artifacts/test_program_methods/simple_balance_transfer.bin b/artifacts/test_program_methods/simple_balance_transfer.bin index 25ef436e..79efa3f8 100644 Binary files a/artifacts/test_program_methods/simple_balance_transfer.bin and b/artifacts/test_program_methods/simple_balance_transfer.bin differ diff --git a/artifacts/test_program_methods/time_locked_transfer.bin b/artifacts/test_program_methods/time_locked_transfer.bin index bf0cfef2..f991da9a 100644 Binary files a/artifacts/test_program_methods/time_locked_transfer.bin and b/artifacts/test_program_methods/time_locked_transfer.bin differ diff --git a/artifacts/test_program_methods/validity_window.bin b/artifacts/test_program_methods/validity_window.bin index fad0c516..42a18ae2 100644 Binary files a/artifacts/test_program_methods/validity_window.bin and b/artifacts/test_program_methods/validity_window.bin differ diff --git a/artifacts/test_program_methods/validity_window_chain_caller.bin b/artifacts/test_program_methods/validity_window_chain_caller.bin index 678073f6..feef1cc0 100644 Binary files a/artifacts/test_program_methods/validity_window_chain_caller.bin and b/artifacts/test_program_methods/validity_window_chain_caller.bin differ diff --git a/indexer/core/src/lib.rs b/indexer/core/src/lib.rs index 120ed707..102acbd4 100644 --- a/indexer/core/src/lib.rs +++ b/indexer/core/src/lib.rs @@ -72,7 +72,10 @@ impl IndexerCore { acc.program_owner = nssa::program::Program::authenticated_transfer_program().id(); - nssa_core::Commitment::new(&AccountId::private_account_id(npk, Identifier(0_u128)), &acc) + nssa_core::Commitment::new( + &AccountId::private_account_id(npk, Identifier(0_u128)), + &acc, + ) }) .collect() }); diff --git a/integration_tests/src/config.rs b/integration_tests/src/config.rs index 630552ac..e6533d00 100644 --- a/integration_tests/src/config.rs +++ b/integration_tests/src/config.rs @@ -3,9 +3,13 @@ use std::{net::SocketAddr, path::PathBuf, time::Duration}; use anyhow::{Context as _, Result}; use bytesize::ByteSize; use indexer_service::{BackoffConfig, ChannelId, ClientConfig, IndexerConfig}; -use key_protocol::key_management::KeyChain; +use key_protocol::{key_management::KeyChain, key_protocol_core::PrivateBundle}; use nssa::{Account, AccountId}; -use nssa_core::{PrivateKey, PublicKey, account::{Data, Identifier}, program::DEFAULT_PROGRAM_ID}; +use nssa_core::{ + PrivateKey, PublicKey, + account::{Data, Identifier}, + program::DEFAULT_PROGRAM_ID, +}; use sequencer_core::config::{BedrockConfig, SequencerConfig}; use testnet_initial_state::{ PrivateAccountPrivateInitialData, PrivateAccountPublicInitialData, @@ -36,7 +40,7 @@ impl Default for SequencerPartialConfig { pub struct InitialData { pub public_accounts: Vec<(PrivateKey, u128)>, - pub private_accounts: Vec<(KeyChain, Account)>, + pub private_accounts: Vec, } impl InitialData { @@ -45,8 +49,7 @@ impl InitialData { let mut public_alice_private_key = PrivateKey::new_os_random(); let mut public_alice_public_key = PublicKey::new_from_private_key(&public_alice_private_key); - let mut public_alice_account_id = - AccountId::public_account_id(&public_alice_public_key); + let mut public_alice_account_id = AccountId::public_account_id(&public_alice_public_key); let mut public_bob_private_key = PrivateKey::new_os_random(); let mut public_bob_public_key = PublicKey::new_from_private_key(&public_bob_private_key); @@ -60,12 +63,18 @@ impl InitialData { } let mut private_charlie_key_chain = KeyChain::new_os_random(); - let mut private_charlie_account_id = - AccountId::private_account_id(&private_charlie_key_chain.nullifier_public_key, Identifier(0_u128)); + let private_charlie_identifier = Identifier::new_os_random(); + let mut private_charlie_account_id = AccountId::private_account_id( + &private_charlie_key_chain.nullifier_public_key, + private_charlie_identifier, + ); let mut private_david_key_chain = KeyChain::new_os_random(); - let mut private_david_account_id = - AccountId::private_account_id(&private_david_key_chain.nullifier_public_key, Identifier(0_u128)); + let private_david_identifier = Identifier::new_os_random(); + let mut private_david_account_id = AccountId::private_account_id( + &private_david_key_chain.nullifier_public_key, + private_david_identifier, + ); // Ensure consistent ordering if private_charlie_account_id > private_david_account_id { @@ -82,24 +91,26 @@ impl InitialData { (public_bob_private_key, 20_000), ], private_accounts: vec![ - ( - private_charlie_key_chain, - Account { + PrivateBundle { + key_chain: private_charlie_key_chain, + identifier: private_charlie_identifier, + account: Account { balance: 10_000, data: Data::default(), program_owner: DEFAULT_PROGRAM_ID, nonce: 0_u128.into(), }, - ), - ( - private_david_key_chain, - Account { + }, + PrivateBundle { + key_chain: private_david_key_chain, + identifier: private_david_identifier, + account: Account { balance: 20_000, data: Data::default(), program_owner: DEFAULT_PROGRAM_ID, nonce: 0_u128.into(), }, - ), + }, ], } } @@ -121,9 +132,10 @@ impl InitialData { fn sequencer_initial_private_accounts(&self) -> Vec { self.private_accounts .iter() - .map(|(key_chain, account)| PrivateAccountPublicInitialData { - npk: key_chain.nullifier_public_key.clone(), - account: account.clone(), + .map(|bundle| PrivateAccountPublicInitialData { + npk: bundle.key_chain.nullifier_public_key.clone(), + identifier: bundle.identifier, + account: bundle.account.clone(), }) .collect() } @@ -139,13 +151,16 @@ impl InitialData { pub_sign_key: priv_key.clone(), }) }) - .chain(self.private_accounts.iter().map(|(key_chain, account)| { - let account_id = - AccountId::private_account_id(&key_chain.nullifier_public_key, Identifier(0_u128)); + .chain(self.private_accounts.iter().map(|bundle| { + let account_id = AccountId::private_account_id( + &bundle.key_chain.nullifier_public_key, + bundle.identifier, + ); InitialAccountData::Private(Box::new(PrivateAccountPrivateInitialData { account_id, - account: account.clone(), - key_chain: key_chain.clone(), + account: bundle.account.clone(), + identifier: bundle.identifier, + key_chain: bundle.key_chain.clone(), })) })) .collect() diff --git a/integration_tests/tests/keys_restoration.rs b/integration_tests/tests/keys_restoration.rs index 54b9474a..e95e8622 100644 --- a/integration_tests/tests/keys_restoration.rs +++ b/integration_tests/tests/keys_restoration.rs @@ -259,16 +259,16 @@ async fn restore_keys_from_seed() -> Result<()> { .expect("Acc 4 should be restored"); assert_eq!( - acc1.value.1.program_owner, + acc1.value.account.program_owner, Program::authenticated_transfer_program().id() ); assert_eq!( - acc2.value.1.program_owner, + acc2.value.account.program_owner, Program::authenticated_transfer_program().id() ); - assert_eq!(acc1.value.1.balance, 100); - assert_eq!(acc2.value.1.balance, 101); + assert_eq!(acc1.value.account.balance, 100); + assert_eq!(acc2.value.account.balance, 101); info!("Tree checks passed, testing restored accounts can transact"); diff --git a/integration_tests/tests/tps.rs b/integration_tests/tests/tps.rs index 58e1b001..ea8a23b3 100644 --- a/integration_tests/tests/tps.rs +++ b/integration_tests/tests/tps.rs @@ -18,7 +18,10 @@ use integration_tests::{ TestContext, config::{InitialData, SequencerPartialConfig}, }; -use key_protocol::key_management::{KeyChain, ephemeral_key_holder::EphemeralKeyHolder}; +use key_protocol::{ + key_management::{KeyChain, ephemeral_key_holder::EphemeralKeyHolder}, + key_protocol_core::PrivateBundle, +}; use log::info; use nssa::{ Account, AccountId, PrivacyPreservingTransaction, PublicTransaction, @@ -107,6 +110,7 @@ impl TpsTestManager { // Generate an initial commitment to be used with the privacy preserving transaction // created with the `build_privacy_transaction` function. let key_chain = KeyChain::new_os_random(); + let identifier = Identifier::new_os_random(); let account = Account { balance: 100, nonce: Nonce(0xdead_beef), @@ -116,7 +120,11 @@ impl TpsTestManager { InitialData { public_accounts, - private_accounts: vec![(key_chain, account)], + private_accounts: vec![PrivateBundle { + key_chain, + identifier, + account, + }], } } diff --git a/key_protocol/src/key_management/key_tree/keys_private.rs b/key_protocol/src/key_management/key_tree/keys_private.rs index e3e3414d..9141b120 100644 --- a/key_protocol/src/key_management/key_tree/keys_private.rs +++ b/key_protocol/src/key_management/key_tree/keys_private.rs @@ -13,7 +13,7 @@ use crate::{ #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ChildKeysPrivate { - pub value: (KeyChain, nssa::Account), + pub value: PrivateBundle, pub ccc: [u8; 32], /// Can be [`None`] if root. pub cci: Option, @@ -39,8 +39,8 @@ impl KeyNode for ChildKeysPrivate { let vpk = ViewingPublicKey::from_scalar(vsk); Self { - value: ( - KeyChain { + value: PrivateBundle { + key_chain: KeyChain { secret_spending_key: ssk, nullifier_public_key: npk, viewing_public_key: vpk, @@ -49,8 +49,9 @@ impl KeyNode for ChildKeysPrivate { viewing_secret_key: vsk, }, }, - nssa::Account::default(), - ), + identifier: Identifier::default(), + account: nssa::Account::default(), + }, ccc, cci: None, } @@ -58,11 +59,22 @@ impl KeyNode for ChildKeysPrivate { fn nth_child(&self, cci: u32) -> Self { #[expect(clippy::arithmetic_side_effects, reason = "TODO: fix later")] - let parent_pt = - Scalar::from_repr(self.value.0.private_key_holder.nullifier_secret_key.into()) - .expect("Key generated as scalar, must be valid representation") - * Scalar::from_repr(self.value.0.private_key_holder.viewing_secret_key.into()) - .expect("Key generated as scalar, must be valid representation"); + let parent_pt = Scalar::from_repr( + self.value + .key_chain + .private_key_holder + .nullifier_secret_key + .into(), + ) + .expect("Key generated as scalar, must be valid representation") + * Scalar::from_repr( + self.value + .key_chain + .private_key_holder + .viewing_secret_key + .into(), + ) + .expect("Key generated as scalar, must be valid representation"); let mut input = vec![]; input.extend_from_slice(b"LEE_seed_priv"); @@ -88,8 +100,8 @@ impl KeyNode for ChildKeysPrivate { let vpk = ViewingPublicKey::from_scalar(vsk); Self { - value: ( - KeyChain { + value: PrivateBundle { + key_chain: KeyChain { secret_spending_key: ssk, nullifier_public_key: npk, viewing_public_key: vpk, @@ -98,8 +110,9 @@ impl KeyNode for ChildKeysPrivate { viewing_secret_key: vsk, }, }, - nssa::Account::default(), - ), + identifier: Identifier(0_u128), + account: nssa::Account::default(), + }, ccc, cci: Some(cci), } @@ -114,17 +127,10 @@ impl KeyNode for ChildKeysPrivate { } fn account_id(&self) -> nssa::AccountId { - nssa::AccountId::private_account_id(&self.value.0.nullifier_public_key, Identifier(0_u128)) - } -} - -#[expect( - clippy::single_char_lifetime_names, - reason = "TODO add meaningful name" -)] -impl<'a> From<&'a ChildKeysPrivate> for &'a (KeyChain, nssa::Account) { - fn from(value: &'a ChildKeysPrivate) -> Self { - &value.value + nssa::AccountId::private_account_id( + &self.value.key_chain.nullifier_public_key, + Identifier(0_u128), + ) } } @@ -134,10 +140,7 @@ impl<'a> From<&'a ChildKeysPrivate> for &'a (KeyChain, nssa::Account) { )] impl<'a> From<&'a mut ChildKeysPrivate> for PrivateBundle { fn from(value: &'a mut ChildKeysPrivate) -> Self { - Self { - key_chain: value.value.0.clone(), - account: value.value.1.clone(), - } + value.value.clone() } } @@ -189,12 +192,12 @@ mod tests { 80, 170, 66, 217, 79, 38, 80, 11, 74, 147, 123, 221, 159, 166, ]; - assert!(expected_ssk == keys.value.0.secret_spending_key); + assert!(expected_ssk == keys.value.key_chain.secret_spending_key); assert!(expected_ccc == keys.ccc); - assert!(expected_nsk == keys.value.0.private_key_holder.nullifier_secret_key); - assert!(expected_npk == keys.value.0.nullifier_public_key); - assert!(expected_vsk == keys.value.0.private_key_holder.viewing_secret_key); - assert!(expected_vpk_as_bytes == keys.value.0.viewing_public_key.to_bytes()); + assert!(expected_nsk == keys.value.key_chain.private_key_holder.nullifier_secret_key); + assert!(expected_npk == keys.value.key_chain.nullifier_public_key); + assert!(expected_vsk == keys.value.key_chain.private_key_holder.viewing_secret_key); + assert!(expected_vpk_as_bytes == keys.value.key_chain.viewing_public_key.to_bytes()); } #[test] @@ -233,9 +236,23 @@ mod tests { ]; assert!(expected_ccc == child_node.ccc); - assert!(expected_nsk == child_node.value.0.private_key_holder.nullifier_secret_key); - assert!(expected_npk == child_node.value.0.nullifier_public_key); - assert!(expected_vsk == child_node.value.0.private_key_holder.viewing_secret_key); - assert!(expected_vpk_as_bytes == child_node.value.0.viewing_public_key.to_bytes()); + assert!( + expected_nsk + == child_node + .value + .key_chain + .private_key_holder + .nullifier_secret_key + ); + assert!(expected_npk == child_node.value.key_chain.nullifier_public_key); + assert!( + expected_vsk + == child_node + .value + .key_chain + .private_key_holder + .viewing_secret_key + ); + assert!(expected_vpk_as_bytes == child_node.value.key_chain.viewing_public_key.to_bytes()); } } diff --git a/key_protocol/src/key_management/key_tree/mod.rs b/key_protocol/src/key_management/key_tree/mod.rs index 08a576e5..c9db4d2d 100644 --- a/key_protocol/src/key_management/key_tree/mod.rs +++ b/key_protocol/src/key_management/key_tree/mod.rs @@ -212,7 +212,7 @@ impl KeyTree { println!("Cleanup of tree at depth {i}"); for id in ChainIndex::chain_ids_at_depth(i) { if let Some(node) = self.key_map.get(&id) { - if node.value.1 == nssa::Account::default() { + if node.value.account == nssa::Account::default() { let addr = node.account_id(); self.remove(addr); } else { @@ -478,25 +478,25 @@ mod tests { .key_map .get_mut(&ChainIndex::from_str("/1").unwrap()) .unwrap(); - acc.value.1.balance = 2; + acc.value.account.balance = 2; let acc = tree .key_map .get_mut(&ChainIndex::from_str("/2").unwrap()) .unwrap(); - acc.value.1.balance = 3; + acc.value.account.balance = 3; let acc = tree .key_map .get_mut(&ChainIndex::from_str("/0/1").unwrap()) .unwrap(); - acc.value.1.balance = 5; + acc.value.account.balance = 5; let acc = tree .key_map .get_mut(&ChainIndex::from_str("/1/0").unwrap()) .unwrap(); - acc.value.1.balance = 6; + acc.value.account.balance = 6; tree.cleanup_tree_remove_uninit_layered(10); @@ -518,15 +518,15 @@ mod tests { assert_eq!(key_set, key_set_res); let acc = &tree.key_map[&ChainIndex::from_str("/1").unwrap()]; - assert_eq!(acc.value.1.balance, 2); + assert_eq!(acc.value.account.balance, 2); let acc = &tree.key_map[&ChainIndex::from_str("/2").unwrap()]; - assert_eq!(acc.value.1.balance, 3); + assert_eq!(acc.value.account.balance, 3); let acc = &tree.key_map[&ChainIndex::from_str("/0/1").unwrap()]; - assert_eq!(acc.value.1.balance, 5); + assert_eq!(acc.value.account.balance, 5); let acc = &tree.key_map[&ChainIndex::from_str("/1/0").unwrap()]; - assert_eq!(acc.value.1.balance, 6); + assert_eq!(acc.value.account.balance, 6); } } diff --git a/key_protocol/src/key_management/mod.rs b/key_protocol/src/key_management/mod.rs index 17dbb007..d17c23a2 100644 --- a/key_protocol/src/key_management/mod.rs +++ b/key_protocol/src/key_management/mod.rs @@ -178,7 +178,7 @@ mod tests { .get_node(second_child_id) .unwrap() .value - .0 + .key_chain .clone() } diff --git a/key_protocol/src/key_protocol_core/mod.rs b/key_protocol/src/key_protocol_core/mod.rs index 4fb6a178..e2910a05 100644 --- a/key_protocol/src/key_protocol_core/mod.rs +++ b/key_protocol/src/key_protocol_core/mod.rs @@ -28,12 +28,13 @@ pub struct NSSAUserData { /// TODO: eventually, this should have `sign_key: Option` and `pub_key: PublicKey`. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PublicBundle { - pub sign_key: nssa::PrivateKey, + pub sign_key: nssa_core::PrivateKey, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PrivateBundle { pub key_chain: KeyChain, + pub identifier: Identifier, pub account: nssa_core::account::Account, } @@ -44,7 +45,7 @@ impl NSSAUserData { let mut check_res = true; for (account_id, public_bundle) in accounts_keys_map { let expected_account_id = nssa::AccountId::public_account_id( - &nssa::PublicKey::new_from_private_key(&public_bundle.sign_key), + &nssa_core::PublicKey::new_from_private_key(&public_bundle.sign_key), ); if &expected_account_id != account_id { println!("{expected_account_id}, {account_id}"); @@ -59,7 +60,10 @@ impl NSSAUserData { ) -> bool { let mut check_res = true; for (account_id, bundle) in accounts_keys_map { - let expected_account_id = nssa::AccountId::privte_account_id(&bundle.key_chain.nullifier_public_key, Identifier(0_u128)); + let expected_account_id = nssa::AccountId::private_account_id( + &bundle.key_chain.nullifier_public_key, + bundle.identifier, + ); if expected_account_id != *account_id { println!("{expected_account_id}, {account_id}"); check_res = false; @@ -154,8 +158,9 @@ impl NSSAUserData { self.private_key_tree .get_node(account_id) .map(|child_keys_private| PrivateBundle { - key_chain: child_keys_private.value.0.clone(), - account: child_keys_private.value.1.clone(), + key_chain: child_keys_private.value.key_chain.clone(), + identifier: child_keys_private.value.identifier, + account: child_keys_private.value.account.clone(), }) }) } diff --git a/nssa/core/src/account.rs b/nssa/core/src/account.rs index 5d56a240..52dc0fc6 100644 --- a/nssa/core/src/account.rs +++ b/nssa/core/src/account.rs @@ -6,6 +6,7 @@ use std::{ use base58::{FromBase58 as _, ToBase58 as _}; use borsh::{BorshDeserialize, BorshSerialize}; pub use data::Data; +use rand::{RngCore as _, rngs::OsRng}; use risc0_zkvm::sha::{Impl, Sha256 as _}; use serde::{Deserialize, Serialize}; use serde_with::{DeserializeFromStr, SerializeDisplay}; @@ -18,7 +19,7 @@ pub mod data; #[derive(Copy, Debug, Default, Clone, Eq, PartialEq)] pub struct Nonce(pub u128); -#[derive(Copy, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)] pub struct Identifier(pub u128); impl Nonce { @@ -110,6 +111,13 @@ impl Identifier { Self(u128::from_le_bytes(value)) } + + #[must_use] + pub fn new_os_random() -> Self { + let mut bytes = [0_u8; 16]; + OsRng.fill_bytes(&mut bytes); + Self(u128::from_le_bytes(bytes)) + } } /// Account to be used both in public and private contexts. @@ -201,13 +209,13 @@ impl AccountId { } #[must_use] - pub fn private_account_id(value: &NullifierPublicKey, identifier: Identifier) -> Self { + pub fn private_account_id(npk: &NullifierPublicKey, identifier: Identifier) -> Self { const PRIVATE_ACCOUNT_ID_PREFIX: &[u8; 32] = b"/LEE/v0.3/AccountId/Private/\x00\x00\x00\x00"; let mut bytes = Vec::::new(); bytes.extend_from_slice(PRIVATE_ACCOUNT_ID_PREFIX); - bytes.extend_from_slice(&value.0); + bytes.extend_from_slice(&npk.0); bytes.extend_from_slice(&identifier.0.to_le_bytes()); Self::new( @@ -457,4 +465,9 @@ mod tests { assert_eq!(identifier, expected_identifier); } + + #[test] + fn default_identifier() { + assert_eq!(0_u128, Identifier::default().0); + } } diff --git a/nssa/src/state.rs b/nssa/src/state.rs index 5e898dde..1e8bb6ce 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -356,11 +356,10 @@ pub mod tests { use std::collections::HashMap; - use nssa_core::account::Identifier; use nssa_core::{ BlockId, Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, PrivateKey, PublicKey, SharedSecretKey, Timestamp, - account::{Account, AccountId, AccountWithMetadata, Nonce, data::Data}, + account::{Account, AccountId, AccountWithMetadata, Identifier, Nonce, data::Data}, encryption::{EphemeralPublicKey, Scalar, ViewingPublicKey}, program::{BlockValidityWindow, PdaSeed, ProgramId, TimestampValidityWindow}, }; @@ -2593,7 +2592,8 @@ pub mod tests { fn unauthorized_public_account_claiming_fails() { let program = Program::authenticated_transfer_program(); let account_key = PrivateKey::try_new([9; 32]).unwrap(); - let account_id = AccountId::public_account_id(&PublicKey::new_from_private_key(&account_key)); + let account_id = + AccountId::public_account_id(&PublicKey::new_from_private_key(&account_key)); let mut state = V03State::new_with_genesis_accounts(&[], &[], 0); assert_eq!(state.get_account_by_id(account_id), Account::default()); @@ -2614,7 +2614,8 @@ pub mod tests { fn authorized_public_account_claiming_succeeds() { let program = Program::authenticated_transfer_program(); let account_key = PrivateKey::try_new([10; 32]).unwrap(); - let account_id = AccountId::public_account_id(&PublicKey::new_from_private_key(&account_key)); + let account_id = + AccountId::public_account_id(&PublicKey::new_from_private_key(&account_key)); let mut state = V03State::new_with_genesis_accounts(&[], &[], 0); assert_eq!(state.get_account_by_id(account_id), Account::default()); diff --git a/testnet_initial_state/src/lib.rs b/testnet_initial_state/src/lib.rs index 14d800bd..ca07f6b9 100644 --- a/testnet_initial_state/src/lib.rs +++ b/testnet_initial_state/src/lib.rs @@ -78,6 +78,9 @@ const PUB_ACC_B_INITIAL_BALANCE: u128 = 20000; const PRIV_ACC_A_INITIAL_BALANCE: u128 = 10000; const PRIV_ACC_B_INITIAL_BALANCE: u128 = 20000; +const PRIV_ACC_A_IDENTIFIER: u128 = 13; +const PRIV_ACC_B_IDENTIFIER: u128 = 42; + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct PublicAccountPublicInitialData { pub account_id: AccountId, @@ -87,6 +90,7 @@ pub struct PublicAccountPublicInitialData { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct PrivateAccountPublicInitialData { pub npk: nssa_core::NullifierPublicKey, + pub identifier: Identifier, pub account: nssa_core::account::Account, } @@ -100,6 +104,7 @@ pub struct PublicAccountPrivateInitialData { pub struct PrivateAccountPrivateInitialData { pub account_id: nssa::AccountId, pub account: nssa_core::account::Account, + pub identifier: Identifier, pub key_chain: KeyChain, } @@ -147,6 +152,9 @@ pub fn initial_priv_accounts_private_keys() -> Vec Vec Vec Vec { .into_iter() .map(|data| PrivateAccountPublicInitialData { npk: data.key_chain.nullifier_public_key.clone(), + identifier: data.identifier, account: data.account, }) .collect() @@ -212,8 +223,7 @@ pub fn initial_state() -> V03State { let initial_commitments: Vec = initial_commitments() .iter() .map(|init_comm_data| { - let npk = &init_comm_data.npk; - let acc_id = &AccountId::private_account_id(npk, Identifier(0_u128)); + let acc_id = &AccountId::private_account_id(&init_comm_data.npk, init_comm_data.identifier); let mut acc = init_comm_data.account.clone(); @@ -385,6 +395,7 @@ mod tests { init_comms[0], PrivateAccountPublicInitialData { npk: NullifierPublicKey(NPK_PRIV_ACC_A), + identifier: Identifier(PRIV_ACC_A_IDENTIFIER), account: Account { program_owner: DEFAULT_PROGRAM_OWNER, balance: PRIV_ACC_A_INITIAL_BALANCE, @@ -398,6 +409,7 @@ mod tests { init_comms[1], PrivateAccountPublicInitialData { npk: NullifierPublicKey(NPK_PRIV_ACC_B), + identifier: Identifier(PRIV_ACC_B_IDENTIFIER), account: Account { program_owner: DEFAULT_PROGRAM_OWNER, balance: PRIV_ACC_B_INITIAL_BALANCE, diff --git a/wallet/src/chain_storage.rs b/wallet/src/chain_storage.rs index c9d07d08..e17998fe 100644 --- a/wallet/src/chain_storage.rs +++ b/wallet/src/chain_storage.rs @@ -86,6 +86,7 @@ impl WalletChainStore { data.account_id, PrivateBundle { key_chain: data.key_chain, + identifier: data.identifier, account: data.account, }, ); @@ -136,6 +137,7 @@ impl WalletChainStore { data.account_id, PrivateBundle { key_chain: data.key_chain, + identifier: data.identifier, account, }, ); @@ -211,7 +213,7 @@ impl WalletChainStore { .private_key_tree .key_map .entry(chain_index.clone()) - .and_modify(|data| data.value.1 = account) + .and_modify(|data| data.value.account = account) }); } } diff --git a/wallet/src/helperfunctions.rs b/wallet/src/helperfunctions.rs index 6cfe00c8..3a548984 100644 --- a/wallet/src/helperfunctions.rs +++ b/wallet/src/helperfunctions.rs @@ -193,6 +193,7 @@ pub fn produce_data_for_storage( InitialAccountData::Private(Box::new(PrivateAccountPrivateInitialData { account_id: *account_id, account: bundle.account.clone(), + identifier: bundle.identifier, key_chain: bundle.key_chain.clone(), })) .into(), diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index a3afb7e6..a45b1f97 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -27,7 +27,9 @@ use nssa::{ }, }; use nssa_core::{ - Commitment, MembershipProof, SharedSecretKey, account::{Identifier, Nonce}, program::InstructionData, + Commitment, MembershipProof, SharedSecretKey, + account::{Identifier, Nonce}, + program::InstructionData, }; pub use privacy_preserving_tx::PrivacyPreservingAccount; use sequencer_service_rpc::{RpcClient as _, SequencerClient, SequencerClientBuilder}; @@ -305,7 +307,10 @@ impl WalletCore { pub fn get_private_account_commitment(&self, account_id: AccountId) -> Option { let bundle = self.storage.user_data.get_private_account(account_id)?; Some(Commitment::new( - &bundle.key_chain.nullifier_public_key, + &AccountId::private_account_id( + &bundle.key_chain.nullifier_public_key, + Identifier(0_u128), + ), &bundle.account, )) } @@ -393,6 +398,7 @@ impl WalletCore { )?; let private_account_keys = acc_manager.private_account_keys(); + let private_account_identifiers = acc_manager.private_account_identifiers(); let (output, proof) = nssa::privacy_preserving_transaction::circuit::execute_and_prove( pre_states, instruction_data, @@ -402,7 +408,7 @@ impl WalletCore { .map(|keys| (keys.npk.clone(), keys.ssk)) .collect::>(), acc_manager.private_account_auth(), - vec![], + private_account_identifiers.clone(), acc_manager.private_account_membership_proofs(), &program.to_owned(), ) @@ -414,9 +420,10 @@ impl WalletCore { Vec::from_iter(acc_manager.public_account_nonces()), private_account_keys .iter() - .map(|keys| { + .zip(private_account_identifiers) + .map(|(keys, identifier)| { ( - AccountId::private_account_id(&keys.npk.clone(), Identifier(0_u128)), + AccountId::private_account_id(&keys.npk.clone(), identifier), keys.vpk.clone(), keys.epk.clone(), ) @@ -502,6 +509,7 @@ impl WalletCore { acc_account_id, PrivateBundle { key_chain, + identifier: _, account: _, }, )| (*acc_account_id, key_chain, None), @@ -510,7 +518,7 @@ impl WalletCore { |(chain_index, keys_node)| { ( keys_node.account_id(), - &keys_node.value.0, + &keys_node.value.key_chain, chain_index.index(), ) }, diff --git a/wallet/src/privacy_preserving_tx.rs b/wallet/src/privacy_preserving_tx.rs index a7ceb7c3..bce96592 100644 --- a/wallet/src/privacy_preserving_tx.rs +++ b/wallet/src/privacy_preserving_tx.rs @@ -81,11 +81,13 @@ impl AccountManager { (State::Private(pre), mask) } + PrivacyPreservingAccount::PrivateForeign { npk, vpk } => { - let account_id = AccountId::private_account_id(&npk, Identifier(0_u128)); + let account_id = AccountId::private_account_id(&npk, Identifier::default()); //TODO: here (Marvin) Should be based on epk let acc = nssa_core::account::Account::default(); let auth_acc = AccountWithMetadata::new(acc, false, account_id); let pre = AccountPreparedData { + identifier: Identifier::default(), //TODO: here nsk: None, npk, vpk, @@ -137,12 +139,13 @@ impl AccountManager { .filter_map(|state| match state { State::Private(pre) => { let eph_holder = EphemeralKeyHolder::new(&pre.npk); + let epk = eph_holder.generate_ephemeral_public_key(); Some(PrivateAccountKeys { npk: pre.npk.clone(), ssk: eph_holder.calculate_shared_secret_sender(&pre.vpk), vpk: pre.vpk.clone(), - epk: eph_holder.generate_ephemeral_public_key(), + epk, }) } State::Public { .. } => None, @@ -150,6 +153,18 @@ impl AccountManager { .collect() } + pub fn private_account_identifiers(&self) -> Vec { + self.states + .iter() + .filter_map(|state| match state { + State::Private(pre) => { + Some(pre.identifier) + } + State::Public { .. } => None, + }) + .collect() + } + pub fn private_account_auth(&self) -> Vec { self.states .iter() @@ -192,6 +207,7 @@ impl AccountManager { } struct AccountPreparedData { + identifier: Identifier, nsk: Option, npk: NullifierPublicKey, vpk: ViewingPublicKey, @@ -209,6 +225,7 @@ async fn private_acc_preparation( let from_keys = from_bundle.key_chain; let from_acc = from_bundle.account; + let from_identifier = from_bundle.identifier; let nsk = from_keys.private_key_holder.nullifier_secret_key; @@ -226,6 +243,7 @@ async fn private_acc_preparation( let sender_pre = AccountWithMetadata::new(from_acc.clone(), true, account_id); Ok(AccountPreparedData { + identifier: from_identifier, nsk: Some(nsk), npk: from_npk, vpk: from_vpk,