diff --git a/ironfish-rust-wasm/src/lib.rs b/ironfish-rust-wasm/src/lib.rs index 5c6ad85a3d..d92f15465a 100644 --- a/ironfish-rust-wasm/src/lib.rs +++ b/ironfish-rust-wasm/src/lib.rs @@ -16,6 +16,7 @@ use getrandom as _; pub mod assets; pub mod errors; pub mod keys; +pub mod merkle_note; pub mod primitives; #[cfg(test)] diff --git a/ironfish-rust-wasm/src/merkle_note.rs b/ironfish-rust-wasm/src/merkle_note.rs new file mode 100644 index 0000000000..a02d1ec444 --- /dev/null +++ b/ironfish-rust-wasm/src/merkle_note.rs @@ -0,0 +1,118 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::{errors::IronfishError, primitives::Scalar}; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct MerkleNote(ironfish::MerkleNote); + +#[wasm_bindgen] +impl MerkleNote { + #[wasm_bindgen(constructor)] + pub fn deserialize(bytes: &[u8]) -> Result { + Ok(Self(ironfish::MerkleNote::read(bytes)?)) + } + + #[wasm_bindgen] + pub fn serialize(&self) -> Vec { + let mut buf = Vec::new(); + self.0 + .write(&mut buf) + .expect("failed to serialize merkle note"); + buf + } + + #[wasm_bindgen(getter, js_name = merkleHash)] + pub fn merkle_hash(&self) -> MerkleNoteHash { + self.0.merkle_hash().into() + } +} + +impl From for MerkleNote { + fn from(d: ironfish::MerkleNote) -> Self { + Self(d) + } +} + +impl AsRef for MerkleNote { + fn as_ref(&self) -> &ironfish::MerkleNote { + &self.0 + } +} + +#[wasm_bindgen] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct MerkleNoteHash(ironfish::MerkleNoteHash); + +#[wasm_bindgen] +impl MerkleNoteHash { + #[wasm_bindgen(constructor)] + pub fn deserialize(bytes: &[u8]) -> Result { + Ok(Self(ironfish::MerkleNoteHash::read(bytes)?)) + } + + #[wasm_bindgen] + pub fn serialize(&self) -> Vec { + let mut buf = Vec::new(); + self.0 + .write(&mut buf) + .expect("failed to serialize merkle note hash"); + buf + } + + #[wasm_bindgen(js_name = fromValue)] + pub fn from_value(value: Scalar) -> Self { + ironfish::MerkleNoteHash(value.as_ref().to_owned()).into() + } + + #[wasm_bindgen(getter)] + pub fn value(&self) -> Scalar { + self.0 .0.into() + } + + #[wasm_bindgen(js_name = combineHash)] + pub fn combine_hash(depth: usize, left: &Self, right: &Self) -> Self { + let hash = ironfish::MerkleNoteHash::combine_hash(depth, &left.0 .0, &right.0 .0); + ironfish::MerkleNoteHash(hash).into() + } +} + +impl From for MerkleNoteHash { + fn from(d: ironfish::MerkleNoteHash) -> Self { + Self(d) + } +} + +impl AsRef for MerkleNoteHash { + fn as_ref(&self) -> &ironfish::MerkleNoteHash { + &self.0 + } +} + +#[cfg(test)] +mod tests { + use crate::merkle_note::MerkleNoteHash; + use hex_literal::hex; + use wasm_bindgen_test::wasm_bindgen_test; + + #[test] + #[wasm_bindgen_test] + fn combine_hash() { + let a = MerkleNoteHash::deserialize( + hex!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa00").as_slice(), + ) + .unwrap(); + let b = MerkleNoteHash::deserialize( + hex!("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb00").as_slice(), + ) + .unwrap(); + let c = MerkleNoteHash::combine_hash(10, &a, &b); + assert_eq!( + c.serialize(), + hex!("65fa868a24f39bead19143c23b7c37c6966bec5cf5e60269cb7964d407fe3d47") + ); + } +} diff --git a/ironfish-rust/src/merkle_note.rs b/ironfish-rust/src/merkle_note.rs index a9aec78617..b038508e84 100644 --- a/ironfish-rust/src/merkle_note.rs +++ b/ironfish-rust/src/merkle_note.rs @@ -73,6 +73,8 @@ impl PartialEq for MerkleNote { } } +impl Eq for MerkleNote {} + impl MerkleNote { pub fn new( outgoing_view_key: &OutgoingViewKey,