93 lines
2.6 KiB
Rust
93 lines
2.6 KiB
Rust
//! Signature hashes for Zcash transactions
|
|
|
|
use super::Transaction;
|
|
|
|
use crate::{parameters::NetworkUpgrade, transparent};
|
|
|
|
use crate::primitives::zcash_primitives::sighash;
|
|
|
|
static ZIP143_EXPLANATION: &str = "Invalid transaction version: after Overwinter activation transaction versions 1 and 2 are rejected";
|
|
|
|
bitflags::bitflags! {
|
|
/// The different SigHash types, as defined in https://zips.z.cash/zip-0143
|
|
pub struct HashType: u32 {
|
|
/// Sign all the outputs
|
|
const ALL = 0b0000_0001;
|
|
/// Sign none of the outputs - anyone can spend
|
|
const NONE = 0b0000_0010;
|
|
/// Sign one of the outputs - anyone can spend the rest
|
|
const SINGLE = Self::ALL.bits | Self::NONE.bits;
|
|
/// Anyone can add inputs to this transaction
|
|
const ANYONECANPAY = 0b1000_0000;
|
|
}
|
|
}
|
|
|
|
/// A Signature Hash (or SIGHASH) as specified in
|
|
/// https://zips.z.cash/protocol/protocol.pdf#sighash
|
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
|
pub struct SigHash(pub [u8; 32]);
|
|
|
|
impl AsRef<[u8; 32]> for SigHash {
|
|
fn as_ref(&self) -> &[u8; 32] {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl AsRef<[u8]> for SigHash {
|
|
fn as_ref(&self) -> &[u8] {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
pub(super) struct SigHasher<'a> {
|
|
trans: &'a Transaction,
|
|
hash_type: HashType,
|
|
network_upgrade: NetworkUpgrade,
|
|
input: Option<(transparent::Output, &'a transparent::Input, usize)>,
|
|
}
|
|
|
|
impl<'a> SigHasher<'a> {
|
|
pub fn new(
|
|
trans: &'a Transaction,
|
|
hash_type: HashType,
|
|
network_upgrade: NetworkUpgrade,
|
|
input: Option<(u32, transparent::Output)>,
|
|
) -> Self {
|
|
let input = if let Some((index, prevout)) = input {
|
|
let index = index as usize;
|
|
let inputs = trans.inputs();
|
|
|
|
Some((prevout, &inputs[index], index))
|
|
} else {
|
|
None
|
|
};
|
|
|
|
SigHasher {
|
|
trans,
|
|
hash_type,
|
|
network_upgrade,
|
|
input,
|
|
}
|
|
}
|
|
|
|
pub(super) fn sighash(self) -> SigHash {
|
|
use NetworkUpgrade::*;
|
|
|
|
match self.network_upgrade {
|
|
Genesis | BeforeOverwinter => unreachable!(ZIP143_EXPLANATION),
|
|
Overwinter | Sapling | Blossom | Heartwood | Canopy | Nu5 => {
|
|
self.hash_sighash_librustzcash()
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Compute a signature hash using librustzcash.
|
|
fn hash_sighash_librustzcash(&self) -> SigHash {
|
|
let input = self
|
|
.input
|
|
.as_ref()
|
|
.map(|(output, input, idx)| (output, *input, *idx));
|
|
sighash(self.trans, self.hash_type, self.network_upgrade, input)
|
|
}
|
|
}
|