use ::miniscript::descriptor::TapTree;
use ::miniscript::*;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::Hash;
use bitcoin::XOnlyPublicKey;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::sync::Arc;
pub fn pick_key_from_miniscripts<'a, I: Iterator<Item = &'a Miniscript<XOnlyPublicKey, Tap>>>(
branches: I,
) -> XOnlyPublicKey {
branches
.filter_map(|f| {
if let Terminal::Check(check) = &f.node {
if let Terminal::PkK(k) = &check.node {
return Some(*k);
}
}
None
})
.next()
.unwrap_or(
XOnlyPublicKey::from_slice(&Sha256::hash(&[1u8; 32]).into_inner()).expect("constant"),
)
}
pub fn branches_to_tree(
branches: Vec<Miniscript<XOnlyPublicKey, Tap>>,
) -> Option<TapTree<XOnlyPublicKey>> {
let mut scripts: BinaryHeap<(Reverse<u64>, TapTree<XOnlyPublicKey>)> = branches
.into_iter()
.map(|b| (Reverse(1), TapTree::Leaf(Arc::new(b))))
.collect();
while scripts.len() > 1 {
let (w1, v1) = scripts.pop().unwrap();
let (w2, v2) = scripts.pop().unwrap();
scripts.push((
Reverse(w1.0.saturating_add(w2.0)),
TapTree::Tree(Arc::new(v1), Arc::new(v2)),
));
}
scripts.pop().map(|v| v.1)
}