diff --git a/Cargo.lock b/Cargo.lock index 86fa7914..e006a1b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -654,7 +654,7 @@ dependencies = [ "ansi_term 0.11.0", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", @@ -858,6 +858,41 @@ dependencies = [ "zeroize", ] +[[package]] +name = "darling" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 1.0.24", + "quote 1.0.9", + "strsim 0.10.0", + "syn 1.0.64", +] + +[[package]] +name = "darling_macro" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" +dependencies = [ + "darling_core", + "quote 1.0.9", + "syn 1.0.64", +] + [[package]] name = "data-encoding" version = "2.3.2" @@ -1578,6 +1613,12 @@ dependencies = [ "webpki", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.1.5" @@ -2345,6 +2386,7 @@ dependencies = [ "reqwest", "serde", "serde_json", + "serde_with", "tokio", "tracing", ] @@ -3513,6 +3555,29 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edeeaecd5445109b937a3a335dc52780ca7779c4b4b7374cc6340dedfe44cfca" +dependencies = [ + "rustversion", + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48b35457e9d855d3dc05ef32a73e0df1e2c0fd72c38796a4ee909160c8eeec2" +dependencies = [ + "darling", + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.64", +] + [[package]] name = "serial_test" version = "0.4.0" @@ -3825,6 +3890,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "structopt" version = "0.3.21" diff --git a/monero-rpc/Cargo.toml b/monero-rpc/Cargo.toml index 54b3d64c..c7adac45 100644 --- a/monero-rpc/Cargo.toml +++ b/monero-rpc/Cargo.toml @@ -16,6 +16,7 @@ reqwest = { version = "0.11", default-features = false, features = [ "json" ] } serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" tracing = "0.1" +serde_with = "1" [dev-dependencies] hex-literal = "0.3" diff --git a/monero-rpc/src/monerod.rs b/monero-rpc/src/monerod.rs index 17139732..7c0f8942 100644 --- a/monero-rpc/src/monerod.rs +++ b/monero-rpc/src/monerod.rs @@ -1,6 +1,8 @@ use anyhow::{Context, Result}; -use monero::{cryptonote::hash::Hash, util::ringct, PublicKey, Transaction}; -use serde::{de::DeserializeOwned, Deserialize, Serialize, Serializer}; +use curve25519_dalek::edwards::EdwardsPoint; +use monero::{cryptonote::hash::Hash, Transaction}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde_with::{serde_as, TryFromInto}; #[jsonrpc_client::api(version = "2.0")] pub trait MonerodRpc { @@ -184,9 +186,10 @@ struct GetTransactionsResponseEntry { as_hex: Transaction, } +#[serde_as] #[derive(Clone, Debug, Serialize)] struct GetOIndexesPayload { - #[serde(with = "byte_array")] + #[serde_as(as = "TryFromInto<[u8; 32]>")] txid: Hash, } @@ -227,14 +230,15 @@ pub struct SendRawTransactionResponse { pub too_big: bool, } +#[serde_as] #[derive(Clone, Copy, Debug, Deserialize, PartialEq)] pub struct OutKey { pub height: u64, - #[serde(with = "byte_array")] - pub key: PublicKey, - #[serde(with = "byte_array")] - pub mask: PublicKey, - #[serde(with = "byte_array")] + #[serde_as(as = "TryFromInto<[u8; 32]>")] + pub key: EdwardsPoint, + #[serde_as(as = "TryFromInto<[u8; 32]>")] + pub mask: EdwardsPoint, + #[serde_as(as = "TryFromInto<[u8; 32]>")] pub txid: Hash, pub unlocked: bool, } @@ -304,55 +308,3 @@ mod monero_serde_hex_transaction { Ok(block) } } - -mod byte_array { - use super::*; - use serde::{de::Error, Deserializer}; - use std::{convert::TryFrom, fmt, marker::PhantomData}; - - pub fn serialize(bytes: B, serializer: S) -> Result - where - S: Serializer, - B: AsRef<[u8]>, - { - serializer.serialize_bytes(bytes.as_ref()) - } - - pub fn deserialize<'de, D, B, const N: usize>(deserializer: D) -> Result - where - D: Deserializer<'de>, - B: TryFrom<[u8; N]>, - { - struct Visitor { - phantom: PhantomData<(T, [u8; N])>, - } - - impl<'de, T, const N: usize> serde::de::Visitor<'de> for Visitor - where - T: TryFrom<[u8; N]>, - { - type Value = T; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "a byte buffer") - } - - fn visit_byte_buf(self, v: Vec) -> Result - where - E: Error, - { - let bytes = <[u8; N]>::try_from(v).map_err(|_| { - E::custom(format!("Failed to construct [u8; {}] from buffer", N)) - })?; - let result = T::try_from(bytes) - .map_err(|_| E::custom(format!("Failed to construct T from [u8; {}]", N)))?; - - Ok(result) - } - } - - deserializer.deserialize_byte_buf(Visitor { - phantom: PhantomData, - }) - } -} diff --git a/monero-wallet/src/v2.rs b/monero-wallet/src/v2.rs index 72c2ae21..5d0941bf 100644 --- a/monero-wallet/src/v2.rs +++ b/monero-wallet/src/v2.rs @@ -17,6 +17,7 @@ impl EmptyTransaction { } } +#[derive(Debug)] pub struct MissingOpening; // The opening was missing from the TX pub struct InputAdded {} @@ -46,6 +47,7 @@ impl InputAdded { } } +#[derive(Debug)] pub struct DuplicateIndex; // One of the indices was an evil twin pub struct DecoyOffsetsAdded {} @@ -61,6 +63,7 @@ impl DecoyOffsetsAdded { } } +#[derive(Debug)] pub struct InsufficientFunds; pub struct OutputsAdded {} @@ -108,6 +111,7 @@ impl OutputsBlinded { } } +#[derive(Debug)] pub struct InvalidSignature; // TODO: We can break the CLSAG fn signature down into two parts: @@ -124,3 +128,21 @@ pub struct SignatureParameters { // signing_key_index: usize, pseudo_output_commitment: EdwardsPoint, } + +#[cfg(test)] +mod tests { + use super::*; + use rand::thread_rng; + + // #[test] + // fn api_test() { + // let tx = EmptyTransaction::spend_from(todo!(), todo!()) + // .unwrap() + // .with_random_decoys(&mut thread_rng(), todo!()) + // .add_output(todo!(), todo!(), &mut thread_rng()) + // .unwrap() + // .blind_outputs(todo!()); + // + // tx.with_signature(todo!()); + // } +}