Skip to content

Commit 5c91ae1

Browse files
committed
Allow interpreter to access tx and prevouts
update extension interpreter API
1 parent 3a56d9f commit 5c91ae1

File tree

6 files changed

+52
-17
lines changed

6 files changed

+52
-17
lines changed

examples/verify_tx.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,15 @@ fn main() {
124124
)
125125
.unwrap();
126126

127-
let iter = interpreter.iter_custom(Box::new(|key_sig: &KeySigPair| {
128-
let (pk, ecdsa_sig) = key_sig.as_ecdsa().expect("Ecdsa Sig");
129-
ecdsa_sig.1 == elements::EcdsaSigHashType::All
130-
&& secp.verify_ecdsa(&message, &ecdsa_sig.0, &pk.inner).is_ok()
131-
}));
127+
let iter = interpreter.iter_custom(
128+
Box::new(|key_sig: &KeySigPair| {
129+
let (pk, ecdsa_sig) = key_sig.as_ecdsa().expect("Ecdsa Sig");
130+
ecdsa_sig.1 == elements::EcdsaSigHashType::All
131+
&& secp.verify_ecdsa(&message, &ecdsa_sig.0, &pk.inner).is_ok()
132+
}),
133+
None, // tx
134+
None, //prevouts
135+
);
132136
println!("\nExample three");
133137
for elem in iter {
134138
let error = elem.expect_err("evaluation error");

src/extensions/csfs.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use std::str::FromStr;
77
use bitcoin::hashes::hex::{FromHex, ToHex};
88
use bitcoin::XOnlyPublicKey;
99
use elements::hashes::hex;
10-
use elements::{self, opcodes, secp256k1_zkp};
10+
use elements::sighash::Prevouts;
11+
use elements::{self, opcodes, secp256k1_zkp, Transaction};
1112

1213
use super::{ArgFromStr, CovExtArgs, ExtParam, ParseableExt};
1314
use crate::miniscript::context::ScriptContextError;
@@ -274,6 +275,8 @@ impl ParseableExt for CheckSigFromStack<CovExtArgs> {
274275
fn evaluate<'intp, 'txin>(
275276
&'intp self,
276277
stack: &mut interpreter::Stack<'txin>,
278+
_tx: Option<&Transaction>,
279+
_prevouts: Option<&Prevouts<'txin>>,
277280
) -> Result<bool, interpreter::Error> {
278281
let sig = stack[0].try_push()?;
279282

src/extensions/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use std::{fmt, hash};
66

77
use elements::script::Builder;
8+
use elements::sighash::Prevouts;
9+
use elements::Transaction;
810

911
use crate::expression::Tree;
1012
use crate::interpreter::{self, Stack};
@@ -104,6 +106,8 @@ pub trait ParseableExt:
104106
fn evaluate<'intp, 'txin>(
105107
&'intp self,
106108
stack: &mut Stack<'txin>,
109+
tx: Option<&Transaction>,
110+
prevouts: Option<&Prevouts<'txin>>,
107111
) -> Result<bool, interpreter::Error>;
108112

109113
/// Encoding of the current fragment
@@ -194,6 +198,8 @@ impl ParseableExt for NoExt {
194198
fn evaluate<'intp, 'txin>(
195199
&'intp self,
196200
_stack: &mut Stack<'txin>,
201+
_tx: Option<&Transaction>,
202+
_prevouts: Option<&Prevouts<'txin>>,
197203
) -> Result<bool, interpreter::Error> {
198204
match *self {}
199205
}
@@ -351,8 +357,13 @@ impl ParseableExt for CovenantExt<CovExtArgs> {
351357
all_arms_fn!(self, ParseableExt, dissatisfy, sat,)
352358
}
353359

354-
fn evaluate(&self, stack: &mut Stack) -> Result<bool, interpreter::Error> {
355-
all_arms_fn!(self, ParseableExt, evaluate, stack,)
360+
fn evaluate<'intp, 'txin>(
361+
&self,
362+
stack: &mut Stack<'txin>,
363+
tx: Option<&Transaction>,
364+
prevouts: Option<&Prevouts<'txin>>,
365+
) -> Result<bool, interpreter::Error> {
366+
all_arms_fn!(self, ParseableExt, evaluate, stack, tx, prevouts,)
356367
}
357368

358369
fn push_to_builder(&self, builder: Builder) -> Builder {

src/extensions/outputs_pref.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use std::fmt;
77
use elements::encode::serialize;
88
use elements::hashes::hex::{FromHex, ToHex};
99
use elements::hashes::{sha256d, Hash};
10-
use elements::{self};
10+
use elements::sighash::Prevouts;
11+
use elements::{self, Transaction};
1112

1213
use super::{ExtParam, ParseableExt};
1314
use crate::descriptor::CovError;
@@ -245,6 +246,8 @@ impl ParseableExt for LegacyOutputsPref {
245246
fn evaluate<'intp, 'txin>(
246247
&'intp self,
247248
stack: &mut interpreter::Stack<'txin>,
249+
_tx: Option<&Transaction>,
250+
_prevouts: Option<&Prevouts<'txin>>,
248251
) -> Result<bool, interpreter::Error> {
249252
// Hash Outputs is at index 3
250253
let hash_outputs = stack[3];

src/extensions/tx_ver.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
use std::fmt;
66

77
use elements::encode::serialize;
8-
use elements::{self};
8+
use elements::sighash::Prevouts;
9+
use elements::{self, Transaction};
910

1011
use super::{ExtParam, ParseableExt};
1112
use crate::descriptor::CovError;
@@ -168,6 +169,8 @@ impl ParseableExt for LegacyVerEq {
168169
fn evaluate<'intp, 'txin>(
169170
&'intp self,
170171
stack: &mut interpreter::Stack<'txin>,
172+
_tx: Option<&Transaction>,
173+
_prevouts: Option<&Prevouts<'txin>>,
171174
) -> Result<bool, interpreter::Error> {
172175
// Version is at index 11
173176
let ver = stack[11];

src/interpreter/mod.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ use std::str::FromStr;
2424

2525
use bitcoin;
2626
use elements::hashes::{hash160, ripemd160, sha256, sha256d, Hash, HashEngine};
27-
use elements::{self, secp256k1_zkp, sighash, EcdsaSigHashType, SigHash};
27+
use elements::sighash::Prevouts;
28+
use elements::{self, secp256k1_zkp, sighash, EcdsaSigHashType, SigHash, Transaction};
2829

2930
use crate::extensions::{CovExtArgs, ParseableExt};
3031
use crate::miniscript::context::NoChecks;
@@ -233,6 +234,8 @@ where
233234
pub fn iter_custom<'iter>(
234235
&'iter self,
235236
verify_sig: Box<dyn FnMut(&KeySigPair) -> bool + 'iter>,
237+
tx: Option<&'txin Transaction>,
238+
prevouts: Option<&'iter Prevouts<'txin>>,
236239
) -> Iter<'txin, 'iter, Ext> {
237240
Iter {
238241
verify_sig,
@@ -265,6 +268,8 @@ where
265268
None
266269
},
267270
has_errored: false,
271+
tx: tx,
272+
prevouts: prevouts,
268273
}
269274
}
270275

@@ -380,14 +385,16 @@ where
380385
prevouts: &'iter sighash::Prevouts<'_>, // actually a 'prevouts, but 'prevouts: 'iter
381386
genesis_hash: elements::BlockHash, // required for sighash computation in BIP341
382387
) -> Iter<'txin, 'iter, Ext> {
383-
self.iter_custom(Box::new(move |sig| {
384-
self.verify_sig(secp, tx, input_idx, prevouts, genesis_hash, sig)
385-
}))
388+
self.iter_custom(
389+
Box::new(move |sig| self.verify_sig(secp, tx, input_idx, prevouts, genesis_hash, sig)),
390+
Some(tx),
391+
Some(prevouts),
392+
)
386393
}
387394

388395
/// Creates an iterator over the satisfied spending conditions without checking signatures
389396
pub fn iter_assume_sigs<'iter>(&'iter self) -> Iter<'txin, 'iter, Ext> {
390-
self.iter_custom(Box::new(|_| true))
397+
self.iter_custom(Box::new(|_| true), None, None)
391398
}
392399

393400
/// Outputs a "descriptor" string which reproduces the spent coins
@@ -619,6 +626,8 @@ where
619626
public_key: Option<&'intp BitcoinKey>,
620627
state: Vec<NodeEvaluationState<'intp, Ext>>,
621628
stack: Stack<'txin>,
629+
tx: Option<&'txin Transaction>,
630+
prevouts: Option<&'intp Prevouts<'txin>>,
622631
age: u32,
623632
lock_time: u32,
624633
cov: Option<&'intp BitcoinKey>,
@@ -746,7 +755,7 @@ where
746755
}
747756
}
748757
Terminal::Ext(ref ext) => {
749-
let res = ext.evaluate(&mut self.stack);
758+
let res = ext.evaluate(&mut self.stack, self.tx, self.prevouts);
750759
match res {
751760
Ok(true) => {
752761
return Some(Ok(SatisfiedConstraint::Ext {
@@ -1288,17 +1297,19 @@ mod tests {
12881297
) -> Iter<'elem, 'txin, NoExt> {
12891298
Iter {
12901299
verify_sig: verify_fn,
1291-
stack: stack,
12921300
public_key: None,
12931301
state: vec![NodeEvaluationState {
12941302
node: &ms,
12951303
n_evaluated: 0,
12961304
n_satisfied: 0,
12971305
}],
1306+
stack: stack,
12981307
age: 1002,
12991308
lock_time: 1002,
13001309
cov: None,
13011310
has_errored: false,
1311+
tx: None,
1312+
prevouts: None,
13021313
}
13031314
}
13041315

0 commit comments

Comments
 (0)