elements_miniscript/descriptor/csfs_cov/
satisfy.rs1use elements::encode::Encodable;
18use elements::hashes::{sha256d, Hash};
19use elements::sighash::SighashCache;
20use elements::{self, confidential, EcdsaSighashType, OutPoint, Script, Sighash, Transaction};
21
22use super::CovError;
23use crate::{MiniscriptKey, Satisfier, ToPublicKey};
24
25#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct LegacyCovSatisfier<'tx, 'ptx> {
32 tx: &'tx Transaction,
35 idx: u32,
38 hash_type: EcdsaSighashType,
40
41 script_code: Option<&'ptx Script>,
44 value: Option<confidential::Value>,
46}
47
48impl<'tx, 'ptx> LegacyCovSatisfier<'tx, 'ptx> {
49 pub fn new_segwitv0(
52 tx: &'tx Transaction,
53 idx: u32,
54 value: confidential::Value,
55 script_code: &'ptx Script,
56 hash_type: EcdsaSighashType,
57 ) -> Self {
58 assert!((idx as usize) < tx.input.len());
59 Self {
60 tx,
61 idx,
62 hash_type,
63 script_code: Some(script_code),
64 value: Some(value),
65 }
66 }
67
68 pub fn segwit_sighash(&self) -> Result<Sighash, CovError> {
74 let mut cache = SighashCache::new(self.tx);
75 let script_code = self.script_code.ok_or(CovError::MissingScriptCode)?;
77 let value = self.value.ok_or(CovError::MissingValue)?;
78 Ok(cache.segwitv0_sighash(self.idx as usize, script_code, value, self.hash_type))
79 }
80}
81
82impl<'tx, 'ptx, Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for LegacyCovSatisfier<'tx, 'ptx> {
83 fn lookup_nversion(&self) -> Option<u32> {
84 Some(self.tx.version)
85 }
86
87 fn lookup_hashprevouts(&self) -> Option<sha256d::Hash> {
88 let mut enc = sha256d::Hash::engine();
89 for txin in &self.tx.input {
90 txin.previous_output.consensus_encode(&mut enc).unwrap();
91 }
92 Some(sha256d::Hash::from_engine(enc))
93 }
94
95 fn lookup_hashsequence(&self) -> Option<sha256d::Hash> {
96 let mut enc = sha256d::Hash::engine();
97 for txin in &self.tx.input {
98 txin.sequence.consensus_encode(&mut enc).unwrap();
99 }
100 Some(sha256d::Hash::from_engine(enc))
101 }
102
103 fn lookup_hashissuances(&self) -> Option<sha256d::Hash> {
104 let mut enc = sha256d::Hash::engine();
105 for txin in &self.tx.input {
106 if txin.has_issuance() {
107 txin.asset_issuance.consensus_encode(&mut enc).unwrap();
108 } else {
109 0u8.consensus_encode(&mut enc).unwrap();
110 }
111 }
112 Some(sha256d::Hash::from_engine(enc))
113 }
114
115 fn lookup_outpoint(&self) -> Option<OutPoint> {
116 Some(self.tx.input[self.idx as usize].previous_output)
117 }
118
119 fn lookup_scriptcode(&self) -> Option<&Script> {
120 self.script_code
121 }
122
123 fn lookup_value(&self) -> Option<confidential::Value> {
124 self.value
125 }
126
127 fn lookup_nsequence(&self) -> Option<u32> {
128 Some(self.tx.input[self.idx as usize].sequence.to_consensus_u32())
129 }
130
131 fn lookup_outputs(&self) -> Option<&[elements::TxOut]> {
132 Some(&self.tx.output)
133 }
134
135 fn lookup_nlocktime(&self) -> Option<u32> {
136 Some(self.tx.lock_time.to_consensus_u32())
137 }
138
139 fn lookup_sighashu32(&self) -> Option<u32> {
140 Some(self.hash_type.as_u32())
141 }
142}