Merge pull request #497 from LNP-BP/pending/psbt-serde
PSBT serde implementation
This commit is contained in:
commit
65b52cfe39
|
@ -24,7 +24,7 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::{error, fmt, io};
|
use std::{error, fmt, io, str};
|
||||||
|
|
||||||
use hashes::{self, Hash, sha256d};
|
use hashes::{self, Hash, sha256d};
|
||||||
use hashes::hex::FromHex;
|
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)
|
/// 0x83: Sign one output and only this input (see `Single` for what "one output" means)
|
||||||
SinglePlusAnyoneCanPay = 0x83
|
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<Self, Self::Err> {
|
||||||
|
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 {
|
impl SigHashType {
|
||||||
/// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean
|
/// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean
|
||||||
|
@ -665,6 +696,7 @@ mod tests {
|
||||||
use hashes::hex::FromHex;
|
use hashes::hex::FromHex;
|
||||||
|
|
||||||
use hash_types::*;
|
use hash_types::*;
|
||||||
|
use SigHashType;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_outpoint() {
|
fn test_outpoint() {
|
||||||
|
@ -916,6 +948,34 @@ mod tests {
|
||||||
assert_eq!(consensus_encoded, tx_bytes);
|
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
|
// 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
|
// They were transformed by replacing {...} with run_test_sighash(...), then the ones containing
|
||||||
|
|
|
@ -32,6 +32,7 @@ pub struct Global {
|
||||||
/// Unknown global key-value pairs.
|
/// Unknown global key-value pairs.
|
||||||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
serde_struct_impl!(Global, unsigned_tx, unknown);
|
||||||
|
|
||||||
impl Global {
|
impl Global {
|
||||||
/// Create a Global from an unsigned transaction, error if not unsigned
|
/// Create a Global from an unsigned transaction, error if not unsigned
|
||||||
|
|
|
@ -58,6 +58,11 @@ pub struct Input {
|
||||||
/// Unknown key-value pairs for this input.
|
/// Unknown key-value pairs for this input.
|
||||||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
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 {
|
impl Map for Input {
|
||||||
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
|
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
|
||||||
|
|
|
@ -38,6 +38,9 @@ pub struct Output {
|
||||||
/// Unknown key-value pairs for this output.
|
/// Unknown key-value pairs for this output.
|
||||||
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
pub unknown: BTreeMap<raw::Key, Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
serde_struct_impl!(
|
||||||
|
Output, redeem_script, witness_script, hd_keypaths, unknown
|
||||||
|
);
|
||||||
|
|
||||||
impl Map for Output {
|
impl Map for Output {
|
||||||
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
|
fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
|
||||||
|
|
|
@ -49,6 +49,7 @@ pub struct PartiallySignedTransaction {
|
||||||
/// transaction.
|
/// transaction.
|
||||||
pub outputs: Vec<Output>,
|
pub outputs: Vec<Output>,
|
||||||
}
|
}
|
||||||
|
serde_struct_impl!(PartiallySignedTransaction, global, inputs, outputs);
|
||||||
|
|
||||||
impl PartiallySignedTransaction {
|
impl PartiallySignedTransaction {
|
||||||
/// Create a PartiallySignedTransaction from an unsigned transaction, error
|
/// Create a PartiallySignedTransaction from an unsigned transaction, error
|
||||||
|
|
|
@ -31,6 +31,7 @@ pub struct Key {
|
||||||
/// The key itself in raw byte form.
|
/// The key itself in raw byte form.
|
||||||
pub key: Vec<u8>,
|
pub key: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
serde_struct_impl!(Key, type_value, key);
|
||||||
|
|
||||||
/// A PSBT key-value pair in its raw byte form.
|
/// A PSBT key-value pair in its raw byte form.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
|
@ -40,6 +41,7 @@ pub struct Pair {
|
||||||
/// The value of this key-value pair in raw byte form.
|
/// The value of this key-value pair in raw byte form.
|
||||||
pub value: Vec<u8>,
|
pub value: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
serde_struct_impl!(Pair, key, value);
|
||||||
|
|
||||||
impl fmt::Display for Key {
|
impl fmt::Display for Key {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
Loading…
Reference in New Issue