Skip to content

Commit 670e808

Browse files
committed
Merge rust-bitcoin/rust-bitcoin#681: Add support for taproot psbt fields BIP 371
7d982fa Add all tests from BIP 371 (sanket1729) d22e014 Taproot psbt impl BIP 371 (sanket1729) 108fc3d Impl encodable traits for TapLeafhash (sanket1729) c7478d8 Derive serde for taproot stuctures (sanket1729) Pull request description: Built on top of #677 . Will rebase and mark ready for review after #677 is merged. ACKs for top commit: apoelstra: ACK 7d982fa dr-orlovsky: re-tACK 7d982fa basing on `git range-diff`. The original PR before last re-base was tested commit-by-commit. Tree-SHA512: feb30e4b38d13110a9c0fabf6466d8f0fb7df09a82f4e01d70b8371b34ab0187004a6c63f9796c6585ee30841e8ee765ae9becae139d2e1e3d839553d64c3d1e
2 parents 86055d9 + 7d982fa commit 670e808

File tree

9 files changed

+496
-15
lines changed

9 files changed

+496
-15
lines changed

src/consensus/encode.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use io::{self, Cursor, Read};
3939

4040
use util::endian;
4141
use util::psbt;
42+
use util::taproot::TapLeafHash;
4243
use hashes::hex::ToHex;
4344

4445
use blockdata::transaction::{TxOut, Transaction, TxIn};
@@ -594,6 +595,7 @@ impl_vec!(TxOut);
594595
impl_vec!(TxIn);
595596
impl_vec!(Vec<u8>);
596597
impl_vec!(u64);
598+
impl_vec!(TapLeafHash);
597599

598600
#[cfg(feature = "std")] impl_vec!(Inventory);
599601
#[cfg(feature = "std")] impl_vec!((u32, Address));
@@ -767,6 +769,18 @@ impl Decodable for sha256::Hash {
767769
}
768770
}
769771

772+
impl Encodable for TapLeafHash {
773+
fn consensus_encode<S: io::Write>(&self, s: S) -> Result<usize, io::Error> {
774+
self.into_inner().consensus_encode(s)
775+
}
776+
}
777+
778+
impl Decodable for TapLeafHash {
779+
fn consensus_decode<D: io::Read>(d: D) -> Result<Self, Error> {
780+
Ok(Self::from_inner(<<Self as Hash>::Inner>::consensus_decode(d)?))
781+
}
782+
}
783+
770784
// Tests
771785
#[cfg(test)]
772786
mod tests {

src/util/psbt/map/input.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ use util::psbt::raw;
2828
use util::psbt::serialize::Deserialize;
2929
use util::psbt::{Error, error};
3030

31+
use schnorr;
32+
use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash};
33+
3134
/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
3235
const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
3336
/// Type: Witness UTXO PSBT_IN_WITNESS_UTXO = 0x01
@@ -54,6 +57,18 @@ const PSBT_IN_SHA256: u8 = 0x0b;
5457
const PSBT_IN_HASH160: u8 = 0x0c;
5558
/// Type: HASH256 preimage PSBT_IN_HASH256 = 0x0d
5659
const PSBT_IN_HASH256: u8 = 0x0d;
60+
/// Type: Schnorr Signature in Key Spend PSBT_IN_TAP_KEY_SIG = 0x13
61+
const PSBT_IN_TAP_KEY_SIG: u8 = 0x13;
62+
/// Type: Schnorr Signature in Script Spend PSBT_IN_TAP_SCRIPT_SIG = 0x14
63+
const PSBT_IN_TAP_SCRIPT_SIG: u8 = 0x14;
64+
/// Type: Taproot Leaf Script PSBT_IN_TAP_LEAF_SCRIPT = 0x14
65+
const PSBT_IN_TAP_LEAF_SCRIPT: u8 = 0x15;
66+
/// Type: Taproot Key BIP 32 Derivation Path PSBT_IN_TAP_BIP32_DERIVATION = 0x16
67+
const PSBT_IN_TAP_BIP32_DERIVATION : u8 = 0x16;
68+
/// Type: Taproot Internal Key PSBT_IN_TAP_INTERNAL_KEY = 0x17
69+
const PSBT_IN_TAP_INTERNAL_KEY : u8 = 0x17;
70+
/// Type: Taproot Merkle Root PSBT_IN_TAP_MERKLE_ROOT = 0x18
71+
const PSBT_IN_TAP_MERKLE_ROOT : u8 = 0x18;
5772
/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC
5873
const PSBT_IN_PROPRIETARY: u8 = 0xFC;
5974

@@ -104,6 +119,21 @@ pub struct Input {
104119
/// HAS256 hash to preimage map
105120
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
106121
pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
122+
/// Serialized schnorr signature with sighash type for key spend
123+
pub tap_key_sig: Option<schnorr::SchnorrSig>,
124+
/// Map of <xonlypubkey>|<leafhash> with signature
125+
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
126+
pub tap_script_sigs: BTreeMap<(schnorr::PublicKey, TapLeafHash), schnorr::SchnorrSig>,
127+
/// Map of Control blocks to Script version pair
128+
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
129+
pub tap_scripts: BTreeMap<ControlBlock, (Script, LeafVersion)>,
130+
/// Map of tap root x only keys to origin info and leaf hashes contained in it
131+
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
132+
pub tap_key_origins: BTreeMap<schnorr::PublicKey, (Vec<TapLeafHash>, KeySource)>,
133+
/// Taproot Internal key
134+
pub tap_internal_key : Option<schnorr::PublicKey>,
135+
/// Taproot Merkle root
136+
pub tap_merkle_root : Option<TapBranchHash>,
107137
/// Proprietary key-value pairs for this input.
108138
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
109139
pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
@@ -177,6 +207,36 @@ impl Map for Input {
177207
PSBT_IN_HASH256 => {
178208
psbt_insert_hash_pair(&mut self.hash256_preimages, raw_key, raw_value, error::PsbtHash::Hash256)?;
179209
}
210+
PSBT_IN_TAP_KEY_SIG => {
211+
impl_psbt_insert_pair! {
212+
self.tap_key_sig <= <raw_key: _>|<raw_value: schnorr::SchnorrSig>
213+
}
214+
}
215+
PSBT_IN_TAP_SCRIPT_SIG => {
216+
impl_psbt_insert_pair! {
217+
self.tap_script_sigs <= <raw_key: (schnorr::PublicKey, TapLeafHash)>|<raw_value: schnorr::SchnorrSig>
218+
}
219+
}
220+
PSBT_IN_TAP_LEAF_SCRIPT=> {
221+
impl_psbt_insert_pair! {
222+
self.tap_scripts <= <raw_key: ControlBlock>|< raw_value: (Script, LeafVersion)>
223+
}
224+
}
225+
PSBT_IN_TAP_BIP32_DERIVATION => {
226+
impl_psbt_insert_pair! {
227+
self.tap_key_origins <= <raw_key: schnorr::PublicKey>|< raw_value: (Vec<TapLeafHash>, KeySource)>
228+
}
229+
}
230+
PSBT_IN_TAP_INTERNAL_KEY => {
231+
impl_psbt_insert_pair! {
232+
self.tap_internal_key <= <raw_key: _>|< raw_value: schnorr::PublicKey>
233+
}
234+
}
235+
PSBT_IN_TAP_MERKLE_ROOT => {
236+
impl_psbt_insert_pair! {
237+
self.tap_merkle_root <= <raw_key: _>|< raw_value: TapBranchHash>
238+
}
239+
}
180240
PSBT_IN_PROPRIETARY => match self.proprietary.entry(raw::ProprietaryKey::from_key(raw_key.clone())?) {
181241
btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
182242
btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()),
@@ -249,6 +309,30 @@ impl Map for Input {
249309
rv.push(self.hash256_preimages as <PSBT_IN_HASH256, sha256d::Hash>|<Vec<u8>>)
250310
}
251311

312+
impl_psbt_get_pair! {
313+
rv.push(self.tap_key_sig as <PSBT_IN_TAP_KEY_SIG, _>|<Vec<u8>>)
314+
}
315+
316+
impl_psbt_get_pair! {
317+
rv.push(self.tap_script_sigs as <PSBT_IN_TAP_SCRIPT_SIG, (schnorr::PublicKey, TapLeafHash)>|<Vec<u8>>)
318+
}
319+
320+
impl_psbt_get_pair! {
321+
rv.push(self.tap_scripts as <PSBT_IN_TAP_LEAF_SCRIPT, ControlBlock>|<(Script, LeafVersion)>)
322+
}
323+
324+
impl_psbt_get_pair! {
325+
rv.push(self.tap_key_origins as <PSBT_IN_TAP_BIP32_DERIVATION,
326+
schnorr::PublicKey>|<(Vec<TapLeafHash>, KeySource)>)
327+
}
328+
329+
impl_psbt_get_pair! {
330+
rv.push(self.tap_internal_key as <PSBT_IN_TAP_INTERNAL_KEY, _>|<schnorr::PublicKey>)
331+
}
332+
333+
impl_psbt_get_pair! {
334+
rv.push(self.tap_merkle_root as <PSBT_IN_TAP_MERKLE_ROOT, _>|<TapBranchHash>)
335+
}
252336
for (key, value) in self.proprietary.iter() {
253337
rv.push(raw::Pair {
254338
key: key.to_key(),
@@ -280,13 +364,19 @@ impl Map for Input {
280364
self.sha256_preimages.extend(other.sha256_preimages);
281365
self.hash160_preimages.extend(other.hash160_preimages);
282366
self.hash256_preimages.extend(other.hash256_preimages);
367+
self.tap_script_sigs.extend(other.tap_script_sigs);
368+
self.tap_scripts.extend(other.tap_scripts);
369+
self.tap_key_origins.extend(other.tap_key_origins);
283370
self.proprietary.extend(other.proprietary);
284371
self.unknown.extend(other.unknown);
285372

286373
merge!(redeem_script, self, other);
287374
merge!(witness_script, self, other);
288375
merge!(final_script_sig, self, other);
289376
merge!(final_script_witness, self, other);
377+
merge!(tap_key_sig, self, other);
378+
merge!(tap_internal_key, self, other);
379+
merge!(tap_merkle_root, self, other);
290380

291381
Ok(())
292382
}

src/util/psbt/map/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,4 @@ mod output;
5555

5656
pub use self::input::Input;
5757
pub use self::output::Output;
58+
pub use self::output::TapTree;

src/util/psbt/map/output.rs

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,23 @@ use util::psbt::map::Map;
2525
use util::psbt::raw;
2626
use util::psbt::Error;
2727

28+
use schnorr;
29+
use util::taproot::TapLeafHash;
30+
31+
use util::taproot::{NodeInfo, TaprootBuilder};
32+
2833
/// Type: Redeem Script PSBT_OUT_REDEEM_SCRIPT = 0x00
2934
const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00;
3035
/// Type: Witness Script PSBT_OUT_WITNESS_SCRIPT = 0x01
3136
const PSBT_OUT_WITNESS_SCRIPT: u8 = 0x01;
3237
/// Type: BIP 32 Derivation Path PSBT_OUT_BIP32_DERIVATION = 0x02
3338
const PSBT_OUT_BIP32_DERIVATION: u8 = 0x02;
39+
/// Type: Taproot Internal Key PSBT_OUT_TAP_INTERNAL_KEY = 0x05
40+
const PSBT_OUT_TAP_INTERNAL_KEY: u8 = 0x05;
41+
/// Type: Taproot Tree PSBT_OUT_TAP_TREE = 0x06
42+
const PSBT_OUT_TAP_TREE: u8 = 0x06;
43+
/// Type: Taproot Key BIP 32 Derivation Path PSBT_OUT_TAP_BIP32_DERIVATION = 0x07
44+
const PSBT_OUT_TAP_BIP32_DERIVATION: u8 = 0x07;
3445
/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC
3546
const PSBT_OUT_PROPRIETARY: u8 = 0xFC;
3647

@@ -47,14 +58,67 @@ pub struct Output {
4758
/// corresponding master key fingerprints and derivation paths.
4859
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
4960
pub bip32_derivation: BTreeMap<PublicKey, KeySource>,
61+
/// The internal pubkey
62+
pub tap_internal_key: Option<schnorr::PublicKey>,
63+
/// Taproot Output tree
64+
pub tap_tree: Option<TapTree>,
65+
/// Map of tap root x only keys to origin info and leaf hashes contained in it
66+
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
67+
pub tap_key_origins: BTreeMap<schnorr::PublicKey, (Vec<TapLeafHash>, KeySource)>,
5068
/// Proprietary key-value pairs for this output.
51-
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
69+
#[cfg_attr(
70+
feature = "serde",
71+
serde(with = "::serde_utils::btreemap_as_seq_byte_values")
72+
)]
5273
pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
5374
/// Unknown key-value pairs for this output.
54-
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
75+
#[cfg_attr(
76+
feature = "serde",
77+
serde(with = "::serde_utils::btreemap_as_seq_byte_values")
78+
)]
5579
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
5680
}
5781

82+
/// Taproot Tree representing a finalized [`TaprootBuilder`] (a complete binary tree)
83+
#[derive(Clone, Debug)]
84+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
85+
pub struct TapTree(pub(crate) TaprootBuilder);
86+
87+
impl PartialEq for TapTree {
88+
fn eq(&self, other: &Self) -> bool {
89+
self.node_info().hash.eq(&other.node_info().hash)
90+
}
91+
}
92+
93+
impl Eq for TapTree {}
94+
95+
impl TapTree {
96+
// get the inner node info as the builder is finalized
97+
fn node_info(&self) -> &NodeInfo {
98+
// The builder algorithm invariant guarantees that is_complete builder
99+
// have only 1 element in branch and that is not None.
100+
// We make sure that we only allow is_complete builders via the from_inner
101+
// constructor
102+
self.0.branch()[0].as_ref().expect("from_inner only parses is_complete builders")
103+
}
104+
105+
/// Convert a [`TaprootBuilder`] into a tree if it is complete binary tree.
106+
/// Returns the inner as Err if it is not a complete tree
107+
pub fn from_inner(inner: TaprootBuilder) -> Result<Self, TaprootBuilder> {
108+
if inner.is_complete() {
109+
Ok(TapTree(inner))
110+
} else {
111+
Err(inner)
112+
}
113+
}
114+
115+
/// Convert self into builder [`TaprootBuilder`]. The builder is guaranteed to
116+
/// be finalized.
117+
pub fn into_inner(self) -> TaprootBuilder {
118+
self.0
119+
}
120+
}
121+
58122
impl Map for Output {
59123
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
60124
let raw::Pair {
@@ -82,10 +146,29 @@ impl Map for Output {
82146
btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
83147
btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()),
84148
}
85-
_ => match self.unknown.entry(raw_key) {
86-
btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
87-
btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()),
149+
PSBT_OUT_TAP_INTERNAL_KEY => {
150+
impl_psbt_insert_pair! {
151+
self.tap_internal_key <= <raw_key: _>|<raw_value: schnorr::PublicKey>
152+
}
153+
}
154+
PSBT_OUT_TAP_TREE => {
155+
impl_psbt_insert_pair! {
156+
self.tap_tree <= <raw_key: _>|<raw_value: TapTree>
157+
}
158+
}
159+
PSBT_OUT_TAP_BIP32_DERIVATION => {
160+
impl_psbt_insert_pair! {
161+
self.tap_key_origins <= <raw_key: schnorr::PublicKey>|< raw_value: (Vec<TapLeafHash>, KeySource)>
162+
}
88163
}
164+
_ => match self.unknown.entry(raw_key) {
165+
btree_map::Entry::Vacant(empty_key) => {
166+
empty_key.insert(raw_value);
167+
}
168+
btree_map::Entry::Occupied(k) => {
169+
return Err(Error::DuplicateKey(k.key().clone()).into())
170+
}
171+
},
89172
}
90173

91174
Ok(())
@@ -106,6 +189,19 @@ impl Map for Output {
106189
rv.push(self.bip32_derivation as <PSBT_OUT_BIP32_DERIVATION, PublicKey>|<KeySource>)
107190
}
108191

192+
impl_psbt_get_pair! {
193+
rv.push(self.tap_internal_key as <PSBT_OUT_TAP_INTERNAL_KEY, _>|<schnorr::PublicKey>)
194+
}
195+
196+
impl_psbt_get_pair! {
197+
rv.push(self.tap_tree as <PSBT_OUT_TAP_TREE, _>|<TaprootBuilder>)
198+
}
199+
200+
impl_psbt_get_pair! {
201+
rv.push(self.tap_key_origins as <PSBT_OUT_TAP_BIP32_DERIVATION,
202+
schnorr::PublicKey>|<(Vec<TapLeafHash>, KeySource)>)
203+
}
204+
109205
for (key, value) in self.proprietary.iter() {
110206
rv.push(raw::Pair {
111207
key: key.to_key(),
@@ -127,9 +223,12 @@ impl Map for Output {
127223
self.bip32_derivation.extend(other.bip32_derivation);
128224
self.proprietary.extend(other.proprietary);
129225
self.unknown.extend(other.unknown);
226+
self.tap_key_origins.extend(other.tap_key_origins);
130227

131228
merge!(redeem_script, self, other);
132229
merge!(witness_script, self, other);
230+
merge!(tap_internal_key, self, other);
231+
merge!(tap_tree, self, other);
133232

134233
Ok(())
135234
}

0 commit comments

Comments
 (0)