Skip to content

Commit

Permalink
Merge #646: Introduce an example binary useful for profiling
Browse files Browse the repository at this point in the history
c8d3b9a fix formatting in big example (Riccardo Casatta)
bc47538 add taproot calls in big executable (Riccardo Casatta)
545bbbe add satisfy call in big executable (Riccardo Casatta)
959546b add psbt finalize call in big executable (Riccardo Casatta)
883132e add policy calls in big executable (Riccardo Casatta)
ec751fb Introduce an example binary useful for profiling (Riccardo Casatta)

Pull request description:

  Tools like `cargo bloat` don't work on libraries but on final executable.

  As seen in #585 and #584 the parse example is used as a base to profile binary bloat.

  However, since the parse example is not using all the API surface, we may have good optimization that are not recognized as such because the optimized function are not in the tree of the functions used.

  For benchmarking size optimization a specific binary that ideally touch all the API surface is needed and this MR introduce it.

  More coverage will be added if this seem a good idea for reviewers.

ACKs for top commit:
  apoelstra:
    ACK c8d3b9a thanks!

Tree-SHA512: 70ac51a222b59b5de76a2ef314be2f3d82b3f5831d90dd7110929a4956a27a6d1eaa4889525dbf54575fb7e07db60f19d67556f2539b61979b4ba681fec0523e
  • Loading branch information
apoelstra committed Mar 4, 2024
2 parents 02504cb + c8d3b9a commit 551932e
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
93 changes: 93 additions & 0 deletions examples/big.rs
Original file line number Diff line number Diff line change
@@ -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::<Vec<_>>();
let i = args.pop().unwrap_or(empty);

let d = Descriptor::<DescriptorPublicKey>::from_str(&i).unwrap();
use_descriptor(d.clone());
use_descriptor(Descriptor::<DefiniteDescriptorKey>::from_str(&i).unwrap());
use_descriptor(Descriptor::<bitcoin::PublicKey>::from_str(&i).unwrap());
use_descriptor(Descriptor::<String>::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::<bitcoin::PublicKey>::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::<bitcoin::PublicKey>::from_str(&i).unwrap();
let sigs = HashMap::<bitcoin::PublicKey, ecdsa::Signature>::new();
d.satisfy(&mut tx.input[0], &sigs).unwrap();

let pol = Concrete::<String>::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<K: MiniscriptKey>(d: Descriptor<K>) {
println!("{}", d);
println!("{:?}", d);
println!("{:?}", d.desc_type());
println!("{:?}", d.sanity_check());
}

struct StrPkTranslator {
pk_map: HashMap<String, XOnlyPublicKey>,
}

impl Translator<String, XOnlyPublicKey, ()> for StrPkTranslator {
fn pk(&mut self, pk: &String) -> Result<XOnlyPublicKey, ()> {
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, ());
}

0 comments on commit 551932e

Please sign in to comment.