diff --git a/Cargo.toml b/Cargo.toml index ac2a504c9..1d2a0bfd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,10 @@ required-features = ["compiler","std"] name = "psbt_sign_finalize" required-features = ["std", "base64"] +[[example]] +name = "big" +required-features = ["std", "base64", "compiler"] + [workspace] members = ["bitcoind-tests", "fuzz"] exclude = ["embedded"] diff --git a/examples/big.rs b/examples/big.rs new file mode 100644 index 000000000..cf0bd099a --- /dev/null +++ b/examples/big.rs @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: CC0-1.0 +//! This is not an example and will surely panic if executed, the purpose of this is using the +//! compiled binary with tools like `cargo bloat` that cannot work with libraries. +//! +//! Ideal properties: +//! +//! * Call all the library API surface. +//! * Depend on user input so that functions are not stripped out on the base of static input. +//! * Use results so that calls are not stripped out. +//! + +use std::collections::HashMap; +use std::str::FromStr; + +use bitcoin::{ecdsa, XOnlyPublicKey}; +use miniscript::descriptor::Wsh; +use miniscript::policy::{Concrete, Liftable}; +use miniscript::psbt::PsbtExt; +use miniscript::{ + translate_hash_fail, DefiniteDescriptorKey, Descriptor, DescriptorPublicKey, MiniscriptKey, + TranslatePk, Translator, +}; +use secp256k1::Secp256k1; +fn main() { + let empty = "".to_string(); + let mut args = std::env::args().collect::>(); + let i = args.pop().unwrap_or(empty); + + let d = Descriptor::::from_str(&i).unwrap(); + use_descriptor(d.clone()); + use_descriptor(Descriptor::::from_str(&i).unwrap()); + use_descriptor(Descriptor::::from_str(&i).unwrap()); + use_descriptor(Descriptor::::from_str(&i).unwrap()); + + let a = d + .at_derivation_index(0) + .unwrap() + .address(bitcoin::Network::Bitcoin) + .unwrap(); + println!("{}", a); + + let secp = Secp256k1::new(); + let (d, m) = Descriptor::parse_descriptor(&secp, &i).unwrap(); + use_descriptor(d); + println!("{:?}", m); + + let p = Concrete::::from_str(&i).unwrap(); + let h = Wsh::new(p.compile().unwrap()).unwrap(); + println!("{}", h); + println!("{:?}", h.lift()); + println!("{:?}", h.script_pubkey()); + println!("{:?}", h.address(bitcoin::Network::Bitcoin)); + + let psbt: bitcoin::Psbt = i.parse().unwrap(); + let psbt = psbt.finalize(&secp).unwrap(); + let mut tx = psbt.extract_tx().unwrap(); + println!("{:?}", tx); + + let d = miniscript::Descriptor::::from_str(&i).unwrap(); + let sigs = HashMap::::new(); + d.satisfy(&mut tx.input[0], &sigs).unwrap(); + + let pol = Concrete::::from_str(&i).unwrap(); + let desc = pol.compile_tr(Some("UNSPENDABLE_KEY".to_string())).unwrap(); + println!("{}", desc); + let pk_map = HashMap::new(); + let mut t = StrPkTranslator { pk_map }; + let real_desc = desc.translate_pk(&mut t).unwrap(); + println!("{}", real_desc); + let addr = real_desc.address(bitcoin::Network::Bitcoin).unwrap(); + println!("{}", addr); +} + +fn use_descriptor(d: Descriptor) { + println!("{}", d); + println!("{:?}", d); + println!("{:?}", d.desc_type()); + println!("{:?}", d.sanity_check()); +} + +struct StrPkTranslator { + pk_map: HashMap, +} + +impl Translator for StrPkTranslator { + fn pk(&mut self, pk: &String) -> Result { + self.pk_map.get(pk).copied().ok_or(()) + } + + // We don't need to implement these methods as we are not using them in the policy. + // Fail if we encounter any hash fragments. See also translate_hash_clone! macro. + translate_hash_fail!(String, XOnlyPublicKey, ()); +}