From 2defe78830a05a95f4f00d913c7400a135a69076 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 13 Dec 2024 17:02:18 +0000 Subject: [PATCH 1/8] zcash_address: Only require `alloc` instead of `std` Co-authored-by: Kris Nuttycombe --- Cargo.lock | 1 + Cargo.toml | 9 +++-- components/zcash_address/CHANGELOG.md | 1 + components/zcash_address/Cargo.toml | 7 ++++ components/zcash_address/src/convert.rs | 7 +++- components/zcash_address/src/encoding.rs | 12 +++++- components/zcash_address/src/kind/unified.rs | 40 +++++++++++-------- .../zcash_address/src/kind/unified/address.rs | 15 +++++-- .../zcash_address/src/kind/unified/fvk.rs | 12 ++++-- .../zcash_address/src/kind/unified/ivk.rs | 12 ++++-- components/zcash_address/src/lib.rs | 13 +++++- components/zcash_address/src/test_vectors.rs | 3 +- components/zcash_encoding/Cargo.toml | 2 +- 13 files changed, 98 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c74234c1d..61f5806f2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6148,6 +6148,7 @@ dependencies = [ "assert_matches", "bech32", "bs58", + "core2", "f4jumble", "proptest", "serde", diff --git a/Cargo.toml b/Cargo.toml index 27e593e253..21a16a20a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,9 +35,9 @@ categories = ["cryptography::cryptocurrencies"] equihash = { version = "0.2", path = "components/equihash" } zcash_address = { version = "0.6", path = "components/zcash_address" } zcash_client_backend = { version = "0.15", path = "zcash_client_backend" } -zcash_encoding = { version = "0.2.1", path = "components/zcash_encoding" } +zcash_encoding = { version = "0.2.1", path = "components/zcash_encoding", default-features = false } zcash_keys = { version = "0.5", path = "zcash_keys" } -zcash_protocol = { version = "0.4.1", path = "components/zcash_protocol" } +zcash_protocol = { version = "0.4.1", path = "components/zcash_protocol", default-features = false } zip321 = { version = "0.2", path = "components/zip321" } zcash_note_encryption = "0.4.1" @@ -93,7 +93,7 @@ document-features = "0.2" # Encodings base64 = "0.22" bech32 = "0.9" -bs58 = { version = "0.5", features = ["check"] } +bs58 = { version = "0.5", default-features = false, features = ["alloc", "check"] } byteorder = "1" hex = "0.4" percent-encoding = "2.1.0" @@ -112,6 +112,9 @@ webpki-roots = "0.25" memuse = "0.2.1" tracing = "0.1" +# No-std support +core2 = { version = "0.3", default-features = false, features = ["alloc"] } + # Parallel processing crossbeam-channel = "0.5" maybe-rayon = { version = "0.1.0", default-features = false } diff --git a/components/zcash_address/CHANGELOG.md b/components/zcash_address/CHANGELOG.md index 885f056ad9..595a0c3ff8 100644 --- a/components/zcash_address/CHANGELOG.md +++ b/components/zcash_address/CHANGELOG.md @@ -7,6 +7,7 @@ and this library adheres to Rust's notion of ## [Unreleased] ### Added +- `no-std` support, via a default-enabled `std` feature flag. - `impl serde::{Serialize, Deserialize} for zcash_address::ZcashAddress` behind the `serde` feature flag. diff --git a/components/zcash_address/Cargo.toml b/components/zcash_address/Cargo.toml index 128e47309f..c4bf070f61 100644 --- a/components/zcash_address/Cargo.toml +++ b/components/zcash_address/Cargo.toml @@ -21,6 +21,7 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] bech32.workspace = true bs58.workspace = true +core2.workspace = true f4jumble = { version = "0.1", path = "../f4jumble" } zcash_protocol.workspace = true zcash_encoding.workspace = true @@ -32,6 +33,12 @@ assert_matches.workspace = true proptest.workspace = true [features] +default = ["std"] +std = [ + "core2/std", + "zcash_encoding/std", + "zcash_protocol/std", +] test-dependencies = ["dep:proptest"] serde = ["dep:serde"] diff --git a/components/zcash_address/src/convert.rs b/components/zcash_address/src/convert.rs index 225b8775bb..f49ab2e4c6 100644 --- a/components/zcash_address/src/convert.rs +++ b/components/zcash_address/src/convert.rs @@ -1,4 +1,7 @@ -use std::{error::Error, fmt}; +use core::fmt; + +#[cfg(feature = "std")] +use std::error::Error; use crate::{kind::*, AddressKind, Network, ZcashAddress}; @@ -43,7 +46,9 @@ impl fmt::Display for ConversionError { } } +#[cfg(feature = "std")] impl Error for UnsupportedAddress {} +#[cfg(feature = "std")] impl Error for ConversionError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { diff --git a/components/zcash_address/src/encoding.rs b/components/zcash_address/src/encoding.rs index a0d3c117d6..2d97611fb3 100644 --- a/components/zcash_address/src/encoding.rs +++ b/components/zcash_address/src/encoding.rs @@ -1,4 +1,11 @@ -use std::{convert::TryInto, error::Error, fmt, str::FromStr}; +use alloc::string::String; +use alloc::vec::Vec; +use core::convert::TryInto; +use core::fmt; +use core::str::FromStr; + +#[cfg(feature = "std")] +use std::error::Error; use bech32::{self, FromBase32, ToBase32, Variant}; use zcash_protocol::consensus::{NetworkConstants, NetworkType}; @@ -38,6 +45,7 @@ impl fmt::Display for ParseError { } } +#[cfg(feature = "std")] impl Error for ParseError {} impl FromStr for ZcashAddress { @@ -177,6 +185,8 @@ impl fmt::Display for ZcashAddress { #[cfg(test)] mod tests { + use alloc::string::ToString; + use assert_matches::assert_matches; use super::*; diff --git a/components/zcash_address/src/kind/unified.rs b/components/zcash_address/src/kind/unified.rs index fd7e4d5703..9a4a6c575f 100644 --- a/components/zcash_address/src/kind/unified.rs +++ b/components/zcash_address/src/kind/unified.rs @@ -1,11 +1,16 @@ //! Implementation of [ZIP 316](https://zips.z.cash/zip-0316) Unified Addresses and Viewing Keys. -use bech32::{self, FromBase32, ToBase32, Variant}; -use std::cmp; -use std::convert::{TryFrom, TryInto}; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use core::cmp; +use core::convert::{TryFrom, TryInto}; +use core::fmt; +use core::num::TryFromIntError; + +#[cfg(feature = "std")] use std::error::Error; -use std::fmt; -use std::num::TryFromIntError; + +use bech32::{self, FromBase32, ToBase32, Variant}; use crate::Network; @@ -155,16 +160,18 @@ impl fmt::Display for ParseError { } } +#[cfg(feature = "std")] impl Error for ParseError {} pub(crate) mod private { + use alloc::borrow::ToOwned; + use alloc::vec::Vec; + use core::cmp; + use core::convert::{TryFrom, TryInto}; + use core2::io::Write; + use super::{ParseError, Typecode, PADDING_LEN}; use crate::Network; - use std::{ - cmp, - convert::{TryFrom, TryInto}, - io::Write, - }; use zcash_encoding::CompactSize; /// A raw address or viewing key. @@ -188,7 +195,7 @@ pub(crate) mod private { } /// A Unified Container containing addresses or viewing keys. - pub trait SealedContainer: super::Container + std::marker::Sized { + pub trait SealedContainer: super::Container + core::marker::Sized { const MAINNET: &'static str; const TESTNET: &'static str; const REGTEST: &'static str; @@ -235,14 +242,13 @@ pub(crate) mod private { fn to_jumbled_bytes(&self, hrp: &str) -> Vec { assert!(hrp.len() <= PADDING_LEN); - let mut writer = std::io::Cursor::new(Vec::new()); - self.write_raw_encoding(&mut writer); + let mut padded = Vec::new(); + self.write_raw_encoding(&mut padded); let mut padding = [0u8; PADDING_LEN]; padding[0..hrp.len()].copy_from_slice(hrp.as_bytes()); - writer.write_all(&padding).unwrap(); + padded.write_all(&padding).unwrap(); - let padded = writer.into_inner(); f4jumble::f4jumble(&padded) .unwrap_or_else(|e| panic!("f4jumble failed on {:?}: {}", padded, e)) } @@ -250,7 +256,7 @@ pub(crate) mod private { /// Parse the items of the unified container. fn parse_items>>(hrp: &str, buf: T) -> Result, ParseError> { fn read_receiver( - mut cursor: &mut std::io::Cursor<&[u8]>, + mut cursor: &mut core2::io::Cursor<&[u8]>, ) -> Result { let typecode = CompactSize::read(&mut cursor) .map(|v| u32::try_from(v).expect("CompactSize::read enforces MAX_SIZE limit")) @@ -308,7 +314,7 @@ pub(crate) mod private { )), }?; - let mut cursor = std::io::Cursor::new(encoded); + let mut cursor = core2::io::Cursor::new(encoded); let mut result = vec![]; while cursor.position() < encoded.len().try_into().unwrap() { result.push(read_receiver(&mut cursor)?); diff --git a/components/zcash_address/src/kind/unified/address.rs b/components/zcash_address/src/kind/unified/address.rs index 9b50e9b1ec..6ff2958aa1 100644 --- a/components/zcash_address/src/kind/unified/address.rs +++ b/components/zcash_address/src/kind/unified/address.rs @@ -2,7 +2,8 @@ use zcash_protocol::PoolType; use super::{private::SealedItem, ParseError, Typecode}; -use std::convert::{TryFrom, TryInto}; +use alloc::vec::Vec; +use core::convert::{TryFrom, TryInto}; /// The set of known Receivers for Unified Addresses. #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -61,14 +62,16 @@ impl SealedItem for Receiver { /// # Examples /// /// ``` -/// # use std::convert::Infallible; -/// # use std::error::Error; +/// # use core::convert::Infallible; /// use zcash_address::{ /// unified::{self, Container, Encoding}, /// ConversionError, TryFromRawAddress, ZcashAddress, /// }; /// -/// # fn main() -> Result<(), Box> { +/// # #[cfg(not(feature = "std"))] +/// # fn main() {} +/// # #[cfg(feature = "std")] +/// # fn main() -> Result<(), Box> { /// # let address_from_user = || "u1pg2aaph7jp8rpf6yhsza25722sg5fcn3vaca6ze27hqjw7jvvhhuxkpcg0ge9xh6drsgdkda8qjq5chpehkcpxf87rnjryjqwymdheptpvnljqqrjqzjwkc2ma6hcq666kgwfytxwac8eyex6ndgr6ezte66706e3vaqrd25dzvzkc69kw0jgywtd0cmq52q5lkw6uh7hyvzjse8ksx"; /// let example_ua: &str = address_from_user(); /// @@ -161,6 +164,8 @@ impl super::Container for Address { #[cfg(any(test, feature = "test-dependencies"))] pub mod testing { + use alloc::vec::Vec; + use proptest::{ array::{uniform11, uniform20, uniform32}, collection::vec, @@ -246,6 +251,8 @@ pub mod test_vectors; #[cfg(test)] mod tests { + use alloc::borrow::ToOwned; + use assert_matches::assert_matches; use crate::{ diff --git a/components/zcash_address/src/kind/unified/fvk.rs b/components/zcash_address/src/kind/unified/fvk.rs index 2133c54d0e..50131898f2 100644 --- a/components/zcash_address/src/kind/unified/fvk.rs +++ b/components/zcash_address/src/kind/unified/fvk.rs @@ -1,4 +1,5 @@ -use std::convert::{TryFrom, TryInto}; +use alloc::vec::Vec; +use core::convert::{TryFrom, TryInto}; use super::{ private::{SealedContainer, SealedItem}, @@ -82,10 +83,12 @@ impl SealedItem for Fvk { /// # Examples /// /// ``` -/// # use std::error::Error; /// use zcash_address::unified::{self, Container, Encoding}; /// -/// # fn main() -> Result<(), Box> { +/// # #[cfg(not(feature = "std"))] +/// # fn main() {} +/// # #[cfg(feature = "std")] +/// # fn main() -> Result<(), Box> { /// # let ufvk_from_user = || "uview1cgrqnry478ckvpr0f580t6fsahp0a5mj2e9xl7hv2d2jd4ldzy449mwwk2l9yeuts85wjls6hjtghdsy5vhhvmjdw3jxl3cxhrg3vs296a3czazrycrr5cywjhwc5c3ztfyjdhmz0exvzzeyejamyp0cr9z8f9wj0953fzht0m4lenk94t70ruwgjxag2tvp63wn9ftzhtkh20gyre3w5s24f6wlgqxnjh40gd2lxe75sf3z8h5y2x0atpxcyf9t3em4h0evvsftluruqne6w4sm066sw0qe5y8qg423grple5fftxrqyy7xmqmatv7nzd7tcjadu8f7mqz4l83jsyxy4t8pkayytyk7nrp467ds85knekdkvnd7hqkfer8mnqd7pv"; /// let example_ufvk: &str = ufvk_from_user(); /// @@ -144,6 +147,9 @@ impl SealedContainer for Ufvk { #[cfg(test)] mod tests { + use alloc::borrow::ToOwned; + use alloc::vec::Vec; + use assert_matches::assert_matches; use proptest::{array::uniform1, array::uniform32, prelude::*, sample::select}; diff --git a/components/zcash_address/src/kind/unified/ivk.rs b/components/zcash_address/src/kind/unified/ivk.rs index 2a4ebb4fa2..2024427aac 100644 --- a/components/zcash_address/src/kind/unified/ivk.rs +++ b/components/zcash_address/src/kind/unified/ivk.rs @@ -1,4 +1,5 @@ -use std::convert::{TryFrom, TryInto}; +use alloc::vec::Vec; +use core::convert::{TryFrom, TryInto}; use super::{ private::{SealedContainer, SealedItem}, @@ -87,10 +88,12 @@ impl SealedItem for Ivk { /// # Examples /// /// ``` -/// # use std::error::Error; /// use zcash_address::unified::{self, Container, Encoding}; /// -/// # fn main() -> Result<(), Box> { +/// # #[cfg(not(feature = "std"))] +/// # fn main() {} +/// # #[cfg(feature = "std")] +/// # fn main() -> Result<(), Box> { /// # let uivk_from_user = || "uivk1djetqg3fws7y7qu5tekynvcdhz69gsyq07ewvppmzxdqhpfzdgmx8urnkqzv7ylz78ez43ux266pqjhecd59fzhn7wpe6zarnzh804hjtkyad25ryqla5pnc8p5wdl3phj9fczhz64zprun3ux7y9jc08567xryumuz59rjmg4uuflpjqwnq0j0tzce0x74t4tv3gfjq7nczkawxy6y7hse733ae3vw7qfjd0ss0pytvezxp42p6rrpzeh6t2zrz7zpjk0xhngcm6gwdppxs58jkx56gsfflugehf5vjlmu7vj3393gj6u37wenavtqyhdvcdeaj86s6jczl4zq"; /// let example_uivk: &str = uivk_from_user(); /// @@ -149,6 +152,9 @@ impl SealedContainer for Uivk { #[cfg(test)] mod tests { + use alloc::borrow::ToOwned; + use alloc::vec::Vec; + use assert_matches::assert_matches; use proptest::{ diff --git a/components/zcash_address/src/lib.rs b/components/zcash_address/src/lib.rs index e33a991629..dcf71fba0e 100644 --- a/components/zcash_address/src/lib.rs +++ b/components/zcash_address/src/lib.rs @@ -124,11 +124,20 @@ //! } //! ``` +#![no_std] #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))] // Catch documentation errors caused by code changes. #![deny(rustdoc::broken_intra_doc_links)] +#[macro_use] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + +use alloc::string::String; + mod convert; mod encoding; mod kind; @@ -168,7 +177,7 @@ impl<'de> serde::Deserialize<'de> for ZcashAddress { where D: serde::Deserializer<'de>, { - use std::fmt; + use core::fmt; struct AddrVisitor; impl<'de> serde::de::Visitor<'de> for AddrVisitor { @@ -349,7 +358,7 @@ impl ZcashAddress { #[cfg(feature = "test-dependencies")] pub mod testing { - use std::convert::TryInto; + use core::convert::TryInto; use proptest::{array::uniform20, collection::vec, prelude::any, prop_compose, prop_oneof}; diff --git a/components/zcash_address/src/test_vectors.rs b/components/zcash_address/src/test_vectors.rs index 61cffcef90..a502f266eb 100644 --- a/components/zcash_address/src/test_vectors.rs +++ b/components/zcash_address/src/test_vectors.rs @@ -11,7 +11,8 @@ use { }, Network, ToAddress, ZcashAddress, }, - std::iter, + alloc::string::ToString, + core::iter, }; #[test] diff --git a/components/zcash_encoding/Cargo.toml b/components/zcash_encoding/Cargo.toml index 897a7da382..d6782bced1 100644 --- a/components/zcash_encoding/Cargo.toml +++ b/components/zcash_encoding/Cargo.toml @@ -16,7 +16,7 @@ categories = ["cryptography::cryptocurrencies", "encoding"] keywords = ["zcash"] [dependencies] -core2 = { version = "0.3", default-features = false, features = ["alloc"] } +core2.workspace = true nonempty = { workspace = true, optional = true } [features] From b61652e6fee1f5987cc62ec426d057db0a15c5b7 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 13 Dec 2024 18:57:27 +0000 Subject: [PATCH 2/8] zcash_address: Remove serde implementation for `ZcashAddress` We only needed it for `zcash_client_backend` to encode recipient addresses inside proprietary fields of PCZTs, but now that we are explicitly encoding them as strings, it is not necessary. Co-authored-by: Kris Nuttycombe --- Cargo.lock | 1 - components/zcash_address/CHANGELOG.md | 2 -- components/zcash_address/Cargo.toml | 2 -- components/zcash_address/src/lib.rs | 43 --------------------------- zcash_client_backend/Cargo.toml | 1 - 5 files changed, 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61f5806f2a..8753180470 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6151,7 +6151,6 @@ dependencies = [ "core2", "f4jumble", "proptest", - "serde", "zcash_encoding", "zcash_protocol", ] diff --git a/components/zcash_address/CHANGELOG.md b/components/zcash_address/CHANGELOG.md index 595a0c3ff8..4c8fc83f3d 100644 --- a/components/zcash_address/CHANGELOG.md +++ b/components/zcash_address/CHANGELOG.md @@ -8,8 +8,6 @@ and this library adheres to Rust's notion of ## [Unreleased] ### Added - `no-std` support, via a default-enabled `std` feature flag. -- `impl serde::{Serialize, Deserialize} for zcash_address::ZcashAddress` behind - the `serde` feature flag. ## [0.6.0] - 2024-10-02 ### Changed diff --git a/components/zcash_address/Cargo.toml b/components/zcash_address/Cargo.toml index c4bf070f61..eb0b0145e8 100644 --- a/components/zcash_address/Cargo.toml +++ b/components/zcash_address/Cargo.toml @@ -26,7 +26,6 @@ f4jumble = { version = "0.1", path = "../f4jumble" } zcash_protocol.workspace = true zcash_encoding.workspace = true proptest = { workspace = true, optional = true } -serde = { workspace = true, optional = true } [dev-dependencies] assert_matches.workspace = true @@ -40,7 +39,6 @@ std = [ "zcash_protocol/std", ] test-dependencies = ["dep:proptest"] -serde = ["dep:serde"] [lib] bench = false diff --git a/components/zcash_address/src/lib.rs b/components/zcash_address/src/lib.rs index dcf71fba0e..b2bb614927 100644 --- a/components/zcash_address/src/lib.rs +++ b/components/zcash_address/src/lib.rs @@ -161,49 +161,6 @@ pub struct ZcashAddress { kind: AddressKind, } -#[cfg(feature = "serde")] -impl serde::Serialize for ZcashAddress { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(&self.encode()) - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for ZcashAddress { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - use core::fmt; - struct AddrVisitor; - - impl<'de> serde::de::Visitor<'de> for AddrVisitor { - type Value = ZcashAddress; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a valid Zcash address string") - } - - fn visit_str(self, value: &str) -> Result - where - E: serde::de::Error, - { - ZcashAddress::try_from_encoded(value).map_err(|_| { - serde::de::Error::invalid_value( - serde::de::Unexpected::Str(value), - &"a valid Zcash address string", - ) - }) - } - } - - deserializer.deserialize_str(AddrVisitor) - } -} - /// Known kinds of Zcash addresses. #[derive(Clone, Debug, PartialEq, Eq, Hash)] enum AddressKind { diff --git a/zcash_client_backend/Cargo.toml b/zcash_client_backend/Cargo.toml index ceb7defd4f..8bde6f1945 100644 --- a/zcash_client_backend/Cargo.toml +++ b/zcash_client_backend/Cargo.toml @@ -185,7 +185,6 @@ pczt = [ "pczt/zcp-builder", "dep:postcard", "dep:serde", - "zcash_address/serde", ] ## Exposes a wallet synchronization function that implements the necessary state machine. From cf05139913ae88d6e5265e47a4b4c17a557a5e0d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 13 Dec 2024 20:14:20 +0000 Subject: [PATCH 3/8] Migrate to `bech32 0.11` Co-authored-by: Kris Nuttycombe --- Cargo.lock | 4 +- Cargo.toml | 2 +- components/zcash_address/src/encoding.rs | 98 ++++++++++---------- components/zcash_address/src/kind/unified.rs | 32 +++++-- devtools/src/bin/inspect/keys.rs | 45 +++------ devtools/src/bin/inspect/keys/view.rs | 31 ++----- devtools/src/bin/inspect/main.rs | 19 ++-- supply-chain/config.toml | 2 +- zcash_keys/CHANGELOG.md | 1 + zcash_keys/src/encoding.rs | 87 ++++++++--------- 10 files changed, 148 insertions(+), 173 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8753180470..7354101526 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -419,9 +419,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bech32" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" [[package]] name = "bellman" diff --git a/Cargo.toml b/Cargo.toml index 21a16a20a5..fdb915a456 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,7 +92,7 @@ document-features = "0.2" # Encodings base64 = "0.22" -bech32 = "0.9" +bech32 = { version = "0.11", default-features = false, features = ["alloc"] } bs58 = { version = "0.5", default-features = false, features = ["alloc", "check"] } byteorder = "1" hex = "0.4" diff --git a/components/zcash_address/src/encoding.rs b/components/zcash_address/src/encoding.rs index 2d97611fb3..0a28d60046 100644 --- a/components/zcash_address/src/encoding.rs +++ b/components/zcash_address/src/encoding.rs @@ -7,7 +7,7 @@ use core::str::FromStr; #[cfg(feature = "std")] use std::error::Error; -use bech32::{self, FromBase32, ToBase32, Variant}; +use bech32::{primitives::decode::CheckedHrpstring, Bech32, Bech32m, Checksum, Hrp}; use zcash_protocol::consensus::{NetworkConstants, NetworkType}; use zcash_protocol::constants::{mainnet, regtest, testnet}; @@ -72,48 +72,48 @@ impl FromStr for ZcashAddress { } } - // Try decoding as a Sapling or TEX address (Bech32/Bech32m) - if let Ok((hrp, data, variant)) = bech32::decode(s) { - // If we reached this point, the encoding is found to be valid Bech32 or Bech32m. - let data = Vec::::from_base32(&data).map_err(|_| ParseError::InvalidEncoding)?; - - match variant { - Variant::Bech32 => { - let net = match hrp.as_str() { - mainnet::HRP_SAPLING_PAYMENT_ADDRESS => NetworkType::Main, - testnet::HRP_SAPLING_PAYMENT_ADDRESS => NetworkType::Test, - regtest::HRP_SAPLING_PAYMENT_ADDRESS => NetworkType::Regtest, - // We will not define new Bech32 address encodings. - _ => { - return Err(ParseError::NotZcash); - } - }; - - return data[..] - .try_into() - .map(AddressKind::Sapling) - .map_err(|_| ParseError::InvalidEncoding) - .map(|kind| ZcashAddress { net, kind }); + // Try decoding as a Sapling address (Bech32) + if let Ok(parsed) = CheckedHrpstring::new::(s) { + // If we reached this point, the encoding is found to be valid Bech32. + let net = match parsed.hrp().as_str() { + mainnet::HRP_SAPLING_PAYMENT_ADDRESS => NetworkType::Main, + testnet::HRP_SAPLING_PAYMENT_ADDRESS => NetworkType::Test, + regtest::HRP_SAPLING_PAYMENT_ADDRESS => NetworkType::Regtest, + // We will not define new Bech32 address encodings. + _ => { + return Err(ParseError::NotZcash); } - Variant::Bech32m => { - // Try decoding as a TEX address (Bech32m) - let net = match hrp.as_str() { - mainnet::HRP_TEX_ADDRESS => NetworkType::Main, - testnet::HRP_TEX_ADDRESS => NetworkType::Test, - regtest::HRP_TEX_ADDRESS => NetworkType::Regtest, - // Not recognized as a Zcash address type - _ => { - return Err(ParseError::NotZcash); - } - }; - - return data[..] - .try_into() - .map(AddressKind::Tex) - .map_err(|_| ParseError::InvalidEncoding) - .map(|kind| ZcashAddress { net, kind }); + }; + + let data = parsed.byte_iter().collect::>(); + + return data + .try_into() + .map(AddressKind::Sapling) + .map_err(|_| ParseError::InvalidEncoding) + .map(|kind| ZcashAddress { net, kind }); + } + + // Try decoding as a TEX address (Bech32m) + if let Ok(parsed) = CheckedHrpstring::new::(s) { + // If we reached this point, the encoding is found to be valid Bech32m. + let net = match parsed.hrp().as_str() { + mainnet::HRP_TEX_ADDRESS => NetworkType::Main, + testnet::HRP_TEX_ADDRESS => NetworkType::Test, + regtest::HRP_TEX_ADDRESS => NetworkType::Regtest, + // Not recognized as a Zcash address type + _ => { + return Err(ParseError::NotZcash); } - } + }; + + let data = parsed.byte_iter().collect::>(); + + return data + .try_into() + .map(AddressKind::Tex) + .map_err(|_| ParseError::InvalidEncoding) + .map(|kind| ZcashAddress { net, kind }); } // The rest use Base58Check. @@ -152,8 +152,8 @@ impl FromStr for ZcashAddress { } } -fn encode_bech32(hrp: &str, data: &[u8], variant: Variant) -> String { - bech32::encode(hrp, data.to_base32(), variant).expect("hrp is invalid") +fn encode_bech32(hrp: &str, data: &[u8]) -> String { + bech32::encode::(Hrp::parse_unchecked(hrp), data).expect("encoding is short enough") } fn encode_b58(prefix: [u8; 2], data: &[u8]) -> String { @@ -167,17 +167,13 @@ impl fmt::Display for ZcashAddress { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let encoded = match &self.kind { AddressKind::Sprout(data) => encode_b58(self.net.b58_sprout_address_prefix(), data), - AddressKind::Sapling(data) => encode_bech32( - self.net.hrp_sapling_payment_address(), - data, - Variant::Bech32, - ), + AddressKind::Sapling(data) => { + encode_bech32::(self.net.hrp_sapling_payment_address(), data) + } AddressKind::Unified(addr) => addr.encode(&self.net), AddressKind::P2pkh(data) => encode_b58(self.net.b58_pubkey_address_prefix(), data), AddressKind::P2sh(data) => encode_b58(self.net.b58_script_address_prefix(), data), - AddressKind::Tex(data) => { - encode_bech32(self.net.hrp_tex_address(), data, Variant::Bech32m) - } + AddressKind::Tex(data) => encode_bech32::(self.net.hrp_tex_address(), data), }; write!(f, "{}", encoded) } diff --git a/components/zcash_address/src/kind/unified.rs b/components/zcash_address/src/kind/unified.rs index 9a4a6c575f..b92d572d33 100644 --- a/components/zcash_address/src/kind/unified.rs +++ b/components/zcash_address/src/kind/unified.rs @@ -10,7 +10,7 @@ use core::num::TryFromIntError; #[cfg(feature = "std")] use std::error::Error; -use bech32::{self, FromBase32, ToBase32, Variant}; +use bech32::{primitives::decode::CheckedHrpstring, Bech32m, Checksum, Hrp}; use crate::Network; @@ -364,6 +364,22 @@ pub(crate) mod private { use private::SealedItem; +/// The bech32m checksum algorithm, defined in [BIP-350], extended to allow all lengths +/// supported by [ZIP 316]. +/// +/// [BIP-350]: https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki +/// [ZIP 316]: https://zips.z.cash/zip-0316#solution +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Bech32mZip316 {} +impl Checksum for Bech32mZip316 { + type MidstateRepr = ::MidstateRepr; + // l^MAX from ZIP 316. + const CODE_LENGTH: usize = 4194368; + const CHECKSUM_LENGTH: usize = Bech32m::CHECKSUM_LENGTH; + const GENERATOR_SH: [u32; 5] = Bech32m::GENERATOR_SH; + const TARGET_RESIDUE: u32 = Bech32m::TARGET_RESIDUE; +} + /// Trait providing common encoding and decoding logic for Unified containers. pub trait Encoding: private::SealedContainer { /// Constructs a value of a unified container type from a vector @@ -385,14 +401,14 @@ pub trait Encoding: private::SealedContainer { /// the order of its components so that it correctly obeys round-trip /// serialization invariants. fn decode(s: &str) -> Result<(Network, Self), ParseError> { - if let Ok((hrp, data, Variant::Bech32m)) = bech32::decode(s) { + if let Ok(parsed) = CheckedHrpstring::new::(s) { + let hrp = parsed.hrp(); let hrp = hrp.as_str(); // validate that the HRP corresponds to a known network. let net = Self::hrp_network(hrp).ok_or_else(|| ParseError::UnknownPrefix(hrp.to_string()))?; - let data = Vec::::from_base32(&data) - .map_err(|e| ParseError::InvalidEncoding(e.to_string()))?; + let data = parsed.byte_iter().collect::>(); Self::parse_internal(hrp, data).map(|value| (net, value)) } else { @@ -406,12 +422,8 @@ pub trait Encoding: private::SealedContainer { /// serialization invariants. fn encode(&self, network: &Network) -> String { let hrp = Self::network_hrp(network); - bech32::encode( - hrp, - self.to_jumbled_bytes(hrp).to_base32(), - Variant::Bech32m, - ) - .expect("hrp is invalid") + bech32::encode::(Hrp::parse_unchecked(hrp), &self.to_jumbled_bytes(hrp)) + .expect("F4Jumble ensures length is short enough by construction") } } diff --git a/devtools/src/bin/inspect/keys.rs b/devtools/src/bin/inspect/keys.rs index a45486cab0..a828931751 100644 --- a/devtools/src/bin/inspect/keys.rs +++ b/devtools/src/bin/inspect/keys.rs @@ -1,7 +1,7 @@ use std::convert::TryInto; use std::iter; -use bech32::{FromBase32, ToBase32}; +use bech32::{Bech32, Hrp}; use secrecy::Zeroize; use zcash_address::{ unified::{self, Encoding}, @@ -68,10 +68,9 @@ pub(crate) fn inspect_mnemonic(mnemonic: bip0039::Mnemonic, context: Option( + Hrp::parse_unchecked(network.hrp_sapling_extended_spending_key()), + &sapling_extsk_bytes, ) .unwrap(), ); @@ -80,10 +79,9 @@ pub(crate) fn inspect_mnemonic(mnemonic: bip0039::Mnemonic, context: Option( + Hrp::parse_unchecked(network.hrp_sapling_extended_full_viewing_key()), + &sapling_extfvk_bytes ) .unwrap(), ); @@ -91,10 +89,9 @@ pub(crate) fn inspect_mnemonic(mnemonic: bip0039::Mnemonic, context: Option( + Hrp::parse_unchecked(network.hrp_sapling_payment_address()), + &sapling_addr_bytes, ) .unwrap(), ); @@ -169,32 +166,20 @@ pub(crate) fn inspect_mnemonic(mnemonic: bip0039::Mnemonic, context: Option, - variant: bech32::Variant, - network: NetworkType, -) { - match Vec::::from_base32(&raw) - .map_err(|_| ()) - .and_then(|data| sapling::zip32::ExtendedSpendingKey::read(&data[..]).map_err(|_| ())) - { +pub(crate) fn inspect_sapling_extsk(data: Vec, network: NetworkType) { + match sapling::zip32::ExtendedSpendingKey::read(&data[..]).map_err(|_| ()) { Err(_) => { eprintln!("Invalid encoding that claims to be a Sapling extended spending key"); } Ok(extsk) => { eprintln!("Sapling extended spending key"); - match variant { - bech32::Variant::Bech32 => (), - bech32::Variant::Bech32m => eprintln!("⚠️ Incorrectly encoded with Bech32m"), - } let default_addr_bytes = extsk.default_address().1.to_bytes(); eprintln!( "- Default address: {}", - bech32::encode( - network.hrp_sapling_payment_address(), - default_addr_bytes.to_base32(), - bech32::Variant::Bech32, + bech32::encode::( + Hrp::parse_unchecked(network.hrp_sapling_payment_address()), + &default_addr_bytes, ) .unwrap(), ); diff --git a/devtools/src/bin/inspect/keys/view.rs b/devtools/src/bin/inspect/keys/view.rs index 037aff8dde..d09e65b919 100644 --- a/devtools/src/bin/inspect/keys/view.rs +++ b/devtools/src/bin/inspect/keys/view.rs @@ -1,4 +1,4 @@ -use bech32::{FromBase32, ToBase32}; +use bech32::{Bech32, Hrp}; use zcash_address::unified::{self, Container, Encoding}; use zcash_keys::keys::UnifiedFullViewingKey; use zcash_protocol::{ @@ -30,10 +30,9 @@ pub(crate) fn inspect_ufvk(ufvk: unified::Ufvk, network: NetworkType) { unified::Fvk::Sapling(data) => { eprintln!( " - Sapling ({})", - bech32::encode( - network.hrp_sapling_extended_full_viewing_key(), - data.to_base32(), - bech32::Variant::Bech32, + bech32::encode::( + Hrp::parse_unchecked(network.hrp_sapling_extended_full_viewing_key()), + &data ) .unwrap(), ); @@ -89,32 +88,20 @@ pub(crate) fn inspect_uivk(uivk: unified::Uivk, network: NetworkType) { } } -pub(crate) fn inspect_sapling_extfvk( - raw: Vec, - variant: bech32::Variant, - network: NetworkType, -) { - match Vec::::from_base32(&raw) - .map_err(|_| ()) - .and_then(|data| sapling::zip32::ExtendedFullViewingKey::read(&data[..]).map_err(|_| ())) - { +pub(crate) fn inspect_sapling_extfvk(data: Vec, network: NetworkType) { + match sapling::zip32::ExtendedFullViewingKey::read(&data[..]).map_err(|_| ()) { Err(_) => { eprintln!("Invalid encoding that claims to be a Sapling extended full viewing key"); } Ok(extfvk) => { eprintln!("Sapling extended full viewing key"); - match variant { - bech32::Variant::Bech32 => (), - bech32::Variant::Bech32m => eprintln!("⚠️ Incorrectly encoded with Bech32m"), - } let default_addr_bytes = extfvk.default_address().1.to_bytes(); eprintln!( "- Default address: {}", - bech32::encode( - network.hrp_sapling_payment_address(), - default_addr_bytes.to_base32(), - bech32::Variant::Bech32, + bech32::encode::( + Hrp::parse_unchecked(network.hrp_sapling_payment_address()), + &default_addr_bytes, ) .unwrap(), ); diff --git a/devtools/src/bin/inspect/main.rs b/devtools/src/bin/inspect/main.rs index 03869a4f00..2540fbb6da 100644 --- a/devtools/src/bin/inspect/main.rs +++ b/devtools/src/bin/inspect/main.rs @@ -3,6 +3,8 @@ use std::io; use std::io::Cursor; use std::process; +use bech32::primitives::decode::CheckedHrpstring; +use bech32::Bech32; use gumdrop::{Options, ParsingStyle}; use lazy_static::lazy_static; use secrecy::Zeroize; @@ -81,25 +83,26 @@ fn main() { keys::view::inspect_uivk(uivk, network); } else if let Ok((network, ufvk)) = unified::Ufvk::decode(&opts.data) { keys::view::inspect_ufvk(ufvk, network); - } else if let Ok((hrp, data, variant)) = bech32::decode(&opts.data) { - match hrp.as_str() { + } else if let Ok(parsed) = CheckedHrpstring::new::(&opts.data) { + let data = parsed.byte_iter().collect::>(); + match parsed.hrp().as_str() { constants::mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => { - keys::view::inspect_sapling_extfvk(data, variant, NetworkType::Main); + keys::view::inspect_sapling_extfvk(data, NetworkType::Main); } constants::testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => { - keys::view::inspect_sapling_extfvk(data, variant, NetworkType::Test); + keys::view::inspect_sapling_extfvk(data, NetworkType::Test); } constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => { - keys::view::inspect_sapling_extfvk(data, variant, NetworkType::Regtest); + keys::view::inspect_sapling_extfvk(data, NetworkType::Regtest); } constants::mainnet::HRP_SAPLING_EXTENDED_SPENDING_KEY => { - keys::inspect_sapling_extsk(data, variant, NetworkType::Main); + keys::inspect_sapling_extsk(data, NetworkType::Main); } constants::testnet::HRP_SAPLING_EXTENDED_SPENDING_KEY => { - keys::inspect_sapling_extsk(data, variant, NetworkType::Test); + keys::inspect_sapling_extsk(data, NetworkType::Test); } constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY => { - keys::inspect_sapling_extsk(data, variant, NetworkType::Regtest); + keys::inspect_sapling_extsk(data, NetworkType::Regtest); } _ => { // Unknown data format. diff --git a/supply-chain/config.toml b/supply-chain/config.toml index 1d49ceb1a4..c1161bde75 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -179,7 +179,7 @@ version = "1.6.0" criteria = "safe-to-deploy" [[exemptions.bech32]] -version = "0.9.1" +version = "0.11.0" criteria = "safe-to-deploy" [[exemptions.bellman]] diff --git a/zcash_keys/CHANGELOG.md b/zcash_keys/CHANGELOG.md index 42259e7b7d..b8eaead524 100644 --- a/zcash_keys/CHANGELOG.md +++ b/zcash_keys/CHANGELOG.md @@ -7,6 +7,7 @@ and this library adheres to Rust's notion of ## [Unreleased] ### Changed +- Migrated to `bech32 0.11`. - The `UnifiedAddressRequest` argument to the following methods is now optional: - `zcash_keys::keys::UnifiedSpendingKey::address` - `zcash_keys::keys::UnifiedSpendingKey::default_address` diff --git a/zcash_keys/src/encoding.rs b/zcash_keys/src/encoding.rs index cb31b625a8..93d282fdbe 100644 --- a/zcash_keys/src/encoding.rs +++ b/zcash_keys/src/encoding.rs @@ -4,6 +4,7 @@ //! [zcash_primitives::constants] module. use crate::address::UnifiedAddress; +use bech32::primitives::decode::CheckedHrpstringError; use bs58::{self, decode::Error as Bs58Error}; use std::fmt; use zcash_primitives::consensus::NetworkConstants; @@ -13,7 +14,7 @@ use zcash_primitives::{consensus, legacy::TransparentAddress}; #[cfg(feature = "sapling")] use { - bech32::{self, Error, FromBase32, ToBase32, Variant}, + bech32::{primitives::decode::CheckedHrpstring, Bech32, Hrp}, sapling::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, std::io::{self, Write}, zcash_primitives::consensus::NetworkType, @@ -26,35 +27,38 @@ where { let mut data: Vec = vec![]; write(&mut data).expect("Should be able to write to a Vec"); - bech32::encode(hrp, data.to_base32(), Variant::Bech32).expect("hrp is invalid") + bech32::encode::(Hrp::parse_unchecked(hrp), &data).expect("encoding is short enough") } #[derive(Clone, Debug, PartialEq, Eq)] #[cfg(feature = "sapling")] pub enum Bech32DecodeError { - Bech32Error(Error), - IncorrectVariant(Variant), + Bech32Error(bech32::DecodeError), + Hrp(CheckedHrpstringError), ReadError, HrpMismatch { expected: String, actual: String }, } #[cfg(feature = "sapling")] -impl From for Bech32DecodeError { - fn from(err: Error) -> Self { +impl From for Bech32DecodeError { + fn from(err: bech32::DecodeError) -> Self { Bech32DecodeError::Bech32Error(err) } } +#[cfg(feature = "sapling")] +impl From for Bech32DecodeError { + fn from(err: CheckedHrpstringError) -> Self { + Bech32DecodeError::Hrp(err) + } +} + #[cfg(feature = "sapling")] impl fmt::Display for Bech32DecodeError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match &self { Bech32DecodeError::Bech32Error(e) => write!(f, "{}", e), - Bech32DecodeError::IncorrectVariant(variant) => write!( - f, - "Incorrect bech32 encoding (wrong variant: {:?})", - variant - ), + Bech32DecodeError::Hrp(e) => write!(f, "Incorrect HRP encoding: {e}"), Bech32DecodeError::ReadError => { write!(f, "Failed to decode key from its binary representation.") } @@ -68,30 +72,21 @@ impl fmt::Display for Bech32DecodeError { } #[cfg(feature = "sapling")] -impl std::error::Error for Bech32DecodeError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match &self { - Bech32DecodeError::Bech32Error(e) => Some(e), - _ => None, - } - } -} +impl std::error::Error for Bech32DecodeError {} #[cfg(feature = "sapling")] fn bech32_decode(hrp: &str, s: &str, read: F) -> Result where F: Fn(Vec) -> Option, { - let (decoded_hrp, data, variant) = bech32::decode(s)?; - if variant != Variant::Bech32 { - Err(Bech32DecodeError::IncorrectVariant(variant)) - } else if decoded_hrp != hrp { + let parsed = CheckedHrpstring::new::(s)?; + if parsed.hrp().as_str() != hrp { Err(Bech32DecodeError::HrpMismatch { expected: hrp.to_string(), - actual: decoded_hrp, + actual: parsed.hrp().as_str().to_owned(), }) } else { - read(Vec::::from_base32(&data)?).ok_or(Bech32DecodeError::ReadError) + read(parsed.byte_iter().collect::>()).ok_or(Bech32DecodeError::ReadError) } } @@ -274,29 +269,25 @@ pub fn decode_extfvk_with_network( ) -> Result<(NetworkType, ExtendedFullViewingKey), Bech32DecodeError> { use zcash_protocol::constants::{mainnet, regtest, testnet}; - let (decoded_hrp, data, variant) = bech32::decode(s)?; - if variant != Variant::Bech32 { - Err(Bech32DecodeError::IncorrectVariant(variant)) - } else { - let network = match &decoded_hrp[..] { - mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => Ok(NetworkType::Main), - testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => Ok(NetworkType::Test), - regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => Ok(NetworkType::Regtest), - other => Err(Bech32DecodeError::HrpMismatch { - expected: format!( - "One of {}, {}, or {}", - mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, - testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, - regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, - ), - actual: other.to_string(), - }), - }?; - let fvk = ExtendedFullViewingKey::read(&Vec::::from_base32(&data)?[..]) - .map_err(|_| Bech32DecodeError::ReadError)?; - - Ok((network, fvk)) - } + let parsed = CheckedHrpstring::new::(s)?; + let network = match parsed.hrp().as_str() { + mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => Ok(NetworkType::Main), + testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => Ok(NetworkType::Test), + regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY => Ok(NetworkType::Regtest), + other => Err(Bech32DecodeError::HrpMismatch { + expected: format!( + "One of {}, {}, or {}", + mainnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + testnet::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY, + ), + actual: other.to_string(), + }), + }?; + let fvk = ExtendedFullViewingKey::read(&parsed.byte_iter().collect::>()[..]) + .map_err(|_| Bech32DecodeError::ReadError)?; + + Ok((network, fvk)) } /// Writes a [`PaymentAddress`] as a Bech32-encoded string. From 61cf34a70812fa636b65dd806ec608cbab557914 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 13 Dec 2024 20:16:49 +0000 Subject: [PATCH 4/8] zcash_address 0.6.1 --- Cargo.lock | 2 +- components/zcash_address/CHANGELOG.md | 2 ++ components/zcash_address/Cargo.toml | 2 +- supply-chain/imports.lock | 4 ++++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7354101526..43bdb8abc9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6143,7 +6143,7 @@ dependencies = [ [[package]] name = "zcash_address" -version = "0.6.0" +version = "0.6.1" dependencies = [ "assert_matches", "bech32", diff --git a/components/zcash_address/CHANGELOG.md b/components/zcash_address/CHANGELOG.md index 4c8fc83f3d..c8a8f9d39f 100644 --- a/components/zcash_address/CHANGELOG.md +++ b/components/zcash_address/CHANGELOG.md @@ -6,6 +6,8 @@ and this library adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [0.6.1] - 2024-12-13 ### Added - `no-std` support, via a default-enabled `std` feature flag. diff --git a/components/zcash_address/Cargo.toml b/components/zcash_address/Cargo.toml index eb0b0145e8..eb9ac8d298 100644 --- a/components/zcash_address/Cargo.toml +++ b/components/zcash_address/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "zcash_address" description = "Zcash address parsing and serialization" -version = "0.6.0" +version = "0.6.1" authors = [ "Jack Grigg ", ] diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 9694d4bf3b..a330ee7571 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -1,6 +1,10 @@ # cargo-vet imports lock +[[unpublished.zcash_address]] +version = "0.6.1" +audited_as = "0.6.0" + [[publisher.bumpalo]] version = "3.16.0" when = "2024-04-08" From 5c37140a9c751b94097b12cacef58f2998031f41 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 13 Dec 2024 20:35:12 +0000 Subject: [PATCH 5/8] Update cargo vet after publishing zcash_address 0.6.1 --- supply-chain/imports.lock | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index a330ee7571..5157c38371 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -1,10 +1,6 @@ # cargo-vet imports lock -[[unpublished.zcash_address]] -version = "0.6.1" -audited_as = "0.6.0" - [[publisher.bumpalo]] version = "3.16.0" when = "2024-04-08" @@ -242,8 +238,8 @@ user-login = "str4d" user-name = "Jack Grigg" [[publisher.zcash_address]] -version = "0.6.0" -when = "2024-10-02" +version = "0.6.1" +when = "2024-12-13" user-id = 6289 user-login = "str4d" user-name = "Jack Grigg" From 412ff5bba9002a32b0b21960324a715d8c90a0da Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 13 Dec 2024 20:53:17 +0000 Subject: [PATCH 6/8] f4jumble: Add `alloc` feature flag --- components/f4jumble/CHANGELOG.md | 3 +++ components/f4jumble/Cargo.toml | 6 +++++- components/f4jumble/src/lib.rs | 16 ++++++++++------ components/zcash_address/Cargo.toml | 3 ++- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/components/f4jumble/CHANGELOG.md b/components/f4jumble/CHANGELOG.md index 0dd3e14c90..90b9e08859 100644 --- a/components/f4jumble/CHANGELOG.md +++ b/components/f4jumble/CHANGELOG.md @@ -6,6 +6,9 @@ and this library adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- `alloc` feature flag as a mid-point between full `no-std` support and the + `std` feature flag. ## [0.1.0] - 2022-05-11 Initial release. diff --git a/components/f4jumble/Cargo.toml b/components/f4jumble/Cargo.toml index e62afd713c..a8ce442b38 100644 --- a/components/f4jumble/Cargo.toml +++ b/components/f4jumble/Cargo.toml @@ -32,4 +32,8 @@ proptest = "1" [features] default = ["std"] -std = ["blake2b_simd/std"] +alloc = [] +std = [ + "alloc", + "blake2b_simd/std", +] diff --git a/components/f4jumble/src/lib.rs b/components/f4jumble/src/lib.rs index bc86767522..982e9d64ee 100644 --- a/components/f4jumble/src/lib.rs +++ b/components/f4jumble/src/lib.rs @@ -53,11 +53,15 @@ use core::fmt; use core::ops::RangeInclusive; use core::result::Result; +#[cfg(feature = "alloc")] +extern crate alloc; + #[cfg(feature = "std")] #[macro_use] extern crate std; -#[cfg(feature = "std")] -use std::vec::Vec; + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; #[cfg(test)] mod test_vectors; @@ -264,8 +268,8 @@ pub fn f4jumble_inv_mut(message: &mut [u8]) -> Result<(), Error> { /// "af1d55f2695aea02440867bbbfae3b08e8da55b625de3fa91432ab7b2c0a7dff9033ee666db1513ba5761ef482919fb8", /// ); /// ``` -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] pub fn f4jumble(message: &[u8]) -> Result, Error> { let mut result = message.to_vec(); f4jumble_mut(&mut result).map(|()| result) @@ -291,8 +295,8 @@ pub fn f4jumble(message: &[u8]) -> Result, Error> { /// let message_b = f4jumble::f4jumble_inv(&encoded_b).unwrap(); /// assert_eq!(message_b, b"The package from Sarah arrives tomorrow morning."); /// ``` -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] pub fn f4jumble_inv(message: &[u8]) -> Result, Error> { let mut result = message.to_vec(); f4jumble_inv_mut(&mut result).map(|()| result) diff --git a/components/zcash_address/Cargo.toml b/components/zcash_address/Cargo.toml index eb9ac8d298..295cda9ab7 100644 --- a/components/zcash_address/Cargo.toml +++ b/components/zcash_address/Cargo.toml @@ -22,7 +22,7 @@ rustdoc-args = ["--cfg", "docsrs"] bech32.workspace = true bs58.workspace = true core2.workspace = true -f4jumble = { version = "0.1", path = "../f4jumble" } +f4jumble = { version = "0.1", path = "../f4jumble", default-features = false, features = ["alloc"] } zcash_protocol.workspace = true zcash_encoding.workspace = true proptest = { workspace = true, optional = true } @@ -35,6 +35,7 @@ proptest.workspace = true default = ["std"] std = [ "core2/std", + "f4jumble/std", "zcash_encoding/std", "zcash_protocol/std", ] From d660a771749cd7bb202560966458988b88ac65ed Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 13 Dec 2024 20:54:30 +0000 Subject: [PATCH 7/8] f4jumble 0.1.1 --- Cargo.lock | 2 +- components/f4jumble/CHANGELOG.md | 2 ++ components/f4jumble/Cargo.toml | 2 +- supply-chain/imports.lock | 4 ++++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43bdb8abc9..6828f7e5a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1502,7 +1502,7 @@ dependencies = [ [[package]] name = "f4jumble" -version = "0.1.0" +version = "0.1.1" dependencies = [ "blake2b_simd", "hex", diff --git a/components/f4jumble/CHANGELOG.md b/components/f4jumble/CHANGELOG.md index 90b9e08859..0d0e46fc84 100644 --- a/components/f4jumble/CHANGELOG.md +++ b/components/f4jumble/CHANGELOG.md @@ -6,6 +6,8 @@ and this library adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [0.1.1] - 2024-12-13 ### Added - `alloc` feature flag as a mid-point between full `no-std` support and the `std` feature flag. diff --git a/components/f4jumble/Cargo.toml b/components/f4jumble/Cargo.toml index a8ce442b38..64be2ab80f 100644 --- a/components/f4jumble/Cargo.toml +++ b/components/f4jumble/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "f4jumble" description = "Implementation of Zcash's F4Jumble algorithm" -version = "0.1.0" +version = "0.1.1" authors = [ "Jack Grigg ", "Kris Nuttycombe ", diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 5157c38371..1d323828e8 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -1,6 +1,10 @@ # cargo-vet imports lock +[[unpublished.f4jumble]] +version = "0.1.1" +audited_as = "0.1.0" + [[publisher.bumpalo]] version = "3.16.0" when = "2024-04-08" From fb163a3d1de8021f65856e9819e7cddf21f37064 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 13 Dec 2024 20:56:40 +0000 Subject: [PATCH 8/8] zcash_address 0.6.2 --- Cargo.lock | 2 +- components/zcash_address/CHANGELOG.md | 4 ++++ components/zcash_address/Cargo.toml | 4 ++-- supply-chain/imports.lock | 4 ++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6828f7e5a8..afb5ab3fb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6143,7 +6143,7 @@ dependencies = [ [[package]] name = "zcash_address" -version = "0.6.1" +version = "0.6.2" dependencies = [ "assert_matches", "bech32", diff --git a/components/zcash_address/CHANGELOG.md b/components/zcash_address/CHANGELOG.md index c8a8f9d39f..f8b86661d9 100644 --- a/components/zcash_address/CHANGELOG.md +++ b/components/zcash_address/CHANGELOG.md @@ -7,6 +7,10 @@ and this library adheres to Rust's notion of ## [Unreleased] +## [0.6.2] - 2024-12-13 +### Fixed +- Migrated to `f4jumble 0.1.1` to fix `no-std` support. + ## [0.6.1] - 2024-12-13 ### Added - `no-std` support, via a default-enabled `std` feature flag. diff --git a/components/zcash_address/Cargo.toml b/components/zcash_address/Cargo.toml index 295cda9ab7..3aa72295c8 100644 --- a/components/zcash_address/Cargo.toml +++ b/components/zcash_address/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "zcash_address" description = "Zcash address parsing and serialization" -version = "0.6.1" +version = "0.6.2" authors = [ "Jack Grigg ", ] @@ -22,7 +22,7 @@ rustdoc-args = ["--cfg", "docsrs"] bech32.workspace = true bs58.workspace = true core2.workspace = true -f4jumble = { version = "0.1", path = "../f4jumble", default-features = false, features = ["alloc"] } +f4jumble = { version = "0.1.1", path = "../f4jumble", default-features = false, features = ["alloc"] } zcash_protocol.workspace = true zcash_encoding.workspace = true proptest = { workspace = true, optional = true } diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 1d323828e8..9d881cc9a2 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -5,6 +5,10 @@ version = "0.1.1" audited_as = "0.1.0" +[[unpublished.zcash_address]] +version = "0.6.2" +audited_as = "0.6.1" + [[publisher.bumpalo]] version = "3.16.0" when = "2024-04-08"