psbt_v2/
serialize.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! PSBT serialization.
4//!
5//! Traits to serialize PSBT values to and from raw bytes
6//! according to the BIP-174 specification.
7
8use core::convert::{TryFrom, TryInto};
9use core::fmt;
10
11use bitcoin::bip32::{ChildNumber, Fingerprint, KeySource};
12use bitcoin::consensus::{self, Decodable, Encodable};
13use bitcoin::hashes::{self, hash160, ripemd160, sha256, sha256d, Hash};
14use bitcoin::key::PublicKey;
15use bitcoin::secp256k1::{self, XOnlyPublicKey};
16use bitcoin::taproot::{
17    ControlBlock, LeafVersion, TapLeafHash, TapNodeHash, TapTree, TaprootBuilder,
18};
19use bitcoin::{
20    absolute, ecdsa, taproot, transaction, Amount, ScriptBuf, Sequence, Transaction, TxOut, Txid,
21    VarInt, Witness,
22};
23
24use crate::error::write_err;
25use crate::prelude::*;
26use crate::sighash_type::PsbtSighashType;
27use crate::version;
28
29/// A trait for serializing a value as raw data for insertion into PSBT
30/// key-value maps.
31pub(crate) trait Serialize {
32    /// Serialize a value as raw data.
33    fn serialize(&self) -> Vec<u8>;
34}
35
36/// A trait for deserializing a value from raw data in PSBT key-value maps.
37pub(crate) trait Deserialize: Sized {
38    /// Deserialize a value from raw data.
39    fn deserialize(bytes: &[u8]) -> Result<Self, Error>;
40}
41
42// Strictly speaking these do not need the prefix because the v0 versions are
43// unused but we want to leave thoes in the code so the the files are close as
44// possible to the original from bitcoin/miniscript repos.
45v2_impl_psbt_de_serialize!(absolute::LockTime);
46v2_impl_psbt_de_serialize!(Amount);
47v2_impl_psbt_de_serialize!(Transaction);
48v2_impl_psbt_de_serialize!(transaction::Version);
49v2_impl_psbt_de_serialize!(TxOut);
50v2_impl_psbt_de_serialize!(Witness);
51v2_impl_psbt_de_serialize!(VarInt);
52v2_impl_psbt_hash_de_serialize!(ripemd160::Hash);
53v2_impl_psbt_hash_de_serialize!(sha256::Hash);
54v2_impl_psbt_hash_de_serialize!(TapLeafHash);
55v2_impl_psbt_hash_de_serialize!(TapNodeHash);
56v2_impl_psbt_hash_de_serialize!(Txid);
57v2_impl_psbt_hash_de_serialize!(hash160::Hash);
58v2_impl_psbt_hash_de_serialize!(sha256d::Hash);
59
60// taproot
61v2_impl_psbt_de_serialize!(Vec<TapLeafHash>);
62
63impl Serialize for ScriptBuf {
64    fn serialize(&self) -> Vec<u8> { self.to_bytes() }
65}
66
67impl Deserialize for ScriptBuf {
68    fn deserialize(bytes: &[u8]) -> Result<Self, Error> { Ok(Self::from(bytes.to_vec())) }
69}
70
71impl Serialize for PublicKey {
72    fn serialize(&self) -> Vec<u8> {
73        let mut buf = Vec::new();
74        self.write_into(&mut buf).expect("vecs don't error");
75        buf
76    }
77}
78
79impl Deserialize for PublicKey {
80    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
81        PublicKey::from_slice(bytes).map_err(Error::InvalidPublicKey)
82    }
83}
84
85impl Serialize for secp256k1::PublicKey {
86    fn serialize(&self) -> Vec<u8> { self.serialize().to_vec() }
87}
88
89impl Deserialize for secp256k1::PublicKey {
90    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
91        secp256k1::PublicKey::from_slice(bytes).map_err(Error::InvalidSecp256k1PublicKey)
92    }
93}
94
95impl Serialize for ecdsa::Signature {
96    fn serialize(&self) -> Vec<u8> { self.to_vec() }
97}
98
99impl Deserialize for ecdsa::Signature {
100    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
101        // NB: Since BIP-174 says "the signature as would be pushed to the stack from
102        // a scriptSig or witness" we should ideally use a consensus deserialization and do
103        // not error on a non-standard values. However,
104        //
105        // 1) the current implementation of from_u32_consensus(`flag`) does not preserve
106        // the sighash byte `flag` mapping all unknown values to EcdsaSighashType::All or
107        // EcdsaSighashType::AllPlusAnyOneCanPay. Therefore, break the invariant
108        // EcdsaSig::from_slice(&sl[..]).to_vec = sl.
109        //
110        // 2) This would cause to have invalid signatures because the sighash message
111        // also has a field sighash_u32 (See BIP141). For example, when signing with non-standard
112        // 0x05, the sighash message would have the last field as 0x05u32 while, the verification
113        // would use check the signature assuming sighash_u32 as `0x01`.
114        ecdsa::Signature::from_slice(bytes).map_err(|e| match e {
115            ecdsa::Error::EmptySignature => Error::InvalidEcdsaSignature(e),
116            ecdsa::Error::SighashType(err) => Error::NonStandardSighashType(err.0),
117            ecdsa::Error::Secp256k1(..) => Error::InvalidEcdsaSignature(e),
118            ecdsa::Error::Hex(..) => unreachable!("Decoding from slice, not hex"),
119            _ => panic!("TODO: Handle non_exhaustive error"),
120        })
121    }
122}
123
124impl Serialize for KeySource {
125    fn serialize(&self) -> Vec<u8> {
126        let mut rv: Vec<u8> = Vec::with_capacity(key_source_len(self));
127
128        rv.append(&mut self.0.to_bytes().to_vec());
129
130        for cnum in self.1.into_iter() {
131            rv.append(&mut consensus::serialize(&u32::from(*cnum)))
132        }
133
134        rv
135    }
136}
137
138impl Deserialize for KeySource {
139    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
140        if bytes.len() < 4 {
141            return Err(Error::NotEnoughData);
142        }
143
144        let fprint: Fingerprint = bytes[0..4].try_into().expect("4 is the fingerprint length");
145        let mut dpath: Vec<ChildNumber> = Default::default();
146
147        let mut d = &bytes[4..];
148        while !d.is_empty() {
149            match u32::consensus_decode(&mut d) {
150                Ok(index) => dpath.push(index.into()),
151                Err(e) => return Err(e.into()),
152            }
153        }
154
155        Ok((fprint, dpath.into()))
156    }
157}
158
159impl Serialize for u32 {
160    fn serialize(&self) -> Vec<u8> { consensus::serialize(&self) }
161}
162
163impl Deserialize for u32 {
164    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
165        let val: u32 = consensus::deserialize(bytes)?;
166        Ok(val)
167    }
168}
169
170impl Serialize for Sequence {
171    fn serialize(&self) -> Vec<u8> { consensus::serialize(&self) }
172}
173
174impl Deserialize for Sequence {
175    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
176        let n: Sequence = consensus::deserialize(bytes)?;
177        Ok(n)
178    }
179}
180
181impl Serialize for absolute::Height {
182    fn serialize(&self) -> Vec<u8> { consensus::serialize(&self.to_consensus_u32()) }
183}
184
185impl Deserialize for absolute::Height {
186    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
187        let n: u32 = consensus::deserialize(bytes)?;
188        let lock = absolute::Height::from_consensus(n)?;
189        Ok(lock)
190    }
191}
192
193impl Serialize for absolute::Time {
194    fn serialize(&self) -> Vec<u8> { consensus::serialize(&self.to_consensus_u32()) }
195}
196
197impl Deserialize for absolute::Time {
198    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
199        let n: u32 = consensus::deserialize(bytes)?;
200        let lock = absolute::Time::from_consensus(n)?;
201        Ok(lock)
202    }
203}
204
205// partial sigs
206impl Serialize for Vec<u8> {
207    fn serialize(&self) -> Vec<u8> { self.clone() }
208}
209
210impl Deserialize for Vec<u8> {
211    fn deserialize(bytes: &[u8]) -> Result<Self, Error> { Ok(bytes.to_vec()) }
212}
213
214impl Serialize for PsbtSighashType {
215    fn serialize(&self) -> Vec<u8> { consensus::serialize(&self.to_u32()) }
216}
217
218impl Deserialize for PsbtSighashType {
219    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
220        let raw: u32 = consensus::deserialize(bytes)?;
221        Ok(PsbtSighashType { inner: raw })
222    }
223}
224
225// Taproot related ser/deser
226impl Serialize for XOnlyPublicKey {
227    fn serialize(&self) -> Vec<u8> { XOnlyPublicKey::serialize(self).to_vec() }
228}
229
230impl Deserialize for XOnlyPublicKey {
231    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
232        XOnlyPublicKey::from_slice(bytes).map_err(|_| Error::InvalidXOnlyPublicKey)
233    }
234}
235
236impl Serialize for taproot::Signature {
237    fn serialize(&self) -> Vec<u8> { self.to_vec() }
238}
239
240impl Deserialize for taproot::Signature {
241    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
242        use taproot::SigFromSliceError::*;
243
244        taproot::Signature::from_slice(bytes).map_err(|e| match e {
245            SighashType(err) => Error::NonStandardSighashType(err.0),
246            InvalidSignatureSize(_) => Error::InvalidTaprootSignature(e),
247            Secp256k1(..) => Error::InvalidTaprootSignature(e),
248            _ => panic!("TODO: Handle non_exhaustive error"),
249        })
250    }
251}
252
253impl Serialize for (XOnlyPublicKey, TapLeafHash) {
254    fn serialize(&self) -> Vec<u8> {
255        let ser_pk = self.0.serialize();
256        let mut buf = Vec::with_capacity(ser_pk.len() + self.1.as_byte_array().len());
257        buf.extend(&ser_pk);
258        buf.extend(self.1.as_byte_array());
259        buf
260    }
261}
262
263impl Deserialize for (XOnlyPublicKey, TapLeafHash) {
264    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
265        if bytes.len() < 32 {
266            return Err(Error::NotEnoughData);
267        }
268        let a: XOnlyPublicKey = Deserialize::deserialize(&bytes[..32])?;
269        let b: TapLeafHash = Deserialize::deserialize(&bytes[32..])?;
270        Ok((a, b))
271    }
272}
273
274impl Serialize for ControlBlock {
275    fn serialize(&self) -> Vec<u8> { ControlBlock::serialize(self) }
276}
277
278impl Deserialize for ControlBlock {
279    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
280        Self::decode(bytes).map_err(|_| Error::InvalidControlBlock)
281    }
282}
283
284// Versioned ScriptBuf
285impl Serialize for (ScriptBuf, LeafVersion) {
286    fn serialize(&self) -> Vec<u8> {
287        let mut buf = Vec::with_capacity(self.0.len() + 1);
288        buf.extend(self.0.as_bytes());
289        buf.push(self.1.to_consensus());
290        buf
291    }
292}
293
294impl Deserialize for (ScriptBuf, LeafVersion) {
295    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
296        if bytes.is_empty() {
297            return Err(Error::NotEnoughData);
298        }
299        // The last byte is LeafVersion.
300        let script = ScriptBuf::deserialize(&bytes[..bytes.len() - 1])?;
301        let leaf_ver = LeafVersion::from_consensus(bytes[bytes.len() - 1])
302            .map_err(|_| Error::InvalidLeafVersion)?;
303        Ok((script, leaf_ver))
304    }
305}
306
307impl Serialize for (Vec<TapLeafHash>, KeySource) {
308    fn serialize(&self) -> Vec<u8> {
309        let mut buf = Vec::with_capacity(32 * self.0.len() + key_source_len(&self.1));
310        self.0.consensus_encode(&mut buf).expect("Vecs don't error allocation");
311        // TODO: Add support for writing into a writer for key-source
312        buf.extend(self.1.serialize());
313        buf
314    }
315}
316
317impl Deserialize for (Vec<TapLeafHash>, KeySource) {
318    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
319        let (leafhash_vec, consumed) = consensus::deserialize_partial::<Vec<TapLeafHash>>(bytes)?;
320        let key_source = KeySource::deserialize(&bytes[consumed..])?;
321        Ok((leafhash_vec, key_source))
322    }
323}
324
325impl Serialize for TapTree {
326    fn serialize(&self) -> Vec<u8> {
327        let capacity = self
328            .script_leaves()
329            .map(|l| {
330                l.script().len() + VarInt::from(l.script().len()).size() // script version
331            + 1 // merkle branch
332            + 1 // leaf version
333            })
334            .sum::<usize>();
335        let mut buf = Vec::with_capacity(capacity);
336        for leaf_info in self.script_leaves() {
337            // # Cast Safety:
338            //
339            // TaprootMerkleBranch can only have len atmost 128(TAPROOT_CONTROL_MAX_NODE_COUNT).
340            // safe to cast from usize to u8
341            buf.push(leaf_info.merkle_branch().len() as u8);
342            buf.push(leaf_info.version().to_consensus());
343            leaf_info.script().consensus_encode(&mut buf).expect("Vecs dont err");
344        }
345        buf
346    }
347}
348
349impl Deserialize for TapTree {
350    fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
351        let mut builder = TaprootBuilder::new();
352        let mut bytes_iter = bytes.iter();
353        while let Some(depth) = bytes_iter.next() {
354            let version = bytes_iter.next().ok_or(Error::Taproot("Invalid Taproot Builder"))?;
355            let (script, consumed) =
356                consensus::deserialize_partial::<ScriptBuf>(bytes_iter.as_slice())?;
357            if consumed > 0 {
358                bytes_iter.nth(consumed - 1);
359            }
360            let leaf_version =
361                LeafVersion::from_consensus(*version).map_err(|_| Error::InvalidLeafVersion)?;
362            builder = builder
363                .add_leaf_with_ver(*depth, script, leaf_version)
364                .map_err(|_| Error::Taproot("Tree not in DFS order"))?;
365        }
366        TapTree::try_from(builder).map_err(Error::TapTree)
367    }
368}
369
370// Helper function to compute key source len
371fn key_source_len(key_source: &KeySource) -> usize { 4 + 4 * (key_source.1).as_ref().len() }
372
373// TODO: This error is still too general but splitting it up is
374// non-trivial because it is returned by the Deserialize trait.
375/// Ways that deserializing a PSBT might fail.
376#[derive(Debug)]
377#[non_exhaustive]
378pub enum Error {
379    /// Not enough data to deserialize object.
380    NotEnoughData,
381    /// Non-proprietary key type found when proprietary key was expected
382    InvalidProprietaryKey,
383    /// Signals that there are no more key-value pairs in a key-value map.
384    NoMorePairs,
385    /// Unable to parse as a standard sighash type.
386    NonStandardSighashType(u32),
387    /// Invalid hash when parsing slice.
388    InvalidHash(hashes::FromSliceError),
389    /// Serialization error in bitcoin consensus-encoded structures
390    ConsensusEncoding(consensus::encode::Error),
391    /// Parsing error indicating invalid public keys
392    InvalidPublicKey(bitcoin::key::FromSliceError),
393    /// Parsing error indicating invalid secp256k1 public keys
394    InvalidSecp256k1PublicKey(secp256k1::Error),
395    /// Parsing error indicating invalid xonly public keys
396    InvalidXOnlyPublicKey,
397    /// Parsing error indicating invalid ECDSA signatures
398    InvalidEcdsaSignature(bitcoin::ecdsa::Error),
399    /// Parsing error indicating invalid taproot signatures
400    InvalidTaprootSignature(bitcoin::taproot::SigFromSliceError),
401    /// Parsing error indicating invalid control block
402    InvalidControlBlock,
403    /// Parsing error indicating invalid leaf version
404    InvalidLeafVersion,
405    /// Parsing error indicating a taproot error
406    Taproot(&'static str),
407    /// Taproot tree deserilaization error
408    TapTree(taproot::IncompleteBuilderError),
409    /// Error related to PSBT version
410    /// PSBT data is not consumed entirely
411    PartialDataConsumption,
412    /// Couldn't converting parsed u32 to a lock time.
413    LockTime(absolute::ConversionError),
414    /// Unsupported PSBT version.
415    UnsupportedVersion(version::UnsupportedVersionError),
416}
417
418impl fmt::Display for Error {
419    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
420        use Error::*;
421
422        match *self {
423            NotEnoughData => f.write_str("not enough data to deserialize object"),
424            InvalidProprietaryKey =>
425                write!(f, "non-proprietary key type found when proprietary key was expected"),
426            NoMorePairs => f.write_str("no more key-value pairs for this psbt map"),
427            NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht),
428            InvalidHash(ref e) => write_err!(f, "invalid hash when parsing slice"; e),
429            ConsensusEncoding(ref e) => write_err!(f, "bitcoin consensus encoding error"; e),
430            InvalidPublicKey(ref e) => write_err!(f, "invalid public key"; e),
431            InvalidSecp256k1PublicKey(ref e) => write_err!(f, "invalid secp256k1 public key"; e),
432            InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"),
433            InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e),
434            InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e),
435            InvalidControlBlock => f.write_str("invalid control block"),
436            InvalidLeafVersion => f.write_str("invalid leaf version"),
437            Taproot(s) => write!(f, "taproot error -  {}", s),
438            TapTree(ref e) => write_err!(f, "taproot tree error"; e),
439            PartialDataConsumption =>
440                f.write_str("data not consumed entirely when explicitly deserializing"),
441            LockTime(ref e) => write_err!(f, "parsed locktime invalid"; e),
442            UnsupportedVersion(ref e) => write_err!(f, "unsupported version"; e),
443        }
444    }
445}
446
447#[cfg(feature = "std")]
448impl std::error::Error for Error {
449    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
450        use Error::*;
451
452        match *self {
453            InvalidHash(ref e) => Some(e),
454            ConsensusEncoding(ref e) => Some(e),
455            LockTime(ref e) => Some(e),
456            UnsupportedVersion(ref e) => Some(e),
457            NotEnoughData
458            | InvalidProprietaryKey
459            | NoMorePairs
460            | NonStandardSighashType(_)
461            | InvalidPublicKey(_)
462            | InvalidSecp256k1PublicKey(_)
463            | InvalidXOnlyPublicKey
464            | InvalidEcdsaSignature(_)
465            | InvalidTaprootSignature(_)
466            | InvalidControlBlock
467            | InvalidLeafVersion
468            | Taproot(_)
469            | TapTree(_)
470            | PartialDataConsumption => None,
471        }
472    }
473}
474
475impl From<hashes::FromSliceError> for Error {
476    fn from(e: hashes::FromSliceError) -> Self { Self::InvalidHash(e) }
477}
478
479impl From<consensus::encode::Error> for Error {
480    fn from(e: consensus::encode::Error) -> Self { Self::ConsensusEncoding(e) }
481}
482
483impl From<absolute::ConversionError> for Error {
484    fn from(e: absolute::ConversionError) -> Self { Self::LockTime(e) }
485}
486
487impl From<version::UnsupportedVersionError> for Error {
488    fn from(e: version::UnsupportedVersionError) -> Self { Self::UnsupportedVersion(e) }
489}
490
491#[cfg(test)]
492mod tests {
493    use core::convert::TryFrom;
494
495    use super::*;
496
497    // Composes tree matching a given depth map, filled with dumb script leafs,
498    // each of which consists of a single push-int op code, with int value
499    // increased for each consecutive leaf.
500    pub fn compose_taproot_builder<'map>(
501        opcode: u8,
502        depth_map: impl IntoIterator<Item = &'map u8>,
503    ) -> TaprootBuilder {
504        let mut val = opcode;
505        let mut builder = TaprootBuilder::new();
506        for depth in depth_map {
507            let script = ScriptBuf::from_hex(&format!("{:02x}", val)).unwrap();
508            builder = builder.add_leaf(*depth, script).unwrap();
509            let (new_val, _) = val.overflowing_add(1);
510            val = new_val;
511        }
512        builder
513    }
514
515    #[test]
516    fn taptree_hidden() {
517        let mut builder = compose_taproot_builder(0x51, &[2, 2, 2]);
518        builder = builder
519            .add_leaf_with_ver(
520                3,
521                ScriptBuf::from_hex("b9").unwrap(),
522                LeafVersion::from_consensus(0xC2).unwrap(),
523            )
524            .unwrap();
525        builder = builder.add_hidden_node(3, TapNodeHash::all_zeros()).unwrap();
526        assert!(TapTree::try_from(builder).is_err());
527    }
528
529    #[test]
530    fn taptree_roundtrip() {
531        let mut builder = compose_taproot_builder(0x51, &[2, 2, 2, 3]);
532        builder = builder
533            .add_leaf_with_ver(
534                3,
535                ScriptBuf::from_hex("b9").unwrap(),
536                LeafVersion::from_consensus(0xC2).unwrap(),
537            )
538            .unwrap();
539        let tree = TapTree::try_from(builder).unwrap();
540        let tree_prime = TapTree::deserialize(&tree.serialize()).unwrap();
541        assert_eq!(tree, tree_prime);
542    }
543
544    #[test]
545    fn can_deserialize_non_standard_psbt_sighash_type() {
546        let non_standard_sighash = [222u8, 0u8, 0u8, 0u8]; // 32 byte value.
547        let sighash = PsbtSighashType::deserialize(&non_standard_sighash);
548        assert!(sighash.is_ok())
549    }
550
551    #[test]
552    #[should_panic(expected = "InvalidMagic")]
553    fn invalid_vector_1() {
554        let hex_psbt = b"0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300";
555        crate::v0::Psbt::deserialize(hex_psbt).unwrap();
556    }
557}