Taproot psbt impl BIP 371
This commit is contained in:
parent
108fc3d4db
commit
d22e0149ad
|
@ -28,6 +28,9 @@ use util::psbt::raw;
|
|||
use util::psbt::serialize::Deserialize;
|
||||
use util::psbt::{Error, error};
|
||||
|
||||
use schnorr;
|
||||
use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash};
|
||||
|
||||
/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
|
||||
const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
|
||||
/// Type: Witness UTXO PSBT_IN_WITNESS_UTXO = 0x01
|
||||
|
@ -54,6 +57,18 @@ const PSBT_IN_SHA256: u8 = 0x0b;
|
|||
const PSBT_IN_HASH160: u8 = 0x0c;
|
||||
/// Type: HASH256 preimage PSBT_IN_HASH256 = 0x0d
|
||||
const PSBT_IN_HASH256: u8 = 0x0d;
|
||||
/// Type: Schnorr Signature in Key Spend PSBT_IN_TAP_KEY_SIG = 0x13
|
||||
const PSBT_IN_TAP_KEY_SIG: u8 = 0x13;
|
||||
/// Type: Schnorr Signature in Script Spend PSBT_IN_TAP_SCRIPT_SIG = 0x14
|
||||
const PSBT_IN_TAP_SCRIPT_SIG: u8 = 0x14;
|
||||
/// Type: Taproot Leaf Script PSBT_IN_TAP_LEAF_SCRIPT = 0x14
|
||||
const PSBT_IN_TAP_LEAF_SCRIPT: u8 = 0x15;
|
||||
/// Type: Taproot Key BIP 32 Derivation Path PSBT_IN_TAP_BIP32_DERIVATION = 0x16
|
||||
const PSBT_IN_TAP_BIP32_DERIVATION : u8 = 0x16;
|
||||
/// Type: Taproot Internal Key PSBT_IN_TAP_INTERNAL_KEY = 0x17
|
||||
const PSBT_IN_TAP_INTERNAL_KEY : u8 = 0x17;
|
||||
/// Type: Taproot Merkle Root PSBT_IN_TAP_MERKLE_ROOT = 0x18
|
||||
const PSBT_IN_TAP_MERKLE_ROOT : u8 = 0x18;
|
||||
/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC
|
||||
const PSBT_IN_PROPRIETARY: u8 = 0xFC;
|
||||
|
||||
|
@ -104,6 +119,21 @@ pub struct Input {
|
|||
/// HAS256 hash to preimage map
|
||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
|
||||
pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
|
||||
/// Serialized schnorr signature with sighash type for key spend
|
||||
pub tap_key_sig: Option<schnorr::SchnorrSig>,
|
||||
/// Map of <xonlypubkey>|<leafhash> with signature
|
||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
|
||||
pub tap_script_sigs: BTreeMap<(schnorr::PublicKey, TapLeafHash), schnorr::SchnorrSig>,
|
||||
/// Map of Control blocks to Script version pair
|
||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
|
||||
pub tap_scripts: BTreeMap<ControlBlock, (Script, LeafVersion)>,
|
||||
/// Map of tap root x only keys to origin info and leaf hashes contained in it
|
||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
|
||||
pub tap_key_origins: BTreeMap<schnorr::PublicKey, (Vec<TapLeafHash>, KeySource)>,
|
||||
/// Taproot Internal key
|
||||
pub tap_internal_key : Option<schnorr::PublicKey>,
|
||||
/// Taproot Merkle root
|
||||
pub tap_merkle_root : Option<TapBranchHash>,
|
||||
/// Proprietary key-value pairs for this input.
|
||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
|
||||
pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
|
||||
|
@ -177,6 +207,36 @@ impl Map for Input {
|
|||
PSBT_IN_HASH256 => {
|
||||
psbt_insert_hash_pair(&mut self.hash256_preimages, raw_key, raw_value, error::PsbtHash::Hash256)?;
|
||||
}
|
||||
PSBT_IN_TAP_KEY_SIG => {
|
||||
impl_psbt_insert_pair! {
|
||||
self.tap_key_sig <= <raw_key: _>|<raw_value: schnorr::SchnorrSig>
|
||||
}
|
||||
}
|
||||
PSBT_IN_TAP_SCRIPT_SIG => {
|
||||
impl_psbt_insert_pair! {
|
||||
self.tap_script_sigs <= <raw_key: (schnorr::PublicKey, TapLeafHash)>|<raw_value: schnorr::SchnorrSig>
|
||||
}
|
||||
}
|
||||
PSBT_IN_TAP_LEAF_SCRIPT=> {
|
||||
impl_psbt_insert_pair! {
|
||||
self.tap_scripts <= <raw_key: ControlBlock>|< raw_value: (Script, LeafVersion)>
|
||||
}
|
||||
}
|
||||
PSBT_IN_TAP_BIP32_DERIVATION => {
|
||||
impl_psbt_insert_pair! {
|
||||
self.tap_key_origins <= <raw_key: schnorr::PublicKey>|< raw_value: (Vec<TapLeafHash>, KeySource)>
|
||||
}
|
||||
}
|
||||
PSBT_IN_TAP_INTERNAL_KEY => {
|
||||
impl_psbt_insert_pair! {
|
||||
self.tap_internal_key <= <raw_key: _>|< raw_value: schnorr::PublicKey>
|
||||
}
|
||||
}
|
||||
PSBT_IN_TAP_MERKLE_ROOT => {
|
||||
impl_psbt_insert_pair! {
|
||||
self.tap_merkle_root <= <raw_key: _>|< raw_value: TapBranchHash>
|
||||
}
|
||||
}
|
||||
PSBT_IN_PROPRIETARY => match self.proprietary.entry(raw::ProprietaryKey::from_key(raw_key.clone())?) {
|
||||
btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
|
||||
btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()),
|
||||
|
@ -249,6 +309,30 @@ impl Map for Input {
|
|||
rv.push(self.hash256_preimages as <PSBT_IN_HASH256, sha256d::Hash>|<Vec<u8>>)
|
||||
}
|
||||
|
||||
impl_psbt_get_pair! {
|
||||
rv.push(self.tap_key_sig as <PSBT_IN_TAP_KEY_SIG, _>|<Vec<u8>>)
|
||||
}
|
||||
|
||||
impl_psbt_get_pair! {
|
||||
rv.push(self.tap_script_sigs as <PSBT_IN_TAP_SCRIPT_SIG, (schnorr::PublicKey, TapLeafHash)>|<Vec<u8>>)
|
||||
}
|
||||
|
||||
impl_psbt_get_pair! {
|
||||
rv.push(self.tap_scripts as <PSBT_IN_TAP_LEAF_SCRIPT, ControlBlock>|<(Script, LeafVersion)>)
|
||||
}
|
||||
|
||||
impl_psbt_get_pair! {
|
||||
rv.push(self.tap_key_origins as <PSBT_IN_TAP_BIP32_DERIVATION,
|
||||
schnorr::PublicKey>|<(Vec<TapLeafHash>, KeySource)>)
|
||||
}
|
||||
|
||||
impl_psbt_get_pair! {
|
||||
rv.push(self.tap_internal_key as <PSBT_IN_TAP_INTERNAL_KEY, _>|<schnorr::PublicKey>)
|
||||
}
|
||||
|
||||
impl_psbt_get_pair! {
|
||||
rv.push(self.tap_merkle_root as <PSBT_IN_TAP_MERKLE_ROOT, _>|<TapBranchHash>)
|
||||
}
|
||||
for (key, value) in self.proprietary.iter() {
|
||||
rv.push(raw::Pair {
|
||||
key: key.to_key(),
|
||||
|
@ -280,6 +364,9 @@ impl Map for Input {
|
|||
self.sha256_preimages.extend(other.sha256_preimages);
|
||||
self.hash160_preimages.extend(other.hash160_preimages);
|
||||
self.hash256_preimages.extend(other.hash256_preimages);
|
||||
self.tap_script_sigs.extend(other.tap_script_sigs);
|
||||
self.tap_scripts.extend(other.tap_scripts);
|
||||
self.tap_key_origins.extend(other.tap_key_origins);
|
||||
self.proprietary.extend(other.proprietary);
|
||||
self.unknown.extend(other.unknown);
|
||||
|
||||
|
@ -287,6 +374,9 @@ impl Map for Input {
|
|||
merge!(witness_script, self, other);
|
||||
merge!(final_script_sig, self, other);
|
||||
merge!(final_script_witness, self, other);
|
||||
merge!(tap_key_sig, self, other);
|
||||
merge!(tap_internal_key, self, other);
|
||||
merge!(tap_merkle_root, self, other);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -55,3 +55,4 @@ mod output;
|
|||
|
||||
pub use self::input::Input;
|
||||
pub use self::output::Output;
|
||||
pub use self::output::TapTree;
|
||||
|
|
|
@ -25,12 +25,23 @@ use util::psbt::map::Map;
|
|||
use util::psbt::raw;
|
||||
use util::psbt::Error;
|
||||
|
||||
use schnorr;
|
||||
use util::taproot::TapLeafHash;
|
||||
|
||||
use util::taproot::{NodeInfo, TaprootBuilder};
|
||||
|
||||
/// Type: Redeem Script PSBT_OUT_REDEEM_SCRIPT = 0x00
|
||||
const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00;
|
||||
/// Type: Witness Script PSBT_OUT_WITNESS_SCRIPT = 0x01
|
||||
const PSBT_OUT_WITNESS_SCRIPT: u8 = 0x01;
|
||||
/// Type: BIP 32 Derivation Path PSBT_OUT_BIP32_DERIVATION = 0x02
|
||||
const PSBT_OUT_BIP32_DERIVATION: u8 = 0x02;
|
||||
/// Type: Taproot Internal Key PSBT_OUT_TAP_INTERNAL_KEY = 0x05
|
||||
const PSBT_OUT_TAP_INTERNAL_KEY: u8 = 0x05;
|
||||
/// Type: Taproot Tree PSBT_OUT_TAP_TREE = 0x06
|
||||
const PSBT_OUT_TAP_TREE: u8 = 0x06;
|
||||
/// Type: Taproot Key BIP 32 Derivation Path PSBT_OUT_TAP_BIP32_DERIVATION = 0x07
|
||||
const PSBT_OUT_TAP_BIP32_DERIVATION: u8 = 0x07;
|
||||
/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC
|
||||
const PSBT_OUT_PROPRIETARY: u8 = 0xFC;
|
||||
|
||||
|
@ -47,14 +58,67 @@ pub struct Output {
|
|||
/// corresponding master key fingerprints and derivation paths.
|
||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
|
||||
pub bip32_derivation: BTreeMap<PublicKey, KeySource>,
|
||||
/// The internal pubkey
|
||||
pub tap_internal_key: Option<schnorr::PublicKey>,
|
||||
/// Taproot Output tree
|
||||
pub tap_tree: Option<TapTree>,
|
||||
/// Map of tap root x only keys to origin info and leaf hashes contained in it
|
||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
|
||||
pub tap_key_origins: BTreeMap<schnorr::PublicKey, (Vec<TapLeafHash>, KeySource)>,
|
||||
/// Proprietary key-value pairs for this output.
|
||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
serde(with = "::serde_utils::btreemap_as_seq_byte_values")
|
||||
)]
|
||||
pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
|
||||
/// Unknown key-value pairs for this output.
|
||||
#[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
serde(with = "::serde_utils::btreemap_as_seq_byte_values")
|
||||
)]
|
||||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||
}
|
||||
|
||||
/// Taproot Tree representing a finalized [`TaprootBuilder`] (a complete binary tree)
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct TapTree(pub(crate) TaprootBuilder);
|
||||
|
||||
impl PartialEq for TapTree {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.node_info().hash.eq(&other.node_info().hash)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for TapTree {}
|
||||
|
||||
impl TapTree {
|
||||
// get the inner node info as the builder is finalized
|
||||
fn node_info(&self) -> &NodeInfo {
|
||||
// The builder algorithm invariant guarantees that is_complete builder
|
||||
// have only 1 element in branch and that is not None.
|
||||
// We make sure that we only allow is_complete builders via the from_inner
|
||||
// constructor
|
||||
self.0.branch()[0].as_ref().expect("from_inner only parses is_complete builders")
|
||||
}
|
||||
|
||||
/// Convert a [`TaprootBuilder`] into a tree if it is complete binary tree.
|
||||
/// Returns the inner as Err if it is not a complete tree
|
||||
pub fn from_inner(inner: TaprootBuilder) -> Result<Self, TaprootBuilder> {
|
||||
if inner.is_complete() {
|
||||
Ok(TapTree(inner))
|
||||
} else {
|
||||
Err(inner)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert self into builder [`TaprootBuilder`]. The builder is guaranteed to
|
||||
/// be finalized.
|
||||
pub fn into_inner(self) -> TaprootBuilder {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Map for Output {
|
||||
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
|
||||
let raw::Pair {
|
||||
|
@ -82,10 +146,29 @@ impl Map for Output {
|
|||
btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
|
||||
btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()),
|
||||
}
|
||||
_ => match self.unknown.entry(raw_key) {
|
||||
btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
|
||||
btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()),
|
||||
PSBT_OUT_TAP_INTERNAL_KEY => {
|
||||
impl_psbt_insert_pair! {
|
||||
self.tap_internal_key <= <raw_key: _>|<raw_value: schnorr::PublicKey>
|
||||
}
|
||||
}
|
||||
PSBT_OUT_TAP_TREE => {
|
||||
impl_psbt_insert_pair! {
|
||||
self.tap_tree <= <raw_key: _>|<raw_value: TapTree>
|
||||
}
|
||||
}
|
||||
PSBT_OUT_TAP_BIP32_DERIVATION => {
|
||||
impl_psbt_insert_pair! {
|
||||
self.tap_key_origins <= <raw_key: schnorr::PublicKey>|< raw_value: (Vec<TapLeafHash>, KeySource)>
|
||||
}
|
||||
}
|
||||
_ => match self.unknown.entry(raw_key) {
|
||||
btree_map::Entry::Vacant(empty_key) => {
|
||||
empty_key.insert(raw_value);
|
||||
}
|
||||
btree_map::Entry::Occupied(k) => {
|
||||
return Err(Error::DuplicateKey(k.key().clone()).into())
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -106,6 +189,19 @@ impl Map for Output {
|
|||
rv.push(self.bip32_derivation as <PSBT_OUT_BIP32_DERIVATION, PublicKey>|<KeySource>)
|
||||
}
|
||||
|
||||
impl_psbt_get_pair! {
|
||||
rv.push(self.tap_internal_key as <PSBT_OUT_TAP_INTERNAL_KEY, _>|<schnorr::PublicKey>)
|
||||
}
|
||||
|
||||
impl_psbt_get_pair! {
|
||||
rv.push(self.tap_tree as <PSBT_OUT_TAP_TREE, _>|<TaprootBuilder>)
|
||||
}
|
||||
|
||||
impl_psbt_get_pair! {
|
||||
rv.push(self.tap_key_origins as <PSBT_OUT_TAP_BIP32_DERIVATION,
|
||||
schnorr::PublicKey>|<(Vec<TapLeafHash>, KeySource)>)
|
||||
}
|
||||
|
||||
for (key, value) in self.proprietary.iter() {
|
||||
rv.push(raw::Pair {
|
||||
key: key.to_key(),
|
||||
|
@ -127,9 +223,12 @@ impl Map for Output {
|
|||
self.bip32_derivation.extend(other.bip32_derivation);
|
||||
self.proprietary.extend(other.proprietary);
|
||||
self.unknown.extend(other.unknown);
|
||||
self.tap_key_origins.extend(other.tap_key_origins);
|
||||
|
||||
merge!(redeem_script, self, other);
|
||||
merge!(witness_script, self, other);
|
||||
merge!(tap_internal_key, self, other);
|
||||
merge!(tap_tree, self, other);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ mod macros;
|
|||
pub mod serialize;
|
||||
|
||||
mod map;
|
||||
pub use self::map::{Map, Input, Output};
|
||||
pub use self::map::{Map, Input, Output, TapTree};
|
||||
|
||||
use util::bip32::{ExtendedPubKey, KeySource};
|
||||
|
||||
|
|
|
@ -24,12 +24,18 @@ use io;
|
|||
|
||||
use blockdata::script::Script;
|
||||
use blockdata::transaction::{EcdsaSigHashType, Transaction, TxOut};
|
||||
use consensus::encode::{self, serialize, Decodable};
|
||||
use consensus::encode::{self, serialize, Decodable, Encodable, deserialize_partial};
|
||||
use secp256k1::schnorrsig;
|
||||
use util::bip32::{ChildNumber, Fingerprint, KeySource};
|
||||
use hashes::{hash160, ripemd160, sha256, sha256d, Hash};
|
||||
use util::ecdsa::PublicKey;
|
||||
use util::psbt;
|
||||
use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion};
|
||||
use schnorr;
|
||||
use super::map::TapTree;
|
||||
|
||||
use util::taproot::TaprootBuilder;
|
||||
use util::sighash::SchnorrSigHashType;
|
||||
/// A trait for serializing a value as raw data for insertion into PSBT
|
||||
/// key-value pairs.
|
||||
pub trait Serialize {
|
||||
|
@ -48,9 +54,14 @@ impl_psbt_de_serialize!(TxOut);
|
|||
impl_psbt_de_serialize!(Vec<Vec<u8>>); // scriptWitness
|
||||
impl_psbt_hash_de_serialize!(ripemd160::Hash);
|
||||
impl_psbt_hash_de_serialize!(sha256::Hash);
|
||||
impl_psbt_hash_de_serialize!(TapLeafHash);
|
||||
impl_psbt_hash_de_serialize!(TapBranchHash);
|
||||
impl_psbt_hash_de_serialize!(hash160::Hash);
|
||||
impl_psbt_hash_de_serialize!(sha256d::Hash);
|
||||
|
||||
// taproot
|
||||
impl_psbt_de_serialize!(Vec<TapLeafHash>);
|
||||
|
||||
impl Serialize for Script {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
self.to_bytes()
|
||||
|
@ -80,7 +91,7 @@ impl Deserialize for PublicKey {
|
|||
|
||||
impl Serialize for KeySource {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
let mut rv: Vec<u8> = Vec::with_capacity(4 + 4 * (self.1).as_ref().len());
|
||||
let mut rv: Vec<u8> = Vec::with_capacity(key_source_len(&self));
|
||||
|
||||
rv.append(&mut self.0.to_bytes().to_vec());
|
||||
|
||||
|
@ -144,3 +155,170 @@ impl Deserialize for EcdsaSigHashType {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Taproot related ser/deser
|
||||
impl Serialize for schnorr::PublicKey {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
schnorr::PublicKey::serialize(&self).to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for schnorr::PublicKey {
|
||||
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
||||
schnorr::PublicKey::from_slice(bytes)
|
||||
.map_err(|_| encode::Error::ParseFailed("Invalid xonly public key"))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for schnorr::SchnorrSig {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
self.to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for schnorr::SchnorrSig {
|
||||
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
||||
match bytes.len() {
|
||||
65 => {
|
||||
let hash_ty = SchnorrSigHashType::from_u8(bytes[64])
|
||||
.map_err(|_| encode::Error::ParseFailed("Invalid Sighash type"))?;
|
||||
let sig = schnorrsig::Signature::from_slice(&bytes[..64])
|
||||
.map_err(|_| encode::Error::ParseFailed("Invalid Schnorr signature"))?;
|
||||
Ok(schnorr::SchnorrSig{ sig, hash_ty })
|
||||
}
|
||||
64 => {
|
||||
let sig = schnorrsig::Signature::from_slice(&bytes[..64])
|
||||
.map_err(|_| encode::Error::ParseFailed("Invalid Schnorr signature"))?;
|
||||
Ok(schnorr::SchnorrSig{ sig, hash_ty: SchnorrSigHashType::Default })
|
||||
}
|
||||
_ => Err(encode::Error::ParseFailed("Invalid Schnorr signature len"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for (schnorr::PublicKey, TapLeafHash) {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
let ser_pk = self.0.serialize();
|
||||
let mut buf = Vec::with_capacity(ser_pk.len() + self.1.as_ref().len());
|
||||
buf.extend(&ser_pk);
|
||||
buf.extend(self.1.as_ref());
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for (schnorr::PublicKey, TapLeafHash) {
|
||||
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
||||
if bytes.len() < 32 {
|
||||
return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into())
|
||||
}
|
||||
let a: schnorr::PublicKey = Deserialize::deserialize(&bytes[..32])?;
|
||||
let b: TapLeafHash = Deserialize::deserialize(&bytes[32..])?;
|
||||
Ok((a, b))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ControlBlock {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
ControlBlock::serialize(&self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for ControlBlock {
|
||||
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
||||
Self::from_slice(bytes)
|
||||
.map_err(|_| encode::Error::ParseFailed("Invalid control block"))
|
||||
}
|
||||
}
|
||||
|
||||
// Versioned Script
|
||||
impl Serialize for (Script, LeafVersion) {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(self.0.len() + 1);
|
||||
buf.extend(self.0.as_bytes());
|
||||
buf.push(self.1.as_u8());
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for (Script, LeafVersion) {
|
||||
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
||||
if bytes.is_empty() {
|
||||
return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into())
|
||||
}
|
||||
// The last byte is LeafVersion.
|
||||
let script = Script::deserialize(&bytes[..bytes.len() - 1])?;
|
||||
let leaf_ver = LeafVersion::from_u8(bytes[bytes.len() - 1])
|
||||
.map_err(|_| encode::Error::ParseFailed("invalid leaf version"))?;
|
||||
Ok((script, leaf_ver))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Serialize for (Vec<TapLeafHash>, KeySource) {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity( 32 * self.0.len() + key_source_len(&self.1));
|
||||
self.0.consensus_encode(&mut buf).expect("Vecs don't error allocation");
|
||||
// TODO: Add support for writing into a writer for key-source
|
||||
buf.extend(self.1.serialize());
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for (Vec<TapLeafHash>, KeySource) {
|
||||
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
||||
let (leafhash_vec, consumed) = deserialize_partial::<Vec::<TapLeafHash>>(&bytes)?;
|
||||
let key_source = KeySource::deserialize(&bytes[consumed..])?;
|
||||
Ok((leafhash_vec, key_source))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for TapTree {
|
||||
fn serialize(&self) -> Vec<u8> {
|
||||
match (self.0.branch().len(), self.0.branch().last()) {
|
||||
(1, Some(Some(root))) => {
|
||||
let mut buf = Vec::new();
|
||||
for leaf_info in root.leaves.iter() {
|
||||
// # Cast Safety:
|
||||
//
|
||||
// TaprootMerkleBranch can only have len atmost 128(TAPROOT_CONTROL_MAX_NODE_COUNT).
|
||||
// safe to cast from usize to u8
|
||||
buf.push(leaf_info.merkle_branch.as_inner().len() as u8);
|
||||
buf.push(leaf_info.ver.as_u8());
|
||||
leaf_info.script.consensus_encode(&mut buf).expect("Vecs dont err");
|
||||
}
|
||||
buf
|
||||
}
|
||||
// This should be unreachable as we Taptree is already finalized
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for TapTree {
|
||||
fn deserialize(bytes: &[u8]) -> Result<Self, encode::Error> {
|
||||
let mut builder = TaprootBuilder::new();
|
||||
let mut bytes_iter = bytes.iter();
|
||||
while let Some(depth) = bytes_iter.next() {
|
||||
let version = bytes_iter.next().ok_or(encode::Error::ParseFailed("Invalid Taproot Builder"))?;
|
||||
let (script, consumed) = deserialize_partial::<Script>(bytes_iter.as_slice())?;
|
||||
if consumed > 0 {
|
||||
bytes_iter.nth(consumed - 1);
|
||||
}
|
||||
|
||||
let leaf_version = LeafVersion::from_u8(*version)
|
||||
.map_err(|_| encode::Error::ParseFailed("Leaf Version Error"))?;
|
||||
builder = builder.add_leaf_with_ver(usize::from(*depth), script, leaf_version)
|
||||
.map_err(|_| encode::Error::ParseFailed("Tree not in DFS order"))?;
|
||||
}
|
||||
if builder.is_complete() {
|
||||
Ok(TapTree(builder))
|
||||
} else {
|
||||
Err(encode::Error::ParseFailed("Incomplete taproot Tree"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to compute key source len
|
||||
fn key_source_len(key_source: &KeySource) -> usize {
|
||||
4 + 4 * (key_source.1).as_ref().len()
|
||||
}
|
||||
|
|
|
@ -420,6 +420,11 @@ impl TaprootBuilder {
|
|||
self.insert(node, depth)
|
||||
}
|
||||
|
||||
/// Check if the builder is a complete tree
|
||||
pub fn is_complete(&self) -> bool {
|
||||
self.branch.len() == 1 && self.branch[0].is_some()
|
||||
}
|
||||
|
||||
/// Create [`TaprootSpendInfo`] with the given internal key
|
||||
pub fn finalize<C: secp256k1::Verification>(
|
||||
mut self,
|
||||
|
@ -437,6 +442,10 @@ impl TaprootBuilder {
|
|||
Ok(TaprootSpendInfo::from_node_info(secp, internal_key, node))
|
||||
}
|
||||
|
||||
pub(crate) fn branch(&self) -> &[Option<NodeInfo>]{
|
||||
&self.branch
|
||||
}
|
||||
|
||||
// Helper function to insert a leaf at a depth
|
||||
fn insert(mut self, mut node: NodeInfo, mut depth: usize) -> Result<Self, TaprootBuilderError> {
|
||||
// early error on invalid depth. Though this will be checked later
|
||||
|
@ -489,9 +498,9 @@ impl TaprootBuilder {
|
|||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub(crate) struct NodeInfo {
|
||||
/// Merkle Hash for this node
|
||||
hash: sha256::Hash,
|
||||
pub(crate) hash: sha256::Hash,
|
||||
/// information about leaves inside this node
|
||||
leaves: Vec<LeafInfo>,
|
||||
pub(crate) leaves: Vec<LeafInfo>,
|
||||
}
|
||||
|
||||
impl NodeInfo {
|
||||
|
@ -543,11 +552,11 @@ impl NodeInfo {
|
|||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub(crate) struct LeafInfo {
|
||||
// The underlying script
|
||||
script: Script,
|
||||
pub(crate) script: Script,
|
||||
// The leaf version
|
||||
ver: LeafVersion,
|
||||
pub(crate) ver: LeafVersion,
|
||||
// The merkle proof(hashing partners) to get this node
|
||||
merkle_branch: TaprootMerkleBranch,
|
||||
pub(crate) merkle_branch: TaprootMerkleBranch,
|
||||
}
|
||||
|
||||
impl LeafInfo {
|
||||
|
|
Loading…
Reference in New Issue