diff --git a/artifacts/program_methods/amm.bin b/artifacts/program_methods/amm.bin index 3fe66c82..4bcacde6 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 145fe6b3..df9f70c4 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 d1b8e8da..b83d1512 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 35253e11..59cb4c99 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 c9f5889e..8705fdca 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 e8f98f89..1d8334fe 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 08658930..08ec4bd8 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 b29e8106..9f13f752 100644 Binary files a/artifacts/program_methods/token.bin and b/artifacts/program_methods/token.bin differ diff --git a/artifacts/test_program_methods/auth_asserting_noop.bin b/artifacts/test_program_methods/auth_asserting_noop.bin index bdf62075..134b7df3 100644 Binary files a/artifacts/test_program_methods/auth_asserting_noop.bin and b/artifacts/test_program_methods/auth_asserting_noop.bin differ diff --git a/artifacts/test_program_methods/auth_transfer_proxy.bin b/artifacts/test_program_methods/auth_transfer_proxy.bin index f442b6d0..e10a306e 100644 Binary files a/artifacts/test_program_methods/auth_transfer_proxy.bin and b/artifacts/test_program_methods/auth_transfer_proxy.bin differ diff --git a/artifacts/test_program_methods/burner.bin b/artifacts/test_program_methods/burner.bin index 3b321249..22a69b34 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 4805301c..2c000b02 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 99414df8..0a264c95 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 3a743982..af19cd53 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 1e161ebf..29d09f9e 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 090e28d8..e87f7e61 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 a7c6c8b3..a8c3ffbd 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 6b46a358..ce11f29a 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 fe8e7917..e1815180 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 ce97c6c3..cab7fbba 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 89350a41..f4e75988 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 ccaacae7..d3a198ca 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 ae3ddafd..47351559 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 fad5e6f4..69d073e0 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 63b7be74..451a6701 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 63904a32..025415dc 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 406360e0..25ea9c5b 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/pda_claimer.bin b/artifacts/test_program_methods/pda_claimer.bin index 614737b3..8a8d7dd4 100644 Binary files a/artifacts/test_program_methods/pda_claimer.bin and b/artifacts/test_program_methods/pda_claimer.bin differ diff --git a/artifacts/test_program_methods/pinata_cooldown.bin b/artifacts/test_program_methods/pinata_cooldown.bin index 0429cdf1..1475eddc 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/private_pda_delegator.bin b/artifacts/test_program_methods/private_pda_delegator.bin index 36329f81..8ce9b6b1 100644 Binary files a/artifacts/test_program_methods/private_pda_delegator.bin and b/artifacts/test_program_methods/private_pda_delegator.bin differ diff --git a/artifacts/test_program_methods/private_pda_spender.bin b/artifacts/test_program_methods/private_pda_spender.bin index 26e94d0c..1b2ee29b 100644 Binary files a/artifacts/test_program_methods/private_pda_spender.bin and b/artifacts/test_program_methods/private_pda_spender.bin differ diff --git a/artifacts/test_program_methods/program_owner_changer.bin b/artifacts/test_program_methods/program_owner_changer.bin index bbfe3610..318c83ea 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 923e6a4e..127954ec 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 93b0a344..8a1356db 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/two_pda_claimer.bin b/artifacts/test_program_methods/two_pda_claimer.bin index d261461e..b6b69192 100644 Binary files a/artifacts/test_program_methods/two_pda_claimer.bin and b/artifacts/test_program_methods/two_pda_claimer.bin differ diff --git a/artifacts/test_program_methods/validity_window.bin b/artifacts/test_program_methods/validity_window.bin index 72fb1d60..d72e84e4 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 e4ed57d1..083270f1 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/integration_tests/tests/private_pda.rs b/integration_tests/tests/private_pda.rs index 7d3c818a..d5afba09 100644 --- a/integration_tests/tests/private_pda.rs +++ b/integration_tests/tests/private_pda.rs @@ -22,11 +22,15 @@ use wallet::{ cli::{Command, account::AccountSubcommand}, }; -/// Funds a private PDA via the proxy program with a chained call to auth_transfer. +/// Funds a private PDA via the proxy program with a chained call to `auth_transfer`. /// -/// A direct call to auth_transfer cannot establish the PDA-to-npk binding because it uses +/// A direct call to `auth_transfer` cannot establish the PDA-to-npk binding because it uses /// `Claim::Authorized` rather than `Claim::Pda`. Routing through the proxy provides the binding -/// via `pda_seeds` in the chained call to auth_transfer. +/// via `pda_seeds` in the chained call to `auth_transfer`. +#[expect( + clippy::too_many_arguments, + reason = "test helper — grouping args would obscure intent" +)] async fn fund_private_pda( wallet: &WalletCore, sender: AccountId, @@ -62,6 +66,10 @@ async fn fund_private_pda( /// Spends from an owned private PDA to a fresh private-foreign recipient. /// /// Alice must own the PDA in the wallet (i.e. it must have been synced after a receive). +#[expect( + clippy::too_many_arguments, + reason = "test helper — grouping args would obscure intent" +)] async fn spend_private_pda( wallet: &WalletCore, pda_account_id: AccountId, diff --git a/nssa/core/src/encryption/mod.rs b/nssa/core/src/encryption/mod.rs index efdb8745..4b675d0e 100644 --- a/nssa/core/src/encryption/mod.rs +++ b/nssa/core/src/encryption/mod.rs @@ -130,8 +130,8 @@ mod tests { #[test] fn encrypt_same_length_for_account_and_pda() { let account = Account::default(); - let secret = SharedSecretKey([0u8; 32]); - let commitment = crate::Commitment::new(&AccountId::new([0u8; 32]), &Account::default()); + let secret = SharedSecretKey([0_u8; 32]); + let commitment = crate::Commitment::new(&AccountId::new([0_u8; 32]), &Account::default()); let account_ct = EncryptionScheme::encrypt( &account, @@ -143,8 +143,8 @@ mod tests { let pda_ct = EncryptionScheme::encrypt( &account, &PrivateAccountKind::Pda { - program_id: [1u32; 8], - seed: PdaSeed::new([2u8; 32]), + program_id: [1_u32; 8], + seed: PdaSeed::new([2_u8; 32]), identifier: 42, }, &secret, diff --git a/nssa/core/src/program.rs b/nssa/core/src/program.rs index 100252f8..a89b0687 100644 --- a/nssa/core/src/program.rs +++ b/nssa/core/src/program.rs @@ -63,21 +63,24 @@ pub enum PrivateAccountKind { } impl PrivateAccountKind { - /// Regular(ident): 0x00 || ident (16 LE) || [0u8; 64] - /// Pda { program_id, seed, ident }: 0x01 || program_id (32 LE) || seed (32) || ident (16 LE) + /// Header layout (all integers little-endian): + /// + /// ```text + /// Regular(ident): 0x00 || ident (16 LE) || [0u8; 64] + /// Pda { program_id, seed, ident }: 0x01 || program_id (32) || seed (32) || ident (16 LE) + /// ``` pub const HEADER_LEN: usize = 81; #[must_use] - pub fn identifier(&self) -> Identifier { + pub const fn identifier(&self) -> Identifier { match self { - Self::Regular(identifier) => *identifier, - Self::Pda { identifier, .. } => *identifier, + Self::Regular(identifier) | Self::Pda { identifier, .. } => *identifier, } } #[must_use] pub fn to_header_bytes(&self) -> [u8; Self::HEADER_LEN] { - let mut bytes = [0u8; Self::HEADER_LEN]; + let mut bytes = [0_u8; Self::HEADER_LEN]; match self { Self::Regular(identifier) => { bytes[0] = 0x00; @@ -90,9 +93,9 @@ impl PrivateAccountKind { identifier, } => { bytes[0] = 0x01; - for (i, &word) in program_id.iter().enumerate() { - bytes[1 + i * 4..1 + (i + 1) * 4].copy_from_slice(&word.to_le_bytes()); - } + let id_bytes: &[u8] = + bytemuck::try_cast_slice(program_id).expect("ProgramId is castable to &[u8]"); + bytes[1..33].copy_from_slice(id_bytes); bytes[33..65].copy_from_slice(seed.as_bytes()); bytes[65..81].copy_from_slice(&identifier.to_le_bytes()); } @@ -109,11 +112,10 @@ impl PrivateAccountKind { Some(Self::Regular(identifier)) } 0x01 => { - let mut program_id = [0u32; 8]; - for (i, word) in program_id.iter_mut().enumerate() { - *word = - u32::from_le_bytes(bytes[1 + i * 4..1 + (i + 1) * 4].try_into().unwrap()); - } + let program_id: ProgramId = bytemuck::try_cast_slice(&bytes[1..33]) + .expect("bytes are castable to &[u32]") + .try_into() + .expect("slice has exactly 8 u32 elements"); let seed = PdaSeed::new(bytes[33..65].try_into().unwrap()); let identifier = Identifier::from_le_bytes(bytes[65..81].try_into().unwrap()); Some(Self::Pda { @@ -1009,8 +1011,8 @@ mod tests { ); } - /// Different identifiers produce different addresses for the same (program_id, seed, npk), - /// confirming that each (program_id, seed, npk) controls a family of 2^128 addresses. + /// Different identifiers produce different addresses for the same `(program_id, seed, npk)`, + /// confirming that each `(program_id, seed, npk)` tuple controls a family of 2^128 addresses. #[test] fn for_private_pda_differs_for_different_identifier() { let program_id: ProgramId = [1; 8]; @@ -1043,8 +1045,8 @@ mod tests { fn private_account_kind_header_round_trips() { let regular = PrivateAccountKind::Regular(42); let pda = PrivateAccountKind::Pda { - program_id: [1u32; 8], - seed: PdaSeed::new([2u8; 32]), + program_id: [1_u32; 8], + seed: PdaSeed::new([2_u8; 32]), identifier: u128::MAX, }; assert_eq!( @@ -1060,7 +1062,7 @@ mod tests { #[cfg(feature = "host")] #[test] fn private_account_kind_unknown_discriminant_returns_none() { - let mut bytes = [0u8; PrivateAccountKind::HEADER_LEN]; + let mut bytes = [0_u8; PrivateAccountKind::HEADER_LEN]; bytes[0] = 0xFF; assert_eq!(PrivateAccountKind::from_header_bytes(&bytes), None); } @@ -1079,7 +1081,11 @@ mod tests { assert_eq!( AccountId::for_private_account( &npk, - &PrivateAccountKind::Pda { program_id, seed, identifier } + &PrivateAccountKind::Pda { + program_id, + seed, + identifier + } ), AccountId::for_private_pda(&program_id, &seed, &npk, identifier), ); diff --git a/nssa/src/privacy_preserving_transaction/circuit.rs b/nssa/src/privacy_preserving_transaction/circuit.rs index b3ec2dba..750e7602 100644 --- a/nssa/src/privacy_preserving_transaction/circuit.rs +++ b/nssa/src/privacy_preserving_transaction/circuit.rs @@ -182,21 +182,6 @@ mod tests { program::{PdaSeed, PrivateAccountKind}, }; - fn decrypt_kind( - output: &PrivacyPreservingCircuitOutput, - ssk: &SharedSecretKey, - idx: usize, - ) -> PrivateAccountKind { - let (kind, _) = EncryptionScheme::decrypt( - &output.ciphertexts[idx], - ssk, - &output.new_commitments[idx], - idx as u32, - ) - .unwrap(); - kind - } - use super::*; use crate::{ error::NssaError, @@ -208,6 +193,21 @@ mod tests { }, }; + fn decrypt_kind( + output: &PrivacyPreservingCircuitOutput, + ssk: &SharedSecretKey, + idx: usize, + ) -> PrivateAccountKind { + let (kind, _) = EncryptionScheme::decrypt( + &output.ciphertexts[idx], + ssk, + &output.new_commitments[idx], + u32::try_from(idx).expect("idx fits in u32"), + ) + .unwrap(); + kind + } + #[test] fn prove_privacy_preserving_execution_circuit_public_and_private_pre_accounts() { let recipient_keys = test_private_account_keys_1(); @@ -453,7 +453,7 @@ mod tests { Program::serialize_instruction(seed).unwrap(), vec![InputAccountIdentity::PrivatePdaInit { npk, - ssk: shared_secret.clone(), + ssk: shared_secret, identifier, }], &program.clone().into(), @@ -589,7 +589,7 @@ mod tests { vec![pre], Program::serialize_instruction(0_u128).unwrap(), vec![InputAccountIdentity::PrivateAuthorizedInit { - ssk: ssk.clone(), + ssk, nsk: keys.nsk, identifier, }], @@ -631,7 +631,7 @@ mod tests { InputAccountIdentity::Public, InputAccountIdentity::PrivateUnauthorized { npk: keys.npk(), - ssk: ssk.clone(), + ssk, identifier, }, ], @@ -671,7 +671,7 @@ mod tests { Program::serialize_instruction(1_u128).unwrap(), vec![ InputAccountIdentity::PrivateAuthorizedUpdate { - ssk: ssk.clone(), + ssk, nsk: keys.nsk, membership_proof: commitment_set.get_proof_for(&commitment).unwrap(), identifier, @@ -725,7 +725,7 @@ mod tests { Program::serialize_instruction((seed, 1_u128, auth_transfer_id, false)).unwrap(), vec![ InputAccountIdentity::PrivatePdaUpdate { - ssk: ssk.clone(), + ssk, nsk: keys.nsk, membership_proof: commitment_set.get_proof_for(&pda_commitment).unwrap(), identifier, @@ -795,10 +795,8 @@ mod tests { let recipient_pre = AccountWithMetadata::new(Account::default(), true, AccountId::new([0; 32])); - let program_with_deps = ProgramWithDependencies::new( - program, - [(auth_transfer_id, auth_transfer)].into(), - ); + let program_with_deps = + ProgramWithDependencies::new(program, [(auth_transfer_id, auth_transfer)].into()); let result = execute_and_prove( vec![pda_pre, recipient_pre], diff --git a/nssa/src/state.rs b/nssa/src/state.rs index 55f75cc4..5e09ab04 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -4355,7 +4355,7 @@ pub mod tests { InputAccountIdentity::Public, InputAccountIdentity::PrivatePdaInit { npk: alice_npk, - ssk: alice_shared_0.clone(), + ssk: alice_shared_0, identifier: 0, }, ], @@ -4397,7 +4397,7 @@ pub mod tests { InputAccountIdentity::Public, InputAccountIdentity::PrivatePdaInit { npk: alice_npk, - ssk: alice_shared_1.clone(), + ssk: alice_shared_1, identifier: 1, }, ], diff --git a/test_program_methods/guest/src/bin/auth_transfer_proxy.rs b/test_program_methods/guest/src/bin/auth_transfer_proxy.rs index 8a0bbd9c..c02261f9 100644 --- a/test_program_methods/guest/src/bin/auth_transfer_proxy.rs +++ b/test_program_methods/guest/src/bin/auth_transfer_proxy.rs @@ -7,15 +7,15 @@ use nssa_core::{ }; use risc0_zkvm::serde::to_vec; -/// Proxy for interacting with private PDAs via auth_transfer. +/// Proxy for interacting with private PDAs via `auth_transfer`. /// /// The `is_fund` flag selects the operating mode: /// -/// - `false` (Spend): pre_states = [pda (authorized), recipient]. Debits the PDA. The PDA-to-npk -/// binding is established via `pda_seeds` in the chained call to auth_transfer. +/// - `false` (Spend): `pre_states = [pda (authorized), recipient]`. Debits the PDA. The PDA-to-npk +/// binding is established via `pda_seeds` in the chained call to `auth_transfer`. /// -/// - `true` (Fund): pre_states = [sender (authorized), pda (foreign/uninitialized)]. Credits the -/// PDA. A direct call to auth_transfer cannot bind the PDA because auth_transfer uses +/// - `true` (Fund): `pre_states = [sender (authorized), pda (foreign/uninitialized)]`. Credits the +/// PDA. A direct call to `auth_transfer` cannot bind the PDA because `auth_transfer` uses /// `Claim::Authorized`, not `Claim::Pda`. Routing through this proxy establishes the binding via /// `pda_seeds` in the chained call. type Instruction = (PdaSeed, u128, ProgramId, bool); diff --git a/wallet/src/privacy_preserving_tx.rs b/wallet/src/privacy_preserving_tx.rs index d83d0584..a42efd3c 100644 --- a/wallet/src/privacy_preserving_tx.rs +++ b/wallet/src/privacy_preserving_tx.rs @@ -19,7 +19,7 @@ pub enum PrivacyPreservingAccount { vpk: ViewingPublicKey, identifier: Identifier, }, - /// An owned private PDA: wallet holds the nsk/npk; account_id was derived via + /// An owned private PDA: wallet holds the nsk/npk; `account_id` was derived via /// `AccountId::for_private_pda`. Produces visibility mask 3. PrivatePdaOwned(AccountId), /// A foreign private PDA: wallet knows the recipient's npk/vpk but not their nsk.