Skip to content

Commit 7649827

Browse files
committed
all_assets method into miniscript
Signed-off-by: Harshil Jani <[email protected]>
1 parent 4849893 commit 7649827

File tree

3 files changed

+359
-4
lines changed

3 files changed

+359
-4
lines changed

src/miniscript/astelem.rs

+212-1
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ use sync::Arc;
1717
use crate::miniscript::context::SigType;
1818
use crate::miniscript::types::{self, Property};
1919
use crate::miniscript::ScriptContext;
20+
use crate::plan::Assets;
2021
use crate::prelude::*;
2122
use crate::util::MsKeyBuilder;
2223
use crate::{
23-
errstr, expression, AbsLockTime, Error, Miniscript, MiniscriptKey, Terminal, ToPublicKey,
24+
errstr, expression, AbsLockTime, DescriptorPublicKey, Error, Miniscript, MiniscriptKey,
25+
Terminal, ToPublicKey,
2426
};
2527

2628
impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
@@ -593,3 +595,212 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
593595
}
594596
}
595597
}
598+
599+
impl<Ctx: ScriptContext> Terminal<DescriptorPublicKey, Ctx> {
600+
/// Retrieve the assets associated with the type of miniscript element.
601+
pub fn all_assets(&self) -> Vec<Assets> {
602+
match self {
603+
Terminal::True => vec![Assets::new()],
604+
Terminal::False => Vec::new(),
605+
Terminal::PkK(k) => {
606+
let mut asset = Assets::new();
607+
asset = asset.add(k.clone());
608+
vec![asset]
609+
}
610+
Terminal::PkH(k) => {
611+
let mut asset = Assets::new();
612+
asset = asset.add(k.clone());
613+
vec![asset]
614+
}
615+
Terminal::RawPkH(k) => {
616+
let mut asset = Assets::new();
617+
asset = asset.add(k.clone());
618+
vec![asset]
619+
}
620+
Terminal::After(k) => {
621+
let mut asset = Assets::new();
622+
asset.absolute_timelock = Some(k.clone().into());
623+
vec![asset]
624+
}
625+
Terminal::Older(k) => {
626+
let mut asset = Assets::new();
627+
asset.relative_timelock = Some(k.clone());
628+
vec![asset]
629+
}
630+
Terminal::Sha256(k) => {
631+
let mut asset = Assets::new();
632+
asset = asset.add(k.clone());
633+
vec![asset]
634+
}
635+
Terminal::Hash256(k) => {
636+
let mut asset = Assets::new();
637+
asset = asset.add(k.clone());
638+
vec![asset]
639+
}
640+
Terminal::Ripemd160(k) => {
641+
let mut asset = Assets::new();
642+
asset = asset.add(k.clone());
643+
vec![asset]
644+
}
645+
Terminal::Hash160(k) => {
646+
let mut asset = Assets::new();
647+
asset = asset.add(k.clone());
648+
vec![asset]
649+
}
650+
Terminal::Alt(k) => k.all_assets(),
651+
Terminal::Swap(k) => k.all_assets(),
652+
Terminal::Check(k) => k.all_assets(),
653+
Terminal::DupIf(k) => k.all_assets(),
654+
Terminal::Verify(k) => k.all_assets(),
655+
Terminal::NonZero(k) => k.all_assets(),
656+
Terminal::ZeroNotEqual(k) => k.all_assets(),
657+
Terminal::AndB(left, right) |
658+
Terminal::AndV(left, right)
659+
=> {
660+
let a = left.all_assets();
661+
let b = right.all_assets();
662+
let result: Vec<Assets> = a
663+
.into_iter()
664+
.flat_map(|x| {
665+
b.clone().into_iter().map(move |y| {
666+
let mut new_asset = Assets::new();
667+
new_asset = new_asset.add(x.clone());
668+
new_asset = new_asset.add(y.clone());
669+
new_asset
670+
})
671+
})
672+
.collect();
673+
result
674+
}
675+
Terminal::AndOr(a, b, c) => {
676+
let a = a.all_assets();
677+
let b = b.all_assets();
678+
let mut c = c.all_assets();
679+
let and: Vec<Assets> = a
680+
.into_iter()
681+
.flat_map(|x| {
682+
b.clone().into_iter().map(move |y| {
683+
let mut new_asset = Assets::new();
684+
new_asset = new_asset.add(x.clone());
685+
new_asset = new_asset.add(y.clone());
686+
new_asset
687+
})
688+
})
689+
.collect();
690+
c.extend(and);
691+
c
692+
}
693+
Terminal::OrB(left, right) |
694+
Terminal::OrC(left, right) |
695+
Terminal::OrD(left, right) |
696+
Terminal::OrI(left, right)
697+
=> {
698+
let mut a = left.all_assets();
699+
let b = right.all_assets();
700+
a.extend(b);
701+
a
702+
}
703+
Terminal::Thresh(k, ms) => {
704+
// In order to understand working of below code consider k of n as 2 of 3 thresh policy
705+
// Eg : thresh(2,ms(A),ms(B),ms(C)) Here ms(A),ms(B) and ms(C) are miniscript policies
706+
// k = 2
707+
// ms = [ms(A),ms(B),ms(C)];
708+
// We would consider the possible combinations of k policies into the ms_v
709+
// here k=2 so all possible combinations of 2.
710+
// ms_v = [[ms(A),ms(B)],[ms(A),ms(C)],[ms(B),ms(C)]]
711+
// Between each set of combination we would need to do an OR
712+
// (i.e ms_v[0] OR ms_v[1] OR ms_v[3])
713+
// Now inside of each policy combination we need to have AND
714+
// Eg : ms_v[0] = [ms(A),ms(B)] so here -> ms(A) AND ms(B)
715+
716+
let ms_v = Self::get_ms_combination_thresh(*k, ms);
717+
let mut result = Vec::new();
718+
for ms in ms_v {
719+
// AND between each miniscript policy
720+
let mut and: Vec<Assets> = Vec::new();
721+
if let Some(first_assets) = ms.first() {
722+
and = first_assets.all_assets().clone();
723+
}
724+
for i in ms.iter().skip(1) {
725+
let i_assets = i.all_assets();
726+
and = and
727+
.iter()
728+
.flat_map(|x| {
729+
i_assets.iter().map(move |y| {
730+
let mut new_asset = x.clone();
731+
new_asset = new_asset.add(y.clone());
732+
new_asset
733+
})
734+
})
735+
.collect();
736+
}
737+
// OR of possible combinations of k miniscript policies.
738+
result.extend(and.clone());
739+
}
740+
result
741+
}
742+
Terminal::Multi(k, dpk_v) |
743+
Terminal::MultiA(k,dpk_v ) => Self::get_asset_combination(*k, dpk_v),
744+
}
745+
}
746+
747+
// Helper to get all possible pairs of K of N assets
748+
fn get_asset_combination(k: usize, dpk_v: &Vec<DescriptorPublicKey>) -> Vec<Assets> {
749+
let mut all_assets: Vec<Assets> = Vec::new();
750+
let current_assets = Assets::new();
751+
Self::combine_assets(k, dpk_v, 0, current_assets, &mut all_assets);
752+
all_assets
753+
}
754+
755+
// Combine K of N assets
756+
fn combine_assets(
757+
k: usize,
758+
dpk_v: &[DescriptorPublicKey],
759+
index: usize,
760+
current_assets: Assets,
761+
all_assets: &mut Vec<Assets>,
762+
) {
763+
if k == 0 {
764+
all_assets.push(current_assets);
765+
return;
766+
}
767+
if index >= dpk_v.len() {
768+
return;
769+
}
770+
Self::combine_assets(k, dpk_v, index + 1, current_assets.clone(), all_assets);
771+
let mut new_asset = current_assets;
772+
new_asset = new_asset.add(dpk_v[index].clone());
773+
println!("{:#?}", new_asset);
774+
Self::combine_assets(k - 1, dpk_v, index + 1, new_asset, all_assets)
775+
}
776+
777+
// Helper to get all combinations of K policies of N for thresh
778+
fn get_ms_combination_thresh(
779+
k: usize,
780+
ms: &Vec<Arc<Miniscript<DescriptorPublicKey, Ctx>>>,
781+
) -> Vec<Vec<Arc<Miniscript<DescriptorPublicKey, Ctx>>>> {
782+
let mut result = Vec::new();
783+
let mut current_combination = Vec::new();
784+
Self::combine_ms(0, &mut current_combination, &mut result, ms, k);
785+
result
786+
}
787+
788+
// combine K policies of N for thresh
789+
fn combine_ms(
790+
start: usize,
791+
current_combination: &mut Vec<Arc<Miniscript<DescriptorPublicKey, Ctx>>>,
792+
result: &mut Vec<Vec<Arc<Miniscript<DescriptorPublicKey, Ctx>>>>,
793+
ms: &Vec<Arc<Miniscript<DescriptorPublicKey, Ctx>>>,
794+
k: usize,
795+
) {
796+
if current_combination.len() == k {
797+
result.push(current_combination.clone());
798+
return;
799+
}
800+
for i in start..ms.len() {
801+
current_combination.push(ms[i].clone());
802+
Self::combine_ms(i + 1, current_combination, result, ms, k);
803+
current_combination.truncate(current_combination.len() - 1);
804+
}
805+
}
806+
}

0 commit comments

Comments
 (0)