Skip to content

Commit

Permalink
Add find_derivation_index_for_spk
Browse files Browse the repository at this point in the history
To replace the functionality lost by changing `update_desc`
  • Loading branch information
LLFourn committed Apr 11, 2022
1 parent 9dc4be9 commit 88e49fe
Showing 1 changed file with 52 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/descriptor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
//! these with BIP32 paths, pay-to-contract instructions, etc.
//!
use std::ops::Range;
use std::{collections::HashMap, sync::Arc};
use std::{
fmt,
Expand Down Expand Up @@ -762,6 +763,30 @@ impl Descriptor<DescriptorPublicKey> {

descriptor.to_string()
}

/// Utility method for deriving the descriptor at each index in a range to find one matching
/// `script_pubkey`.
///
/// If it finds a match then it returns the index it was derived it and the concrete descriptor
/// at that index. If the descriptor is non-derivable then it will simply check the script
/// pubkey against the descriptor (and in that case the index returned will be meaningless).
pub fn find_derivation_index_for_spk<C: secp256k1::Verification>(
&self,
secp: &secp256k1::Secp256k1<C>,
script_pubkey: &Script,
range: Range<u32>,
) -> Result<Option<(u32, Descriptor<bitcoin::PublicKey>)>, ConversionError> {
let range = if self.is_deriveable() { range } else { 0..1 };

for i in range {
let concrete = self.derived_descriptor(&secp, i)?;
if &concrete.script_pubkey() == script_pubkey {
return Ok(Some((i, concrete)));
}
}

Ok(None)
}
}

impl<Pk> expression::FromTree for Descriptor<Pk>
Expand Down Expand Up @@ -1734,4 +1759,31 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
let descriptor: Descriptor<DescriptorPublicKey> = descriptor_str.parse().unwrap();
assert_eq!(descriptor.to_string(), "sh(wsh(pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)))#6c6hwr22");
}

#[test]
fn test_find_derivation_index_for_spk() {
let secp = secp256k1::Secp256k1::verification_only();
let descriptor = Descriptor::from_str("tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)").unwrap();
let script_at_0_1 = Script::from_str(
"5120a82f29944d65b86ae6b5e5cc75e294ead6c59391a1edc5e016e3498c67fc7bbb",
)
.unwrap();
let expected_concrete = Descriptor::from_str(
"tr(0283dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145)",
)
.unwrap();

assert_eq!(
descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..1),
Ok(None)
);
assert_eq!(
descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..2),
Ok(Some((1, expected_concrete.clone())))
);
assert_eq!(
descriptor.find_derivation_index_for_spk(&secp, &script_at_0_1, 0..10),
Ok(Some((1, expected_concrete)))
);
}
}

0 comments on commit 88e49fe

Please # to comment.