diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index f713f39d..c083b712 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -24,7 +24,7 @@ //! use std::default::Default; -use std::{error, fmt, io}; +use std::{error, fmt, io, str}; use hashes::{self, Hash, sha256d}; use hashes::hex::FromHex; @@ -616,6 +616,37 @@ pub enum SigHashType { /// 0x83: Sign one output and only this input (see `Single` for what "one output" means) SinglePlusAnyoneCanPay = 0x83 } +serde_string_impl!(SigHashType, "a SigHashType data"); + +impl fmt::Display for SigHashType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + SigHashType::All => "SIGHASH_ALL", + SigHashType::None => "SIGHASH_NONE", + SigHashType::Single => "SIGHASH_SINGLE", + SigHashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY", + SigHashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY", + SigHashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", + }; + f.write_str(s) + } +} + +impl str::FromStr for SigHashType { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.as_ref() { + "SIGHASH_ALL" => Ok(SigHashType::All), + "SIGHASH_NONE" => Ok(SigHashType::None), + "SIGHASH_SINGLE" => Ok(SigHashType::Single), + "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(SigHashType::AllPlusAnyoneCanPay), + "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(SigHashType::NonePlusAnyoneCanPay), + "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SigHashType::SinglePlusAnyoneCanPay), + _ => Err("can't recognize SIGHASH string".to_string()) + } + } +} impl SigHashType { /// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean @@ -665,6 +696,7 @@ mod tests { use hashes::hex::FromHex; use hash_types::*; + use SigHashType; #[test] fn test_outpoint() { @@ -916,6 +948,34 @@ mod tests { assert_eq!(consensus_encoded, tx_bytes); } + #[test] + fn test_sighashtype_fromstr_display() { + let sighashtypes = vec![("SIGHASH_ALL", SigHashType::All), + ("SIGHASH_NONE", SigHashType::None), + ("SIGHASH_SINGLE", SigHashType::Single), + ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", SigHashType::AllPlusAnyoneCanPay), + ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", SigHashType::NonePlusAnyoneCanPay), + ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", SigHashType::SinglePlusAnyoneCanPay)]; + for (s, sht) in sighashtypes { + assert_eq!(sht.to_string(), s); + assert_eq!(SigHashType::from_str(s).unwrap(), sht); + } + let sht_mistakes = vec![ + "SIGHASH_ALL | SIGHASH_ANYONECANPAY", + "SIGHASH_NONE |SIGHASH_ANYONECANPAY", + "SIGHASH_SINGLE| SIGHASH_ANYONECANPAY", + "SIGHASH_ALL SIGHASH_ANYONECANPAY", + "SIGHASH_NONE |", + "SIGHASH_SIGNLE", + "sighash_none", + "Sighash_none", + "SigHash_None", + "SigHash_NONE", + ]; + for s in sht_mistakes { + assert_eq!(SigHashType::from_str(s).unwrap_err(), "can't recognize SIGHASH string"); + } + } // These test vectors were stolen from libbtc, which is Copyright 2014 Jonas Schnelli MIT // They were transformed by replacing {...} with run_test_sighash(...), then the ones containing diff --git a/src/util/psbt/map/global.rs b/src/util/psbt/map/global.rs index f6b411d4..681a3e1b 100644 --- a/src/util/psbt/map/global.rs +++ b/src/util/psbt/map/global.rs @@ -32,6 +32,7 @@ pub struct Global { /// Unknown global key-value pairs. pub unknown: BTreeMap>, } +serde_struct_impl!(Global, unsigned_tx, unknown); impl Global { /// Create a Global from an unsigned transaction, error if not unsigned diff --git a/src/util/psbt/map/input.rs b/src/util/psbt/map/input.rs index 72f33942..4481f755 100644 --- a/src/util/psbt/map/input.rs +++ b/src/util/psbt/map/input.rs @@ -58,6 +58,11 @@ pub struct Input { /// Unknown key-value pairs for this input. pub unknown: BTreeMap>, } +serde_struct_impl!( + Input, non_witness_utxo, witness_utxo, partial_sigs, + sighash_type, redeem_script, witness_script, hd_keypaths, + final_script_sig, final_script_witness, unknown +); impl Map for Input { fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> { diff --git a/src/util/psbt/map/output.rs b/src/util/psbt/map/output.rs index 856396aa..a089fdbc 100644 --- a/src/util/psbt/map/output.rs +++ b/src/util/psbt/map/output.rs @@ -38,6 +38,9 @@ pub struct Output { /// Unknown key-value pairs for this output. pub unknown: BTreeMap>, } +serde_struct_impl!( + Output, redeem_script, witness_script, hd_keypaths, unknown +); impl Map for Output { fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> { diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 1fe55d04..cbf47ab7 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -49,6 +49,7 @@ pub struct PartiallySignedTransaction { /// transaction. pub outputs: Vec, } +serde_struct_impl!(PartiallySignedTransaction, global, inputs, outputs); impl PartiallySignedTransaction { /// Create a PartiallySignedTransaction from an unsigned transaction, error diff --git a/src/util/psbt/raw.rs b/src/util/psbt/raw.rs index 9bf73ff9..16185715 100644 --- a/src/util/psbt/raw.rs +++ b/src/util/psbt/raw.rs @@ -31,6 +31,7 @@ pub struct Key { /// The key itself in raw byte form. pub key: Vec, } +serde_struct_impl!(Key, type_value, key); /// A PSBT key-value pair in its raw byte form. #[derive(Debug, PartialEq)] @@ -40,6 +41,7 @@ pub struct Pair { /// The value of this key-value pair in raw byte form. pub value: Vec, } +serde_struct_impl!(Pair, key, value); impl fmt::Display for Key { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {