Merge rust-bitcoin/rust-bitcoin#836: Bug: Change type of pbst partial sig from secp key to bitcoin key

4e19973d4e Add a breaking test (sanket1729)
69c6eb6173 Bug: Change type of pbst partial sig from secp key to bitcoin key (sanket1729)

Pull request description:

  This changes the type of secp signature from secp256k1::PublicKey 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.

ACKs for top commit:
  Kixunil:
    ACK 4e19973d4e
  apoelstra:
    ACK 4e19973d4e

Tree-SHA512: 2a326bafc050cd101e75899c32224a9ac2fcb2ec0b9f7f173404a46f2b3a92ecb78d0002db252a5af06705566bdc10102d20f4718eaeeebd3730fdb5ee89ff5a
This commit is contained in:
Andrew Poelstra 2022-02-17 14:45:32 +00:00
commit 61f20b72cc
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
3 changed files with 29 additions and 2 deletions

View File

@ -28,6 +28,7 @@ use util::psbt::map::Map;
use util::psbt::raw; use util::psbt::raw;
use util::psbt::serialize::Deserialize; use util::psbt::serialize::Deserialize;
use util::psbt::{Error, error}; use util::psbt::{Error, error};
use util::key::PublicKey;
use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash}; use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash};
use util::sighash; use util::sighash;
@ -89,7 +90,7 @@ pub struct Input {
pub witness_utxo: Option<TxOut>, pub witness_utxo: Option<TxOut>,
/// A map from public keys to their corresponding signature as would be /// 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. /// pushed to the stack from a scriptSig or witness for a non-taproot inputs.
pub partial_sigs: BTreeMap<secp256k1::PublicKey, EcdsaSig>, pub partial_sigs: BTreeMap<PublicKey, EcdsaSig>,
/// The sighash type to be used for this input. Signatures for this input /// The sighash type to be used for this input. Signatures for this input
/// must use the sighash type. /// must use the sighash type.
pub sighash_type: Option<PsbtSigHashType>, pub sighash_type: Option<PsbtSigHashType>,
@ -209,7 +210,7 @@ impl Input {
} }
PSBT_IN_PARTIAL_SIG => { PSBT_IN_PARTIAL_SIG => {
impl_psbt_insert_pair! { impl_psbt_insert_pair! {
self.partial_sigs <= <raw_key: secp256k1::PublicKey>|<raw_value: EcdsaSig> self.partial_sigs <= <raw_key: PublicKey>|<raw_value: EcdsaSig>
} }
} }
PSBT_IN_SIGHASH_TYPE => { PSBT_IN_SIGHASH_TYPE => {

View File

@ -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] #[test]
fn serialize_then_deserialize_output() { fn serialize_then_deserialize_output() {
let secp = &Secp256k1::new(); let secp = &Secp256k1::new();

View File

@ -33,6 +33,7 @@ use util::ecdsa::{EcdsaSig, EcdsaSigError};
use util::psbt; use util::psbt;
use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion}; use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion};
use schnorr; use schnorr;
use util::key::PublicKey;
use super::map::{TapTree, PsbtSigHashType}; use super::map::{TapTree, PsbtSigHashType};
@ -75,6 +76,21 @@ impl Deserialize for Script {
} }
} }
impl Serialize for PublicKey {
fn serialize(&self) -> Vec<u8> {
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<Self, encode::Error> {
PublicKey::from_slice(bytes)
.map_err(|_| encode::Error::ParseFailed("invalid public key"))
}
}
impl Serialize for secp256k1::PublicKey { impl Serialize for secp256k1::PublicKey {
fn serialize(&self) -> Vec<u8> { fn serialize(&self) -> Vec<u8> {
self.serialize().to_vec() self.serialize().to_vec()