@@ -36,6 +36,9 @@ pub enum ExprInner {
36
36
/// A constant i64 value
37
37
/// Minimal push of this <i64>
38
38
Const ( i64 ) ,
39
+ /// Value under the current executing input
40
+ /// INSPECTCURRENTINPUTINDEX INPSECTINPUTVALUE <1> EQUALVERIFY
41
+ CurrInputIdx ,
39
42
/// Explicit amount at the given input index
40
43
/// i INPSECTINPUTVALUE <1> EQUALVERIFY
41
44
Input ( usize ) ,
@@ -127,6 +130,7 @@ impl Expr {
127
130
pub fn from_inner ( inner : ExprInner ) -> Self {
128
131
let ( script_size, depth) = match & inner {
129
132
ExprInner :: Const ( _c) => ( 8 + 1 , 0 ) ,
133
+ ExprInner :: CurrInputIdx => ( 4 , 0 ) , // INSPECTCURRENTINPUTINDEX INPSECTINPUTVALUE <1> EQUALVERIFY
130
134
ExprInner :: Input ( i) => (
131
135
script_num_size ( * i) + 3 , // i INPSECTINPUTVALUE <1> EQUALVERIFY
132
136
0 ,
@@ -194,11 +198,22 @@ impl Expr {
194
198
/// Evaluate this expression
195
199
fn eval (
196
200
& self ,
201
+ curr_ind : usize ,
197
202
tx : & elements:: Transaction ,
198
203
utxos : & [ elements:: TxOut ] ,
199
204
) -> Result < i64 , EvalError > {
200
205
match & self . inner {
201
206
ExprInner :: Const ( c) => Ok ( * c) ,
207
+ ExprInner :: CurrInputIdx => {
208
+ if curr_ind >= utxos. len ( ) {
209
+ return Err ( EvalError :: UtxoIndexOutOfBounds ( curr_ind, utxos. len ( ) ) ) ;
210
+ }
211
+ utxos[ curr_ind]
212
+ . value
213
+ . explicit ( )
214
+ . map ( |x| x as i64 ) // safe conversion bitcoin values from u64 to i64 because 21 mil
215
+ . ok_or ( EvalError :: NonExplicitInput ( curr_ind) )
216
+ }
202
217
ExprInner :: Input ( i) => {
203
218
if * i >= utxos. len ( ) {
204
219
return Err ( EvalError :: UtxoIndexOutOfBounds ( * i, utxos. len ( ) ) ) ;
@@ -242,51 +257,51 @@ impl Expr {
242
257
. ok_or ( EvalError :: NonExplicitInputReIssuance ( * i) )
243
258
}
244
259
ExprInner :: Add ( x, y) => {
245
- let x = x. eval ( tx, utxos) ?;
246
- let y = y. eval ( tx, utxos) ?;
260
+ let x = x. eval ( curr_ind , tx, utxos) ?;
261
+ let y = y. eval ( curr_ind , tx, utxos) ?;
247
262
x. checked_add ( y) . ok_or ( EvalError :: AddOverflow ( x, y) )
248
263
}
249
264
ExprInner :: Sub ( x, y) => {
250
- let x = x. eval ( tx, utxos) ?;
251
- let y = y. eval ( tx, utxos) ?;
265
+ let x = x. eval ( curr_ind , tx, utxos) ?;
266
+ let y = y. eval ( curr_ind , tx, utxos) ?;
252
267
x. checked_sub ( y) . ok_or ( EvalError :: SubOverflow ( x, y) )
253
268
}
254
269
ExprInner :: Mul ( x, y) => {
255
- let x = x. eval ( tx, utxos) ?;
256
- let y = y. eval ( tx, utxos) ?;
270
+ let x = x. eval ( curr_ind , tx, utxos) ?;
271
+ let y = y. eval ( curr_ind , tx, utxos) ?;
257
272
x. checked_mul ( y) . ok_or ( EvalError :: MulOverflow ( x, y) )
258
273
}
259
274
ExprInner :: Div ( x, y) => {
260
- let x = x. eval ( tx, utxos) ?;
261
- let y = y. eval ( tx, utxos) ?;
275
+ let x = x. eval ( curr_ind , tx, utxos) ?;
276
+ let y = y. eval ( curr_ind , tx, utxos) ?;
262
277
x. checked_div_euclid ( y) . ok_or ( EvalError :: DivOverflow ( x, y) )
263
278
}
264
279
ExprInner :: Mod ( x, y) => {
265
- let x = x. eval ( tx, utxos) ?;
266
- let y = y. eval ( tx, utxos) ?;
280
+ let x = x. eval ( curr_ind , tx, utxos) ?;
281
+ let y = y. eval ( curr_ind , tx, utxos) ?;
267
282
x. checked_rem_euclid ( y) . ok_or ( EvalError :: ModOverflow ( x, y) )
268
283
}
269
284
ExprInner :: BitAnd ( x, y) => {
270
- let x = x. eval ( tx, utxos) ?;
271
- let y = y. eval ( tx, utxos) ?;
285
+ let x = x. eval ( curr_ind , tx, utxos) ?;
286
+ let y = y. eval ( curr_ind , tx, utxos) ?;
272
287
Ok ( x & y)
273
288
}
274
289
ExprInner :: BitOr ( x, y) => {
275
- let x = x. eval ( tx, utxos) ?;
276
- let y = y. eval ( tx, utxos) ?;
290
+ let x = x. eval ( curr_ind , tx, utxos) ?;
291
+ let y = y. eval ( curr_ind , tx, utxos) ?;
277
292
Ok ( x | y)
278
293
}
279
294
ExprInner :: Xor ( x, y) => {
280
- let x = x. eval ( tx, utxos) ?;
281
- let y = y. eval ( tx, utxos) ?;
295
+ let x = x. eval ( curr_ind , tx, utxos) ?;
296
+ let y = y. eval ( curr_ind , tx, utxos) ?;
282
297
Ok ( x ^ y)
283
298
}
284
299
ExprInner :: Invert ( x) => {
285
- let x = x. eval ( tx, utxos) ?;
300
+ let x = x. eval ( curr_ind , tx, utxos) ?;
286
301
Ok ( !x)
287
302
}
288
303
ExprInner :: Negate ( x) => {
289
- let x = x. eval ( tx, utxos) ?;
304
+ let x = x. eval ( curr_ind , tx, utxos) ?;
290
305
x. checked_neg ( ) . ok_or ( EvalError :: NegOverflow ( x) )
291
306
}
292
307
}
@@ -296,6 +311,11 @@ impl Expr {
296
311
fn push_to_builder ( & self , builder : script:: Builder ) -> script:: Builder {
297
312
match & self . inner {
298
313
ExprInner :: Const ( c) => builder. push_slice ( & c. to_le_bytes ( ) ) ,
314
+ ExprInner :: CurrInputIdx => builder
315
+ . push_opcode ( OP_PUSHCURRENTINPUTINDEX )
316
+ . push_opcode ( OP_INSPECTINPUTVALUE )
317
+ . push_int ( 1 )
318
+ . push_opcode ( OP_EQUALVERIFY ) ,
299
319
ExprInner :: Input ( i) => builder
300
320
. push_int ( * i as i64 )
301
321
. push_opcode ( OP_INSPECTINPUTVALUE )
@@ -453,6 +473,12 @@ impl Expr {
453
473
let ( x, end_pos) = Self :: from_tokens ( tokens, end_pos) ?;
454
474
let expr = Expr :: from_inner ( ExprInner :: Mul ( Box :: new ( x) , Box :: new ( y) ) ) ;
455
475
Some ( ( expr, end_pos) )
476
+ } else if let Some ( & [ Tk :: CurrInp , Tk :: InpValue , Tk :: Num ( 1 ) , Tk :: Equal , Tk :: Verify ] ) =
477
+ tks. get ( e. checked_sub ( 5 ) ?..e)
478
+ {
479
+ let ( x, end_pos) = Self :: from_tokens ( tokens, e - 5 ) ?;
480
+ let expr = Expr :: from_inner ( ExprInner :: Negate ( Box :: new ( x) ) ) ;
481
+ Some ( ( expr, end_pos) )
456
482
} else if let Some ( & [ Tk :: Div64 , Tk :: Num ( 1 ) , Tk :: Equal , Tk :: Verify , Tk :: Nip ] ) =
457
483
tks. get ( e. checked_sub ( 5 ) ?..e)
458
484
{
@@ -540,15 +566,16 @@ impl Arith {
540
566
/// Evaluate this expression with context given transaction and spent utxos
541
567
pub fn eval (
542
568
& self ,
569
+ curr_ind : usize ,
543
570
tx : & elements:: Transaction ,
544
571
utxos : & [ elements:: TxOut ] ,
545
572
) -> Result < bool , EvalError > {
546
573
let res = match self {
547
- Arith :: Eq ( x, y) => x. eval ( tx, utxos) ? == y. eval ( tx, utxos) ?,
548
- Arith :: Le ( x, y) => x. eval ( tx, utxos) ? < y. eval ( tx, utxos) ?,
549
- Arith :: Leq ( x, y) => x. eval ( tx, utxos) ? <= y. eval ( tx, utxos) ?,
550
- Arith :: Ge ( x, y) => x. eval ( tx, utxos) ? > y. eval ( tx, utxos) ?,
551
- Arith :: Geq ( x, y) => x. eval ( tx, utxos) ? >= y. eval ( tx, utxos) ?,
574
+ Arith :: Eq ( x, y) => x. eval ( curr_ind , tx, utxos) ? == y. eval ( curr_ind , tx, utxos) ?,
575
+ Arith :: Le ( x, y) => x. eval ( curr_ind , tx, utxos) ? < y. eval ( curr_ind , tx, utxos) ?,
576
+ Arith :: Leq ( x, y) => x. eval ( curr_ind , tx, utxos) ? <= y. eval ( curr_ind , tx, utxos) ?,
577
+ Arith :: Ge ( x, y) => x. eval ( curr_ind , tx, utxos) ? > y. eval ( curr_ind , tx, utxos) ?,
578
+ Arith :: Geq ( x, y) => x. eval ( curr_ind , tx, utxos) ? >= y. eval ( curr_ind , tx, utxos) ?,
552
579
} ;
553
580
Ok ( res)
554
581
}
@@ -609,6 +636,7 @@ impl fmt::Display for Expr {
609
636
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
610
637
match & self . inner {
611
638
ExprInner :: Const ( c) => write ! ( f, "{}" , c) ,
639
+ ExprInner :: CurrInputIdx => write ! ( f, "curr_inp_v" ) ,
612
640
ExprInner :: Input ( i) => write ! ( f, "inp_v({})" , i) ,
613
641
ExprInner :: Output ( i) => write ! ( f, "out_v({})" , i) ,
614
642
ExprInner :: InputIssue ( i) => write ! ( f, "inp_issue_v({})" , i) ,
@@ -631,6 +659,7 @@ impl fmt::Debug for Expr {
631
659
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
632
660
match & self . inner {
633
661
ExprInner :: Const ( c) => write ! ( f, "{:?}" , c) ,
662
+ ExprInner :: CurrInputIdx => write ! ( f, "curr_inp_v" ) ,
634
663
ExprInner :: Input ( i) => write ! ( f, "inp_v({:?})" , i) ,
635
664
ExprInner :: Output ( i) => write ! ( f, "out_v({:?})" , i) ,
636
665
ExprInner :: InputIssue ( i) => write ! ( f, "inp_issue_v({:?})" , i) ,
@@ -692,6 +721,7 @@ impl FromTree for Expr {
692
721
}
693
722
match ( top. name , top. args . len ( ) ) {
694
723
( "inp_v" , 1 ) => term ( top, ExprInner :: Input ) ,
724
+ ( "curr_inp_v" , 0 ) => Ok ( Expr :: from_inner ( ExprInner :: CurrInputIdx ) ) ,
695
725
( "out_v" , 1 ) => term ( top, ExprInner :: Output ) ,
696
726
( "inp_issue_v" , 1 ) => term ( top, ExprInner :: InputIssue ) ,
697
727
( "inp_reissue_v" , 1 ) => term ( top, ExprInner :: InputReIssue ) ,
@@ -845,16 +875,20 @@ impl ParseableExt for Arith {
845
875
Pk : ToPublicKey ,
846
876
S : Satisfier < Pk > ,
847
877
{
848
- let ( tx, utxos) = match ( sat. lookup_tx ( ) , sat. lookup_spent_utxos ( ) ) {
849
- ( Some ( tx) , Some ( utxos) ) => ( tx, utxos) ,
878
+ let ( tx, utxos, curr_idx) = match (
879
+ sat. lookup_tx ( ) ,
880
+ sat. lookup_spent_utxos ( ) ,
881
+ sat. lookup_curr_inp ( ) ,
882
+ ) {
883
+ ( Some ( tx) , Some ( utxos) , Some ( curr_idx) ) => ( tx, utxos, curr_idx) ,
850
884
_ => {
851
885
return Satisfaction {
852
886
stack : Witness :: Impossible ,
853
887
has_sig : false ,
854
888
}
855
889
}
856
890
} ;
857
- let wit = match self . eval ( tx, utxos) {
891
+ let wit = match self . eval ( curr_idx , tx, utxos) {
858
892
Ok ( false ) => Witness :: Unavailable ,
859
893
Ok ( true ) => Witness :: empty ( ) ,
860
894
Err ( _e) => Witness :: Impossible ,
@@ -870,16 +904,20 @@ impl ParseableExt for Arith {
870
904
Pk : ToPublicKey ,
871
905
S : Satisfier < Pk > ,
872
906
{
873
- let ( tx, utxos) = match ( sat. lookup_tx ( ) , sat. lookup_spent_utxos ( ) ) {
874
- ( Some ( tx) , Some ( utxos) ) => ( tx, utxos) ,
907
+ let ( tx, utxos, curr_idx) = match (
908
+ sat. lookup_tx ( ) ,
909
+ sat. lookup_spent_utxos ( ) ,
910
+ sat. lookup_curr_inp ( ) ,
911
+ ) {
912
+ ( Some ( tx) , Some ( utxos) , Some ( curr_idx) ) => ( tx, utxos, curr_idx) ,
875
913
_ => {
876
914
return Satisfaction {
877
915
stack : Witness :: Impossible ,
878
916
has_sig : false ,
879
917
}
880
918
}
881
919
} ;
882
- let wit = match self . eval ( tx, utxos) {
920
+ let wit = match self . eval ( curr_idx , tx, utxos) {
883
921
Ok ( false ) => Witness :: empty ( ) ,
884
922
Ok ( true ) => Witness :: Unavailable ,
885
923
Err ( _e) => Witness :: Impossible ,
@@ -914,7 +952,7 @@ impl ParseableExt for Arith {
914
952
. as_ref ( )
915
953
. ok_or ( interpreter:: Error :: ArithError ( EvalError :: TxEnvNotPresent ) ) ?;
916
954
917
- match self . eval ( txenv. tx ( ) , txenv. spent_utxos ( ) ) {
955
+ match self . eval ( txenv. idx ( ) , txenv . tx ( ) , txenv. spent_utxos ( ) ) {
918
956
Ok ( true ) => {
919
957
stack. push ( interpreter:: Element :: Satisfied ) ;
920
958
Ok ( true )
0 commit comments