Merge rust-bitcoin/rust-bitcoin#835: Change Prevouts::All(&[TxOut]) to Prevouts::All(&[&TxOut])
10fedfb3b4
Change Prevouts::All(&[TxOut]) to Prevouts::All(&[Borrow<T>]) (sanket1729) Pull request description: I believe this avoids some allocation of creating a vec of TxOut to create a slice incase the data is already available in psbt/other methods. See #834 ACKs for top commit: apoelstra: ACK10fedfb3b4
Kixunil: ACK10fedfb3b4
Tree-SHA512: 20f69c626b38d6b3c03c8cb370cfad097bbf0bfefff9bb2379c8af3bc94e25d8cc45fc5d69488aeefad58a95470e8f30eb7b400349992a9ebd0d3a13870cba43
This commit is contained in:
commit
04787d4867
|
@ -25,6 +25,7 @@ use blockdata::witness::Witness;
|
|||
use consensus::{encode, Encodable};
|
||||
use core::fmt;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::borrow::Borrow;
|
||||
use hashes::{sha256, sha256d, Hash};
|
||||
use io;
|
||||
use util::taproot::{TapLeafHash, TAPROOT_ANNEX_PREFIX, TapSighashHash};
|
||||
|
@ -80,14 +81,14 @@ struct TaprootCache {
|
|||
/// Contains outputs of previous transactions.
|
||||
/// In the case [`SchnorrSigHashType`] variant is `ANYONECANPAY`, [`Prevouts::One`] may be provided
|
||||
#[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
|
||||
/// 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.
|
||||
One(usize, &'u TxOut),
|
||||
One(usize, T),
|
||||
/// When `ANYONECANPAY` is not provided, or the caller is handy giving all prevouts so the same
|
||||
/// variable can be used for multiple inputs.
|
||||
All(&'u [TxOut]),
|
||||
All(&'u [T]),
|
||||
}
|
||||
|
||||
const KEY_VERSION_0: u8 = 0u8;
|
||||
|
@ -188,7 +189,7 @@ impl fmt::Display for Error {
|
|||
#[cfg(feature = "std")]
|
||||
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> {
|
||||
if let Prevouts::All(prevouts) = self {
|
||||
if prevouts.len() != tx.input.len() {
|
||||
|
@ -198,9 +199,9 @@ impl<'u> Prevouts<'u> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_all(&self) -> Result<&[TxOut], Error> {
|
||||
fn get_all(&self) -> Result<&[T], Error> {
|
||||
match self {
|
||||
Prevouts::All(prevouts) => Ok(prevouts),
|
||||
Prevouts::All(prevouts) => Ok(*prevouts),
|
||||
_ => Err(Error::PrevoutKind),
|
||||
}
|
||||
}
|
||||
|
@ -209,12 +210,15 @@ impl<'u> Prevouts<'u> {
|
|||
match self {
|
||||
Prevouts::One(index, prevout) => {
|
||||
if input_index == *index {
|
||||
Ok(prevout)
|
||||
Ok(prevout.borrow())
|
||||
} else {
|
||||
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
|
||||
/// 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 writer: Write,
|
||||
input_index: usize,
|
||||
prevouts: &Prevouts,
|
||||
prevouts: &Prevouts<T>,
|
||||
annex: Option<Annex>,
|
||||
leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
|
||||
sighash_type: SchnorrSigHashType,
|
||||
|
@ -437,10 +441,10 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
|
|||
}
|
||||
|
||||
/// Compute the BIP341 sighash for any flag type.
|
||||
pub fn taproot_signature_hash(
|
||||
pub fn taproot_signature_hash<T: Borrow<TxOut>>(
|
||||
&mut self,
|
||||
input_index: usize,
|
||||
prevouts: &Prevouts,
|
||||
prevouts: &Prevouts<T>,
|
||||
annex: Option<Annex>,
|
||||
leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
|
||||
sighash_type: SchnorrSigHashType,
|
||||
|
@ -458,10 +462,10 @@ impl<R: Deref<Target = Transaction>> SigHashCache<R> {
|
|||
}
|
||||
|
||||
/// 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,
|
||||
input_index: usize,
|
||||
prevouts: &Prevouts,
|
||||
prevouts: &Prevouts<T>,
|
||||
sighash_type: SchnorrSigHashType,
|
||||
) -> Result<TapSighashHash, Error> {
|
||||
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
|
||||
/// 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,
|
||||
input_index: usize,
|
||||
prevouts: &Prevouts,
|
||||
prevouts: &Prevouts<T>,
|
||||
leaf_hash: S,
|
||||
sighash_type: SchnorrSigHashType,
|
||||
) -> 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(|| {
|
||||
let mut enc_amounts = sha256::Hash::engine();
|
||||
let mut enc_script_pubkeys = sha256::Hash::engine();
|
||||
for prevout in prevouts {
|
||||
prevout.value.consensus_encode(&mut enc_amounts).unwrap();
|
||||
prevout.borrow().value.consensus_encode(&mut enc_amounts).unwrap();
|
||||
prevout
|
||||
.borrow()
|
||||
.script_pubkey
|
||||
.consensus_encode(&mut enc_script_pubkeys)
|
||||
.unwrap();
|
||||
|
@ -898,8 +904,11 @@ mod tests {
|
|||
};
|
||||
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!(
|
||||
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)
|
||||
);
|
||||
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 {
|
||||
// for anyonecanpay the `Prevouts::All` variant is good anyway, but sometimes we want to
|
||||
// test other codepaths
|
||||
Prevouts::One(input_index, &prevouts[input_index])
|
||||
Prevouts::One(input_index, prevouts[input_index].clone())
|
||||
} else {
|
||||
Prevouts::All(&prevouts)
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue