From 4b765eeb10f33573c2d8e41e63cea50fd424387a Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Tue, 6 May 2025 18:41:25 -0600 Subject: [PATCH 1/3] zcash_address: Add `Converter` trait This adds a trait that permits contextual conversions from `ZcashAddress` into a target type. Where `TryFromAddress` permits context-less conversions, this trait allows implementers to inspect the contents of an address in the context of other data or operations. --- components/zcash_address/CHANGELOG.md | 4 ++ components/zcash_address/src/convert.rs | 93 +++++++++++++++++++++++++ components/zcash_address/src/lib.rs | 21 +++++- 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/components/zcash_address/CHANGELOG.md b/components/zcash_address/CHANGELOG.md index f8b86661d9..7a741c63c8 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] +### Added +- `zcash_address::Converter` +- `zcash_address::ZcashAddress::convert_with` + ## [0.6.2] - 2024-12-13 ### Fixed - Migrated to `f4jumble 0.1.1` to fix `no-std` support. diff --git a/components/zcash_address/src/convert.rs b/components/zcash_address/src/convert.rs index f49ab2e4c6..1c16dfe21a 100644 --- a/components/zcash_address/src/convert.rs +++ b/components/zcash_address/src/convert.rs @@ -286,6 +286,99 @@ impl TryFromAddress for (Network, T) { } } +/// A trait for converter types that can project from a [`ZcashAddress`] into another type. +/// +/// [`ZcashAddress`]: crate::ZcashAddress +/// +/// # Examples +/// +/// ``` +/// use zcash_address::{ConversionError, Network, Converter, UnsupportedAddress, ZcashAddress}; +/// +/// struct KeyFinder { } +/// +/// impl KeyFinder { +/// fn find_sapling_extfvk(&self, data: [u8; 43]) -> Option<[u8; 73]> { +/// todo!() +/// } +/// } +/// +/// // Makes it possible to use a KeyFinder to find the Sapling extfvk that corresponds +/// // to a given ZcashAddress. +/// impl Converter> for KeyFinder { +/// type Error = &'static str; +/// +/// fn convert_sapling( +/// &self, +/// net: Network, +/// data: [u8; 43], +/// ) -> Result, ConversionError> { +/// Ok(self.find_sapling_extfvk(data)) +/// } +/// } +/// ``` +pub trait Converter { + /// Conversion errors for the user type (e.g. failing to parse the data passed to + /// [`Self::convert_sapling`] as a valid Sapling address). + type Error; + + fn convert_sprout( + &self, + net: Network, + data: [u8; 64], + ) -> Result> { + let _ = (net, data); + Err(ConversionError::Unsupported(UnsupportedAddress("Sprout"))) + } + + fn convert_sapling( + &self, + net: Network, + data: [u8; 43], + ) -> Result> { + let _ = (net, data); + Err(ConversionError::Unsupported(UnsupportedAddress("Sapling"))) + } + + fn convert_unified( + &self, + net: Network, + data: unified::Address, + ) -> Result> { + let _ = (net, data); + Err(ConversionError::Unsupported(UnsupportedAddress("Unified"))) + } + + fn convert_transparent_p2pkh( + &self, + net: Network, + data: [u8; 20], + ) -> Result> { + let _ = (net, data); + Err(ConversionError::Unsupported(UnsupportedAddress( + "transparent P2PKH", + ))) + } + + fn convert_transparent_p2sh( + &self, + net: Network, + data: [u8; 20], + ) -> Result> { + let _ = (net, data); + Err(ConversionError::Unsupported(UnsupportedAddress( + "transparent P2SH", + ))) + } + + fn convert_tex(&self, net: Network, data: [u8; 20]) -> Result> { + let _ = (net, data); + Err(ConversionError::Unsupported(UnsupportedAddress( + "transparent-source restricted P2PKH", + ))) + } +} + /// A helper trait for converting another type into a [`ZcashAddress`]. /// /// This trait is sealed and cannot be implemented for types outside this crate. Its diff --git a/components/zcash_address/src/lib.rs b/components/zcash_address/src/lib.rs index b2bb614927..901979aa17 100644 --- a/components/zcash_address/src/lib.rs +++ b/components/zcash_address/src/lib.rs @@ -146,7 +146,7 @@ mod kind; pub mod test_vectors; pub use convert::{ - ConversionError, ToAddress, TryFromAddress, TryFromRawAddress, UnsupportedAddress, + ConversionError, Converter, ToAddress, TryFromAddress, TryFromRawAddress, UnsupportedAddress, }; pub use encoding::ParseError; pub use kind::unified; @@ -278,6 +278,25 @@ impl ZcashAddress { } } + /// Converts this address into another type using the specified converter. + /// + /// `convert` can convert into any type `T` for which an implementation of the [`Converter`] + /// trait exists. This enables conversion of [`ZcashAddress`] values into other types to rely + /// on additional context. + pub fn convert_with>( + self, + converter: C, + ) -> Result> { + match self.kind { + AddressKind::Sprout(data) => converter.convert_sprout(self.net, data), + AddressKind::Sapling(data) => converter.convert_sapling(self.net, data), + AddressKind::Unified(data) => converter.convert_unified(self.net, data), + AddressKind::P2pkh(data) => converter.convert_transparent_p2pkh(self.net, data), + AddressKind::P2sh(data) => converter.convert_transparent_p2sh(self.net, data), + AddressKind::Tex(data) => converter.convert_tex(self.net, data), + } + } + /// Returns whether this address has the ability to receive transfers of the given pool type. pub fn can_receive_as(&self, pool_type: PoolType) -> bool { use AddressKind::*; From 8bbdf9a0ccefa41780b49942260b0f47fc081937 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Wed, 7 May 2025 10:04:16 -0600 Subject: [PATCH 2/3] ci: Ensure that synthetic crates are set up using the correct toolchain. --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 416f563f68..df7421123a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -265,10 +265,12 @@ jobs: path: crates # We use a synthetic crate to ensure no dev-dependencies are enabled, which can # be incompatible with some of these targets. + - name: Copy Rust toolchain into the root for use in synthetic crate setup + run: cp crates/rust-toolchain.toml . - name: Create synthetic crate for testing run: cargo init --lib ci-build - - name: Copy Rust version into synthetic crate - run: cp crates/rust-toolchain.toml ci-build/ + - name: Move Rust toolchain file into synthetic crate + run: mv rust-toolchain.toml ci-build/ - name: Copy patch directives into synthetic crate run: | echo "[patch.crates-io]" >> ./ci-build/Cargo.toml From 456e83e789af14fa006c52b62139444f26d3b705 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Tue, 6 May 2025 19:48:40 -0600 Subject: [PATCH 3/3] Release zcash_address 0.6.3 --- Cargo.lock | 2 +- components/zcash_address/CHANGELOG.md | 1 + components/zcash_address/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index afb5ab3fb7..a0f3cdd5ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6143,7 +6143,7 @@ dependencies = [ [[package]] name = "zcash_address" -version = "0.6.2" +version = "0.6.3" dependencies = [ "assert_matches", "bech32", diff --git a/components/zcash_address/CHANGELOG.md b/components/zcash_address/CHANGELOG.md index 7a741c63c8..04f133faf9 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] +## [0.6.3] - 2025-05-07 ### Added - `zcash_address::Converter` - `zcash_address::ZcashAddress::convert_with` diff --git a/components/zcash_address/Cargo.toml b/components/zcash_address/Cargo.toml index 3aa72295c8..263067a26f 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.2" +version = "0.6.3" authors = [ "Jack Grigg ", ]