diff --git a/Cargo.lock b/Cargo.lock index 16c0e2a856..5306272fa8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1637,6 +1637,7 @@ dependencies = [ "blstrs", "getrandom", "group 0.12.1", + "hex-literal", "ironfish", "ironfish-jubjub", "ironfish_zkp", diff --git a/ironfish-rust-wasm/Cargo.toml b/ironfish-rust-wasm/Cargo.toml index edbf84a64a..f1ed075051 100644 --- a/ironfish-rust-wasm/Cargo.toml +++ b/ironfish-rust-wasm/Cargo.toml @@ -22,3 +22,6 @@ ironfish-jubjub = "0.1.0" ironfish_zkp = { version = "0.2.0", path = "../ironfish-zkp" } rand = "0.8.5" wasm-bindgen = "0.2.95" + +[dev-dependencies] +hex-literal = "0.4.1" diff --git a/ironfish-rust-wasm/src/keys/mod.rs b/ironfish-rust-wasm/src/keys/mod.rs new file mode 100644 index 0000000000..7fda23142a --- /dev/null +++ b/ironfish-rust-wasm/src/keys/mod.rs @@ -0,0 +1,5 @@ +/* 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/. */ + +pub mod public_address; diff --git a/ironfish-rust-wasm/src/keys/public_address.rs b/ironfish-rust-wasm/src/keys/public_address.rs new file mode 100644 index 0000000000..adb15924ac --- /dev/null +++ b/ironfish-rust-wasm/src/keys/public_address.rs @@ -0,0 +1,71 @@ +/* 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; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct PublicAddress(ironfish::PublicAddress); + +#[wasm_bindgen] +impl PublicAddress { + #[wasm_bindgen(constructor)] + pub fn deserialize(bytes: &[u8]) -> Result { + Ok(Self(ironfish::PublicAddress::read(bytes)?)) + } + + #[wasm_bindgen] + pub fn serialize(&self) -> Vec { + self.0.public_address().to_vec() + } + + #[wasm_bindgen(getter)] + pub fn bytes(&self) -> Vec { + self.0.public_address().to_vec() + } + + #[wasm_bindgen(getter)] + pub fn hex(&self) -> String { + self.0.hex_public_address() + } +} + +impl From for PublicAddress { + fn from(d: ironfish::PublicAddress) -> Self { + Self(d) + } +} + +impl AsRef for PublicAddress { + fn as_ref(&self) -> &ironfish::PublicAddress { + &self.0 + } +} + +#[cfg(test)] +mod tests { + use crate::keys::public_address::PublicAddress; + use hex_literal::hex; + + #[test] + fn valid_address() { + let bytes = hex!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0"); + let addr = PublicAddress::deserialize(&bytes[..]) + .expect("valid address deserialization should have succeeded"); + assert_eq!(addr.serialize(), bytes); + assert_eq!(addr.bytes(), bytes); + assert_eq!( + addr.hex(), + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0" + ); + } + + #[test] + fn invalid_address() { + let bytes = hex!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1"); + PublicAddress::deserialize(&bytes[..]) + .expect_err("invalid address deserialization should have failed"); + } +} diff --git a/ironfish-rust-wasm/src/lib.rs b/ironfish-rust-wasm/src/lib.rs index 3815e3640c..28dc6c6999 100644 --- a/ironfish-rust-wasm/src/lib.rs +++ b/ironfish-rust-wasm/src/lib.rs @@ -1,3 +1,7 @@ +/* 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/. */ + #![warn(clippy::dbg_macro)] #![warn(clippy::print_stderr)] #![warn(clippy::print_stdout)] @@ -10,4 +14,5 @@ use getrandom as _; pub mod errors; +pub mod keys; pub mod primitives; diff --git a/ironfish-rust/src/keys/public_address.rs b/ironfish-rust/src/keys/public_address.rs index b2b9285af2..e38f574365 100644 --- a/ironfish-rust/src/keys/public_address.rs +++ b/ironfish-rust/src/keys/public_address.rs @@ -38,13 +38,13 @@ impl PublicAddress { } /// Load a public address from a Read implementation (e.g: socket, file) - pub fn read(reader: &mut R) -> Result { + pub fn read(mut reader: R) -> Result { let mut address_bytes = [0; PUBLIC_ADDRESS_SIZE]; reader.read_exact(&mut address_bytes)?; Self::new(&address_bytes) } - pub fn read_unchecked(reader: &mut R) -> Result { + pub fn read_unchecked(mut reader: R) -> Result { let mut address_bytes = [0; PUBLIC_ADDRESS_SIZE]; reader.read_exact(&mut address_bytes)?; Self::new_unchecked(&address_bytes) @@ -100,6 +100,8 @@ impl PartialEq for PublicAddress { } } +impl Eq for PublicAddress {} + #[cfg(test)] mod test { use crate::{