diff --git a/nssa/core/src/program.rs b/nssa/core/src/program.rs index e8c56414..5d78ce79 100644 --- a/nssa/core/src/program.rs +++ b/nssa/core/src/program.rs @@ -68,8 +68,8 @@ pub struct ChainedCall { /// PDA seeds authorized for the callee. For each callee `pre_state`, the outer circuit /// checks whether its `AccountId` matches a public PDA derivation /// `AccountId::from((&caller, seed))` (mask 0) or a private PDA derivation - /// `private_pda_account_id(&caller, seed, npk)` (mask 3, where `npk` is the wallet-supplied - /// npk for that `pre_state`). Programs stay privacy-agnostic: they emit seeds, the circuit + /// `private_pda_account_id(&caller, seed, npk)` (mask 3, where `npk` is the supplied npk + /// for that `pre_state`). Programs stay privacy-agnostic: they emit seeds, the circuit /// resolves public vs private based on the `pre_state`'s mask. pub pda_seeds: Vec, } @@ -123,7 +123,7 @@ pub enum Claim { /// The program requests ownership of the account through a PDA. The `pre_state`'s /// visibility mask selects the derivation formula: mask 0 uses /// `AccountId::from((&program_id, &seed))`, mask 3 uses - /// `private_pda_account_id(&program_id, &seed, &npk)` with the wallet-supplied npk for that + /// `private_pda_account_id(&program_id, &seed, &npk)` with the supplied npk for that /// `pre_state`. Programs stay privacy-agnostic: they emit a seed, the circuit resolves the /// rest from the mask. Pda(PdaSeed), @@ -520,8 +520,8 @@ pub fn private_pda_account_id( /// /// Returns only public-form derivations, suitable for contexts where all accounts are public /// (e.g. the public-execution path). The privacy circuit must additionally check each mask-3 -/// `pre_state` against `private_pda_account_id(caller, seed, npk)` with the wallet-supplied -/// npk for that `pre_state`. +/// `pre_state` against `private_pda_account_id(caller, seed, npk)` with the supplied npk for +/// that `pre_state`. #[must_use] pub fn compute_authorized_pdas( caller_program_id: Option, diff --git a/nssa/src/state.rs b/nssa/src/state.rs index 81d441e6..a75f61f0 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -2315,9 +2315,9 @@ pub mod tests { } /// A mask-3 account that no program claims via `Claim::Pda` and no caller authorizes via - /// `ChainedCall.pda_seeds` has no binding between its wallet-supplied npk and its - /// `account_id`, so the circuit must reject. Here `simple_balance_transfer` emits no claim - /// for the second account, leaving position 1 unbound. + /// `ChainedCall.pda_seeds` has no binding between its supplied npk and its `account_id`, + /// so the circuit must reject. Here `simple_balance_transfer` emits no claim for the + /// second account, leaving position 1 unbound. #[test] fn mask_3_without_binding_panics() { let program = Program::simple_balance_transfer(); @@ -2354,7 +2354,7 @@ pub mod tests { /// reads the npk for that `pre_state` from `private_account_keys` at the `pre_state`'s /// position, derives `AccountId` via `private_pda_account_id(program_id, seed, npk)`, and /// asserts it equals the `pre_state`'s `account_id`. The equality both validates the claim - /// and binds the wallet-supplied npk to the `account_id`. + /// and binds the supplied npk to the `account_id`. #[test] fn mask_3_private_pda_claim_succeeds() { let program = Program::pda_claimer(); @@ -2384,29 +2384,31 @@ pub mod tests { assert!(output.public_post_states.is_empty()); } - /// The wallet supplies an npk that does not match the `pre_state`'s `account_id` under + /// An npk is supplied that does not match the `pre_state`'s `account_id` under /// `private_pda_account_id(program, claim_seed, npk)`. The claim equality check rejects. #[test] fn mask_3_wallet_npk_mismatch_panics() { + // `keys_a` produces the `pre_state`'s `account_id` (the registered pair), `keys_b` is + // the mismatched pair supplied in `private_account_keys` for that pre_state. let program = Program::pda_claimer(); - let attested_keys = test_private_account_keys_1(); - let wallet_keys = test_private_account_keys_2(); - let attested_npk = attested_keys.npk(); - let wallet_npk = wallet_keys.npk(); + let keys_a = test_private_account_keys_1(); + let keys_b = test_private_account_keys_2(); + let npk_a = keys_a.npk(); + let npk_b = keys_b.npk(); let seed = PdaSeed::new([42; 32]); - let shared_secret = SharedSecretKey::new(&[55; 32], &wallet_keys.vpk()); + let shared_secret = SharedSecretKey::new(&[55; 32], &keys_b.vpk()); - // account_id is derived from `attested_npk`, but the wallet provides `wallet_npk` for - // this pre_state. `private_pda_account_id(program, seed, wallet_npk) != account_id`, so - // the claim check in the circuit must reject. - let account_id = private_pda_account_id(&program.id(), &seed, &attested_npk); + // `account_id` is derived from `npk_a`, but `npk_b` is supplied for this pre_state. + // `private_pda_account_id(program, seed, npk_b) != account_id`, so the claim check in + // the circuit must reject. + let account_id = private_pda_account_id(&program.id(), &seed, &npk_a); let pre_state = AccountWithMetadata::new(Account::default(), false, account_id); let result = execute_and_prove( vec![pre_state], Program::serialize_instruction(seed).unwrap(), vec![3], - vec![(wallet_npk, shared_secret)], + vec![(npk_b, shared_secret)], vec![], vec![None], &program.into(), diff --git a/program_methods/guest/src/bin/privacy_preserving_circuit.rs b/program_methods/guest/src/bin/privacy_preserving_circuit.rs index 597a0c98..435a0221 100644 --- a/program_methods/guest/src/bin/privacy_preserving_circuit.rs +++ b/program_methods/guest/src/bin/privacy_preserving_circuit.rs @@ -187,7 +187,7 @@ impl ExecutionState { // Every mask-3 pre_state must have had its npk bound to its account_id, either via a // `Claim::Pda(seed)` in some program's post_state or via a caller's `pda_seeds` matching // the private derivation. An unbound mask-3 pre_state has no cryptographic link between - // the wallet-supplied npk and the account_id, and must be rejected. + // the supplied npk and the account_id, and must be rejected. for (pos, &mask) in visibility_mask.iter().enumerate() { if mask == 3 { assert!( @@ -575,7 +575,7 @@ fn compute_circuit_output( .unwrap_or_else(|| panic!("Too many private accounts, output index overflow")); } 3 => { - // Private PDA account. The wallet-supplied npk has already been bound to + // Private PDA account. The supplied npk has already been bound to // `pre_state.account_id` upstream in `validate_and_sync_states`, either via a // `Claim::Pda(seed)` match or via a caller `pda_seeds` match, both of which // assert `private_pda_account_id(owner, seed, npk) == account_id`. The post-loop