Skip to content

Commit 0aaa34f

Browse files
committed
Incomplete: Draft commit
temp More fixes
1 parent 5356476 commit 0aaa34f

File tree

16 files changed

+574
-292
lines changed

16 files changed

+574
-292
lines changed

examples/verify_tx.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ fn main() {
103103
0,
104104
0,
105105
);
106-
107106
println!("\nExample one");
108107
for elem in iter {
109108
match elem.expect("no evaluation error") {
@@ -129,7 +128,6 @@ fn main() {
129128
0,
130129
0,
131130
);
132-
133131
println!("\nExample two");
134132
for elem in iter {
135133
match elem.expect("no evaluation error") {
@@ -154,7 +152,6 @@ fn main() {
154152
0,
155153
0,
156154
);
157-
158155
println!("\nExample three");
159156
for elem in iter {
160157
let error = elem.expect_err("evaluation error");

src/descriptor/create_descriptor.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use bitcoin::blockdata::script::Instruction;
99
use descriptor::satisfied_constraints::Error as IntError;
1010
use descriptor::satisfied_constraints::{Stack, StackElement};
1111
use descriptor::Descriptor;
12-
use miniscript::Miniscript;
12+
use miniscript::{Legacy, Miniscript, Segwitv0};
1313
use Error;
1414
use ToPublicKey;
1515

@@ -112,7 +112,7 @@ fn verify_wsh<'txin>(
112112
script_pubkey: &bitcoin::Script,
113113
script_sig: &bitcoin::Script,
114114
witness: &'txin [Vec<u8>],
115-
) -> Result<(Miniscript<bitcoin::PublicKey>, Stack<'txin>), Error> {
115+
) -> Result<(Miniscript<bitcoin::PublicKey, Segwitv0>, Stack<'txin>), Error> {
116116
if !script_sig.is_empty() {
117117
return Err(Error::NonEmptyScriptSig);
118118
}
@@ -121,7 +121,7 @@ fn verify_wsh<'txin>(
121121
if witness_script.to_v0_p2wsh() != *script_pubkey {
122122
return Err(Error::IncorrectScriptHash);
123123
}
124-
let ms = Miniscript::parse(&witness_script)?;
124+
let ms = Miniscript::<bitcoin::PublicKey, Segwitv0>::parse(&witness_script)?;
125125
//only iter till len -1 to not include the witness script
126126
let stack: Vec<StackElement> = witness
127127
.iter()
@@ -218,7 +218,7 @@ pub fn from_txin_with_witness_stack<'txin>(
218218
if !witness.is_empty() {
219219
return Err(Error::NonEmptyWitness);
220220
}
221-
let ms = Miniscript::parse(&redeem_script)?;
221+
let ms = Miniscript::<bitcoin::PublicKey, Legacy>::parse(&redeem_script)?;
222222
Ok((Descriptor::Sh(ms), stack))
223223
}
224224
} else {
@@ -230,7 +230,7 @@ pub fn from_txin_with_witness_stack<'txin>(
230230
if !witness.is_empty() {
231231
return Err(Error::NonEmptyWitness);
232232
}
233-
let ms = Miniscript::parse(script_pubkey)?;
233+
let ms = Miniscript::<bitcoin::PublicKey, Legacy>::parse(script_pubkey)?;
234234
Ok((Descriptor::Bare(ms), Stack(stack?)))
235235
}
236236
}

src/descriptor/mod.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use std::fmt;
3131
use std::str::{self, FromStr};
3232

3333
use expression;
34-
use miniscript::Miniscript;
34+
use miniscript::{Legacy, Miniscript, Segwitv0};
3535
use Error;
3636
use MiniscriptKey;
3737
use Satisfier;
@@ -50,7 +50,7 @@ pub use self::satisfied_constraints::Stack;
5050
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
5151
pub enum Descriptor<Pk: MiniscriptKey> {
5252
/// A raw scriptpubkey (including pay-to-pubkey)
53-
Bare(Miniscript<Pk>),
53+
Bare(Miniscript<Pk, Legacy>),
5454
/// Pay-to-Pubkey
5555
Pk(Pk),
5656
/// Pay-to-PubKey-Hash
@@ -60,11 +60,11 @@ pub enum Descriptor<Pk: MiniscriptKey> {
6060
/// Pay-to-Witness-PubKey-Hash inside P2SH
6161
ShWpkh(Pk),
6262
/// Pay-to-ScriptHash
63-
Sh(Miniscript<Pk>),
63+
Sh(Miniscript<Pk, Legacy>),
6464
/// Pay-to-Witness-ScriptHash
65-
Wsh(Miniscript<Pk>),
65+
Wsh(Miniscript<Pk, Segwitv0>),
6666
/// P2SH-P2WSH
67-
ShWsh(Miniscript<Pk>),
67+
ShWsh(Miniscript<Pk, Segwitv0>),
6868
}
6969

7070
impl<Pk: MiniscriptKey> Descriptor<Pk> {
@@ -200,7 +200,8 @@ impl<Pk: MiniscriptKey + ToPublicKey> Descriptor<Pk> {
200200
let addr = bitcoin::Address::p2wpkh(&pk.to_public_key(), bitcoin::Network::Bitcoin);
201201
addr.script_pubkey()
202202
}
203-
Descriptor::Sh(ref d) | Descriptor::Wsh(ref d) | Descriptor::ShWsh(ref d) => d.encode(),
203+
Descriptor::Sh(ref d) => d.encode(),
204+
Descriptor::Wsh(ref d) | Descriptor::ShWsh(ref d) => d.encode(),
204205
}
205206
}
206207

@@ -395,25 +396,29 @@ where
395396
expression::terminal(&top.args[0], |pk| Pk::from_str(pk).map(Descriptor::Pkh))
396397
}
397398
("wpkh", 1) => {
398-
expression::terminal(&top.args[0], |pk| Pk::from_str(pk).map(Descriptor::Wpkh))
399+
let wpkh = expression::terminal(&top.args[0], |pk| Pk::from_str(pk))?;
400+
if wpkh.is_uncompressed() {
401+
Err(Error::BadDescriptor)
402+
} else {
403+
Ok(Descriptor::Wpkh(wpkh))
404+
}
399405
}
400406
("sh", 1) => {
401407
let newtop = &top.args[0];
402408
match (newtop.name, newtop.args.len()) {
403-
("wsh", 1) => {
404-
let sub = Miniscript::from_tree(&newtop.args[0])?;
405-
Ok(Descriptor::ShWsh(sub))
406-
}
407-
("wpkh", 1) => expression::terminal(&newtop.args[0], |pk| {
408-
Pk::from_str(pk).map(Descriptor::ShWpkh)
409-
}),
410-
_ => {
411-
let sub = Miniscript::from_tree(&top.args[0])?;
412-
Ok(Descriptor::Sh(sub))
409+
("wsh", 1) => Miniscript::from_tree(&newtop.args[0]).map(Descriptor::ShWsh),
410+
("wpkh", 1) => {
411+
let wpkh = expression::terminal(&newtop.args[0], |pk| Pk::from_str(pk))?;
412+
if wpkh.is_uncompressed() {
413+
Err(Error::BadDescriptor)
414+
} else {
415+
Ok(Descriptor::ShWpkh(wpkh))
416+
}
413417
}
418+
_ => Miniscript::from_tree(&top.args[0]).map(Descriptor::Sh),
414419
}
415420
}
416-
("wsh", 1) => expression::unary(top, Descriptor::Wsh),
421+
("wsh", 1) => Miniscript::from_tree(&top.args[0]).map(Descriptor::Wsh),
417422
_ => {
418423
let sub = expression::FromTree::from_tree(&top)?;
419424
Ok(Descriptor::Bare(sub))
@@ -852,6 +857,8 @@ mod tests {
852857
);
853858
assert_eq!(sh.unsigned_script_sig(), bitcoin::Script::new());
854859

860+
let ms = ms_str!("c:pk_k({})", pk);
861+
855862
let wsh = Descriptor::Wsh(ms.clone());
856863
wsh.satisfy(&mut txin, &satisfier).expect("satisfaction");
857864
assert_eq!(

src/descriptor/satisfied_constraints.rs

Lines changed: 82 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
1616
use bitcoin::{self, secp256k1};
1717
use fmt;
18+
use miniscript::{Any, Legacy, ScriptContext, Segwitv0};
1819
use Descriptor;
1920
use Terminal;
2021
use {error, Miniscript};
@@ -200,9 +201,9 @@ pub enum SatisfiedConstraint<'desc, 'stack> {
200201
///the top of the stack, we need to decide whether to execute right child or not.
201202
///This is also useful for wrappers and thresholds which push a value on the stack
202203
///depending on evaluation of the children.
203-
struct NodeEvaluationState<'desc> {
204+
struct NodeEvaluationState<'desc, Ctx: ScriptContext> {
204205
///The node which is being evaluated
205-
node: &'desc Miniscript<bitcoin::PublicKey>,
206+
node: &'desc Miniscript<bitcoin::PublicKey, Ctx>,
206207
///number of children evaluated
207208
n_evaluated: usize,
208209
///number of children satisfied
@@ -217,24 +218,35 @@ struct NodeEvaluationState<'desc> {
217218
/// In case the script would abort on the given witness stack OR if the entire
218219
/// script is dissatisfied, this would return keep on returning values
219220
///_until_Error.
220-
pub struct SatisfiedConstraints<'desc, 'stack, F: FnMut(&bitcoin::PublicKey, BitcoinSig) -> bool> {
221+
pub struct SatisfiedConstraintsIter<
222+
'desc,
223+
'stack,
224+
Ctx: ScriptContext,
225+
F: FnMut(&bitcoin::PublicKey, BitcoinSig) -> bool,
226+
> {
221227
verify_sig: F,
222228
public_key: Option<&'desc bitcoin::PublicKey>,
223-
state: Vec<NodeEvaluationState<'desc>>,
229+
state: Vec<NodeEvaluationState<'desc, Ctx>>,
224230
stack: Stack<'stack>,
225231
age: u32,
226232
height: u32,
227233
has_errored: bool,
228234
}
229235

236+
pub enum SatisfiedConstraints<'desc, 'stack, F: FnMut(&bitcoin::PublicKey, BitcoinSig) -> bool> {
237+
Legacy(SatisfiedConstraintsIter<'desc, 'stack, Legacy, F>),
238+
Segwitv0(SatisfiedConstraintsIter<'desc, 'stack, Segwitv0, F>),
239+
Any(SatisfiedConstraintsIter<'desc, 'stack, Any, F>),
240+
}
230241
/// Stack Data structure representing the stack input to Miniscript. This Stack
231242
/// is created from the combination of ScriptSig and Witness stack.
232243
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
233244
pub struct Stack<'stack>(pub Vec<StackElement<'stack>>);
234245

235-
///Iterator for SatisfiedConstraints
236-
impl<'desc, 'stack, F> Iterator for SatisfiedConstraints<'desc, 'stack, F>
246+
///Iterator for SatisfiedConstraintsIter
247+
impl<'desc, 'stack, Ctx, F> Iterator for SatisfiedConstraintsIter<'desc, 'stack, Ctx, F>
237248
where
249+
Ctx: ScriptContext,
238250
F: FnMut(&bitcoin::PublicKey, BitcoinSig) -> bool,
239251
{
240252
type Item = Result<SatisfiedConstraint<'desc, 'stack>, Error>;
@@ -257,36 +269,21 @@ impl<'desc, 'stack, F> SatisfiedConstraints<'desc, 'stack, F>
257269
where
258270
F: FnMut(&bitcoin::PublicKey, BitcoinSig) -> bool,
259271
{
260-
/// Helper function to push a NodeEvaluationState on state stack
261-
fn push_evaluation_state(
262-
&mut self,
263-
node: &'desc Miniscript<bitcoin::PublicKey>,
264-
n_evaluated: usize,
265-
n_satisfied: usize,
266-
) -> () {
267-
self.state.push(NodeEvaluationState {
268-
node,
269-
n_evaluated,
270-
n_satisfied,
271-
})
272-
}
273-
274-
/// Creates a new iterator over all constraints satisfied for a given
272+
// Creates a new iterator over all constraints satisfied for a given
275273
/// descriptor by a given witness stack. Because this iterator is lazy,
276274
/// it may return satisfied constraints even if these turn out to be
277275
/// irrelevant to the final (dis)satisfaction of the descriptor.
276+
/// Because the iterator is dependent evaluating the miniscript, it is
277+
/// dependent on scriptContext
278278
pub fn from_descriptor(
279279
des: &'desc Descriptor<bitcoin::PublicKey>,
280280
stack: Stack<'stack>,
281281
verify_sig: F,
282282
age: u32,
283283
height: u32,
284-
) -> SatisfiedConstraints<'desc, 'stack, F> {
284+
) -> SatisfiedConstraintsIter<'desc, 'stack, Any, F> {
285285
match des {
286-
&Descriptor::Pk(ref pk)
287-
| &Descriptor::Pkh(ref pk)
288-
| &Descriptor::ShWpkh(ref pk)
289-
| &Descriptor::Wpkh(ref pk) => SatisfiedConstraints {
286+
&Descriptor::Pk(ref pk) | &Descriptor::Pkh(ref pk) => SatisfiedConstraintsIter {
290287
verify_sig: verify_sig,
291288
public_key: Some(pk),
292289
state: vec![],
@@ -295,24 +292,67 @@ where
295292
height,
296293
has_errored: false,
297294
},
298-
&Descriptor::Sh(ref miniscript)
299-
| &Descriptor::Bare(ref miniscript)
300-
| &Descriptor::ShWsh(ref miniscript)
301-
| &Descriptor::Wsh(ref miniscript) => SatisfiedConstraints {
295+
&Descriptor::ShWpkh(ref pk) | &Descriptor::Wpkh(ref pk) => SatisfiedConstraintsIter {
302296
verify_sig: verify_sig,
303-
public_key: None,
304-
state: vec![NodeEvaluationState {
305-
node: miniscript,
306-
n_evaluated: 0,
307-
n_satisfied: 0,
308-
}],
297+
public_key: Some(pk),
298+
state: vec![],
309299
stack: stack,
310300
age,
311301
height,
312302
has_errored: false,
313303
},
304+
&Descriptor::Wsh(ref miniscript) | &Descriptor::ShWsh(ref miniscript) => {
305+
SatisfiedConstraintsIter {
306+
verify_sig: verify_sig,
307+
public_key: None,
308+
state: vec![NodeEvaluationState {
309+
node: Any::from_segwitv0(miniscript),
310+
n_evaluated: 0,
311+
n_satisfied: 0,
312+
}],
313+
stack: stack,
314+
age,
315+
height,
316+
has_errored: false,
317+
}
318+
}
319+
&Descriptor::Sh(ref miniscript) | &Descriptor::Bare(ref miniscript) => {
320+
SatisfiedConstraintsIter {
321+
verify_sig: verify_sig,
322+
public_key: None,
323+
state: vec![NodeEvaluationState {
324+
node: Any::from_legacy(miniscript),
325+
n_evaluated: 0,
326+
n_satisfied: 0,
327+
}],
328+
stack: stack,
329+
age,
330+
height,
331+
has_errored: false,
332+
}
333+
}
314334
}
315335
}
336+
}
337+
338+
impl<'desc, 'stack, Ctx, F> SatisfiedConstraintsIter<'desc, 'stack, Ctx, F>
339+
where
340+
Ctx: ScriptContext,
341+
F: FnMut(&bitcoin::PublicKey, BitcoinSig) -> bool,
342+
{
343+
/// Helper function to push a NodeEvaluationState on state stack
344+
fn push_evaluation_state(
345+
&mut self,
346+
node: &'desc Miniscript<bitcoin::PublicKey, Ctx>,
347+
n_evaluated: usize,
348+
n_satisfied: usize,
349+
) -> () {
350+
self.state.push(NodeEvaluationState {
351+
node,
352+
n_evaluated,
353+
n_satisfied,
354+
})
355+
}
316356

317357
/// Helper function to step the iterator
318358
fn iter_next(&mut self) -> Option<Result<SatisfiedConstraint<'desc, 'stack>, Error>> {
@@ -1019,9 +1059,10 @@ mod tests {
10191059
use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
10201060
use bitcoin::secp256k1::{self, Secp256k1, VerifyOnly};
10211061
use descriptor::satisfied_constraints::{
1022-
Error, HashLockType, NodeEvaluationState, SatisfiedConstraint, SatisfiedConstraints, Stack,
1023-
StackElement,
1062+
Error, HashLockType, NodeEvaluationState, SatisfiedConstraint, SatisfiedConstraintsIter,
1063+
Stack, StackElement,
10241064
};
1065+
use miniscript::Legacy;
10251066
use std::str::FromStr;
10261067
use BitcoinSig;
10271068
use Miniscript;
@@ -1074,12 +1115,12 @@ mod tests {
10741115
fn from_stack<'stack, 'elem, F>(
10751116
verify_fn: F,
10761117
stack: Stack<'stack>,
1077-
ms: &'elem Miniscript<bitcoin::PublicKey>,
1078-
) -> SatisfiedConstraints<'elem, 'stack, F>
1118+
ms: &'elem Miniscript<bitcoin::PublicKey, Legacy>,
1119+
) -> SatisfiedConstraintsIter<'elem, 'stack, Legacy, F>
10791120
where
10801121
F: FnMut(&bitcoin::PublicKey, BitcoinSig) -> bool,
10811122
{
1082-
SatisfiedConstraints {
1123+
SatisfiedConstraintsIter {
10831124
verify_sig: verify_fn,
10841125
stack: stack,
10851126
public_key: None,

0 commit comments

Comments
 (0)