Skip to content

Commit

Permalink
Partial fix: fail deserialization of Taproot PSBTs with non BIP-174 c…
Browse files Browse the repository at this point in the history
…ompliant PSBTs
  • Loading branch information
JeremyRubin committed Aug 16, 2022
1 parent 9f37fdd commit 9dd74e7
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
8 changes: 7 additions & 1 deletion src/util/psbt/error.rs
Expand Up @@ -7,6 +7,7 @@ use core::fmt;
use crate::blockdata::transaction::Transaction;
use crate::consensus::encode;
use crate::util::psbt::raw;
use crate::util::psbt::map::IncompleteTapTree;

use crate::hashes;
use crate::util::bip32::ExtendedPubKey;
Expand Down Expand Up @@ -73,6 +74,9 @@ pub enum Error {
CombineInconsistentKeySources(Box<ExtendedPubKey>),
/// Serialization error in bitcoin consensus-encoded structures
ConsensusEncoding,
/// Incomplete TapTree Error
// N.B. No need to Box as it's just a vector internally.
IncompleteTapTree(IncompleteTapTree)
}

impl fmt::Display for Error {
Expand Down Expand Up @@ -100,6 +104,7 @@ impl fmt::Display for Error {
},
Error::CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) },
Error::ConsensusEncoding => f.write_str("bitcoin consensus or BIP-174 encoding error"),
Error::IncompleteTapTree(ref b) => write!(f, "{}", b),
}
}
}
Expand Down Expand Up @@ -127,7 +132,8 @@ impl std::error::Error for Error {
| NonStandardSighashType(_)
| InvalidPreimageHashPair{ .. }
| CombineInconsistentKeySources(_)
| ConsensusEncoding => None,
| ConsensusEncoding
| IncompleteTapTree(_) => None,
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/util/psbt/map/output.rs
Expand Up @@ -99,6 +99,12 @@ impl core::fmt::Display for IncompleteTapTree {
}
}

impl From<IncompleteTapTree> for crate::util::psbt::Error {
fn from(i: IncompleteTapTree) -> Self {
crate::util::psbt::Error::IncompleteTapTree(i)
}
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for IncompleteTapTree {
Expand Down
15 changes: 14 additions & 1 deletion src/util/psbt/serialize.rs
Expand Up @@ -7,6 +7,8 @@
//!

use crate::prelude::*;
use core;
use core::convert::TryFrom;

use crate::io;

Expand Down Expand Up @@ -344,7 +346,7 @@ impl Deserialize for TapTree {
.map_err(|_| encode::Error::ParseFailed("Tree not in DFS order"))?;
}
if builder.is_finalizable() && !builder.has_hidden_nodes() {
Ok(TapTree(builder))
Ok(TapTree::try_from(builder).map_err(psbt::Error::from)?)
} else {
Err(encode::Error::ParseFailed("Incomplete taproot Tree"))
}
Expand All @@ -361,6 +363,7 @@ mod tests {
use core::convert::TryFrom;

use crate::hashes::hex::FromHex;
use crate::psbt::PartiallySignedTransaction;
use super::*;

// Composes tree matching a given depth map, filled with dumb script leafs,
Expand Down Expand Up @@ -395,6 +398,16 @@ mod tests {
assert_eq!(tree, tree_prime);
}

#[cfg(feature = "base64")]
#[test]
fn taptree_empty() {
use core::str::FromStr;
let test_data_containing_empty =
"cHNidP8BAIkCAAAAAWlZ9F5/nRjE0quO8bE8cfKIiVTKHa/Zu6PKwWfpZDmpAAAAAAD9////Anz3nHYAAAAAIlEg7T17MEFOm47gN7FhZB5g4HjviGW4YxZWReJr1c/w0I+AlpgAAAAAACJRIDspRhxBQj5+aJw088IczFSbyRKB7wofy/SQXnErwCcQAAAAAAABASsAlDV3AAAAACJRIBMUosKNoVNU5tEW2Q/tylLRzabMGIprODHM0LbB8h1/IRaXdf3KRBBZMc8epg7uuU3pr42i3YMFnheNDW10F0cpnxkAHzYIzlYAAIABAACAAAAAgAAAAABRAAAAARcgl3X9ykQQWTHPHqYO7rlN6a+Not2DBZ4XjQ1tdBdHKZ8AAQUgT+NhtL213EJgJ51h6FiZYhPgUv48YQKACnnMYpOZPMEBBgAhB0/jYbS9tdxCYCedYehYmWIT4FL+PGECgAp5zGKTmTzBGQAfNgjOVgAAgAEAAIAAAACAAQAAADEBAAAAAQUgrUXPD+fhaOeY7GlxJDZ0pAgUZ0reW+A3wmxMwBAIt14BBgAhB61Fzw/n4WjnmOxpcSQ2dKQIFGdK3lvgN8JsTMAQCLdeGQAfNgjOVgAAgAEAAIAAAACAAAAAAFIAAAAA";
let psbt = PartiallySignedTransaction::from_str(test_data_containing_empty);
assert!(matches!(psbt, Err(psbt::PsbtParseError::PsbtEncoding(encode::Error::ParseFailed("Incomplete taproot Tree")))));
}

#[test]
fn can_deserialize_non_standard_psbt_sighash_type() {
let non_standard_sighash = [222u8, 0u8, 0u8, 0u8]; // 32 byte value.
Expand Down

0 comments on commit 9dd74e7

Please sign in to comment.