Add PSBT-specific Error data type

- Implement psbt::Error data type
- Implement conversion from psbt::Error to util::Error
- Create util::psbt module
- Create non-public util::psbt::error module
This commit is contained in:
Carl Dong 2018-08-07 23:36:51 -07:00
parent 919bbeae4a
commit 4fa39c4a3e
4 changed files with 94 additions and 0 deletions

View File

@ -45,6 +45,7 @@ use bitcoin_hashes::{sha256d, Hash as HashTrait};
use secp256k1; use secp256k1;
use util::base58; use util::base58;
use util::psbt;
/// Encoding error /// Encoding error
#[derive(Debug)] #[derive(Debug)]
@ -59,6 +60,8 @@ pub enum Error {
ByteOrder(io::Error), ByteOrder(io::Error),
/// secp-related error /// secp-related error
Secp256k1(secp256k1::Error), Secp256k1(secp256k1::Error),
/// PSBT-related error
Psbt(psbt::Error),
/// Network magic was not expected /// Network magic was not expected
UnexpectedNetworkMagic { UnexpectedNetworkMagic {
/// The expected network magic /// The expected network magic
@ -102,6 +105,7 @@ impl fmt::Display for Error {
Error::Bech32(ref e) => fmt::Display::fmt(e, f), Error::Bech32(ref e) => fmt::Display::fmt(e, f),
Error::ByteOrder(ref e) => fmt::Display::fmt(e, f), Error::ByteOrder(ref e) => fmt::Display::fmt(e, f),
Error::Secp256k1(ref e) => fmt::Display::fmt(e, f), Error::Secp256k1(ref e) => fmt::Display::fmt(e, f),
Error::Psbt(ref e) => fmt::Display::fmt(e, f),
Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e, a), Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e, a),
Error::OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, "{}: requested {}, maximum {}", error::Error::description(self), r, m), Error::OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, "{}: requested {}, maximum {}", error::Error::description(self), r, m),
Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), hex_encode(e), hex_encode(a)), Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), hex_encode(e), hex_encode(a)),
@ -123,6 +127,7 @@ impl error::Error for Error {
Error::Bech32(ref e) => Some(e), Error::Bech32(ref e) => Some(e),
Error::ByteOrder(ref e) => Some(e), Error::ByteOrder(ref e) => Some(e),
Error::Secp256k1(ref e) => Some(e), Error::Secp256k1(ref e) => Some(e),
Error::Psbt(ref e) => Some(e),
Error::UnexpectedNetworkMagic { .. } Error::UnexpectedNetworkMagic { .. }
| Error::OversizedVectorAllocation { .. } | Error::OversizedVectorAllocation { .. }
| Error::InvalidChecksum { .. } | Error::InvalidChecksum { .. }
@ -142,6 +147,7 @@ impl error::Error for Error {
Error::Bech32(ref e) => e.description(), Error::Bech32(ref e) => e.description(),
Error::ByteOrder(ref e) => e.description(), Error::ByteOrder(ref e) => e.description(),
Error::Secp256k1(ref e) => e.description(), Error::Secp256k1(ref e) => e.description(),
Error::Psbt(ref e) => e.description(),
Error::UnexpectedNetworkMagic { .. } => "unexpected network magic", Error::UnexpectedNetworkMagic { .. } => "unexpected network magic",
Error::OversizedVectorAllocation { .. } => "allocation of oversized vector requested", Error::OversizedVectorAllocation { .. } => "allocation of oversized vector requested",
Error::InvalidChecksum { .. } => "invalid checksum", Error::InvalidChecksum { .. } => "invalid checksum",
@ -183,6 +189,13 @@ impl From<io::Error> for Error {
} }
} }
#[doc(hidden)]
impl From<psbt::Error> for Error {
fn from(e: psbt::Error) -> Error {
Error::Psbt(e)
}
}
/// Encode an object into a vector /// Encode an object into a vector
pub fn serialize<T: ?Sized>(data: &T) -> Vec<u8> pub fn serialize<T: ?Sized>(data: &T) -> Vec<u8>
where T: Encodable<Cursor<Vec<u8>>>, where T: Encodable<Cursor<Vec<u8>>>,

View File

@ -25,6 +25,7 @@ pub mod contracthash;
pub mod decimal; pub mod decimal;
pub mod hash; pub mod hash;
pub mod misc; pub mod misc;
pub mod psbt;
pub mod uint; pub mod uint;
use std::{error, fmt}; use std::{error, fmt};

72
src/util/psbt/error.rs Normal file
View File

@ -0,0 +1,72 @@
use std::error;
use std::fmt;
use blockdata::transaction::Transaction;
/// Ways that a Partially Signed Transaction might fail.
#[derive(Debug)]
pub enum Error {
/// Magic bytes for a PSBT must be the ASCII for "psbt" serialized in most
/// significant byte order.
InvalidMagic,
/// The separator for a PSBT must be `0xff`.
InvalidSeparator,
/// Known keys must be according to spec.
InvalidKey,
/// Keys within key-value map should never be duplicated.
DuplicateKey,
/// The scriptSigs for the unsigned transaction must be empty.
UnsignedTxHasScriptSigs,
/// The scriptWitnesses for the unsigned transaction must be empty.
UnsignedTxHasScriptWitnesses,
/// A PSBT must have an unsigned transaction.
MustHaveUnsignedTx,
/// Signals that there are no more key-value pairs in a key-value map.
NoMorePairs,
/// Attempting to merge with a PSBT describing a different unsigned
/// transaction.
UnexpectedUnsignedTx {
/// Expected
expected: Transaction,
/// Actual
actual: Transaction,
},
/// Unable to parse as a standard SigHash type.
NonStandardSigHashType(u32),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e.txid(), a.txid()),
Error::NonStandardSigHashType(ref sht) => write!(f, "{}: {}", error::Error::description(self), sht),
Error::InvalidMagic
| Error::InvalidSeparator
| Error::InvalidKey
| Error::DuplicateKey
| Error::UnsignedTxHasScriptSigs
| Error::UnsignedTxHasScriptWitnesses
| Error::MustHaveUnsignedTx
| Error::NoMorePairs => f.write_str(error::Error::description(self))
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::InvalidMagic => "invalid magic",
Error::InvalidSeparator => "invalid separator",
Error::InvalidKey => "invalid key",
Error::DuplicateKey => "duplicate key",
Error::UnsignedTxHasScriptSigs => "the unsigned transaction has script sigs",
Error::UnsignedTxHasScriptWitnesses => "the unsigned transaction has script witnesses",
Error::MustHaveUnsignedTx => {
"partially signed transactions must have an unsigned transaction"
}
Error::NoMorePairs => "no more key-value pairs for this psbt map",
Error::UnexpectedUnsignedTx { .. } => "different unsigned transaction",
Error::NonStandardSigHashType(..) => "non-standard sighash type",
}
}
}

8
src/util/psbt/mod.rs Normal file
View File

@ -0,0 +1,8 @@
//! # Partially Signed Transactions
//!
//! Implementation of BIP174 Partially Signed Bitcoin Transaction Format as
//! defined at https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
//! except we define PSBTs containing non-standard SigHash types as invalid.
mod error;
pub use self::error::Error;