Skip to content

Commit b2ead84

Browse files
committed
get_all_assets method for descriptors
Signed-off-by: Harshil Jani <[email protected]>
1 parent 6327521 commit b2ead84

File tree

2 files changed

+194
-3
lines changed

2 files changed

+194
-3
lines changed

src/descriptor/mod.rs

+177-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use sync::Arc;
2323

2424
use self::checksum::verify_checksum;
2525
use crate::miniscript::{satisfy, Legacy, Miniscript, Segwitv0};
26-
use crate::plan::{AssetProvider, Plan};
26+
use crate::plan::{AssetProvider, Plan, Assets};
2727
use crate::prelude::*;
2828
use crate::{
2929
expression, hash256, miniscript, BareCtx, Error, ForEachKey, MiniscriptKey, Satisfier,
@@ -566,6 +566,101 @@ impl Descriptor<DefiniteDescriptorKey> {
566566
}
567567
}
568568

569+
impl Descriptor<DescriptorPublicKey>{
570+
/// Get all possible assets for a given descriptor
571+
pub fn get_all_assets(&self) -> Result<Vec<Assets>, Error> {
572+
573+
match self {
574+
Descriptor::Bare(k) => Ok(k.as_inner().get_all_assets()),
575+
Descriptor::Pkh(k) => {
576+
let mut asset = Assets::new();
577+
asset = asset.add(k.as_inner().clone());
578+
Ok(vec![asset])
579+
}
580+
Descriptor::Wpkh(k) => {
581+
let mut asset = Assets::new();
582+
asset = asset.add(k.as_inner().clone());
583+
Ok(vec![asset])
584+
}
585+
Descriptor::Sh(k) => match k.as_inner() {
586+
ShInner::Wsh(k) => match k.as_inner() {
587+
WshInner::SortedMulti(k) => {
588+
let dpk_v = k.clone().pks;
589+
let k = k.clone().k;
590+
Ok(Self::get_asset_combination(k, &dpk_v))
591+
}
592+
WshInner::Ms(k) => Ok(k.get_all_assets()),
593+
},
594+
ShInner::Wpkh(k) => {
595+
let mut asset = Assets::new();
596+
asset = asset.add(k.as_inner().clone());
597+
Ok(vec![asset])
598+
}
599+
ShInner::SortedMulti(k) => {
600+
let dpk_v = k.clone().pks;
601+
let k = k.clone().k;
602+
Ok(Self::get_asset_combination(k, &dpk_v))
603+
}
604+
ShInner::Ms(k) => Ok(k.get_all_assets()),
605+
},
606+
Descriptor::Wsh(k) => match k.as_inner() {
607+
WshInner::SortedMulti(k) => {
608+
let dpk_v = k.clone().pks;
609+
let k = k.clone().k;
610+
Ok(Self::get_asset_combination(k, &dpk_v))
611+
}
612+
WshInner::Ms(k) => {
613+
println!("{}",k);
614+
let a = k.get_all_assets();
615+
println!("{:#?}",a);
616+
Ok(a)
617+
},
618+
},
619+
Descriptor::Tr(k) => {
620+
let s = k.taptree().clone().unwrap();
621+
match s {
622+
TapTree::Tree(ref left, ref right) => {
623+
let mut a = left.get_all_assets();
624+
let b = right.get_all_assets();
625+
a.extend(b);
626+
Ok(a)
627+
}
628+
TapTree::Leaf(k) => Ok(k.get_all_assets()),
629+
}
630+
}
631+
}
632+
}
633+
634+
fn get_asset_combination(k: usize, dpk_v: &Vec<DescriptorPublicKey>) -> Vec<Assets> {
635+
let mut all_assets: Vec<Assets> = Vec::new();
636+
let current_assets = Assets::new();
637+
Self::combine_assets(k, dpk_v, 0, current_assets, &mut all_assets);
638+
all_assets
639+
}
640+
641+
fn combine_assets(
642+
k: usize,
643+
dpk_v: &[DescriptorPublicKey],
644+
index: usize,
645+
current_assets: Assets,
646+
all_assets: &mut Vec<Assets>,
647+
) {
648+
if k == 0 {
649+
all_assets.push(current_assets);
650+
return;
651+
}
652+
if index >= dpk_v.len() {
653+
return;
654+
}
655+
Self::combine_assets(k, dpk_v, index + 1, current_assets.clone(), all_assets);
656+
let mut new_asset = current_assets;
657+
new_asset = new_asset.add(dpk_v[index].clone());
658+
println!("{:#?}", new_asset);
659+
Self::combine_assets(k - 1, dpk_v, index + 1, new_asset, all_assets)
660+
}
661+
662+
}
663+
569664
impl<P, Q> TranslatePk<P, Q> for Descriptor<P>
570665
where
571666
P: MiniscriptKey,
@@ -2092,4 +2187,85 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
20922187
Desc::from_str(&format!("tr({},pk({}))", x_only_key, uncomp_key)).unwrap_err();
20932188
Desc::from_str(&format!("tr({},pk({}))", x_only_key, x_only_key)).unwrap();
20942189
}
2190+
2191+
#[test]
2192+
fn test_get_all_assets_bare() {
2193+
let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
2194+
"pk(0237b1c59ab055a8d3de40eaeb215c7b1922664b5ac049d849fb3346f81431e77f)",
2195+
)
2196+
.unwrap();
2197+
2198+
// Getting the assets from the get_all_assets method
2199+
let assets = descriptor.get_all_assets().unwrap();
2200+
2201+
let mut expected_asset = Assets::new();
2202+
expected_asset = expected_asset.add(
2203+
DescriptorPublicKey::from_str(
2204+
"0237b1c59ab055a8d3de40eaeb215c7b1922664b5ac049d849fb3346f81431e77f",
2205+
)
2206+
.unwrap(),
2207+
);
2208+
assert_eq!(assets, vec![expected_asset]);
2209+
}
2210+
2211+
#[test]
2212+
fn test_get_all_assets_sh_sortedmulti() {
2213+
let keys = vec![
2214+
"0360eabc52e04f70c89e944f379895cdff28fed60849afe7736815c091765afb3c",
2215+
"03a80a24196e66ccf6bca6e6f96633bb629ec702acd76b074de10922b0cf41cc81",
2216+
];
2217+
2218+
let descriptor = Descriptor::<DescriptorPublicKey>::from_str(&format!(
2219+
"sh(sortedmulti(1,{},{}))",
2220+
keys[0], keys[1]
2221+
))
2222+
.unwrap();
2223+
2224+
let assets = descriptor.get_all_assets().unwrap();
2225+
2226+
let mut expected_assets: Vec<Assets> = Vec::new();
2227+
2228+
let mut asset1 = Assets::new();
2229+
asset1 = asset1.add(
2230+
DescriptorPublicKey::from_str(
2231+
keys[0]
2232+
)
2233+
.unwrap(),
2234+
);
2235+
expected_assets.push(asset1);
2236+
2237+
let mut asset2 = Assets::new();
2238+
asset2 = asset2.add(
2239+
DescriptorPublicKey::from_str(
2240+
keys[1]
2241+
)
2242+
.unwrap(),
2243+
);
2244+
expected_assets.push(asset2);
2245+
2246+
for expected_asset in &expected_assets {
2247+
assert!(assets.contains(expected_asset));
2248+
}
2249+
}
2250+
2251+
#[test]
2252+
fn test_get_all_assets_taproot() {
2253+
let x_only_key = bitcoin::key::XOnlyPublicKey::from_str(
2254+
"015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab",
2255+
)
2256+
.unwrap();
2257+
let descriptor =
2258+
Descriptor::from_str(&format!("tr({},pk({}))", x_only_key, x_only_key)).unwrap();
2259+
let assets = descriptor.get_all_assets().unwrap();
2260+
let mut expected_assets: Vec<Assets> = Vec::new();
2261+
let mut asset_1 = Assets::new();
2262+
asset_1 = asset_1.add(
2263+
DescriptorPublicKey::from_str(
2264+
"015e4cb53458bf813db8c79968e76e10d13ed6426a23fa71c2f41ba021c2a7ab",
2265+
)
2266+
.unwrap(),
2267+
);
2268+
expected_assets.push(asset_1);
2269+
assert_eq!(assets, expected_assets);
2270+
}
20952271
}

src/descriptor/tr.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ use crate::descriptor::DefiniteDescriptorKey;
1616
use crate::expression::{self, FromTree};
1717
use crate::miniscript::satisfy::{Placeholder, Satisfaction, SchnorrSigType, Witness};
1818
use crate::miniscript::Miniscript;
19-
use crate::plan::AssetProvider;
19+
use crate::plan::{AssetProvider, Assets};
2020
use crate::policy::semantic::Policy;
2121
use crate::policy::Liftable;
22-
use crate::prelude::*;
22+
use crate::{prelude::*, DescriptorPublicKey};
2323
use crate::util::{varint_len, witness_size};
2424
use crate::{
2525
errstr, Error, ForEachKey, MiniscriptKey, Satisfier, ScriptContext, Tap, ToPublicKey,
@@ -148,6 +148,21 @@ impl<Pk: MiniscriptKey> TapTree<Pk> {
148148
}
149149
}
150150

151+
impl TapTree<DescriptorPublicKey> {
152+
/// Get all possible assets for Taptree
153+
pub fn get_all_assets(&self) -> Vec<Assets> {
154+
match self {
155+
TapTree::Tree(left, right) => {
156+
let mut a = left.get_all_assets();
157+
let b = right.get_all_assets();
158+
a.extend(b);
159+
a
160+
}
161+
TapTree::Leaf(k) => k.get_all_assets(),
162+
}
163+
}
164+
}
165+
151166
impl<Pk: MiniscriptKey> fmt::Display for TapTree<Pk> {
152167
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153168
match self {

0 commit comments

Comments
 (0)