use crate::legacy::Script;
use blake2b_simd::Hash as Blake2bHash;
use std::convert::TryInto;
use super::{
components::{
sapling::{self, GrothProofBytes},
transparent, Amount,
},
sighash_v4::v4_signature_hash,
sighash_v5::v5_signature_hash,
Authorization, TransactionData, TxDigests, TxVersion,
};
#[cfg(feature = "zfuture")]
use crate::extensions::transparent::Precondition;
pub const SIGHASH_ALL: u8 = 0x01;
pub const SIGHASH_NONE: u8 = 0x02;
pub const SIGHASH_SINGLE: u8 = 0x03;
pub const SIGHASH_MASK: u8 = 0x1f;
pub const SIGHASH_ANYONECANPAY: u8 = 0x80;
pub enum SignableInput<'a> {
Shielded,
Transparent {
hash_type: u8,
index: usize,
script_code: &'a Script,
script_pubkey: &'a Script,
value: Amount,
},
#[cfg(feature = "zfuture")]
Tze {
index: usize,
precondition: &'a Precondition,
value: Amount,
},
}
impl<'a> SignableInput<'a> {
pub fn hash_type(&self) -> u8 {
match self {
SignableInput::Shielded => SIGHASH_ALL,
SignableInput::Transparent { hash_type, .. } => *hash_type,
#[cfg(feature = "zfuture")]
SignableInput::Tze { .. } => SIGHASH_ALL,
}
}
}
pub struct SignatureHash(Blake2bHash);
impl AsRef<[u8; 32]> for SignatureHash {
fn as_ref(&self) -> &[u8; 32] {
self.0.as_ref().try_into().unwrap()
}
}
pub trait TransparentAuthorizingContext: transparent::Authorization {
fn input_amounts(&self) -> Vec<Amount>;
fn input_scriptpubkeys(&self) -> Vec<Script>;
}
pub fn signature_hash<
'a,
TA: TransparentAuthorizingContext,
SA: sapling::Authorization<Proof = GrothProofBytes>,
A: Authorization<SaplingAuth = SA, TransparentAuth = TA>,
>(
tx: &TransactionData<A>,
signable_input: &SignableInput<'a>,
txid_parts: &TxDigests<Blake2bHash>,
) -> SignatureHash {
SignatureHash(match tx.version {
TxVersion::Sprout(_) | TxVersion::Overwinter | TxVersion::Sapling => {
v4_signature_hash(tx, signable_input)
}
TxVersion::Zip225 => v5_signature_hash(tx, signable_input, txid_parts),
#[cfg(feature = "zfuture")]
TxVersion::ZFuture => v5_signature_hash(tx, signable_input, txid_parts),
})
}