Change Prevouts::All(&[TxOut]) to Prevouts::All(&[Borrow<T>])
This avoids some allocation of creating a vec of TxOut to create a slice incase the data is already available in psbt/other methods. Facilitates creation of Prevouts from &[TxOut] as well as &[&TxOut]
This commit is contained in:
parent
0c5b695194
commit
10fedfb3b4
|
@ -25,6 +25,7 @@ use blockdata::witness::Witness;
|
||||||
use consensus::{encode, Encodable};
|
use consensus::{encode, Encodable};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
|
use core::borrow::Borrow;
|
||||||
use hashes::{sha256, sha256d, Hash};
|
use hashes::{sha256, sha256d, Hash};
|
||||||
use io;
|
use io;
|
||||||
use util::taproot::{TapLeafHash, TAPROOT_ANNEX_PREFIX, TapSighashHash};
|
use util::taproot::{TapLeafHash, TAPROOT_ANNEX_PREFIX, TapSighashHash};
|
||||||
|
@ -80,14 +81,14 @@ struct TaprootCache {
|
||||||
/// Contains outputs of previous transactions.
|
/// Contains outputs of previous transactions.
|
||||||
/// In the case [`SchnorrSigHashType`] variant is `ANYONECANPAY`, [`Prevouts::One`] may be provided
|
/// In the case [`SchnorrSigHashType`] variant is `ANYONECANPAY`, [`Prevouts::One`] may be provided
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
pub enum Prevouts<'u> {
|
pub enum Prevouts<'u, T> where T: 'u + Borrow<TxOut> {
|
||||||
/// `One` variant allows to provide the single Prevout needed. It's useful for example
|
/// `One` variant allows to provide the single Prevout needed. It's useful for example
|
||||||
/// when modifier `ANYONECANPAY` is provided, only prevout of the current input is needed.
|
/// when modifier `ANYONECANPAY` is provided, only prevout of the current input is needed.
|
||||||
/// The first `usize` argument is the input index this [`TxOut`] is referring to.
|
/// The first `usize` argument is the input index this [`TxOut`] is referring to.
|
||||||
One(usize, &'u TxOut),
|
One(usize, T),
|
||||||
/// When `ANYONECANPAY` is not provided, or the caller is handy giving all prevouts so the same
|
/// When `ANYONECANPAY` is not provided, or the caller is handy giving all prevouts so the same
|
||||||
/// variable can be used for multiple inputs.
|
/// variable can be used for multiple inputs.
|
||||||
All(&'u [TxOut]),
|
All(&'u [T]),
|
||||||
}
|
}
|
||||||
|
|
||||||
const KEY_VERSION_0: u8 = 0u8;
|
const KEY_VERSION_0: u8 = 0u8;
|
||||||
|
@ -188,7 +189,7 @@ impl fmt::Display for Error {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl ::std::error::Error for Error {}
|
impl ::std::error::Error for Error {}
|
||||||
|
|
||||||
impl<'u> Prevouts<'u> {
|
impl<'u, T> Prevouts<'u, T> where T: Borrow<TxOut> {
|
||||||
fn check_all(&self, tx: &Transaction) -> Result<(), Error> {
|
fn check_all(&self, tx: &Transaction) -> Result<(), Error> {
|
||||||
if let Prevouts::All(prevouts) = self {
|
if let Prevouts::All(prevouts) = self {
|
||||||
if prevouts.len() != tx.input.len() {
|
if prevouts.len() != tx.input.len() {
|
||||||
|
@ -198,9 +199,9 @@ impl<'u> Prevouts<'u> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_all(&self) -> Result<&[TxOut], Error> {
|
fn get_all(&self) -> Result<&[T], Error> {
|
||||||
match self {
|
match self {
|
||||||
Prevouts::All(prevouts) => Ok(prevouts),
|
Prevouts::All(prevouts) => Ok(*prevouts),
|
||||||
_ => Err(Error::PrevoutKind),
|
_ => Err(Error::PrevoutKind),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,12 +210,15 @@ impl<'u> Prevouts<'u> {
|
||||||
match self {
|
match self {
|
||||||
Prevouts::One(index, prevout) => {
|
Prevouts::One(index, prevout) => {
|
||||||
if input_index == *index {
|
if input_index == *index {
|
||||||
Ok(prevout)
|
Ok(prevout.borrow())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::PrevoutIndex)
|
Err(Error::PrevoutIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Prevouts::All(prevouts) => prevouts.get(input_index).ok_or(Error::PrevoutIndex),
|
Prevouts::All(prevouts) => prevouts
|
||||||
|
.get(input_index)
|
||||||
|
.map(|x| x.borrow())
|
||||||
|
.ok_or(Error::PrevoutIndex),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,11 +311,11 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
|
||||||
|
|
||||||
/// Encode the BIP341 signing data for any flag type into a given object implementing a
|
/// Encode the BIP341 signing data for any flag type into a given object implementing a
|
||||||
/// io::Write trait.
|
/// io::Write trait.
|
||||||
pub fn taproot_encode_signing_data_to<Write: io::Write>(
|
pub fn taproot_encode_signing_data_to<Write: io::Write, T: Borrow<TxOut>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut writer: Write,
|
mut writer: Write,
|
||||||
input_index: usize,
|
input_index: usize,
|
||||||
prevouts: &Prevouts,
|
prevouts: &Prevouts<T>,
|
||||||
annex: Option<Annex>,
|
annex: Option<Annex>,
|
||||||
leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
|
leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
|
||||||
sighash_type: SchnorrSigHashType,
|
sighash_type: SchnorrSigHashType,
|
||||||
|
@ -437,10 +441,10 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the BIP341 sighash for any flag type.
|
/// Compute the BIP341 sighash for any flag type.
|
||||||
pub fn taproot_signature_hash(
|
pub fn taproot_signature_hash<T: Borrow<TxOut>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input_index: usize,
|
input_index: usize,
|
||||||
prevouts: &Prevouts,
|
prevouts: &Prevouts<T>,
|
||||||
annex: Option<Annex>,
|
annex: Option<Annex>,
|
||||||
leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
|
leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
|
||||||
sighash_type: SchnorrSigHashType,
|
sighash_type: SchnorrSigHashType,
|
||||||
|
@ -458,10 +462,10 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the BIP341 sighash for a key spend
|
/// Compute the BIP341 sighash for a key spend
|
||||||
pub fn taproot_key_spend_signature_hash(
|
pub fn taproot_key_spend_signature_hash<T: Borrow<TxOut>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input_index: usize,
|
input_index: usize,
|
||||||
prevouts: &Prevouts,
|
prevouts: &Prevouts<T>,
|
||||||
sighash_type: SchnorrSigHashType,
|
sighash_type: SchnorrSigHashType,
|
||||||
) -> Result<TapSighashHash, Error> {
|
) -> Result<TapSighashHash, Error> {
|
||||||
let mut enc = TapSighashHash::engine();
|
let mut enc = TapSighashHash::engine();
|
||||||
|
@ -480,10 +484,10 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
|
||||||
///
|
///
|
||||||
/// Assumes the default `OP_CODESEPARATOR` position of `0xFFFFFFFF`. Custom values can be
|
/// Assumes the default `OP_CODESEPARATOR` position of `0xFFFFFFFF`. Custom values can be
|
||||||
/// provided through the more fine-grained API of [`SigHashCache::taproot_encode_signing_data_to`].
|
/// provided through the more fine-grained API of [`SigHashCache::taproot_encode_signing_data_to`].
|
||||||
pub fn taproot_script_spend_signature_hash<S: Into<TapLeafHash>>(
|
pub fn taproot_script_spend_signature_hash<S: Into<TapLeafHash>, T: Borrow<TxOut>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input_index: usize,
|
input_index: usize,
|
||||||
prevouts: &Prevouts,
|
prevouts: &Prevouts<T>,
|
||||||
leaf_hash: S,
|
leaf_hash: S,
|
||||||
sighash_type: SchnorrSigHashType,
|
sighash_type: SchnorrSigHashType,
|
||||||
) -> Result<TapSighashHash, Error> {
|
) -> Result<TapSighashHash, Error> {
|
||||||
|
@ -667,13 +671,15 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn taproot_cache(&mut self, prevouts: &[TxOut]) -> &TaprootCache {
|
fn taproot_cache<T: Borrow<TxOut>>(&mut self, prevouts: &[T]) -> &TaprootCache
|
||||||
|
{
|
||||||
self.taproot_cache.get_or_insert_with(|| {
|
self.taproot_cache.get_or_insert_with(|| {
|
||||||
let mut enc_amounts = sha256::Hash::engine();
|
let mut enc_amounts = sha256::Hash::engine();
|
||||||
let mut enc_script_pubkeys = sha256::Hash::engine();
|
let mut enc_script_pubkeys = sha256::Hash::engine();
|
||||||
for prevout in prevouts {
|
for prevout in prevouts {
|
||||||
prevout.value.consensus_encode(&mut enc_amounts).unwrap();
|
prevout.borrow().value.consensus_encode(&mut enc_amounts).unwrap();
|
||||||
prevout
|
prevout
|
||||||
|
.borrow()
|
||||||
.script_pubkey
|
.script_pubkey
|
||||||
.consensus_encode(&mut enc_script_pubkeys)
|
.consensus_encode(&mut enc_script_pubkeys)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -898,8 +904,11 @@ mod tests {
|
||||||
};
|
};
|
||||||
let mut c = SigHashCache::new(&dumb_tx);
|
let mut c = SigHashCache::new(&dumb_tx);
|
||||||
|
|
||||||
|
// 1.29 fixes
|
||||||
|
let empty_vec = vec![];
|
||||||
|
let empty_prevouts : Prevouts<TxOut> = Prevouts::All(&empty_vec);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
c.taproot_signature_hash(0, &Prevouts::All(&vec![]), None, None, SchnorrSigHashType::All),
|
c.taproot_signature_hash(0, &empty_prevouts, None, None, SchnorrSigHashType::All),
|
||||||
Err(Error::PrevoutsSize)
|
Err(Error::PrevoutsSize)
|
||||||
);
|
);
|
||||||
let two = vec![TxOut::default(), TxOut::default()];
|
let two = vec![TxOut::default(), TxOut::default()];
|
||||||
|
@ -988,7 +997,7 @@ mod tests {
|
||||||
let prevouts = if sighash_type.split_anyonecanpay_flag().1 && tx_bytes[0] % 2 == 0 {
|
let prevouts = if sighash_type.split_anyonecanpay_flag().1 && tx_bytes[0] % 2 == 0 {
|
||||||
// for anyonecanpay the `Prevouts::All` variant is good anyway, but sometimes we want to
|
// for anyonecanpay the `Prevouts::All` variant is good anyway, but sometimes we want to
|
||||||
// test other codepaths
|
// test other codepaths
|
||||||
Prevouts::One(input_index, &prevouts[input_index])
|
Prevouts::One(input_index, prevouts[input_index].clone())
|
||||||
} else {
|
} else {
|
||||||
Prevouts::All(&prevouts)
|
Prevouts::All(&prevouts)
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue