Skip to content

Commit 0ca5943

Browse files
committed
Adding taptree_of_horror example.
Adding bitcoin_hashes as dev dependency.
1 parent 3a85952 commit 0ca5943

File tree

6 files changed

+440
-4
lines changed

6 files changed

+440
-4
lines changed

Cargo.toml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
[package]
22
name = "miniscript"
33
version = "12.2.0"
4-
authors = ["Andrew Poelstra <[email protected]>, Sanket Kanjalkar <[email protected]>"]
4+
authors = [
5+
"Andrew Poelstra <[email protected]>, Sanket Kanjalkar <[email protected]>",
6+
]
57
license = "CC0-1.0"
68
homepage = "https://github.com/rust-bitcoin/rust-miniscript/"
79
repository = "https://github.com/rust-bitcoin/rust-miniscript/"
810
description = "Miniscript: a subset of Bitcoin Script designed for analysis"
9-
keywords = [ "crypto", "bitcoin", "miniscript", "script" ]
11+
keywords = ["crypto", "bitcoin", "miniscript", "script"]
1012
readme = "README.md"
1113
edition = "2021"
1214
rust-version = "1.63.0"
@@ -32,7 +34,8 @@ actual-serde = { package = "serde", version = "1.0.103", optional = true }
3234
[dev-dependencies]
3335
serde_test = "1.0.147"
3436
bitcoin = { version = "0.32.0", features = ["base64"] }
35-
secp256k1 = {version = "0.29.0", features = ["rand-std"]}
37+
secp256k1 = { version = "0.29.0", features = ["rand-std"] }
38+
bitcoin_hashes = "0.14.0"
3639

3740
[[example]]
3841
name = "htlc"
@@ -56,7 +59,7 @@ required-features = ["std"]
5659

5760
[[example]]
5861
name = "taproot"
59-
required-features = ["compiler","std"]
62+
required-features = ["compiler", "std"]
6063

6164
[[example]]
6265
name = "psbt_sign_finalize"
@@ -66,6 +69,12 @@ required-features = ["std", "base64"]
6669
name = "big"
6770
required-features = ["std", "base64", "compiler"]
6871

72+
[[example]]
73+
name = "taptree_of_horror"
74+
path = "examples/taptree_of_horror/taptree_of_horror.rs"
75+
required-features = ["compiler"]
76+
77+
6978
[workspace]
7079
members = ["fuzz"]
7180
exclude = ["embedded", "bitcoind-tests"]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Taptree of Horror Example
2+
3+
### Running this example:
4+
- `cargo run --example taptree_of_horror --features "compiler"`
5+
6+
### Originally based on the TABConf 6, CTB.
7+
The challenge can be found here:
8+
- https://tabctb.com/six
9+
- https://tabctb.com/six/thebeginning/thetree/grim/iacceptyourterms.html
10+
11+
### This example demonstrates:
12+
- Providing multiple extended private key (xpriv) descriptors for sample personas.
13+
- Creating a policy using logical 'and/or' conditions with preimages and signatures and timelocks.
14+
- Structuring a Taproot tree (taptree) with an internal key into logical branches and leaves based on the policy.
15+
- Implementing nine complex tapleaves within the taptree.
16+
- Building a spending transaction that signs and satisfies one of the tapleaves using signatures, preimages and a timelock.
17+
18+
### Helpful Graphic to visualize using Excalidraw
19+
![taptree_of_horror](./taptree_of_horror.png)
20+
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use std::str::FromStr;
2+
3+
use bitcoin::{
4+
bip32::{DerivationPath, Xpriv},
5+
hashes::{ripemd160, sha256},
6+
};
7+
use bitcoin_hashes::Hash;
8+
use miniscript::{descriptor::DescriptorSecretKey, ToPublicKey};
9+
use secp256k1::Secp256k1;
10+
11+
pub fn produce_grim_hash(secret: &str) -> (sha256::Hash, ripemd160::Hash) {
12+
let mut hash_holder = sha256::Hash::hash(secret.as_bytes());
13+
for _i in 0..5 {
14+
hash_holder = sha256::Hash::hash(hash_holder.as_byte_array());
15+
//println!("{} hash: {}", i, hash_holder);
16+
}
17+
18+
let ripemd_160_final = ripemd160::Hash::hash(hash_holder.as_byte_array());
19+
(hash_holder, ripemd_160_final)
20+
}
21+
22+
pub fn produce_kelly_hash(secret: &str) -> (sha256::Hash, sha256::Hash) {
23+
let prepreimage: Vec<u8> = secret.as_bytes().to_vec();
24+
let preimage_256_hash = sha256::Hash::hash(&prepreimage);
25+
let result256_final = sha256::Hash::hash(&preimage_256_hash.to_byte_array());
26+
(preimage_256_hash, result256_final)
27+
}
28+
29+
pub fn produce_key_pairs(
30+
desc: DescriptorSecretKey,
31+
secp: &Secp256k1<secp256k1::All>,
32+
derivation_without_index: &str,
33+
_alias: &str,
34+
) -> (Vec<bitcoin::PublicKey>, Vec<Xpriv>) {
35+
let mut pks = Vec::new();
36+
let mut prvs = Vec::new();
37+
38+
let xprv = match &desc {
39+
DescriptorSecretKey::XPrv(xpriv) => xpriv,
40+
_ => panic!("not an xpriv"),
41+
};
42+
43+
for i in 0..9 {
44+
let pk = desc
45+
.to_public(secp)
46+
.unwrap()
47+
.at_derivation_index(i)
48+
.unwrap()
49+
.to_public_key();
50+
51+
let derivation_with_index = format!("{}/{}", derivation_without_index, i);
52+
let derivation_path = DerivationPath::from_str(&derivation_with_index).unwrap();
53+
let derived_xpriv: Xpriv = xprv.xkey.derive_priv(secp, &derivation_path).unwrap();
54+
55+
pks.insert(i.try_into().unwrap(), pk);
56+
prvs.insert(i.try_into().unwrap(), derived_xpriv);
57+
}
58+
(pks, prvs)
59+
}

examples/taptree_of_horror/taptree_of_horror.excalidraw

Lines changed: 57 additions & 0 deletions
Large diffs are not rendered by default.
270 KB
Loading

0 commit comments

Comments
 (0)