Skip to content

Commit 079a1d3

Browse files
committed
Adding taptree_of_horror example.
Adding bitcoin_hashes as dev dependency.
1 parent acbd120 commit 079a1d3

File tree

6 files changed

+2973
-0
lines changed

6 files changed

+2973
-0
lines changed

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ required-features = ["std", "base64"]
6666
name = "big"
6767
required-features = ["std", "base64", "compiler"]
6868

69+
[[example]]
70+
name = "taptree_of_horror"
71+
path = "examples/taptree_of_horror/taptree_of_horror.rs"
72+
required-features = ["compiler"]
73+
6974
[workspace]
7075
members = ["fuzz"]
7176
exclude = ["embedded", "bitcoind-tests"]

examples/taptree_of_horror/README.md

+20
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+
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use std::str::FromStr;
2+
3+
use bitcoin::bip32::{DerivationPath, Xpriv};
4+
use bitcoin::hashes::{ripemd160, sha256, Hash};
5+
use miniscript::descriptor::DescriptorSecretKey;
6+
use miniscript::ToPublicKey;
7+
use secp256k1::Secp256k1;
8+
9+
pub fn produce_grim_hash(secret: &str) -> (sha256::Hash, ripemd160::Hash) {
10+
let mut hash_holder = sha256::Hash::hash(secret.as_bytes());
11+
for _i in 0..5 {
12+
hash_holder = sha256::Hash::hash(hash_holder.as_byte_array());
13+
//println!("{} hash: {}", i, hash_holder);
14+
}
15+
16+
let ripemd_160_final = ripemd160::Hash::hash(hash_holder.as_byte_array());
17+
(hash_holder, ripemd_160_final)
18+
}
19+
20+
pub fn produce_kelly_hash(secret: &str) -> (sha256::Hash, sha256::Hash) {
21+
let prepreimage: Vec<u8> = secret.as_bytes().to_vec();
22+
let preimage_256_hash = sha256::Hash::hash(&prepreimage);
23+
let result256_final = sha256::Hash::hash(&preimage_256_hash.to_byte_array());
24+
(preimage_256_hash, result256_final)
25+
}
26+
27+
pub fn produce_key_pairs(
28+
desc: DescriptorSecretKey,
29+
secp: &Secp256k1<secp256k1::All>,
30+
derivation_without_index: &str,
31+
_alias: &str,
32+
) -> (Vec<bitcoin::PublicKey>, Vec<Xpriv>) {
33+
let mut pks = Vec::new();
34+
let mut prvs = Vec::new();
35+
36+
let xprv = match &desc {
37+
DescriptorSecretKey::XPrv(xpriv) => xpriv,
38+
_ => panic!("not an xpriv"),
39+
};
40+
41+
for i in 0..9 {
42+
let pk = desc
43+
.to_public(secp)
44+
.unwrap()
45+
.at_derivation_index(i)
46+
.unwrap()
47+
.to_public_key();
48+
49+
let derivation_with_index = format!("{}/{}", derivation_without_index, i);
50+
let derivation_path = DerivationPath::from_str(&derivation_with_index).unwrap();
51+
let derived_xpriv: Xpriv = xprv.xkey.derive_priv(secp, &derivation_path).unwrap();
52+
53+
pks.insert(i.try_into().unwrap(), pk);
54+
prvs.insert(i.try_into().unwrap(), derived_xpriv);
55+
}
56+
(pks, prvs)
57+
}

0 commit comments

Comments
 (0)