diff --git a/Cargo.lock b/Cargo.lock index 6e19d119cf..526a3fb8c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3841,9 +3841,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64", "chrono", @@ -3859,9 +3859,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling 0.20.10", "proc-macro2", @@ -6057,6 +6057,7 @@ dependencies = [ "ripemd", "sapling-crypto", "secp256k1", + "serde", "sha2 0.10.8", "subtle", "tracing", @@ -6101,6 +6102,8 @@ dependencies = [ "incrementalmerkletree-testing", "memuse", "proptest", + "serde", + "serde_with", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 89f067c7e9..7c75eab907 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,7 @@ hex = "0.4" percent-encoding = "2.1.0" serde = { version = "1", features = ["derive"] } serde_json = "1" +serde_with = "3.9" # HTTP hyper = "1" diff --git a/components/zcash_protocol/Cargo.toml b/components/zcash_protocol/Cargo.toml index 5424e16cbf..a3cbbb4998 100644 --- a/components/zcash_protocol/Cargo.toml +++ b/components/zcash_protocol/Cargo.toml @@ -33,6 +33,9 @@ proptest = { workspace = true, optional = true } incrementalmerkletree = { workspace = true, optional = true } incrementalmerkletree-testing = { workspace = true, optional = true } +serde.workspace = true +serde_with.workspace = true + [dev-dependencies] proptest.workspace = true diff --git a/components/zcash_protocol/src/consensus.rs b/components/zcash_protocol/src/consensus.rs index c757368690..1f158c81bc 100644 --- a/components/zcash_protocol/src/consensus.rs +++ b/components/zcash_protocol/src/consensus.rs @@ -1,6 +1,7 @@ //! Consensus logic and parameters. use memuse::DynamicUsage; +use serde::{Deserialize, Serialize}; use std::cmp::{Ord, Ordering}; use std::convert::TryFrom; use std::fmt; @@ -13,7 +14,7 @@ use crate::constants::{mainnet, regtest, testnet}; /// Safe conversion from various integer types, as well as addition and subtraction, are /// provided. #[repr(transparent)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct BlockHeight(u32); memuse::impl_no_dynamic_usage!(BlockHeight); diff --git a/components/zcash_protocol/src/lib.rs b/components/zcash_protocol/src/lib.rs index f73564751d..7e45ae731f 100644 --- a/components/zcash_protocol/src/lib.rs +++ b/components/zcash_protocol/src/lib.rs @@ -17,6 +17,8 @@ use core::fmt; +use serde::{Deserialize, Serialize}; + pub mod consensus; pub mod constants; #[cfg(feature = "local-consensus")] @@ -25,7 +27,7 @@ pub mod memo; pub mod value; /// A Zcash shielded transfer protocol. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum ShieldedProtocol { /// The Sapling protocol Sapling, @@ -34,7 +36,7 @@ pub enum ShieldedProtocol { } /// A value pool in the Zcash protocol. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum PoolType { /// The transparent value pool Transparent, diff --git a/components/zcash_protocol/src/memo.rs b/components/zcash_protocol/src/memo.rs index 10258a52d9..a0fac8a10a 100644 --- a/components/zcash_protocol/src/memo.rs +++ b/components/zcash_protocol/src/memo.rs @@ -6,6 +6,9 @@ use std::fmt; use std::ops::Deref; use std::str; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; + /// Format a byte array as a colon-delimited hex string. /// /// - Source: @@ -46,8 +49,9 @@ impl fmt::Display for Error { impl error::Error for Error {} /// The unencrypted memo bytes received alongside a shielded note in a Zcash transaction. -#[derive(Clone)] -pub struct MemoBytes(pub(crate) Box<[u8; 512]>); +#[serde_as] +#[derive(Clone, Serialize, Deserialize)] +pub struct MemoBytes(#[serde_as(as = "Box<[_; 512]>")] pub(crate) Box<[u8; 512]>); impl fmt::Debug for MemoBytes { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/components/zcash_protocol/src/value.rs b/components/zcash_protocol/src/value.rs index 395ac8edc2..aaf4571333 100644 --- a/components/zcash_protocol/src/value.rs +++ b/components/zcash_protocol/src/value.rs @@ -4,6 +4,7 @@ use std::iter::Sum; use std::ops::{Add, Mul, Neg, Sub}; use memuse::DynamicUsage; +use serde::{Deserialize, Serialize}; pub const COIN: u64 = 1_0000_0000; pub const MAX_MONEY: u64 = 21_000_000 * COIN; @@ -17,7 +18,8 @@ pub const MAX_BALANCE: i64 = MAX_MONEY as i64; /// invalid ZatBalances would also be rejected by the network consensus rules.) /// /// [`Transaction`]: https://docs.rs/zcash_primitives/latest/zcash_primitives/transaction/struct.Transaction.html -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)] +#[serde(try_from = "i64", into = "i64")] pub struct ZatBalance(i64); memuse::impl_no_dynamic_usage!(ZatBalance); @@ -226,7 +228,8 @@ impl Mul for ZatBalance { /// /// A Zatoshis can only be constructed from an integer that is within the valid monetary /// range of `{0..MAX_MONEY}` (where `MAX_MONEY` = 21,000,000 × 10⁸ zatoshis). -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)] +#[serde(try_from = "u64", into = "u64")] pub struct Zatoshis(u64); impl Zatoshis { diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index c499cee436..905f528cdb 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -47,6 +47,7 @@ rand_core.workspace = true base64.workspace = true bech32.workspace = true bs58.workspace = true +serde.workspace = true # - Errors bip32 = { workspace = true, optional = true } @@ -123,7 +124,6 @@ tower = { workspace = true, optional = true } http-body-util = { workspace = true, optional = true } hyper-util = { workspace = true, optional = true } rand = { workspace = true, optional = true } -serde = { workspace = true, optional = true } tokio-rustls = { workspace = true, optional = true } webpki-roots = { workspace = true, optional = true } @@ -186,7 +186,6 @@ tor = [ "dep:hyper-util", "dep:rand", "dep:rust_decimal", - "dep:serde", "dep:serde_json", "dep:tokio", "dep:tokio-rustls", diff --git a/zcash_client_backend/src/wallet.rs b/zcash_client_backend/src/wallet.rs index f3bca04baa..ab66582b47 100644 --- a/zcash_client_backend/src/wallet.rs +++ b/zcash_client_backend/src/wallet.rs @@ -2,6 +2,7 @@ //! light client. use incrementalmerkletree::Position; +use serde::{Deserialize, Serialize}; use zcash_address::ZcashAddress; use zcash_note_encryption::EphemeralKeyBytes; use zcash_primitives::{ @@ -28,7 +29,7 @@ use crate::fees::orchard as orchard_fees; use zcash_primitives::legacy::keys::{NonHardenedChildIndex, TransparentKeyScope}; /// A unique identifier for a shielded transaction output -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct NoteId { txid: TxId, protocol: ShieldedProtocol, @@ -171,6 +172,7 @@ impl Recipient, O> { /// The shielded subset of a [`Transaction`]'s data that is relevant to a particular wallet. /// /// [`Transaction`]: zcash_primitives::transaction::Transaction +#[derive(Clone)] pub struct WalletTx { txid: TxId, block_index: usize, @@ -300,6 +302,7 @@ impl transparent_fees::InputView for WalletTransparentOutput { } /// A reference to a spent note belonging to the wallet within a transaction. +#[derive(Clone)] pub struct WalletSpend { index: usize, nf: Nf, @@ -339,6 +342,7 @@ pub type WalletSaplingSpend = WalletSpend = WalletSpend; /// An output that was successfully decrypted in the process of wallet scanning. +#[derive(Clone)] pub struct WalletOutput { index: usize, ephemeral_key: EphemeralKeyBytes, diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index a12cd9c9a2..9478fd5f52 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -72,6 +72,7 @@ document-features.workspace = true bs58.workspace = true byteorder.workspace = true hex.workspace = true +serde.workspace = true # - Shielded protocols redjubjub = "0.7" diff --git a/zcash_primitives/src/legacy.rs b/zcash_primitives/src/legacy.rs index 23ba7cf830..6548dee745 100644 --- a/zcash_primitives/src/legacy.rs +++ b/zcash_primitives/src/legacy.rs @@ -1,6 +1,7 @@ //! Support for legacy transparent addresses and scripts. use byteorder::{ReadBytesExt, WriteBytesExt}; +use serde::{Deserialize, Serialize}; use zcash_address::TryFromRawAddress; use std::fmt; @@ -272,7 +273,7 @@ impl OpCode { } /// A serialized script, used inside transparent inputs and outputs of a transaction. -#[derive(Clone, Default, PartialEq, Eq)] +#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub struct Script(pub Vec); impl fmt::Debug for Script { diff --git a/zcash_primitives/src/transaction/components/transparent.rs b/zcash_primitives/src/transaction/components/transparent.rs index e2c82fd848..ca2a379b39 100644 --- a/zcash_primitives/src/transaction/components/transparent.rs +++ b/zcash_primitives/src/transaction/components/transparent.rs @@ -1,6 +1,7 @@ //! Structs representing the components within Zcash transactions. use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use serde::{Deserialize, Serialize}; use std::fmt::Debug; use std::io::{self, Read, Write}; @@ -92,7 +93,7 @@ impl Bundle { } } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct OutPoint { hash: TxId, n: u32, @@ -180,7 +181,7 @@ impl TxIn { } } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct TxOut { pub value: NonNegativeAmount, pub script_pubkey: Script, diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index adf1dffdf1..874e9ef4b1 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -14,6 +14,7 @@ mod tests; use blake2b_simd::Hash as Blake2bHash; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use memuse::DynamicUsage; +use serde::{Deserialize, Serialize}; use std::convert::TryFrom; use std::fmt; use std::fmt::Debug; @@ -67,7 +68,7 @@ const ZFUTURE_TX_VERSION: u32 = 0x0000FFFF; /// that have been mined. /// - For v5 transactions onwards, this identifier is derived only from "effecting" data, /// and is non-malleable in all contexts. -#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct TxId([u8; 32]); memuse::impl_no_dynamic_usage!(TxId);