diff --git a/artifacts/program_methods/amm.bin b/artifacts/program_methods/amm.bin index 36caad85..31e0bd7b 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 9f5474a9..ddbfff47 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 bdbcef61..c343394d 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 d3ca0dab..983bd43e 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 5e6a011b..7557bfc5 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 57a201c4..04dd51c6 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 dd613143..e9b2ca7f 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 6366eba6..9664737c 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 f9e4d1d4..eddfb92b 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/burner.bin b/artifacts/test_program_methods/burner.bin index 94a90236..9373e039 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 58331d6c..b0a65b7e 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 2760b7a3..42885442 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 ff504da1..d0e869ca 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 37c9a004..1ff6f849 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 3d69b8cb..c7b4900f 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 873ce66a..e7d210db 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 0846f255..84f245f5 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 1e285245..a374d90e 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 cc757683..bd70757e 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 f152051d..b7538bf6 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 6d83b95b..3ee29400 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 29bcd715..d5fcf65e 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 c7cc1571..f1258f73 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 8f2b1e39..e719836f 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 993c1451..c548c76b 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 579db977..80d37034 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 1a541384..f5d8f49b 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 2b0d979a..c5d22535 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 4b55e871..33948d96 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/program_owner_changer.bin b/artifacts/test_program_methods/program_owner_changer.bin index 3bdabade..18a5019d 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 0aaf1a23..12f5d9fd 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 5700322e..7214c10f 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 600b819d..8eba6554 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 02ccc149..daca701e 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 d239c750..f7c9bab1 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/nssa/core/src/program.rs b/nssa/core/src/program.rs index 1ef2ef6c..14390f25 100644 --- a/nssa/core/src/program.rs +++ b/nssa/core/src/program.rs @@ -6,7 +6,7 @@ use risc0_zkvm::{DeserializeOwned, guest::env, serde::Deserializer}; use serde::{Deserialize, Serialize}; use crate::{ - BlockId, NullifierPublicKey, Timestamp, + BlockId, Identifier, NullifierPublicKey, Timestamp, account::{Account, AccountId, AccountWithMetadata}, }; @@ -59,27 +59,31 @@ impl AccountId { ) } - /// Derives an [`AccountId`] for a private PDA from the program ID, seed, and nullifier - /// public key. + /// Derives an [`AccountId`] for a private PDA from the program ID, seed, nullifier public + /// key, and identifier. /// /// Unlike public PDAs ([`AccountId::for_public_pda`]), this includes the `npk` in the /// derivation, making the address unique per group of controllers sharing viewing keys. + /// The `identifier` further diversifies the address, so a single `(program_id, seed, npk)` + /// tuple controls a family of 2^128 addresses. #[must_use] pub fn for_private_pda( program_id: &ProgramId, seed: &PdaSeed, npk: &NullifierPublicKey, + identifier: Identifier, ) -> Self { use risc0_zkvm::sha::{Impl, Sha256 as _}; const PRIVATE_PDA_PREFIX: &[u8; 32] = b"/LEE/v0.3/AccountId/PrivatePDA/\x00"; - let mut bytes = [0_u8; 128]; + let mut bytes = [0_u8; 144]; bytes[0..32].copy_from_slice(PRIVATE_PDA_PREFIX); let program_id_bytes: &[u8] = bytemuck::try_cast_slice(program_id).expect("ProgramId should be castable to &[u8]"); bytes[32..64].copy_from_slice(program_id_bytes); bytes[64..96].copy_from_slice(&seed.0); bytes[96..128].copy_from_slice(&npk.to_byte_array()); + bytes[128..144].copy_from_slice(&identifier.to_le_bytes()); Self::new( Impl::hash_bytes(&bytes) .as_bytes() @@ -845,19 +849,20 @@ mod tests { // ---- AccountId::for_private_pda tests ---- /// Pins `AccountId::for_private_pda` against a hardcoded expected output for a specific - /// `(program_id, seed, npk)` triple. Any change to `PRIVATE_PDA_PREFIX`, byte ordering, - /// or the underlying hash breaks this test. + /// `(program_id, seed, npk, identifier)` tuple. Any change to `PRIVATE_PDA_PREFIX`, byte + /// ordering, or the underlying hash breaks this test. #[test] fn for_private_pda_matches_pinned_value() { let program_id: ProgramId = [1; 8]; let seed = PdaSeed::new([2; 32]); let npk = NullifierPublicKey([3; 32]); + let identifier: Identifier = u128::MAX; let expected = AccountId::new([ - 132, 198, 103, 173, 244, 211, 188, 217, 249, 99, 126, 205, 152, 120, 192, 47, 13, 53, - 133, 3, 17, 69, 92, 243, 140, 94, 182, 211, 218, 75, 215, 45, + 59, 239, 182, 97, 14, 220, 96, 115, 238, 133, 143, 33, 234, 82, 237, 255, 148, 110, + 54, 124, 98, 159, 245, 101, 146, 182, 150, 54, 37, 62, 25, 17, ]); assert_eq!( - AccountId::for_private_pda(&program_id, &seed, &npk), + AccountId::for_private_pda(&program_id, &seed, &npk, identifier), expected ); } @@ -870,8 +875,8 @@ mod tests { let npk_a = NullifierPublicKey([3; 32]); let npk_b = NullifierPublicKey([4; 32]); assert_ne!( - AccountId::for_private_pda(&program_id, &seed, &npk_a), - AccountId::for_private_pda(&program_id, &seed, &npk_b), + AccountId::for_private_pda(&program_id, &seed, &npk_a, u128::MAX), + AccountId::for_private_pda(&program_id, &seed, &npk_b, u128::MAX), ); } @@ -883,8 +888,8 @@ mod tests { let seed_b = PdaSeed::new([5; 32]); let npk = NullifierPublicKey([3; 32]); assert_ne!( - AccountId::for_private_pda(&program_id, &seed_a, &npk), - AccountId::for_private_pda(&program_id, &seed_b, &npk), + AccountId::for_private_pda(&program_id, &seed_a, &npk, u128::MAX), + AccountId::for_private_pda(&program_id, &seed_b, &npk, u128::MAX), ); } @@ -896,8 +901,8 @@ mod tests { let seed = PdaSeed::new([2; 32]); let npk = NullifierPublicKey([3; 32]); assert_ne!( - AccountId::for_private_pda(&program_id_a, &seed, &npk), - AccountId::for_private_pda(&program_id_b, &seed, &npk), + AccountId::for_private_pda(&program_id_a, &seed, &npk, u128::MAX), + AccountId::for_private_pda(&program_id_b, &seed, &npk, u128::MAX), ); } @@ -908,7 +913,7 @@ mod tests { let program_id: ProgramId = [1; 8]; let seed = PdaSeed::new([2; 32]); let npk = NullifierPublicKey([3; 32]); - let private_id = AccountId::for_private_pda(&program_id, &seed, &npk); + let private_id = AccountId::for_private_pda(&program_id, &seed, &npk, u128::MAX); let public_id = AccountId::for_public_pda(&program_id, &seed); assert_ne!(private_id, public_id); } diff --git a/nssa/src/state.rs b/nssa/src/state.rs index ff16175c..6285677e 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -2395,7 +2395,7 @@ pub mod tests { let seed = PdaSeed::new([42; 32]); let shared_secret = SharedSecretKey::new(&[55; 32], &keys.vpk()); - let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk); + let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk, u128::MAX); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let result = execute_and_prove( @@ -2433,7 +2433,7 @@ pub mod tests { // `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); + let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk_a, u128::MAX); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let result = execute_and_prove( @@ -2463,7 +2463,7 @@ pub mod tests { let seed = PdaSeed::new([77; 32]); let shared_secret = SharedSecretKey::new(&[55; 32], &keys.vpk()); - let account_id = AccountId::for_private_pda(&delegator.id(), &seed, &npk); + let account_id = AccountId::for_private_pda(&delegator.id(), &seed, &npk, u128::MAX); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let callee_id = callee.id(); @@ -2500,7 +2500,7 @@ pub mod tests { let wrong_delegated_seed = PdaSeed::new([88; 32]); let shared_secret = SharedSecretKey::new(&[55; 32], &keys.vpk()); - let account_id = AccountId::for_private_pda(&delegator.id(), &claim_seed, &npk); + let account_id = AccountId::for_private_pda(&delegator.id(), &claim_seed, &npk, u128::MAX); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let callee_id = callee.id(); @@ -2537,8 +2537,8 @@ pub mod tests { let shared_a = SharedSecretKey::new(&[66; 32], &keys_a.vpk()); let shared_b = SharedSecretKey::new(&[77; 32], &keys_b.vpk()); - let account_a = AccountId::for_private_pda(&program.id(), &seed, &keys_a.npk()); - let account_b = AccountId::for_private_pda(&program.id(), &seed, &keys_b.npk()); + 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 pre_a = AccountWithMetadata::new(Account::default(), false, account_a); let pre_b = AccountWithMetadata::new(Account::default(), false, account_b); @@ -2577,7 +2577,7 @@ pub mod tests { // 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); + let account_id = AccountId::for_private_pda(&program.id(), &seed, &npk, u128::MAX); let owned_pre_state = AccountWithMetadata::new( Account { program_owner: program.id(), diff --git a/program_methods/guest/src/bin/privacy_preserving_circuit.rs b/program_methods/guest/src/bin/privacy_preserving_circuit.rs index 70979b7e..a1e2ca61 100644 --- a/program_methods/guest/src/bin/privacy_preserving_circuit.rs +++ b/program_methods/guest/src/bin/privacy_preserving_circuit.rs @@ -367,7 +367,7 @@ impl ExecutionState { .private_pda_npk_by_position .get(&pre_state_position) .expect("private PDA pre_state must have an npk in the position map"); - let pda = AccountId::for_private_pda(&program_id, &seed, npk); + let pda = AccountId::for_private_pda(&program_id, &seed, npk, PRIVATE_PDA_FIXED_IDENTIFIER); assert_eq!( pre_account_id, pda, "Invalid private PDA claim for account {pre_account_id}" @@ -468,7 +468,7 @@ fn resolve_authorization_and_record_bindings( return Some((*seed, false, caller)); } if let Some(npk) = private_pda_npk_by_position.get(&pre_state_position) - && AccountId::for_private_pda(&caller, seed, npk) == pre_account_id + && AccountId::for_private_pda(&caller, seed, npk, PRIVATE_PDA_FIXED_IDENTIFIER) == pre_account_id { return Some((*seed, true, caller)); }