psbt_v2/v2/miniscript/
mod.rs1mod finalize;
22mod satisfy;
23
24use core::fmt;
25
26use bitcoin::consensus::encode::VarInt;
27use bitcoin::secp256k1::{Secp256k1, Verification};
28use bitcoin::sighash::Prevouts;
29use bitcoin::{Script, Sequence, Transaction, TxOut, Witness};
30use miniscript::miniscript::satisfy::Placeholder;
31use miniscript::{interpreter, Interpreter, MiniscriptKey};
32
33use crate::error::write_err;
34use crate::prelude::*;
35use crate::v2::map::input::Input;
36use crate::v2::{DetermineLockTimeError, Psbt};
37
38#[rustfmt::skip] pub use self::finalize::{InputError, Finalizer, FinalizeError, FinalizeInputError};
40
41impl Psbt {
42 pub fn interpreter_check<C: Verification>(
49 &self,
50 secp: &Secp256k1<C>,
51 ) -> Result<(), InterpreterCheckError> {
52 debug_assert!(self.is_finalized());
53
54 let unsigned_tx = self.unsigned_tx()?; let utxos: Vec<&TxOut> = self
57 .iter_funding_utxos()
58 .map(|res| res.expect("finalized PSBT has funding utxos"))
59 .collect();
60 let utxos = &Prevouts::All(&utxos);
61 for (index, input) in self.inputs.iter().enumerate() {
62 self.interpreter_check_input(
63 secp,
64 &unsigned_tx,
65 index,
66 input,
67 utxos,
68 input.final_script_witness.as_ref().expect("checked in is_finalized"),
69 input.final_script_sig.as_ref().expect("checked in is_finalized"),
70 )?;
71 }
72 Ok(())
73 }
74
75 #[allow(clippy::too_many_arguments)] fn interpreter_check_input<C: Verification, T: Borrow<TxOut>>(
78 &self,
79 secp: &Secp256k1<C>,
80 unsigned_tx: &Transaction,
81 index: usize,
82 input: &Input,
83 utxos: &Prevouts<T>,
84 witness: &Witness,
85 script_sig: &Script,
86 ) -> Result<(), InterpreterCheckInputError> {
87 use InterpreterCheckInputError::*;
88
89 let spk = &input.funding_utxo().expect("have funding utxo").script_pubkey;
90
91 let cltv = input.lock_time();
93 let csv = input.sequence.unwrap_or(Sequence::MAX);
95
96 let interpreter = Interpreter::from_txdata(spk, script_sig, witness, csv, cltv)
97 .map_err(|error| Constructor { input_index: index, error })?;
98
99 let iter = interpreter.iter(secp, unsigned_tx, index, utxos);
100 if let Some(error) = iter.filter_map(Result::err).next() {
102 return Err(Satisfaction { input_index: index, error });
103 };
104
105 Ok(())
106 }
107}
108
109pub(crate) trait ItemSize {
110 fn size(&self) -> usize;
111}
112
113impl<Pk: MiniscriptKey> ItemSize for Placeholder<Pk> {
114 fn size(&self) -> usize {
115 match self {
116 Placeholder::Pubkey(_, size) => *size,
117 Placeholder::PubkeyHash(_, size) => *size,
118 Placeholder::EcdsaSigPk(_) | Placeholder::EcdsaSigPkHash(_) => 73,
119 Placeholder::SchnorrSigPk(_, _, size) | Placeholder::SchnorrSigPkHash(_, _, size) =>
120 size + 1, Placeholder::HashDissatisfaction
122 | Placeholder::Sha256Preimage(_)
123 | Placeholder::Hash256Preimage(_)
124 | Placeholder::Ripemd160Preimage(_)
125 | Placeholder::Hash160Preimage(_) => 33,
126 Placeholder::PushOne => 2, Placeholder::PushZero => 1,
128 Placeholder::TapScript(s) => s.len(),
129 Placeholder::TapControlBlock(cb) => cb.serialize().len(),
130 }
131 }
132}
133
134impl ItemSize for Vec<u8> {
135 fn size(&self) -> usize { self.len() }
136}
137
138pub(crate) fn witness_size<T: ItemSize>(wit: &[T]) -> usize {
140 wit.iter().map(T::size).sum::<usize>() + varint_len(wit.len())
141}
142
143pub(crate) fn varint_len(n: usize) -> usize { VarInt(n as u64).size() }
144
145#[derive(Debug)]
147pub enum InterpreterCheckError {
148 DetermineLockTime(DetermineLockTimeError),
150 InterpreterCheckInput(InterpreterCheckInputError),
152}
153
154impl fmt::Display for InterpreterCheckError {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 use InterpreterCheckError::*;
157
158 match *self {
159 DetermineLockTime(ref e) => write_err!(f, "interpreter check determine locktime"; e),
160 InterpreterCheckInput(ref e) => write_err!(f, "interpreter check failed for input"; e),
161 }
162 }
163}
164
165#[cfg(feature = "std")]
166impl std::error::Error for InterpreterCheckError {
167 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
168 use InterpreterCheckError::*;
169
170 match *self {
171 DetermineLockTime(ref e) => Some(e),
172 InterpreterCheckInput(ref e) => Some(e),
173 }
174 }
175}
176
177impl From<DetermineLockTimeError> for InterpreterCheckError {
178 fn from(e: DetermineLockTimeError) -> Self { Self::DetermineLockTime(e) }
179}
180
181impl From<InterpreterCheckInputError> for InterpreterCheckError {
182 fn from(e: InterpreterCheckInputError) -> Self { Self::InterpreterCheckInput(e) }
183}
184
185#[derive(Debug)]
187pub enum InterpreterCheckInputError {
188 Constructor {
190 input_index: usize,
192 error: interpreter::Error,
194 },
195 Satisfaction {
197 input_index: usize,
199 error: interpreter::Error,
201 },
202}
203
204impl fmt::Display for InterpreterCheckInputError {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 use InterpreterCheckInputError::*;
207
208 match *self {
209 Constructor { input_index, ref error } =>
210 write_err!(f, "Interpreter constructor failed for input {}", input_index; error),
211 Satisfaction { input_index, ref error } =>
212 write_err!(f, "Interpreter satisfaction failed for input {}", input_index; error),
213 }
214 }
215}
216
217#[cfg(feature = "std")]
218impl std::error::Error for InterpreterCheckInputError {
219 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
220 use InterpreterCheckInputError::*;
221
222 match *self {
223 Constructor { input_index: _, ref error } => Some(error),
224 Satisfaction { input_index: _, ref error } => Some(error),
225 }
226 }
227}