Introduce segwit sighash error types
Introduce two new error types to use for the segwit v0 sighash calculation functions.
This commit is contained in:
parent
f0b567313b
commit
c17324c574
|
@ -859,7 +859,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
||||||
script_code: &Script,
|
script_code: &Script,
|
||||||
value: Amount,
|
value: Amount,
|
||||||
sighash_type: EcdsaSighashType,
|
sighash_type: EcdsaSighashType,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), SegwitV0Error> {
|
||||||
let zero_hash = sha256d::Hash::all_zeros();
|
let zero_hash = sha256d::Hash::all_zeros();
|
||||||
|
|
||||||
let (sighash, anyone_can_pay) = sighash_type.split_anyonecanpay_flag();
|
let (sighash, anyone_can_pay) = sighash_type.split_anyonecanpay_flag();
|
||||||
|
@ -882,12 +882,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let txin =
|
let txin = &self.tx.borrow().tx_in(input_index)?;
|
||||||
&self.tx.borrow().input.get(input_index).ok_or(Error::IndexOutOfInputsBounds {
|
|
||||||
index: input_index,
|
|
||||||
inputs_size: self.tx.borrow().input.len(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
txin.previous_output.consensus_encode(writer)?;
|
txin.previous_output.consensus_encode(writer)?;
|
||||||
script_code.consensus_encode(writer)?;
|
script_code.consensus_encode(writer)?;
|
||||||
value.consensus_encode(writer)?;
|
value.consensus_encode(writer)?;
|
||||||
|
@ -921,8 +916,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
||||||
script_pubkey: &Script,
|
script_pubkey: &Script,
|
||||||
value: Amount,
|
value: Amount,
|
||||||
sighash_type: EcdsaSighashType,
|
sighash_type: EcdsaSighashType,
|
||||||
) -> Result<SegwitV0Sighash, Error> {
|
) -> Result<SegwitV0Sighash, P2wpkhError> {
|
||||||
let script_code = script_pubkey.p2wpkh_script_code().ok_or(Error::NotP2wpkhScript)?;
|
let script_code = script_pubkey.p2wpkh_script_code().ok_or(P2wpkhError::NotP2wpkhScript)?;
|
||||||
|
|
||||||
let mut enc = SegwitV0Sighash::engine();
|
let mut enc = SegwitV0Sighash::engine();
|
||||||
self.segwit_v0_encode_signing_data_to(
|
self.segwit_v0_encode_signing_data_to(
|
||||||
|
@ -942,7 +937,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
||||||
witness_script: &Script,
|
witness_script: &Script,
|
||||||
value: Amount,
|
value: Amount,
|
||||||
sighash_type: EcdsaSighashType,
|
sighash_type: EcdsaSighashType,
|
||||||
) -> Result<SegwitV0Sighash, Error> {
|
) -> Result<SegwitV0Sighash, SegwitV0Error> {
|
||||||
let mut enc = SegwitV0Sighash::engine();
|
let mut enc = SegwitV0Sighash::engine();
|
||||||
self.segwit_v0_encode_signing_data_to(
|
self.segwit_v0_encode_signing_data_to(
|
||||||
&mut enc,
|
&mut enc,
|
||||||
|
@ -1312,6 +1307,85 @@ impl From<PrevoutsIndexError> for TaprootError {
|
||||||
fn from(e: PrevoutsIndexError) -> Self { Self::PrevoutsIndex(e) }
|
fn from(e: PrevoutsIndexError) -> Self { Self::PrevoutsIndex(e) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error computing a P2WPKH sighash.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum P2wpkhError {
|
||||||
|
/// Error computing the sighash.
|
||||||
|
Sighash(SegwitV0Error),
|
||||||
|
/// Script is not a witness program for a p2wpkh output.
|
||||||
|
NotP2wpkhScript,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for P2wpkhError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
use P2wpkhError::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Sighash(ref e) => write_err!(f, "error encoding segwit v0 signing data"; e),
|
||||||
|
NotP2wpkhScript => write!(f, "script is not a script pubkey for a p2wpkh output"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for P2wpkhError {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
use P2wpkhError::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Sighash(ref e) => Some(e),
|
||||||
|
NotP2wpkhScript => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SegwitV0Error> for P2wpkhError {
|
||||||
|
fn from(e: SegwitV0Error) -> Self { Self::Sighash(e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error computing the segwit sighash.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum SegwitV0Error {
|
||||||
|
/// Index out of bounds when accessing transaction input vector.
|
||||||
|
InputsIndex(transaction::InputsIndexError),
|
||||||
|
/// Writer errored during consensus encoding.
|
||||||
|
Io(io::ErrorKind),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SegwitV0Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
use SegwitV0Error::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
InputsIndex(ref e) => write_err!(f, "inputs index"; e),
|
||||||
|
Io(error_kind) => write!(f, "write failed: {:?}", error_kind),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for SegwitV0Error {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
use SegwitV0Error::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
InputsIndex(ref e) => Some(e),
|
||||||
|
Io(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<transaction::InputsIndexError> for SegwitV0Error {
|
||||||
|
fn from(e: transaction::InputsIndexError) -> Self { Self::InputsIndex(e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for SegwitV0Error {
|
||||||
|
fn from(e: io::Error) -> Self { Self::Io(e.kind()) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Using `SIGHASH_SINGLE` requires an output at the same index as the input.
|
/// Using `SIGHASH_SINGLE` requires an output at the same index as the input.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
|
@ -770,8 +770,10 @@ pub enum SignError {
|
||||||
NotEcdsa,
|
NotEcdsa,
|
||||||
/// The `scriptPubkey` is not a P2WPKH script.
|
/// The `scriptPubkey` is not a P2WPKH script.
|
||||||
NotWpkh,
|
NotWpkh,
|
||||||
/// Sighash computation error.
|
/// Sighash computation error (segwit v0 input).
|
||||||
SighashComputation(sighash::Error),
|
SegwitV0Sighash(sighash::SegwitV0Error),
|
||||||
|
/// Sighash computation error (p2wpkh input).
|
||||||
|
P2wpkhSighash(sighash::P2wpkhError),
|
||||||
/// Unable to determine the output type.
|
/// Unable to determine the output type.
|
||||||
UnknownOutputType,
|
UnknownOutputType,
|
||||||
/// Unable to find key.
|
/// Unable to find key.
|
||||||
|
@ -796,7 +798,8 @@ impl fmt::Display for SignError {
|
||||||
MismatchedAlgoKey => write!(f, "signing algorithm and key type does not match"),
|
MismatchedAlgoKey => write!(f, "signing algorithm and key type does not match"),
|
||||||
NotEcdsa => write!(f, "attempted to ECDSA sign an non-ECDSA input"),
|
NotEcdsa => write!(f, "attempted to ECDSA sign an non-ECDSA input"),
|
||||||
NotWpkh => write!(f, "the scriptPubkey is not a P2WPKH script"),
|
NotWpkh => write!(f, "the scriptPubkey is not a P2WPKH script"),
|
||||||
SighashComputation(ref e) => write!(f, "sighash: {}", e),
|
SegwitV0Sighash(ref e) => write_err!(f, "segwit v0 sighash"; e),
|
||||||
|
P2wpkhSighash(ref e) => write_err!(f, "p2wpkh sighash"; e),
|
||||||
UnknownOutputType => write!(f, "unable to determine the output type"),
|
UnknownOutputType => write!(f, "unable to determine the output type"),
|
||||||
KeyNotFound => write!(f, "unable to find key"),
|
KeyNotFound => write!(f, "unable to find key"),
|
||||||
WrongSigningAlgorithm =>
|
WrongSigningAlgorithm =>
|
||||||
|
@ -812,7 +815,8 @@ impl std::error::Error for SignError {
|
||||||
use SignError::*;
|
use SignError::*;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
SighashComputation(ref e) => Some(e),
|
SegwitV0Sighash(ref e) => Some(e),
|
||||||
|
P2wpkhSighash(ref e) => Some(e),
|
||||||
IndexOutOfBounds(ref e) => Some(e),
|
IndexOutOfBounds(ref e) => Some(e),
|
||||||
InvalidSighashType
|
InvalidSighashType
|
||||||
| MissingInputUtxo
|
| MissingInputUtxo
|
||||||
|
@ -830,8 +834,12 @@ impl std::error::Error for SignError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<sighash::Error> for SignError {
|
impl From<sighash::SegwitV0Error> for SignError {
|
||||||
fn from(e: sighash::Error) -> Self { SignError::SighashComputation(e) }
|
fn from(e: sighash::SegwitV0Error) -> Self { Self::SegwitV0Sighash(e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<sighash::P2wpkhError> for SignError {
|
||||||
|
fn from(e: sighash::P2wpkhError) -> Self { Self::P2wpkhSighash(e) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<IndexOutOfBoundsError> for SignError {
|
impl From<IndexOutOfBoundsError> for SignError {
|
||||||
|
|
Loading…
Reference in New Issue