From 69c6eb61737d0bbd05df58727c414104a7b59170 Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Wed, 16 Feb 2022 23:45:35 -0800 Subject: [PATCH 1/2] Bug: Change type of pbst partial sig from secp key to bitcoin key This changes the type of secp signature from secp256k1::Signature to bitcoin::PublicKey. Psbt allows storing signatures for both compressed as well as uncompressed keys. This bug was introduced in #591 while trying to change the type of BIP32 keys from bitcoin::PublicKey to secp256k1::PublicKey. --- src/util/psbt/map/input.rs | 5 +++-- src/util/psbt/serialize.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/util/psbt/map/input.rs b/src/util/psbt/map/input.rs index 97473839..34fd18dd 100644 --- a/src/util/psbt/map/input.rs +++ b/src/util/psbt/map/input.rs @@ -28,6 +28,7 @@ use util::psbt::map::Map; use util::psbt::raw; use util::psbt::serialize::Deserialize; use util::psbt::{Error, error}; +use util::key::PublicKey; use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash}; use util::sighash; @@ -89,7 +90,7 @@ pub struct Input { pub witness_utxo: Option, /// A map from public keys to their corresponding signature as would be /// pushed to the stack from a scriptSig or witness for a non-taproot inputs. - pub partial_sigs: BTreeMap, + pub partial_sigs: BTreeMap, /// The sighash type to be used for this input. Signatures for this input /// must use the sighash type. pub sighash_type: Option, @@ -209,7 +210,7 @@ impl Input { } PSBT_IN_PARTIAL_SIG => { impl_psbt_insert_pair! { - self.partial_sigs <= | + self.partial_sigs <= | } } PSBT_IN_SIGHASH_TYPE => { diff --git a/src/util/psbt/serialize.rs b/src/util/psbt/serialize.rs index f11d4e86..0ee01fdf 100644 --- a/src/util/psbt/serialize.rs +++ b/src/util/psbt/serialize.rs @@ -33,6 +33,7 @@ use util::ecdsa::{EcdsaSig, EcdsaSigError}; use util::psbt; use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion}; use schnorr; +use util::key::PublicKey; use super::map::{TapTree, PsbtSigHashType}; @@ -75,6 +76,21 @@ impl Deserialize for Script { } } +impl Serialize for PublicKey { + fn serialize(&self) -> Vec { + let mut buf = Vec::new(); + self.write_into(&mut buf).expect("vecs don't error"); + buf + } +} + +impl Deserialize for PublicKey { + fn deserialize(bytes: &[u8]) -> Result { + PublicKey::from_slice(bytes) + .map_err(|_| encode::Error::ParseFailed("invalid public key")) + } +} + impl Serialize for secp256k1::PublicKey { fn serialize(&self) -> Vec { self.serialize().to_vec() From 4e19973d4e8b569e07fea1f302fdcd61432f4d5f Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Thu, 17 Feb 2022 02:48:29 -0800 Subject: [PATCH 2/2] Add a breaking test This commit can be re-ordered before the fix to see that the test fail during psbt decoding --- src/util/psbt/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 058a7a63..e1cf4cca 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -285,6 +285,16 @@ mod tests { ); } + #[test] + fn psbt_uncompressed_key() { + + let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap(); + + assert!(psbt.inputs[0].partial_sigs.len() == 1); + let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0; + assert!(!pk.compressed); + } + #[test] fn serialize_then_deserialize_output() { let secp = &Secp256k1::new();