diff --git a/src/transaction.rs b/src/transaction.rs index 1b95ec2..7adc3f9 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -23,6 +23,7 @@ use pivx_primitives::transaction::components::{OutPoint, TxOut}; pub use pivx_primitives::transaction::fees::fixed::FeeRule; pub use pivx_primitives::transaction::Transaction; pub use pivx_primitives::zip32::AccountId; +use pivx_primitives::zip32::ExtendedFullViewingKey; pub use pivx_primitives::zip32::ExtendedSpendingKey; pub use pivx_primitives::zip32::Scope; pub use pivx_proofs::prover::LocalTxProver; @@ -276,17 +277,26 @@ pub fn get_nullifier_from_note( ) -> Result { let extfvk = decode_extended_full_viewing_key(&enc_extfvk, is_testnet).map_err(|e| e.to_string())?; + let (note, hex_witness): (Note, String) = serde_wasm_bindgen::from_value(note_data)?; + let ser_nullifiers = + get_nullifier_from_note_internal(extfvk, note, hex_witness).map_err(|e| e.to_string())?; + Ok(serde_wasm_bindgen::to_value(&ser_nullifiers)?) +} + +pub fn get_nullifier_from_note_internal( + extfvk: ExtendedFullViewingKey, + note: Note, + hex_witness: String, +) -> Result> { let nullif_key = extfvk .to_diversifiable_full_viewing_key() .to_nk(Scope::External); - let (note, hex_witness): (Note, String) = serde_wasm_bindgen::from_value(note_data)?; let witness = Cursor::new(hex::decode(hex_witness).map_err(|e| e.to_string())?); let path = IncrementalWitness::::read(witness) .map_err(|_| "Cannot read witness from buffer")? .path() .ok_or("Cannot find witness path")?; - let ser_nullifiers = hex::encode(note.nf(&nullif_key, path.position).0); - Ok(serde_wasm_bindgen::to_value(&ser_nullifiers)?) + Ok(hex::encode(note.nf(&nullif_key, path.position).0)) } #[derive(Serialize, Deserialize)] diff --git a/src/transaction/test.rs b/src/transaction/test.rs index 3965e8d..74c65b6 100644 --- a/src/transaction/test.rs +++ b/src/transaction/test.rs @@ -1,6 +1,6 @@ #![cfg(test)] -use crate::transaction::create_transaction_internal; +use crate::transaction::{create_transaction_internal, get_nullifier_from_note_internal}; use super::handle_transaction_internal; use either::Either; @@ -15,6 +15,7 @@ use pivx_primitives::sapling::value::NoteValue; use pivx_primitives::sapling::Node; use pivx_primitives::sapling::Note; use pivx_primitives::sapling::Rseed::BeforeZip212; +use pivx_primitives::zip32::Scope; use std::error::Error; use std::io::Cursor; @@ -92,7 +93,7 @@ pub async fn test_create_transaction() -> Result<(), Box> { path.write(&mut path_vec)?; let path = hex::encode(path_vec); let tx = create_transaction_internal( - Either::Left(vec![(note.clone(), path)]), + Either::Left(vec![(note.clone(), path.clone())]), &extended_spending_key, output, address, @@ -108,7 +109,15 @@ pub async fn test_create_transaction() -> Result<(), Box> { nullifier, "5269442d8022af933774f9f22775566d92089a151ba733f6d751f5bb65a7f56d" ); - // When we implement mempool, test that new notes work correctly + // Verify that get_nullifier_from_note_internal yields the same nullifier + assert_eq!( + get_nullifier_from_note_internal( + extended_spending_key.to_extended_full_viewing_key(), + note.clone(), + path + )?, + "5269442d8022af933774f9f22775566d92089a151ba733f6d751f5bb65a7f56d" + ); Ok(()) }