From 29ec9ada6016ac2177c6e304348c7162c3ddbfe3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 17 Dec 2024 17:40:18 +0000 Subject: [PATCH] pczt: Add `Zip32Derivation::extract_account_index` --- CHANGELOG.md | 3 +++ src/pczt.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0808f7..53186af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this library adheres to Rust's notion of ## [Unreleased] +### Added +- `sapling_crypto::pczt::Zip32Derivation::extract_account_index` + ## [0.4.0] - 2024-12-16 ### Added diff --git a/src/pczt.rs b/src/pczt.rs index d478b44..0a6ca0c 100644 --- a/src/pczt.rs +++ b/src/pczt.rs @@ -306,3 +306,32 @@ pub struct Zip32Derivation { /// The sequence of indices corresponding to the shielded HD path. derivation_path: Vec, } + +impl Zip32Derivation { + /// Extracts the ZIP 32 account index from this derivation path. + /// + /// Returns `None` if the seed fingerprints don't match, or if this is a non-standard + /// derivation path. + pub fn extract_account_index( + &self, + seed_fp: &zip32::fingerprint::SeedFingerprint, + expected_coin_type: zip32::ChildIndex, + ) -> Option { + if self.seed_fingerprint == seed_fp.to_bytes() { + match &self.derivation_path[..] { + [purpose, coin_type, account_index] + if purpose == &zip32::ChildIndex::hardened(32) + && coin_type == &expected_coin_type => + { + Some( + zip32::AccountId::try_from(account_index.index() - (1 << 31)) + .expect("zip32::ChildIndex only supports hardened"), + ) + } + _ => None, + } + } else { + None + } + } +}