fix identifier for pda

This commit is contained in:
Sergio Chouhy 2026-04-24 17:04:40 -03:00
parent 7c45b5af3c
commit 52992a124a
39 changed files with 20 additions and 28 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -913,18 +913,6 @@ mod tests {
assert_ne!(private_id, public_id);
}
/// A private PDA address differs from a standard private account address at the same `npk`,
/// because the private PDA formula includes `program_id` and `seed`.
#[test]
fn for_private_pda_differs_from_standard_private() {
let program_id: ProgramId = [1; 8];
let seed = PdaSeed::new([2; 32]);
let npk = NullifierPublicKey([3; 32]);
let private_pda_id = AccountId::for_private_pda(&program_id, &seed, &npk);
let standard_private_id = AccountId::from(&npk);
assert_ne!(private_pda_id, standard_private_id);
}
// ---- compute_public_authorized_pdas tests ----
/// `compute_public_authorized_pdas` returns the public PDA addresses for the caller's seeds.

View File

@ -2373,7 +2373,7 @@ pub mod tests {
vec![public_account_1, private_pda_account],
Program::serialize_instruction(10_u128).unwrap(),
visibility_mask.to_vec(),
vec![(npk, shared_secret)],
vec![(npk, 0, shared_secret)],
vec![],
vec![None],
&program.into(),
@ -2402,7 +2402,7 @@ pub mod tests {
vec![pre_state],
Program::serialize_instruction(seed).unwrap(),
vec![3],
vec![(npk, shared_secret)],
vec![(npk, 0, shared_secret)],
vec![],
vec![None],
&program.into(),
@ -2440,7 +2440,7 @@ pub mod tests {
vec![pre_state],
Program::serialize_instruction(seed).unwrap(),
vec![3],
vec![(npk_b, shared_secret)],
vec![(npk_b, 0, shared_secret)],
vec![],
vec![None],
&program.into(),
@ -2474,7 +2474,7 @@ pub mod tests {
vec![pre_state],
Program::serialize_instruction((seed, seed, callee_id)).unwrap(),
vec![3],
vec![(npk, shared_secret)],
vec![(npk, 0, shared_secret)],
vec![],
vec![None],
&program_with_deps,
@ -2511,7 +2511,7 @@ pub mod tests {
vec![pre_state],
Program::serialize_instruction((claim_seed, wrong_delegated_seed, callee_id)).unwrap(),
vec![3],
vec![(npk, shared_secret)],
vec![(npk, 0, shared_secret)],
vec![],
vec![None],
&program_with_deps,
@ -2547,7 +2547,7 @@ pub mod tests {
vec![pre_a, pre_b],
Program::serialize_instruction(seed).unwrap(),
vec![3, 3],
vec![(keys_a.npk(), shared_a), (keys_b.npk(), shared_b)],
vec![(keys_a.npk(), 0, shared_a), (keys_b.npk(), 0, shared_b)],
vec![],
vec![None, None],
&program.into(),
@ -2591,7 +2591,7 @@ pub mod tests {
vec![owned_pre_state],
Program::serialize_instruction(()).unwrap(),
vec![3],
vec![(npk, shared_secret)],
vec![(npk, 0, shared_secret)],
vec![],
vec![None],
&program.into(),

View File

@ -17,6 +17,8 @@ use nssa_core::{
};
use risc0_zkvm::{guest::env, serde::to_vec};
const PRIVATE_PDA_FIXED_IDENTIFIER: u128 = 0;
/// State of the involved accounts before and after program execution.
struct ExecutionState {
pre_states: Vec<AccountWithMetadata>,
@ -54,7 +56,7 @@ impl ExecutionState {
/// Validate program outputs and derive the overall execution state.
pub fn derive_from_outputs(
visibility_mask: &[u8],
private_account_keys: &[(NullifierPublicKey, SharedSecretKey)],
private_account_keys: &[(NullifierPublicKey, Identifier, SharedSecretKey)],
program_id: ProgramId,
program_outputs: Vec<ProgramOutput>,
) -> Self {
@ -67,7 +69,7 @@ impl ExecutionState {
let mut keys_iter = private_account_keys.iter();
for (pos, &mask) in visibility_mask.iter().enumerate() {
if matches!(mask, 1..=3) {
let (npk, _) = keys_iter.next().unwrap_or_else(|| {
let (npk, _, _) = keys_iter.next().unwrap_or_else(|| {
panic!(
"private_account_keys shorter than visibility_mask demands: no key for masked position {pos} (mask {mask})"
)
@ -627,10 +629,12 @@ fn compute_circuit_output(
// `private_pda_bound_positions` check) guarantees that every mask-3
// position has been through at least one such binding, so this
// branch can safely use the wallet npk without re-verifying.
let Some((npk, shared_secret)) = private_keys_iter.next() else {
let Some((npk, identifier, shared_secret)) = private_keys_iter.next() else {
panic!("Missing private account key");
};
assert_eq!(*identifier, PRIVATE_PDA_FIXED_IDENTIFIER);
let (new_nullifier, new_nonce) = if pre_state.is_authorized {
// Existing private PDA with authentication (like mask 1)
let Some(nsk) = private_nsks_iter.next() else {
@ -649,7 +653,7 @@ fn compute_circuit_output(
let new_nullifier = compute_nullifier_and_set_digest(
membership_proof_opt.as_ref(),
&pre_state.account,
npk,
&pre_state.account_id,
nsk,
);
let new_nonce = pre_state.account.nonce.private_account_nonce_increment(nsk);
@ -676,8 +680,8 @@ fn compute_circuit_output(
"Membership proof must be None for new accounts"
);
let nullifier = Nullifier::for_account_initialization(npk);
let new_nonce = Nonce::private_account_nonce_init(npk);
let nullifier = Nullifier::for_account_initialization(&pre_state.account_id);
let new_nonce = Nonce::private_account_nonce_init(&pre_state.account_id);
((nullifier, DUMMY_COMMITMENT_HASH), new_nonce)
};
output.new_nullifiers.push(new_nullifier);
@ -685,10 +689,11 @@ fn compute_circuit_output(
let mut post_with_updated_nonce = post_state;
post_with_updated_nonce.nonce = new_nonce;
let commitment_post = Commitment::new(npk, &post_with_updated_nonce);
let commitment_post = Commitment::new(&pre_state.account_id, &post_with_updated_nonce);
let encrypted_account = EncryptionScheme::encrypt(
&post_with_updated_nonce,
PRIVATE_PDA_FIXED_IDENTIFIER,
shared_secret,
&commitment_post,
output_index,

View File

@ -280,8 +280,7 @@ impl WalletCore {
.expect("Node was just inserted")
.value
.0
.nullifier_public_key
.clone();
.nullifier_public_key;
let account_id = AccountId::from((&npk, identifier));
self.storage
.insert_private_account_data(account_id, identifier, Account::default());