use elements::encode::Encodable;
use elements::hashes::{sha256d, Hash};
use elements::sighash::SigHashCache;
use elements::{self, confidential, EcdsaSigHashType, OutPoint, Script, SigHash, Transaction};
use super::CovError;
use crate::{MiniscriptKey, Satisfier, ToPublicKey};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LegacyCovSatisfier<'tx, 'ptx> {
tx: &'tx Transaction,
idx: u32,
hash_type: EcdsaSigHashType,
script_code: Option<&'ptx Script>,
value: Option<confidential::Value>,
}
impl<'tx, 'ptx> LegacyCovSatisfier<'tx, 'ptx> {
pub fn new_segwitv0(
tx: &'tx Transaction,
idx: u32,
value: confidential::Value,
script_code: &'ptx Script,
hash_type: EcdsaSigHashType,
) -> Self {
assert!((idx as usize) < tx.input.len());
Self {
tx,
idx,
hash_type,
script_code: Some(script_code),
value: Some(value),
}
}
pub fn segwit_sighash(&self) -> Result<SigHash, CovError> {
let mut cache = SigHashCache::new(self.tx);
let script_code = self.script_code.ok_or(CovError::MissingScriptCode)?;
let value = self.value.ok_or(CovError::MissingValue)?;
Ok(cache.segwitv0_sighash(self.idx as usize, script_code, value, self.hash_type))
}
}
impl<'tx, 'ptx, Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for LegacyCovSatisfier<'tx, 'ptx> {
fn lookup_nversion(&self) -> Option<u32> {
Some(self.tx.version)
}
fn lookup_hashprevouts(&self) -> Option<sha256d::Hash> {
let mut enc = sha256d::Hash::engine();
for txin in &self.tx.input {
txin.previous_output.consensus_encode(&mut enc).unwrap();
}
Some(sha256d::Hash::from_engine(enc))
}
fn lookup_hashsequence(&self) -> Option<sha256d::Hash> {
let mut enc = sha256d::Hash::engine();
for txin in &self.tx.input {
txin.sequence.consensus_encode(&mut enc).unwrap();
}
Some(sha256d::Hash::from_engine(enc))
}
fn lookup_hashissuances(&self) -> Option<sha256d::Hash> {
let mut enc = sha256d::Hash::engine();
for txin in &self.tx.input {
if txin.has_issuance() {
txin.asset_issuance.consensus_encode(&mut enc).unwrap();
} else {
0u8.consensus_encode(&mut enc).unwrap();
}
}
Some(sha256d::Hash::from_engine(enc))
}
fn lookup_outpoint(&self) -> Option<OutPoint> {
Some(self.tx.input[self.idx as usize].previous_output)
}
fn lookup_scriptcode(&self) -> Option<&Script> {
self.script_code
}
fn lookup_value(&self) -> Option<confidential::Value> {
self.value
}
fn lookup_nsequence(&self) -> Option<u32> {
Some(self.tx.input[self.idx as usize].sequence.to_consensus_u32())
}
fn lookup_outputs(&self) -> Option<&[elements::TxOut]> {
Some(&self.tx.output)
}
fn lookup_nlocktime(&self) -> Option<u32> {
Some(self.tx.lock_time.to_consensus_u32())
}
fn lookup_sighashu32(&self) -> Option<u32> {
Some(self.hash_type.as_u32())
}
}