From 5df494ac08d2880127388f750c192bf7bffbc641 Mon Sep 17 00:00:00 2001 From: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> Date: Fri, 3 Apr 2026 19:02:03 -0400 Subject: [PATCH] fixed tests --- .../privacy_preserving_circuit.bin | Bin 537520 -> 537536 bytes integration_tests/tests/tps.rs | 2 +- nssa/src/state.rs | 573 +++++++++--------- .../src/bin/privacy_preserving_circuit.rs | 4 +- 4 files changed, 301 insertions(+), 278 deletions(-) diff --git a/artifacts/program_methods/privacy_preserving_circuit.bin b/artifacts/program_methods/privacy_preserving_circuit.bin index 3b841c8165926b790df4faae0c32719e2c9fb3ba..4d82008fa4273759d6fa0597bb29f346d5c235f3 100644 GIT binary patch delta 100042 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 CzNC!+ delta 100111 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[GReZMem8; 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 diff --git a/integration_tests/tests/tps.rs b/integration_tests/tests/tps.rs index a3cd74ce..b83ae80a 100644 --- a/integration_tests/tests/tps.rs +++ b/integration_tests/tests/tps.rs @@ -256,7 +256,7 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction { vec![1, 2], vec![(sender_npk, sender_ss), (recipient_npk, recipient_ss)], vec![sender_nsk], - vec![], //TODO: marvin fix + vec![], // TODO: marvin fix vec![Some(proof)], &program.into(), ) diff --git a/nssa/src/state.rs b/nssa/src/state.rs index 7d7750cd..2ec2ca32 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -427,7 +427,7 @@ pub mod tests { #[must_use] pub fn with_private_account(mut self, keys: &TestPrivateKeys, account: &Account) -> Self { - let account_id = &AccountId::private_account_id(&keys.npk(), None); + let account_id = &AccountId::private_account_id(&keys.npk(), Some(keys.identifier)); let commitment = Commitment::new(account_id, account); self.private_state.0.extend(&[commitment]); self @@ -447,6 +447,7 @@ pub mod tests { pub struct TestPrivateKeys { pub nsk: NullifierSecretKey, pub vsk: Scalar, + pub identifier: u128, } impl TestPrivateKeys { @@ -941,6 +942,7 @@ pub mod tests { TestPrivateKeys { nsk: [13; 32], vsk: [31; 32], + identifier: 12_u128, } } @@ -948,6 +950,7 @@ pub mod tests { TestPrivateKeys { nsk: [38; 32], vsk: [83; 32], + identifier: 42_u128, } } @@ -965,7 +968,8 @@ pub mod tests { let sender_nonce = sender.account.nonce; - let recipient_id = AccountId::private_account_id(&recipient_keys.npk(), None); + let recipient_id = + AccountId::private_account_id(&recipient_keys.npk(), Some(recipient_keys.identifier)); let recipient = AccountWithMetadata::new(Account::default(), false, recipient_id); let esk = [3; 32]; @@ -978,7 +982,7 @@ pub mod tests { vec![0, 2], vec![(recipient_keys.npk(), shared_secret)], vec![], - vec![], // TODO check (Marvin) + vec![recipient_keys.identifier], // TODO check (Marvin) vec![None], &Program::authenticated_transfer_program().into(), ) @@ -1004,8 +1008,10 @@ pub mod tests { state: &V03State, ) -> PrivacyPreservingTransaction { let program = Program::authenticated_transfer_program(); - let sender_id = AccountId::private_account_id(&sender_keys.npk(), None); - let recipient_id = AccountId::private_account_id(&recipient_keys.npk(), None); + let sender_id = + AccountId::private_account_id(&sender_keys.npk(), Some(sender_keys.identifier)); + let recipient_id = + AccountId::private_account_id(&recipient_keys.npk(), Some(recipient_keys.identifier)); let sender_commitment = Commitment::new(&sender_id, sender_private_account); let sender_pre = AccountWithMetadata::new(sender_private_account.clone(), true, sender_id); let recipient_pre = AccountWithMetadata::new(Account::default(), false, recipient_id); @@ -1027,7 +1033,7 @@ pub mod tests { (recipient_keys.npk(), shared_secret_2), ], vec![sender_keys.nsk], - vec![], // TODO check (Marvin) + vec![sender_keys.identifier, recipient_keys.identifier], // TODO check (Marvin) vec![state.get_proof_for_commitment(&sender_commitment), None], &program.into(), ) @@ -1044,7 +1050,7 @@ pub mod tests { ) .unwrap(); - let witness_set = WitnessSet::for_message(&message, proof, &[]); + let witness_set = WitnessSet::for_message(&message, proof, &[]); //TODO: (Marvin) why no private keys? PrivacyPreservingTransaction::new(message, witness_set) } @@ -1057,7 +1063,8 @@ pub mod tests { state: &V03State, ) -> PrivacyPreservingTransaction { let program = Program::authenticated_transfer_program(); - let sender_id = AccountId::private_account_id(&sender_keys.npk(), None); + let sender_id = + AccountId::private_account_id(&sender_keys.npk(), Some(sender_keys.identifier)); let sender_commitment = Commitment::new(&sender_id, sender_private_account); let sender_pre = AccountWithMetadata::new(sender_private_account.clone(), true, sender_id); let recipient_pre = AccountWithMetadata::new( @@ -1076,7 +1083,7 @@ pub mod tests { vec![1, 0], vec![(sender_keys.npk(), shared_secret)], vec![sender_keys.nsk], - vec![], // TODO check (Marvin) + vec![sender_keys.identifier], // TODO check (Marvin) vec![state.get_proof_for_commitment(&sender_commitment)], &program.into(), ) @@ -1162,8 +1169,10 @@ pub mod tests { &state, ); - let sender_id = AccountId::private_account_id(&sender_keys.npk(), None); - let recipient_id = AccountId::private_account_id(&recipient_keys.npk(), None); + let sender_id = + AccountId::private_account_id(&sender_keys.npk(), Some(sender_keys.identifier)); + let recipient_id = + AccountId::private_account_id(&recipient_keys.npk(), Some(recipient_keys.identifier)); let expected_new_commitment_1 = Commitment::new( &sender_id, @@ -1209,7 +1218,8 @@ pub mod tests { #[test] fn transition_from_privacy_preserving_transaction_deshielded() { let sender_keys = test_private_account_keys_1(); - let sender_id = AccountId::private_account_id(&sender_keys.npk(), None); + let sender_id = + AccountId::private_account_id(&sender_keys.npk(), Some(sender_keys.identifier)); let sender_nonce = Nonce(0xdead_beef); let sender_private_account = Account { @@ -1267,7 +1277,7 @@ pub mod tests { let recipient_post = state.get_account_by_id(recipient_keys.account_id()); assert_eq!(recipient_post, expected_recipient_post); assert!(state.private_state.0.contains(&sender_pre_commitment)); - // assert!(state.private_state.0.contains(&expected_new_commitment)); + assert!(state.private_state.0.contains(&expected_new_commitment)); assert!(state.private_state.1.contains(&expected_new_nullifier)); assert_eq!( state.get_account_by_id(recipient_keys.account_id()).balance, @@ -1995,14 +2005,16 @@ pub mod tests { assert!(matches!(result, Err(NssaError::CircuitProvingError(_)))); } + // TODO: (Marvin) this test does not seem to do what it's supposed to. #[test] fn circuit_should_fail_if_new_private_account_is_provided_with_default_values_but_marked_as_authorized() { let program = Program::simple_balance_transfer(); let sender_keys = test_private_account_keys_1(); - let sender_account_id = AccountId::private_account_id(&sender_keys.npk(), None); + let sender_account_id = AccountId::private_account_id(&sender_keys.npk(), Some(0_u128)); let recipient_keys = test_private_account_keys_2(); - let recipient_account_id = AccountId::private_account_id(&recipient_keys.npk(), None); + let recipient_account_id = + AccountId::private_account_id(&recipient_keys.npk(), Some(1_u128)); let private_account_1 = AccountWithMetadata::new( Account { program_owner: program.id(), @@ -2034,7 +2046,7 @@ pub mod tests { ), ], vec![sender_keys.nsk], - vec![], // TODO check (Marvin) + vec![0_u128, 1_u128], // TODO check (Marvin) vec![Some((0, vec![]))], &program.into(), ); @@ -2042,6 +2054,7 @@ pub mod tests { assert!(matches!(result, Err(NssaError::CircuitProvingError(_)))); } + // TODO: (Marvin) this test does not seem to do what it's supposed to. #[test] fn circuit_should_fail_with_invalid_visibility_mask_value() { let program = Program::simple_balance_transfer(); @@ -2241,7 +2254,7 @@ pub mod tests { .transition_from_privacy_preserving_transaction(&tx, 1, 0) .unwrap(); - let sender_private_account = Account { + let _sender_private_account = Account { program_owner: Program::authenticated_transfer_program().id(), balance: 100, nonce: sender_nonce, @@ -2604,16 +2617,17 @@ pub mod tests { let program = Program::authenticated_transfer_program(); let program_id = program.id(); let sender_keys = test_private_account_keys_1(); - let sender_id = AccountId::private_account_id(&sender_keys.npk(), None); + let sender_account_id = + AccountId::private_account_id(&sender_keys.npk(), Some(sender_keys.identifier)); let sender_private_account = Account { program_owner: program_id, balance: 100, ..Account::default() }; - let sender_commitment = Commitment::new(&sender_id, &sender_private_account); + let sender_commitment = Commitment::new(&sender_account_id, &sender_private_account); let mut state = V03State::new_with_genesis_accounts(&[], std::slice::from_ref(&sender_commitment)); - let sender_pre = AccountWithMetadata::new(sender_private_account, true, sender_id); + let sender_pre = AccountWithMetadata::new(sender_private_account, true, sender_account_id); let recipient_private_key = PrivateKey::try_new([2; 32]).unwrap(); let recipient_account_id = AccountId::public_account_id( &PublicKey::new_from_private_key(&recipient_private_key), @@ -2621,6 +2635,7 @@ pub mod tests { ); let recipient_pre = AccountWithMetadata::new(Account::default(), true, recipient_account_id); + let esk = [5; 32]; let shared_secret = SharedSecretKey::new(&esk, &sender_keys.vpk()); let epk = EphemeralPublicKey::from_scalar(esk); @@ -2631,7 +2646,7 @@ pub mod tests { vec![1, 0], vec![(sender_keys.npk(), shared_secret)], vec![sender_keys.nsk], - vec![], // TODO check (Marvin) + vec![sender_keys.identifier], // TODO check (Marvin) vec![state.get_proof_for_commitment(&sender_commitment)], &program.into(), ) @@ -2640,7 +2655,7 @@ pub mod tests { let message = Message::try_from_circuit_output( vec![recipient_account_id], vec![Nonce(0)], - vec![(sender_id, sender_keys.vpk(), epk)], + vec![(sender_account_id, sender_keys.vpk(), epk)], output, ) .unwrap(); @@ -2974,7 +2989,8 @@ pub mod tests { // Set up keys for the authorized private account let private_keys = test_private_account_keys_1(); - let account_id = AccountId::private_account_id(&private_keys.npk(), None); + let account_id = + AccountId::private_account_id(&private_keys.npk(), Some(private_keys.identifier)); // Create an authorized private account with default values (new account being initialized) let authorized_account = AccountWithMetadata::new(Account::default(), true, account_id); @@ -2996,7 +3012,7 @@ pub mod tests { vec![1], vec![(private_keys.npk(), shared_secret)], vec![private_keys.nsk], - vec![], // TODO check (Marvin) + vec![private_keys.identifier], // TODO check (Marvin) vec![None], &program.into(), ) @@ -3026,7 +3042,8 @@ pub mod tests { let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); let private_keys = test_private_account_keys_1(); - let account_id = AccountId::private_account_id(&private_keys.npk(), None); + let account_id = + AccountId::private_account_id(&private_keys.npk(), Some(private_keys.identifier)); // This is intentional: claim authorization was introduced to protect public accounts, // especially PDAs. Private PDAs are not useful in practice because there is no way to // operate them without the corresponding private keys, so unauthorized private claiming @@ -3044,7 +3061,7 @@ pub mod tests { vec![2], vec![(private_keys.npk(), shared_secret)], vec![], - vec![], // TODO check (Marvin) + vec![private_keys.identifier], // TODO check (Marvin) vec![None], &program.into(), ) @@ -3075,7 +3092,8 @@ pub mod tests { // Set up keys for the private account let private_keys = test_private_account_keys_1(); - let account_id = AccountId::private_account_id(&private_keys.npk(), None); + let account_id = + AccountId::private_account_id(&private_keys.npk(), Some(private_keys.identifier)); // Step 1: Create a new private account with authorization let authorized_account = AccountWithMetadata::new(Account::default(), true, account_id); @@ -3096,7 +3114,7 @@ pub mod tests { vec![1], vec![(private_keys.npk(), shared_secret)], vec![private_keys.nsk], - vec![], // TODO check (Marvin) + vec![private_keys.identifier], // TODO check (Marvin) vec![None], &claimer_program.into(), ) @@ -3201,7 +3219,8 @@ pub mod tests { fn private_changer_claimer_no_data_change_no_claim_succeeds() { let program = Program::changer_claimer(); let sender_keys = test_private_account_keys_1(); - let sender_id = AccountId::private_account_id(&sender_keys.npk(), None); + let sender_id = + AccountId::private_account_id(&sender_keys.npk(), Some(sender_keys.identifier)); let private_account = AccountWithMetadata::new(Account::default(), true, sender_id); // Don't change data (None) and don't claim (false) let instruction: (Option>, bool) = (None, false); @@ -3215,7 +3234,7 @@ pub mod tests { SharedSecretKey::new(&[3; 32], &sender_keys.vpk()), )], vec![sender_keys.nsk], - vec![], // TODO check (Marvin) + vec![sender_keys.identifier], // TODO check (Marvin) vec![Some((0, vec![]))], &program.into(), ); @@ -3305,252 +3324,254 @@ pub mod tests { // Assert - should fail because the malicious program tries to manipulate is_authorized assert!(matches!(result, Err(NssaError::CircuitProvingError(_)))); } - // TODO: marvin fix - // #[test_case::test_case((Some(1), Some(3)), 3; "at upper bound")] - // #[test_case::test_case((Some(1), Some(3)), 2; "inside range")] - // #[test_case::test_case((Some(1), Some(3)), 0; "below range")] - // #[test_case::test_case((Some(1), Some(3)), 1; "at lower bound")] - // #[test_case::test_case((Some(1), Some(3)), 4; "above range")] - // #[test_case::test_case((Some(1), None), 1; "lower bound only - at bound")] - // #[test_case::test_case((Some(1), None), 10; "lower bound only - above")] - // #[test_case::test_case((Some(1), None), 0; "lower bound only - below")] - // #[test_case::test_case((None, Some(3)), 3; "upper bound only - at bound")] - // #[test_case::test_case((None, Some(3)), 0; "upper bound only - below")] - // #[test_case::test_case((None, Some(3)), 4; "upper bound only - above")] - // #[test_case::test_case((None, None), 0; "no bounds - always valid")] - // #[test_case::test_case((None, None), 100; "no bounds - always valid 2")] - // fn validity_window_works_in_public_transactions( - // validity_window: (Option, Option), - // block_id: BlockId, - // ) { - // let block_validity_window: BlockValidityWindow = validity_window.try_into().unwrap(); - // let validity_window_program = Program::validity_window(); - // let account_keys = test_public_account_keys_1(); - // let pre = AccountWithMetadata::new(Account::default(), false, account_keys.account_id()); - // let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); - // let tx = { - // let account_ids = vec![pre.account_id]; - // let nonces = vec![]; - // let program_id = validity_window_program.id(); - // let instruction = ( - // block_validity_window, - // TimestampValidityWindow::new_unbounded(), - // ); - // let message = - // public_transaction::Message::try_new(program_id, account_ids, nonces, instruction) - // .unwrap(); - // let witness_set = public_transaction::WitnessSet::for_message(&message, &[]); - // PublicTransaction::new(message, witness_set) - // }; - // let result = state.transition_from_public_transaction(&tx, block_id, 0); - // let is_inside_validity_window = - // match (block_validity_window.start(), block_validity_window.end()) { - // (Some(s), Some(e)) => s <= block_id && block_id < e, - // (Some(s), None) => s <= block_id, - // (None, Some(e)) => block_id < e, - // (None, None) => true, - // }; - // if is_inside_validity_window { - // assert!(result.is_ok()); - // } else { - // assert!(matches!(result, Err(NssaError::OutOfValidityWindow))); - // } - // } - // - // #[test_case::test_case((Some(1), Some(3)), 3; "at upper bound")] - // #[test_case::test_case((Some(1), Some(3)), 2; "inside range")] - // #[test_case::test_case((Some(1), Some(3)), 0; "below range")] - // #[test_case::test_case((Some(1), Some(3)), 1; "at lower bound")] - // #[test_case::test_case((Some(1), Some(3)), 4; "above range")] - // #[test_case::test_case((Some(1), None), 1; "lower bound only - at bound")] - // #[test_case::test_case((Some(1), None), 10; "lower bound only - above")] - // #[test_case::test_case((Some(1), None), 0; "lower bound only - below")] - // #[test_case::test_case((None, Some(3)), 3; "upper bound only - at bound")] - // #[test_case::test_case((None, Some(3)), 0; "upper bound only - below")] - // #[test_case::test_case((None, Some(3)), 4; "upper bound only - above")] - // #[test_case::test_case((None, None), 0; "no bounds - always valid")] - // #[test_case::test_case((None, None), 100; "no bounds - always valid 2")] - // fn timestamp_validity_window_works_in_public_transactions( - // validity_window: (Option, Option), - // timestamp: Timestamp, - // ) { - // let timestamp_validity_window: TimestampValidityWindow = - // validity_window.try_into().unwrap(); - // let validity_window_program = Program::validity_window(); - // let account_keys = test_public_account_keys_1(); - // let pre = AccountWithMetadata::new(Account::default(), false, account_keys.account_id()); - // let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); - // let tx = { - // let account_ids = vec![pre.account_id]; - // let nonces = vec![]; - // let program_id = validity_window_program.id(); - // let instruction = ( - // BlockValidityWindow::new_unbounded(), - // timestamp_validity_window, - // ); - // let message = - // public_transaction::Message::try_new(program_id, account_ids, nonces, instruction) - // .unwrap(); - // let witness_set = public_transaction::WitnessSet::for_message(&message, &[]); - // PublicTransaction::new(message, witness_set) - // }; - // let result = state.transition_from_public_transaction(&tx, 1, timestamp); - // let is_inside_validity_window = match ( - // timestamp_validity_window.start(), - // timestamp_validity_window.end(), - // ) { - // (Some(s), Some(e)) => s <= timestamp && timestamp < e, - // (Some(s), None) => s <= timestamp, - // (None, Some(e)) => timestamp < e, - // (None, None) => true, - // }; - // if is_inside_validity_window { - // assert!(result.is_ok()); - // } else { - // assert!(matches!(result, Err(NssaError::OutOfValidityWindow))); - // } - // } - // - // #[test_case::test_case((Some(1), Some(3)), 3; "at upper bound")] - // #[test_case::test_case((Some(1), Some(3)), 2; "inside range")] - // #[test_case::test_case((Some(1), Some(3)), 0; "below range")] - // #[test_case::test_case((Some(1), Some(3)), 1; "at lower bound")] - // #[test_case::test_case((Some(1), Some(3)), 4; "above range")] - // #[test_case::test_case((Some(1), None), 1; "lower bound only - at bound")] - // #[test_case::test_case((Some(1), None), 10; "lower bound only - above")] - // #[test_case::test_case((Some(1), None), 0; "lower bound only - below")] - // #[test_case::test_case((None, Some(3)), 3; "upper bound only - at bound")] - // #[test_case::test_case((None, Some(3)), 0; "upper bound only - below")] - // #[test_case::test_case((None, Some(3)), 4; "upper bound only - above")] - // #[test_case::test_case((None, None), 0; "no bounds - always valid")] - // #[test_case::test_case((None, None), 100; "no bounds - always valid 2")] - // fn validity_window_works_in_privacy_preserving_transactions( - // validity_window: (Option, Option), - // block_id: BlockId, - // ) { - // let block_validity_window: BlockValidityWindow = validity_window.try_into().unwrap(); - // let validity_window_program = Program::validity_window(); - // let account_keys = test_private_account_keys_1(); - // let account_id = AccountId::private_account_id(&account_keys.npk()); - // let pre = AccountWithMetadata::new(Account::default(), false, account_id); - // let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); - // let tx = { - // let esk = [3; 32]; - // let shared_secret = SharedSecretKey::new(&esk, &account_keys.vpk()); - // let epk = EphemeralPublicKey::from_scalar(esk); - // - // let instruction = ( - // block_validity_window, - // TimestampValidityWindow::new_unbounded(), - // ); - // let (output, proof) = circuit::execute_and_prove( - // vec![pre], - // Program::serialize_instruction(instruction).unwrap(), - // vec![2], - // vec![(account_keys.npk(), shared_secret)], - // vec![], - // vec![None], - // &validity_window_program.into(), - // ) - // .unwrap(); - // - // let message = Message::try_from_circuit_output( - // vec![], - // vec![], - // vec![(account_id, account_keys.vpk(), epk)], - // output, - // ) - // .unwrap(); - // - // let witness_set = WitnessSet::for_message(&message, proof, &[]); - // PrivacyPreservingTransaction::new(message, witness_set) - // }; - // let result = state.transition_from_privacy_preserving_transaction(&tx, block_id, 0); - // let is_inside_validity_window = - // match (block_validity_window.start(), block_validity_window.end()) { - // (Some(s), Some(e)) => s <= block_id && block_id < e, - // (Some(s), None) => s <= block_id, - // (None, Some(e)) => block_id < e, - // (None, None) => true, - // }; - // if is_inside_validity_window { - // assert!(result.is_ok()); - // } else { - // assert!(matches!(result, Err(NssaError::OutOfValidityWindow))); - // } - // } - // - // #[test_case::test_case((Some(1), Some(3)), 3; "at upper bound")] - // #[test_case::test_case((Some(1), Some(3)), 2; "inside range")] - // #[test_case::test_case((Some(1), Some(3)), 0; "below range")] - // #[test_case::test_case((Some(1), Some(3)), 1; "at lower bound")] - // #[test_case::test_case((Some(1), Some(3)), 4; "above range")] - // #[test_case::test_case((Some(1), None), 1; "lower bound only - at bound")] - // #[test_case::test_case((Some(1), None), 10; "lower bound only - above")] - // #[test_case::test_case((Some(1), None), 0; "lower bound only - below")] - // #[test_case::test_case((None, Some(3)), 3; "upper bound only - at bound")] - // #[test_case::test_case((None, Some(3)), 0; "upper bound only - below")] - // #[test_case::test_case((None, Some(3)), 4; "upper bound only - above")] - // #[test_case::test_case((None, None), 0; "no bounds - always valid")] - // #[test_case::test_case((None, None), 100; "no bounds - always valid 2")] - // fn timestamp_validity_window_works_in_privacy_preserving_transactions( - // validity_window: (Option, Option), - // timestamp: Timestamp, - // ) { - // let timestamp_validity_window: TimestampValidityWindow = - // validity_window.try_into().unwrap(); - // let validity_window_program = Program::validity_window(); - // let account_keys = test_private_account_keys_1(); - // let account_id = AccountId::private_account_id(&account_keys.npk()); - // let pre = AccountWithMetadata::new(Account::default(), false, account_id); - // let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); - // let tx = { - // let esk = [3; 32]; - // let shared_secret = SharedSecretKey::new(&esk, &account_keys.vpk()); - // let epk = EphemeralPublicKey::from_scalar(esk); - // - // let instruction = ( - // BlockValidityWindow::new_unbounded(), - // timestamp_validity_window, - // ); - // let (output, proof) = circuit::execute_and_prove( - // vec![pre], - // Program::serialize_instruction(instruction).unwrap(), - // vec![2], - // vec![(account_keys.npk(), shared_secret)], - // vec![], - // vec![None], - // &validity_window_program.into(), - // ) - // .unwrap(); - // - // let message = Message::try_from_circuit_output( - // vec![], - // vec![], - // vec![(account_id, account_keys.vpk(), epk)], - // output, - // ) - // .unwrap(); - // - // let witness_set = WitnessSet::for_message(&message, proof, &[]); - // PrivacyPreservingTransaction::new(message, witness_set) - // }; - // let result = state.transition_from_privacy_preserving_transaction(&tx, 1, timestamp); - // let is_inside_validity_window = match ( - // timestamp_validity_window.start(), - // timestamp_validity_window.end(), - // ) { - // (Some(s), Some(e)) => s <= timestamp && timestamp < e, - // (Some(s), None) => s <= timestamp, - // (None, Some(e)) => timestamp < e, - // (None, None) => true, - // }; - // if is_inside_validity_window { - // assert!(result.is_ok()); - // } else { - // assert!(matches!(result, Err(NssaError::OutOfValidityWindow))); - // } - // } + + #[test_case::test_case((Some(1), Some(3)), 3; "at upper bound")] + #[test_case::test_case((Some(1), Some(3)), 2; "inside range")] + #[test_case::test_case((Some(1), Some(3)), 0; "below range")] + #[test_case::test_case((Some(1), Some(3)), 1; "at lower bound")] + #[test_case::test_case((Some(1), Some(3)), 4; "above range")] + #[test_case::test_case((Some(1), None), 1; "lower bound only - at bound")] + #[test_case::test_case((Some(1), None), 10; "lower bound only - above")] + #[test_case::test_case((Some(1), None), 0; "lower bound only - below")] + #[test_case::test_case((None, Some(3)), 3; "upper bound only - at bound")] + #[test_case::test_case((None, Some(3)), 0; "upper bound only - below")] + #[test_case::test_case((None, Some(3)), 4; "upper bound only - above")] + #[test_case::test_case((None, None), 0; "no bounds - always valid")] + #[test_case::test_case((None, None), 100; "no bounds - always valid 2")] + fn validity_window_works_in_public_transactions( + validity_window: (Option, Option), + block_id: BlockId, + ) { + let block_validity_window: BlockValidityWindow = validity_window.try_into().unwrap(); + let validity_window_program = Program::validity_window(); + let account_keys = test_public_account_keys_1(); + let pre = AccountWithMetadata::new(Account::default(), false, account_keys.account_id()); + let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); + let tx = { + let account_ids = vec![pre.account_id]; + let nonces = vec![]; + let program_id = validity_window_program.id(); + let instruction = ( + block_validity_window, + TimestampValidityWindow::new_unbounded(), + ); + let message = + public_transaction::Message::try_new(program_id, account_ids, nonces, instruction) + .unwrap(); + let witness_set = public_transaction::WitnessSet::for_message(&message, &[]); + PublicTransaction::new(message, witness_set) + }; + let result = state.transition_from_public_transaction(&tx, block_id, 0); + let is_inside_validity_window = + match (block_validity_window.start(), block_validity_window.end()) { + (Some(s), Some(e)) => s <= block_id && block_id < e, + (Some(s), None) => s <= block_id, + (None, Some(e)) => block_id < e, + (None, None) => true, + }; + if is_inside_validity_window { + assert!(result.is_ok()); + } else { + assert!(matches!(result, Err(NssaError::OutOfValidityWindow))); + } + } + + #[test_case::test_case((Some(1), Some(3)), 3; "at upper bound")] + #[test_case::test_case((Some(1), Some(3)), 2; "inside range")] + #[test_case::test_case((Some(1), Some(3)), 0; "below range")] + #[test_case::test_case((Some(1), Some(3)), 1; "at lower bound")] + #[test_case::test_case((Some(1), Some(3)), 4; "above range")] + #[test_case::test_case((Some(1), None), 1; "lower bound only - at bound")] + #[test_case::test_case((Some(1), None), 10; "lower bound only - above")] + #[test_case::test_case((Some(1), None), 0; "lower bound only - below")] + #[test_case::test_case((None, Some(3)), 3; "upper bound only - at bound")] + #[test_case::test_case((None, Some(3)), 0; "upper bound only - below")] + #[test_case::test_case((None, Some(3)), 4; "upper bound only - above")] + #[test_case::test_case((None, None), 0; "no bounds - always valid")] + #[test_case::test_case((None, None), 100; "no bounds - always valid 2")] + fn timestamp_validity_window_works_in_public_transactions( + validity_window: (Option, Option), + timestamp: Timestamp, + ) { + let timestamp_validity_window: TimestampValidityWindow = + validity_window.try_into().unwrap(); + let validity_window_program = Program::validity_window(); + let account_keys = test_public_account_keys_1(); + let pre = AccountWithMetadata::new(Account::default(), false, account_keys.account_id()); + let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); + let tx = { + let account_ids = vec![pre.account_id]; + let nonces = vec![]; + let program_id = validity_window_program.id(); + let instruction = ( + BlockValidityWindow::new_unbounded(), + timestamp_validity_window, + ); + let message = + public_transaction::Message::try_new(program_id, account_ids, nonces, instruction) + .unwrap(); + let witness_set = public_transaction::WitnessSet::for_message(&message, &[]); + PublicTransaction::new(message, witness_set) + }; + let result = state.transition_from_public_transaction(&tx, 1, timestamp); + let is_inside_validity_window = match ( + timestamp_validity_window.start(), + timestamp_validity_window.end(), + ) { + (Some(s), Some(e)) => s <= timestamp && timestamp < e, + (Some(s), None) => s <= timestamp, + (None, Some(e)) => timestamp < e, + (None, None) => true, + }; + if is_inside_validity_window { + assert!(result.is_ok()); + } else { + assert!(matches!(result, Err(NssaError::OutOfValidityWindow))); + } + } + + #[test_case::test_case((Some(1), Some(3)), 3; "at upper bound")] + #[test_case::test_case((Some(1), Some(3)), 2; "inside range")] + #[test_case::test_case((Some(1), Some(3)), 0; "below range")] + #[test_case::test_case((Some(1), Some(3)), 1; "at lower bound")] + #[test_case::test_case((Some(1), Some(3)), 4; "above range")] + #[test_case::test_case((Some(1), None), 1; "lower bound only - at bound")] + #[test_case::test_case((Some(1), None), 10; "lower bound only - above")] + #[test_case::test_case((Some(1), None), 0; "lower bound only - below")] + #[test_case::test_case((None, Some(3)), 3; "upper bound only - at bound")] + #[test_case::test_case((None, Some(3)), 0; "upper bound only - below")] + #[test_case::test_case((None, Some(3)), 4; "upper bound only - above")] + #[test_case::test_case((None, None), 0; "no bounds - always valid")] + #[test_case::test_case((None, None), 100; "no bounds - always valid 2")] + fn validity_window_works_in_privacy_preserving_transactions( + validity_window: (Option, Option), + block_id: BlockId, + ) { + let block_validity_window: BlockValidityWindow = validity_window.try_into().unwrap(); + let validity_window_program = Program::validity_window(); + let account_keys = test_private_account_keys_1(); + let account_id = AccountId::private_account_id(&account_keys.npk(), Some(account_keys.identifier)); + let pre = AccountWithMetadata::new(Account::default(), false, account_id); + let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); + let tx = { + let esk = [3; 32]; + let shared_secret = SharedSecretKey::new(&esk, &account_keys.vpk()); + let epk = EphemeralPublicKey::from_scalar(esk); + + let instruction = ( + block_validity_window, + TimestampValidityWindow::new_unbounded(), + ); + let (output, proof) = circuit::execute_and_prove( + vec![pre], + Program::serialize_instruction(instruction).unwrap(), + vec![2], + vec![(account_keys.npk(), shared_secret)], + vec![], + vec![account_keys.identifier], + vec![None], + &validity_window_program.into(), + ) + .unwrap(); + + let message = Message::try_from_circuit_output( + vec![], + vec![], + vec![(account_id, account_keys.vpk(), epk)], + output, + ) + .unwrap(); + // + let witness_set = WitnessSet::for_message(&message, proof, &[]); + PrivacyPreservingTransaction::new(message, witness_set) + }; + let result = state.transition_from_privacy_preserving_transaction(&tx, block_id, 0); + let is_inside_validity_window = + match (block_validity_window.start(), block_validity_window.end()) { + (Some(s), Some(e)) => s <= block_id && block_id < e, + (Some(s), None) => s <= block_id, + (None, Some(e)) => block_id < e, + (None, None) => true, + }; + if is_inside_validity_window { + assert!(result.is_ok()); + } else { + assert!(matches!(result, Err(NssaError::OutOfValidityWindow))); + } + } + + #[test_case::test_case((Some(1), Some(3)), 3; "at upper bound")] + #[test_case::test_case((Some(1), Some(3)), 2; "inside range")] + #[test_case::test_case((Some(1), Some(3)), 0; "below range")] + #[test_case::test_case((Some(1), Some(3)), 1; "at lower bound")] + #[test_case::test_case((Some(1), Some(3)), 4; "above range")] + #[test_case::test_case((Some(1), None), 1; "lower bound only - at bound")] + #[test_case::test_case((Some(1), None), 10; "lower bound only - above")] + #[test_case::test_case((Some(1), None), 0; "lower bound only - below")] + #[test_case::test_case((None, Some(3)), 3; "upper bound only - at bound")] + #[test_case::test_case((None, Some(3)), 0; "upper bound only - below")] + #[test_case::test_case((None, Some(3)), 4; "upper bound only - above")] + #[test_case::test_case((None, None), 0; "no bounds - always valid")] + #[test_case::test_case((None, None), 100; "no bounds - always valid 2")] + fn timestamp_validity_window_works_in_privacy_preserving_transactions( + validity_window: (Option, Option), + timestamp: Timestamp, + ) { + let timestamp_validity_window: TimestampValidityWindow = + validity_window.try_into().unwrap(); + let validity_window_program = Program::validity_window(); + let account_keys = test_private_account_keys_1(); + let account_id = AccountId::private_account_id(&account_keys.npk(), Some(account_keys.identifier)); + let pre = AccountWithMetadata::new(Account::default(), false, account_id); + let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs(); + let tx = { + let esk = [3; 32]; + let shared_secret = SharedSecretKey::new(&esk, &account_keys.vpk()); + let epk = EphemeralPublicKey::from_scalar(esk); + + let instruction = ( + BlockValidityWindow::new_unbounded(), + timestamp_validity_window, + ); + let (output, proof) = circuit::execute_and_prove( + vec![pre], + Program::serialize_instruction(instruction).unwrap(), + vec![2], + vec![(account_keys.npk(), shared_secret)], + vec![], + vec![account_keys.identifier], + vec![None], + &validity_window_program.into(), + ) + .unwrap(); + + let message = Message::try_from_circuit_output( + vec![], + vec![], + vec![(account_id, account_keys.vpk(), epk)], + output, + ) + .unwrap(); + + let witness_set = WitnessSet::for_message(&message, proof, &[]); + PrivacyPreservingTransaction::new(message, witness_set) + }; + let result = state.transition_from_privacy_preserving_transaction(&tx, 1, timestamp); + let is_inside_validity_window = match ( + timestamp_validity_window.start(), + timestamp_validity_window.end(), + ) { + (Some(s), Some(e)) => s <= timestamp && timestamp < e, + (Some(s), None) => s <= timestamp, + (None, Some(e)) => timestamp < e, + (None, None) => true, + }; + if is_inside_validity_window { + assert!(result.is_ok()); + } else { + assert!(matches!(result, Err(NssaError::OutOfValidityWindow))); + } + } #[test] fn state_serialization_roundtrip() { let account_id_1 = AccountId::new([1; 32]); diff --git a/program_methods/guest/src/bin/privacy_preserving_circuit.rs b/program_methods/guest/src/bin/privacy_preserving_circuit.rs index 432d04be..f6e974ff 100644 --- a/program_methods/guest/src/bin/privacy_preserving_circuit.rs +++ b/program_methods/guest/src/bin/privacy_preserving_circuit.rs @@ -377,6 +377,7 @@ fn compute_circuit_output( &pre_state.account, npk, nsk, + *identifier, ); let new_nonce = pre_state.account.nonce.private_account_nonce_increment(nsk); @@ -465,10 +466,11 @@ fn compute_nullifier_and_set_digest( pre_account: &Account, npk: &NullifierPublicKey, nsk: &NullifierSecretKey, + identifier: u128, ) -> (Nullifier, CommitmentSetDigest) { // TODO: consider rewriting the function to receive account id instead of npk. // NOTE: this does not use the identifier at all. - let account_id = AccountId::private_account_id(npk, None); + let account_id = AccountId::private_account_id(npk, Some(identifier)); membership_proof_opt.as_ref().map_or_else( || { assert_eq!(