|
| 1 | +// SPDX-License-Identifier: CC0-1.0 |
| 2 | +//! This is not an example and will surely panic if executed, the purpose of this is using the |
| 3 | +//! compiled binary with tools like `cargo bloat` that cannot work with libraries. |
| 4 | +//! |
| 5 | +//! Ideal properties: |
| 6 | +//! |
| 7 | +//! * Call all the library API surface. |
| 8 | +//! * Depend on user input so that functions are not stripped out on the base of static input. |
| 9 | +//! * Use results so that calls are not stripped out. |
| 10 | +//! |
| 11 | +
|
| 12 | +use std::collections::HashMap; |
| 13 | +use std::str::FromStr; |
| 14 | + |
| 15 | +use bitcoin::{ecdsa, XOnlyPublicKey}; |
| 16 | +use miniscript::descriptor::Wsh; |
| 17 | +use miniscript::policy::{Concrete, Liftable}; |
| 18 | +use miniscript::psbt::PsbtExt; |
| 19 | +use miniscript::{ |
| 20 | + translate_hash_fail, DefiniteDescriptorKey, Descriptor, DescriptorPublicKey, MiniscriptKey, |
| 21 | + TranslatePk, Translator, |
| 22 | +}; |
| 23 | +use secp256k1::Secp256k1; |
| 24 | +fn main() { |
| 25 | + let empty = "".to_string(); |
| 26 | + let mut args = std::env::args().collect::<Vec<_>>(); |
| 27 | + let i = args.pop().unwrap_or(empty); |
| 28 | + |
| 29 | + let d = Descriptor::<DescriptorPublicKey>::from_str(&i).unwrap(); |
| 30 | + use_descriptor(d.clone()); |
| 31 | + use_descriptor(Descriptor::<DefiniteDescriptorKey>::from_str(&i).unwrap()); |
| 32 | + use_descriptor(Descriptor::<bitcoin::PublicKey>::from_str(&i).unwrap()); |
| 33 | + use_descriptor(Descriptor::<String>::from_str(&i).unwrap()); |
| 34 | + |
| 35 | + let a = d |
| 36 | + .at_derivation_index(0) |
| 37 | + .unwrap() |
| 38 | + .address(bitcoin::Network::Bitcoin) |
| 39 | + .unwrap(); |
| 40 | + println!("{}", a); |
| 41 | + |
| 42 | + let secp = Secp256k1::new(); |
| 43 | + let (d, m) = Descriptor::parse_descriptor(&secp, &i).unwrap(); |
| 44 | + use_descriptor(d); |
| 45 | + println!("{:?}", m); |
| 46 | + |
| 47 | + let p = Concrete::<bitcoin::PublicKey>::from_str(&i).unwrap(); |
| 48 | + let h = Wsh::new(p.compile().unwrap()).unwrap(); |
| 49 | + println!("{}", h); |
| 50 | + println!("{:?}", h.lift()); |
| 51 | + println!("{:?}", h.script_pubkey()); |
| 52 | + println!("{:?}", h.address(bitcoin::Network::Bitcoin)); |
| 53 | + |
| 54 | + let psbt: bitcoin::Psbt = i.parse().unwrap(); |
| 55 | + let psbt = psbt.finalize(&secp).unwrap(); |
| 56 | + let mut tx = psbt.extract_tx().unwrap(); |
| 57 | + println!("{:?}", tx); |
| 58 | + |
| 59 | + let d = miniscript::Descriptor::<bitcoin::PublicKey>::from_str(&i).unwrap(); |
| 60 | + let sigs = HashMap::<bitcoin::PublicKey, ecdsa::Signature>::new(); |
| 61 | + d.satisfy(&mut tx.input[0], &sigs).unwrap(); |
| 62 | + |
| 63 | + let pol = Concrete::<String>::from_str(&i).unwrap(); |
| 64 | + let desc = pol.compile_tr(Some("UNSPENDABLE_KEY".to_string())).unwrap(); |
| 65 | + println!("{}", desc); |
| 66 | + let pk_map = HashMap::new(); |
| 67 | + let mut t = StrPkTranslator { pk_map }; |
| 68 | + let real_desc = desc.translate_pk(&mut t).unwrap(); |
| 69 | + println!("{}", real_desc); |
| 70 | + let addr = real_desc.address(bitcoin::Network::Bitcoin).unwrap(); |
| 71 | + println!("{}", addr); |
| 72 | +} |
| 73 | + |
| 74 | +fn use_descriptor<K: MiniscriptKey>(d: Descriptor<K>) { |
| 75 | + println!("{}", d); |
| 76 | + println!("{:?}", d); |
| 77 | + println!("{:?}", d.desc_type()); |
| 78 | + println!("{:?}", d.sanity_check()); |
| 79 | +} |
| 80 | + |
| 81 | +struct StrPkTranslator { |
| 82 | + pk_map: HashMap<String, XOnlyPublicKey>, |
| 83 | +} |
| 84 | + |
| 85 | +impl Translator<String, XOnlyPublicKey, ()> for StrPkTranslator { |
| 86 | + fn pk(&mut self, pk: &String) -> Result<XOnlyPublicKey, ()> { |
| 87 | + self.pk_map.get(pk).copied().ok_or(()) |
| 88 | + } |
| 89 | + |
| 90 | + // We don't need to implement these methods as we are not using them in the policy. |
| 91 | + // Fail if we encounter any hash fragments. See also translate_hash_clone! macro. |
| 92 | + translate_hash_fail!(String, XOnlyPublicKey, ()); |
| 93 | +} |
0 commit comments