Skip to content

Commit d22e014

Browse files
committed
Taproot psbt impl BIP 371
1 parent 108fc3d commit d22e014

File tree

6 files changed

+390
-13
lines changed

6 files changed

+390
-13
lines changed

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
}

src/util/psbt/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ mod macros;
3939
pub mod serialize;
4040

4141
mod map;
42-
pub use self::map::{Map, Input, Output};
42+
pub use self::map::{Map, Input, Output, TapTree};
4343

4444
use util::bip32::{ExtendedPubKey, KeySource};
4545

0 commit comments

Comments
 (0)