kaspa_txscript/opcodes/
mod.rs

1#[macro_use]
2mod macros;
3
4use crate::data_stack::{DataStack, OpcodeData};
5use crate::{
6    ScriptSource, TxScriptEngine, TxScriptError, LOCK_TIME_THRESHOLD, MAX_TX_IN_SEQUENCE_NUM, NO_COST_OPCODE,
7    SEQUENCE_LOCK_TIME_DISABLED, SEQUENCE_LOCK_TIME_MASK,
8};
9use blake2b_simd::Params;
10use core::cmp::{max, min};
11use kaspa_consensus_core::hashing::sighash_type::SigHashType;
12use kaspa_consensus_core::tx::VerifiableTransaction;
13use sha2::{Digest, Sha256};
14use std::fmt::{Debug, Formatter};
15
16/// First value in the range formed by the "small integer" Op# opcodes
17pub const OP_SMALL_INT_MIN_VAL: u8 = 1;
18/// Last value in the range formed by the "small integer" Op# opcodes
19pub const OP_SMALL_INT_MAX_VAL: u8 = 16;
20/// First value in the range formed by OpData# opcodes (where opcode == value)
21pub const OP_DATA_MIN_VAL: u8 = self::codes::OpData1;
22/// Last value in the range formed by OpData# opcodes (where opcode == value)
23pub const OP_DATA_MAX_VAL: u8 = self::codes::OpData75;
24/// Minus 1 value
25pub const OP_1_NEGATE_VAL: u8 = 0x81;
26
27#[derive(Debug, PartialEq, Eq)]
28pub(crate) enum OpCond {
29    False,
30    True,
31    Skip,
32}
33
34impl OpCond {
35    pub fn negate(&self) -> OpCond {
36        match self {
37            OpCond::True => OpCond::False,
38            OpCond::False => OpCond::True,
39            OpCond::Skip => OpCond::Skip,
40        }
41    }
42}
43
44type OpCodeResult = Result<(), TxScriptError>;
45
46pub(crate) struct OpCode<const CODE: u8> {
47    data: Vec<u8>,
48}
49
50impl<const CODE: u8> Debug for OpCode<CODE> {
51    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
52        write!(f, "Opcode<{:#2x}>{{ data:{:?} }}", CODE, self.data)
53    }
54}
55
56pub trait OpCodeMetadata: Debug {
57    // Opcode number
58    fn value(&self) -> u8;
59    // length of data
60    fn len(&self) -> usize;
61    // Conditional should be executed also is not in branch
62    fn is_conditional(&self) -> bool;
63    // For push data- check if we can use shorter encoding
64    fn check_minimal_data_push(&self) -> Result<(), TxScriptError>;
65
66    fn is_disabled(&self) -> bool;
67    fn always_illegal(&self) -> bool;
68    fn is_push_opcode(&self) -> bool;
69    fn get_data(&self) -> &[u8];
70
71    fn is_empty(&self) -> bool {
72        self.len() == 0
73    }
74}
75
76pub trait OpCodeExecution<T: VerifiableTransaction> {
77    fn empty() -> Result<Box<dyn OpCodeImplementation<T>>, TxScriptError>
78    where
79        Self: Sized;
80    #[allow(clippy::new_ret_no_self)]
81    fn new(data: Vec<u8>) -> Result<Box<dyn OpCodeImplementation<T>>, TxScriptError>
82    where
83        Self: Sized;
84
85    fn execute(&self, vm: &mut TxScriptEngine<T>) -> OpCodeResult;
86}
87
88pub trait OpcodeSerialization {
89    fn serialize(&self) -> Vec<u8>;
90    fn deserialize<'i, I: Iterator<Item = &'i u8>, T: VerifiableTransaction>(
91        it: &mut I,
92    ) -> Result<Box<dyn OpCodeImplementation<T>>, TxScriptError>
93    where
94        Self: Sized;
95}
96
97pub trait OpCodeImplementation<T: VerifiableTransaction>: OpCodeExecution<T> + OpCodeMetadata + OpcodeSerialization {}
98
99impl<const CODE: u8> OpCodeMetadata for OpCode<CODE> {
100    fn value(&self) -> u8 {
101        CODE
102    }
103
104    fn is_disabled(&self) -> bool {
105        matches!(
106            CODE,
107            codes::OpCat
108                | codes::OpSubStr
109                | codes::OpLeft
110                | codes::OpRight
111                | codes::OpInvert
112                | codes::OpAnd
113                | codes::OpOr
114                | codes::OpXor
115                | codes::Op2Mul
116                | codes::Op2Div
117                | codes::OpMul
118                | codes::OpDiv
119                | codes::OpMod
120                | codes::OpLShift
121                | codes::OpRShift
122        )
123    }
124
125    fn always_illegal(&self) -> bool {
126        matches!(CODE, codes::OpVerIf | codes::OpVerNotIf)
127    }
128
129    fn is_push_opcode(&self) -> bool {
130        CODE <= NO_COST_OPCODE
131    }
132
133    fn len(&self) -> usize {
134        self.data.len()
135    }
136
137    // TODO: add it to opcode specification
138    fn is_conditional(&self) -> bool {
139        self.value() >= 0x63 && self.value() <= 0x68
140    }
141
142    fn check_minimal_data_push(&self) -> Result<(), TxScriptError> {
143        let data_len = self.len();
144        let opcode = self.value();
145
146        if data_len == 0 {
147            if opcode != codes::OpFalse {
148                return Err(TxScriptError::NotMinimalData(format!(
149                    "zero length data push is encoded with opcode {self:?} instead of OpFalse"
150                )));
151            }
152        } else if data_len == 1 && OP_SMALL_INT_MIN_VAL <= self.data[0] && self.data[0] <= OP_SMALL_INT_MAX_VAL {
153            if opcode != codes::OpTrue + self.data[0] - 1 {
154                return Err(TxScriptError::NotMinimalData(format!(
155                    "zero length data push is encoded with opcode {:?} instead of Op_{}",
156                    self, self.data[0]
157                )));
158            }
159        } else if data_len == 1 && self.data[0] == OP_1_NEGATE_VAL {
160            if opcode != codes::Op1Negate {
161                return Err(TxScriptError::NotMinimalData(format!(
162                    "data push of the value -1 encoded \
163                                    with opcode {self:?} instead of OP_1NEGATE"
164                )));
165            }
166        } else if data_len <= OP_DATA_MAX_VAL as usize {
167            if opcode as usize != data_len {
168                return Err(TxScriptError::NotMinimalData(format!(
169                    "data push of {data_len} bytes encoded \
170                                    with opcode {self:?} instead of OP_DATA_{data_len}"
171                )));
172            }
173        } else if data_len <= u8::MAX as usize {
174            if opcode != codes::OpPushData1 {
175                return Err(TxScriptError::NotMinimalData(format!(
176                    "data push of {data_len} bytes encoded \
177                                    with opcode {self:?} instead of OP_PUSHDATA1"
178                )));
179            }
180        } else if data_len < u16::MAX as usize && opcode != codes::OpPushData2 {
181            return Err(TxScriptError::NotMinimalData(format!(
182                "data push of {data_len} bytes encoded \
183                                with opcode {self:?} instead of OP_PUSHDATA2"
184            )));
185        }
186        Ok(())
187    }
188
189    fn get_data(&self) -> &[u8] {
190        &self.data
191    }
192}
193
194// Helpers for some opcodes with shared data
195#[inline]
196fn push_data<T: VerifiableTransaction>(data: Vec<u8>, vm: &mut TxScriptEngine<T>) -> OpCodeResult {
197    vm.dstack.push(data);
198    Ok(())
199}
200
201#[inline]
202fn push_number<T: VerifiableTransaction>(number: i64, vm: &mut TxScriptEngine<T>) -> OpCodeResult {
203    vm.dstack.push_item(number);
204    Ok(())
205}
206
207/*
208The following is the implementation and metadata of all opcodes. Each opcode has unique
209number (and template system makes it impossible to use two opcodes), length specification,
210and execution code.
211
212The syntax is as follows:
213```
214opcode OpCodeName<id, length>(self, vm) {
215    code;
216    output
217}
218// OR
219opcode OpCodeName<id, length>(self, vm) statement
220
221// in case of an opcode alias
222opcode |OpCodeAlias| OpCodeName<id, length>(self, vm) {
223    code;
224    output
225}
226// OR
227opcode |OpCodeAlias| OpCodeName<id, length>(self, vm) statement
228```
229
230Length specification is either a number (for fixed length) or a unsigned integer type
231(for var length).
232The execution code is implementing OpCodeImplementation. You can access the engine using the `vm`
233variable.
234
235Implementation details in `opcodes/macros.rs`.
236*/
237opcode_list! {
238
239    // Data push opcodes.
240    opcode |Op0| OpFalse<0x00, 1>(self , vm) {
241        vm.dstack.push(vec![]);
242        Ok(())
243    }
244
245    opcode OpData1<0x01, 2>(self, vm) push_data(self.data.clone(), vm)
246    opcode OpData2<0x02, 3>(self, vm) push_data(self.data.clone(), vm)
247    opcode OpData3<0x03, 4>(self, vm) push_data(self.data.clone(), vm)
248    opcode OpData4<0x04, 5>(self, vm) push_data(self.data.clone(), vm)
249    opcode OpData5<0x05, 6>(self, vm) push_data(self.data.clone(), vm)
250    opcode OpData6<0x06, 7>(self, vm) push_data(self.data.clone(), vm)
251    opcode OpData7<0x07, 8>(self, vm) push_data(self.data.clone(), vm)
252    opcode OpData8<0x08, 9>(self, vm) push_data(self.data.clone(), vm)
253    opcode OpData9<0x09, 10>(self, vm) push_data(self.data.clone(), vm)
254    opcode OpData10<0x0a, 11>(self, vm) push_data(self.data.clone(), vm)
255    opcode OpData11<0x0b, 12>(self, vm) push_data(self.data.clone(), vm)
256    opcode OpData12<0x0c, 13>(self, vm) push_data(self.data.clone(), vm)
257    opcode OpData13<0x0d, 14>(self, vm) push_data(self.data.clone(), vm)
258    opcode OpData14<0x0e, 15>(self, vm) push_data(self.data.clone(), vm)
259    opcode OpData15<0x0f, 16>(self, vm) push_data(self.data.clone(), vm)
260    opcode OpData16<0x10, 17>(self, vm) push_data(self.data.clone(), vm)
261    opcode OpData17<0x11, 18>(self, vm) push_data(self.data.clone(), vm)
262    opcode OpData18<0x12, 19>(self, vm) push_data(self.data.clone(), vm)
263    opcode OpData19<0x13, 20>(self, vm) push_data(self.data.clone(), vm)
264    opcode OpData20<0x14, 21>(self, vm) push_data(self.data.clone(), vm)
265    opcode OpData21<0x15, 22>(self, vm) push_data(self.data.clone(), vm)
266    opcode OpData22<0x16, 23>(self, vm) push_data(self.data.clone(), vm)
267    opcode OpData23<0x17, 24>(self, vm) push_data(self.data.clone(), vm)
268    opcode OpData24<0x18, 25>(self, vm) push_data(self.data.clone(), vm)
269    opcode OpData25<0x19, 26>(self, vm) push_data(self.data.clone(), vm)
270    opcode OpData26<0x1a, 27>(self, vm) push_data(self.data.clone(), vm)
271    opcode OpData27<0x1b, 28>(self, vm) push_data(self.data.clone(), vm)
272    opcode OpData28<0x1c, 29>(self, vm) push_data(self.data.clone(), vm)
273    opcode OpData29<0x1d, 30>(self, vm) push_data(self.data.clone(), vm)
274    opcode OpData30<0x1e, 31>(self, vm) push_data(self.data.clone(), vm)
275    opcode OpData31<0x1f, 32>(self, vm) push_data(self.data.clone(), vm)
276    opcode OpData32<0x20, 33>(self, vm) push_data(self.data.clone(), vm)
277    opcode OpData33<0x21, 34>(self, vm) push_data(self.data.clone(), vm)
278    opcode OpData34<0x22, 35>(self, vm) push_data(self.data.clone(), vm)
279    opcode OpData35<0x23, 36>(self, vm) push_data(self.data.clone(), vm)
280    opcode OpData36<0x24, 37>(self, vm) push_data(self.data.clone(), vm)
281    opcode OpData37<0x25, 38>(self, vm) push_data(self.data.clone(), vm)
282    opcode OpData38<0x26, 39>(self, vm) push_data(self.data.clone(), vm)
283    opcode OpData39<0x27, 40>(self, vm) push_data(self.data.clone(), vm)
284    opcode OpData40<0x28, 41>(self, vm) push_data(self.data.clone(), vm)
285    opcode OpData41<0x29, 42>(self, vm) push_data(self.data.clone(), vm)
286    opcode OpData42<0x2a, 43>(self, vm) push_data(self.data.clone(), vm)
287    opcode OpData43<0x2b, 44>(self, vm) push_data(self.data.clone(), vm)
288    opcode OpData44<0x2c, 45>(self, vm) push_data(self.data.clone(), vm)
289    opcode OpData45<0x2d, 46>(self, vm) push_data(self.data.clone(), vm)
290    opcode OpData46<0x2e, 47>(self, vm) push_data(self.data.clone(), vm)
291    opcode OpData47<0x2f, 48>(self, vm) push_data(self.data.clone(), vm)
292    opcode OpData48<0x30, 49>(self, vm) push_data(self.data.clone(), vm)
293    opcode OpData49<0x31, 50>(self, vm) push_data(self.data.clone(), vm)
294    opcode OpData50<0x32, 51>(self, vm) push_data(self.data.clone(), vm)
295    opcode OpData51<0x33, 52>(self, vm) push_data(self.data.clone(), vm)
296    opcode OpData52<0x34, 53>(self, vm) push_data(self.data.clone(), vm)
297    opcode OpData53<0x35, 54>(self, vm) push_data(self.data.clone(), vm)
298    opcode OpData54<0x36, 55>(self, vm) push_data(self.data.clone(), vm)
299    opcode OpData55<0x37, 56>(self, vm) push_data(self.data.clone(), vm)
300    opcode OpData56<0x38, 57>(self, vm) push_data(self.data.clone(), vm)
301    opcode OpData57<0x39, 58>(self, vm) push_data(self.data.clone(), vm)
302    opcode OpData58<0x3a, 59>(self, vm) push_data(self.data.clone(), vm)
303    opcode OpData59<0x3b, 60>(self, vm) push_data(self.data.clone(), vm)
304    opcode OpData60<0x3c, 61>(self, vm) push_data(self.data.clone(), vm)
305    opcode OpData61<0x3d, 62>(self, vm) push_data(self.data.clone(), vm)
306    opcode OpData62<0x3e, 63>(self, vm) push_data(self.data.clone(), vm)
307    opcode OpData63<0x3f, 64>(self, vm) push_data(self.data.clone(), vm)
308    opcode OpData64<0x40, 65>(self, vm) push_data(self.data.clone(), vm)
309    opcode OpData65<0x41, 66>(self, vm) push_data(self.data.clone(), vm)
310    opcode OpData66<0x42, 67>(self, vm) push_data(self.data.clone(), vm)
311    opcode OpData67<0x43, 68>(self, vm) push_data(self.data.clone(), vm)
312    opcode OpData68<0x44, 69>(self, vm) push_data(self.data.clone(), vm)
313    opcode OpData69<0x45, 70>(self, vm) push_data(self.data.clone(), vm)
314    opcode OpData70<0x46, 71>(self, vm) push_data(self.data.clone(), vm)
315    opcode OpData71<0x47, 72>(self, vm) push_data(self.data.clone(), vm)
316    opcode OpData72<0x48, 73>(self, vm) push_data(self.data.clone(), vm)
317    opcode OpData73<0x49, 74>(self, vm) push_data(self.data.clone(), vm)
318    opcode OpData74<0x4a, 75>(self, vm) push_data(self.data.clone(), vm)
319    opcode OpData75<0x4b, 76>(self, vm) push_data(self.data.clone(), vm)
320    opcode OpPushData1<0x4c, u8>(self, vm) push_data(self.data.clone(), vm)
321    opcode OpPushData2<0x4d, u16>(self, vm) push_data(self.data.clone(), vm)
322    opcode OpPushData4<0x4e, u32>(self, vm) push_data(self.data.clone(), vm)
323
324    opcode Op1Negate<0x4f, 1>(self, vm) push_number(-1, vm)
325
326    opcode OpReserved<0x50, 1>(self, vm) Err(TxScriptError::OpcodeReserved(format!("{self:?}")))
327
328    opcode |Op1| OpTrue<0x51, 1>(self, vm) push_number(1, vm)
329    opcode Op2<0x52, 1>(self, vm) push_number(2, vm)
330    opcode Op3<0x53, 1>(self, vm) push_number(3, vm)
331    opcode Op4<0x54, 1>(self, vm) push_number(4, vm)
332    opcode Op5<0x55, 1>(self, vm) push_number(5, vm)
333    opcode Op6<0x56, 1>(self, vm) push_number(6, vm)
334    opcode Op7<0x57, 1>(self, vm) push_number(7, vm)
335    opcode Op8<0x58, 1>(self, vm) push_number(8, vm)
336    opcode Op9<0x59, 1>(self, vm) push_number(9, vm)
337    opcode Op10<0x5a, 1>(self, vm) push_number(10, vm)
338    opcode Op11<0x5b, 1>(self, vm) push_number(11, vm)
339    opcode Op12<0x5c, 1>(self, vm) push_number(12, vm)
340    opcode Op13<0x5d, 1>(self, vm) push_number(13, vm)
341    opcode Op14<0x5e, 1>(self, vm) push_number(14, vm)
342    opcode Op15<0x5f, 1>(self, vm) push_number(15, vm)
343    opcode Op16<0x60, 1>(self, vm) push_number(16, vm)
344
345    // Control opcodes.
346    opcode OpNop<0x61, 1>(self, vm) Ok(())
347    opcode OpVer<0x62, 1>(self, vm) Err(TxScriptError::OpcodeReserved(format!("{self:?}")))
348
349    opcode OpIf<0x63, 1>(self, vm) {
350        let mut cond = OpCond::Skip;
351        if vm.is_executing() {
352            // This code seems identical to pop_bool, but was written this way to preserve
353            // the similar flow of go-kaspad
354            if let Some(mut cond_buf) = vm.dstack.pop() {
355                if cond_buf.len() > 1 {
356                    return Err(TxScriptError::InvalidState("expected boolean".to_string()));
357                }
358                cond = match cond_buf.pop() {
359                    Some(stack_cond) => match stack_cond {
360                        1 => OpCond::True,
361                        _ => return Err(TxScriptError::InvalidState("expected boolean".to_string())),
362                    }
363                    None => OpCond::False,
364                }
365            } else {
366                return Err(TxScriptError::EmptyStack);
367            }
368        }
369        vm.cond_stack.push(cond);
370        Ok(())
371    }
372
373    opcode OpNotIf<0x64, 1>(self, vm) {
374        let mut cond = OpCond::Skip;
375        if vm.is_executing() {
376            if let Some(mut cond_buf) = vm.dstack.pop() {
377                if cond_buf.len() > 1 {
378                    return Err(TxScriptError::InvalidState("expected boolean".to_string()));
379                }
380                cond = match cond_buf.pop() {
381                    Some(stack_cond) => match stack_cond {
382                        1 => OpCond::False,
383                        _ => return Err(TxScriptError::InvalidState("expected boolean".to_string())),
384                    }
385                    None => OpCond::True,
386                }
387            } else {
388                return Err(TxScriptError::EmptyStack);
389            }
390        }
391        vm.cond_stack.push(cond);
392        Ok(())
393    }
394
395    opcode OpVerIf<0x65, 1>(self, vm) Err(TxScriptError::OpcodeReserved(format!("{self:?}")))
396    opcode OpVerNotIf<0x66, 1>(self, vm) Err(TxScriptError::OpcodeReserved(format!("{self:?}")))
397
398    opcode OpElse<0x67, 1>(self, vm) {
399        if let Some(cond) = vm.cond_stack.last_mut() {
400            *cond = cond.negate();
401            Ok(())
402        } else {
403            Err(TxScriptError::InvalidState("condition stack empty".to_string()))
404        }
405    }
406
407    opcode OpEndIf<0x68, 1>(self, vm) {
408        match vm.cond_stack.pop() {
409            None => Err(TxScriptError::InvalidState("condition stack empty".to_string())),
410            _ => Ok(())
411        }
412    }
413
414    opcode OpVerify<0x69, 1>(self, vm) {
415        let [result]: [bool; 1] = vm.dstack.pop_items()?;
416        match result {
417            true => Ok(()),
418            false => Err(TxScriptError::VerifyError)
419        }
420    }
421
422    opcode OpReturn<0x6a, 1>(self, vm) Err(TxScriptError::EarlyReturn)
423
424    // Stack opcodes.
425    opcode OpToAltStack<0x6b, 1>(self, vm) {
426        let [item] = vm.dstack.pop_raw()?;
427        vm.astack.push(item);
428        Ok(())
429    }
430
431    opcode OpFromAltStack<0x6c, 1>(self, vm) {
432        match vm.astack.pop() {
433            Some(last) => {
434                vm.dstack.push(last);
435                Ok(())
436            },
437            None => Err(TxScriptError::EmptyStack)
438        }
439    }
440
441    opcode Op2Drop<0x6d, 1>(self, vm) vm.dstack.drop_items::<2>()
442    opcode Op2Dup<0x6e, 1>(self, vm) vm.dstack.dup_items::<2>()
443    opcode Op3Dup<0x6f, 1>(self, vm) vm.dstack.dup_items::<3>()
444    opcode Op2Over<0x70, 1>(self, vm) vm.dstack.over_items::<2>()
445    opcode Op2Rot<0x71, 1>(self, vm) vm.dstack.rot_items::<2>()
446    opcode Op2Swap<0x72, 1>(self, vm) vm.dstack.swap_items::<2>()
447
448    opcode OpIfDup<0x73, 1>(self, vm) {
449        let [result] = vm.dstack.peek_raw()?;
450        if <Vec<u8> as OpcodeData<bool>>::deserialize(&result)? {
451            vm.dstack.push(result);
452        }
453        Ok(())
454    }
455
456    opcode OpDepth<0x74, 1>(self, vm) push_number(vm.dstack.len() as i64, vm)
457
458    opcode OpDrop<0x75, 1>(self, vm) vm.dstack.drop_items::<1>()
459    opcode OpDup<0x76, 1>(self, vm) vm.dstack.dup_items::<1>()
460
461    opcode OpNip<0x77, 1>(self, vm) {
462        match vm.dstack.len() >= 2 {
463            true => {
464                vm.dstack.remove(vm.dstack.len()-2);
465                Ok(())
466            }
467            false => Err(TxScriptError::InvalidStackOperation(2, vm.dstack.len())),
468        }
469    }
470
471    opcode OpOver<0x78, 1>(self, vm) vm.dstack.over_items::<1>()
472
473    opcode OpPick<0x79, 1>(self, vm) {
474        let [loc]: [i32; 1] = vm.dstack.pop_items()?;
475        if  loc < 0 || loc as usize >= vm.dstack.len() {
476            return Err(TxScriptError::InvalidState("pick at an invalid location".to_string()));
477        }
478        vm.dstack.push(vm.dstack[vm.dstack.len()-(loc as usize)-1].clone());
479        Ok(())
480    }
481
482    opcode OpRoll<0x7a, 1>(self, vm) {
483        let [loc]: [i32; 1] = vm.dstack.pop_items()?;
484        if  loc < 0 || loc as usize >= vm.dstack.len() {
485            return Err(TxScriptError::InvalidState("roll at an invalid location".to_string()));
486        }
487        let item = vm.dstack.remove(vm.dstack.len()-(loc as usize)-1);
488        vm.dstack.push(item);
489        Ok(())
490    }
491
492    opcode OpRot<0x7b, 1>(self, vm) vm.dstack.rot_items::<1>()
493    opcode OpSwap<0x7c, 1>(self, vm) vm.dstack.swap_items::<1>()
494
495    opcode OpTuck<0x7d, 1>(self, vm) {
496        match vm.dstack.len() >= 2 {
497            true => {
498                vm.dstack.insert(vm.dstack.len()-2, vm.dstack.last().expect("We have at least two items").clone());
499                Ok(())
500            }
501            false => Err(TxScriptError::InvalidStackOperation(2, vm.dstack.len()))
502        }
503    }
504
505    // Splice opcodes.
506    opcode OpCat<0x7e, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
507    opcode OpSubStr<0x7f, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
508    opcode OpLeft<0x80, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
509    opcode OpRight<0x81, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
510
511    opcode OpSize<0x82, 1>(self, vm) {
512        match vm.dstack.last() {
513            Some(last) => {
514                vm.dstack.push_item(i64::try_from(last.len()).map_err(|e| TxScriptError::NumberTooBig(e.to_string()))?);
515                Ok(())
516            },
517            None => Err(TxScriptError::InvalidStackOperation(1, 0))
518        }
519    }
520
521    // Bitwise logic opcodes.
522    opcode OpInvert<0x83, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
523    opcode OpAnd<0x84, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
524    opcode OpOr<0x85, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
525    opcode OpXor<0x86, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
526
527    opcode OpEqual<0x87, 1>(self, vm) {
528        match vm.dstack.len() >= 2 {
529            true => {
530                let pair = vm.dstack.split_off(vm.dstack.len() - 2);
531                match pair[0] == pair[1] {
532                    true => vm.dstack.push(vec![1]),
533                    false => vm.dstack.push(vec![]),
534                }
535                Ok(())
536            }
537            false => Err(TxScriptError::InvalidStackOperation(2, vm.dstack.len()))
538        }
539    }
540
541    opcode OpEqualVerify<0x88, 1>(self, vm) {
542        match vm.dstack.len() >= 2 {
543            true => {
544                let pair = vm.dstack.split_off(vm.dstack.len() - 2);
545                match pair[0] == pair[1] {
546                    true => Ok(()),
547                    false => Err(TxScriptError::VerifyError),
548                }
549            }
550            false => Err(TxScriptError::InvalidStackOperation(2, vm.dstack.len()))
551        }
552    }
553
554    opcode OpReserved1<0x89, 1>(self, vm) Err(TxScriptError::OpcodeReserved(format!("{self:?}")))
555    opcode OpReserved2<0x8a, 1>(self, vm) Err(TxScriptError::OpcodeReserved(format!("{self:?}")))
556
557    // Numeric related opcodes.
558    opcode Op1Add<0x8b, 1>(self, vm) {
559        let [value]: [i64; 1] = vm.dstack.pop_items()?;
560        vm.dstack.push_item(value + 1);
561        Ok(())
562    }
563
564    opcode Op1Sub<0x8c, 1>(self, vm) {
565        let [value]: [i64; 1] = vm.dstack.pop_items()?;
566        vm.dstack.push_item(value - 1);
567        Ok(())
568    }
569
570    opcode Op2Mul<0x8d, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
571    opcode Op2Div<0x8e, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
572
573    opcode OpNegate<0x8f, 1>(self, vm) {
574        let [value]: [i64; 1] = vm.dstack.pop_items()?;
575        vm.dstack.push_item(-value);
576        Ok(())
577    }
578
579    opcode OpAbs<0x90, 1>(self, vm) {
580        let [m]: [i64; 1] = vm.dstack.pop_items()?;
581        vm.dstack.push_item(m.abs());
582        Ok(())
583    }
584
585    opcode OpNot<0x91, 1>(self, vm) {
586        let [m]: [i64; 1] = vm.dstack.pop_items()?;
587        vm.dstack.push_item((m == 0) as i64);
588        Ok(())
589    }
590
591    opcode Op0NotEqual<0x92, 1>(self, vm) {
592        let [m]: [i64; 1] = vm.dstack.pop_items()?;
593        vm.dstack.push_item((m != 0) as i64 );
594        Ok(())
595    }
596
597    opcode OpAdd<0x93, 1>(self, vm) {
598        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
599        vm.dstack.push_item(a+b);
600        Ok(())
601    }
602
603    opcode OpSub<0x94, 1>(self, vm) {
604        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
605        vm.dstack.push_item(a-b);
606        Ok(())
607    }
608
609    opcode OpMul<0x95, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
610    opcode OpDiv<0x96, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
611    opcode OpMod<0x97, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
612    opcode OpLShift<0x98, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
613    opcode OpRShift<0x99, 1>(self, vm) Err(TxScriptError::OpcodeDisabled(format!("{self:?}")))
614
615    opcode OpBoolAnd<0x9a, 1>(self, vm) {
616        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
617        vm.dstack.push_item(((a != 0) && (b != 0)) as i64);
618        Ok(())
619    }
620
621    opcode OpBoolOr<0x9b, 1>(self, vm) {
622        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
623        vm.dstack.push_item(((a != 0) || (b != 0)) as i64);
624        Ok(())
625    }
626
627    opcode OpNumEqual<0x9c, 1>(self, vm) {
628        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
629        vm.dstack.push_item((a == b) as i64);
630        Ok(())
631    }
632
633    opcode OpNumEqualVerify<0x9d, 1>(self, vm) {
634        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
635        match a == b {
636            true => Ok(()),
637            false => Err(TxScriptError::VerifyError)
638        }
639    }
640
641    opcode OpNumNotEqual<0x9e, 1>(self, vm) {
642        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
643        vm.dstack.push_item((a != b) as i64);
644        Ok(())
645    }
646
647    opcode OpLessThan<0x9f, 1>(self, vm) {
648        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
649        vm.dstack.push_item((a < b) as i64);
650        Ok(())
651    }
652
653    opcode OpGreaterThan<0xa0, 1>(self, vm) {
654        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
655        vm.dstack.push_item((a > b) as i64);
656        Ok(())
657    }
658
659    opcode OpLessThanOrEqual<0xa1, 1>(self, vm) {
660        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
661        vm.dstack.push_item((a <= b) as i64);
662        Ok(())
663    }
664
665    opcode OpGreaterThanOrEqual<0xa2, 1>(self, vm) {
666        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
667        vm.dstack.push_item((a >= b) as i64);
668        Ok(())
669    }
670
671    opcode OpMin<0xa3, 1>(self, vm) {
672        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
673        vm.dstack.push_item(min(a,b));
674        Ok(())
675    }
676
677    opcode OpMax<0xa4, 1>(self, vm) {
678        let [a,b]: [i64; 2] = vm.dstack.pop_items()?;
679        vm.dstack.push_item(max(a,b));
680        Ok(())
681    }
682
683    opcode OpWithin<0xa5, 1>(self, vm) {
684        let [x,l,u]: [i64; 3] = vm.dstack.pop_items()?;
685        vm.dstack.push_item((x >= l && x < u) as i64);
686        Ok(())
687    }
688
689    // Undefined opcodes.
690    opcode OpUnknown166<0xa6, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
691    opcode OpUnknown167<0xa7, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
692
693    // Crypto opcodes.
694    opcode OpSHA256<0xa8, 1>(self, vm) {
695        let [last] = vm.dstack.pop_raw()?;
696        let mut hasher = Sha256::new();
697        hasher.update(last);
698        vm.dstack.push(hasher.finalize().to_vec());
699        Ok(())
700    }
701
702    opcode OpCheckMultiSigECDSA<0xa9, 1>(self, vm) {
703        vm.op_check_multisig_schnorr_or_ecdsa(true)
704    }
705
706    opcode OpBlake2b<0xaa, 1>(self, vm) {
707        let [last] = vm.dstack.pop_raw()?;
708        //let hash = blake2b(last.as_slice());
709        let hash = Params::new().hash_length(32).to_state().update(&last).finalize();
710        vm.dstack.push(hash.as_bytes().to_vec());
711        Ok(())
712    }
713
714    opcode OpCheckSigECDSA<0xab, 1>(self, vm) {
715        let [mut sig, key] = vm.dstack.pop_raw()?;
716        // Hash type
717        match sig.pop() {
718            Some(typ) => {
719                let hash_type = SigHashType::from_u8(typ).map_err(|e| TxScriptError::InvalidSigHashType(typ))?;
720                match vm.check_ecdsa_signature(hash_type, key.as_slice(), sig.as_slice()) {
721                    Ok(valid) => {
722                        vm.dstack.push_item(valid);
723                        Ok(())
724                    },
725                    Err(e) => {
726                        Err(e)
727                    }
728                }
729            }
730            None => {
731                vm.dstack.push_item(false);
732                Ok(())
733            }
734        }
735    }
736
737    opcode OpCheckSig<0xac, 1>(self, vm) {
738        let [mut sig, key] = vm.dstack.pop_raw()?;
739        // Hash type
740        match sig.pop() {
741            Some(typ) => {
742                let hash_type = SigHashType::from_u8(typ).map_err(|e| TxScriptError::InvalidSigHashType(typ))?;
743                match vm.check_schnorr_signature(hash_type, key.as_slice(), sig.as_slice()) {
744                    Ok(valid) => {
745                        vm.dstack.push_item(valid);
746                        Ok(())
747                    },
748                    Err(e) => {
749                        Err(e)
750                    }
751                }
752            }
753            None => {
754                vm.dstack.push_item(false);
755                Ok(())
756            }
757        }
758    }
759
760    opcode OpCheckSigVerify<0xad, 1>(self, vm) {
761        // TODO: when changing impl to array based, change this too
762        OpCheckSig{data: self.data.clone()}.execute(vm)?;
763        let [valid]: [bool; 1] = vm.dstack.pop_items()?;
764        match valid {
765            true => Ok(()),
766            false => Err(TxScriptError::VerifyError)
767        }
768    }
769
770    opcode OpCheckMultiSig<0xae, 1>(self, vm) {
771        vm.op_check_multisig_schnorr_or_ecdsa(false)
772    }
773
774    opcode OpCheckMultiSigVerify<0xaf, 1>(self, vm) {
775        // TODO: when changing impl to array based, change this too
776        OpCheckMultiSig{data: self.data.clone()}.execute(vm)?;
777        let [valid]: [bool; 1] = vm.dstack.pop_items()?;
778        match valid {
779            true => Ok(()),
780            false => Err(TxScriptError::VerifyError)
781        }
782    }
783
784    opcode OpCheckLockTimeVerify<0xb0, 1>(self, vm) {
785        match vm.script_source {
786            ScriptSource::TxInput {input, tx, ..} => {
787                let [mut lock_time_bytes] = vm.dstack.pop_raw()?;
788
789                // Make sure lockTimeBytes is exactly 8 bytes.
790                // If more - return ErrNumberTooBig
791                // If less - pad with 0's
792                if lock_time_bytes.len() > 8 {
793                    return Err(TxScriptError::NumberTooBig(format!("lockTime value represented as {lock_time_bytes:x?} is longer then 8 bytes")))
794                }
795                lock_time_bytes.resize(8, 0);
796                let stack_lock_time = u64::from_le_bytes(lock_time_bytes.try_into().expect("checked vector size"));
797
798                // The lock time field of a transaction is either a DAA score at
799                // which the transaction is finalized or a timestamp depending on if the
800                // value is before the constants.LockTimeThreshold. When it is under the
801                // threshold it is a DAA score.
802                if !(
803                    (tx.tx().lock_time < LOCK_TIME_THRESHOLD && stack_lock_time < LOCK_TIME_THRESHOLD) ||
804                    (tx.tx().lock_time >= LOCK_TIME_THRESHOLD && stack_lock_time >= LOCK_TIME_THRESHOLD)
805                ){
806                    return Err(TxScriptError::UnsatisfiedLockTime(format!("mismatched locktime types -- tx locktime {}, stack locktime {}", tx.tx().lock_time, stack_lock_time)))
807                }
808
809                if stack_lock_time > tx.tx().lock_time {
810                    return Err(TxScriptError::UnsatisfiedLockTime(format!("locktime requirement not satisfied -- locktime is greater than the transaction locktime: {} > {}", stack_lock_time, tx.tx().lock_time)))
811                }
812
813                // The lock time feature can also be disabled, thereby bypassing
814                // OP_CHECKLOCKTIMEVERIFY, if every transaction input has been finalized by
815                // setting its sequence to the maximum value (constants.MaxTxInSequenceNum). This
816                // condition would result in the transaction being allowed into the blockDAG
817                // making the opcode ineffective.
818                //
819                // This condition is prevented by enforcing that the input being used by
820                // the opcode is unlocked (its sequence number is less than the max
821                // value). This is sufficient to prove correctness without having to
822                // check every input.
823                //
824                // NOTE: This implies that even if the transaction is not finalized due to
825                // another input being unlocked, the opcode execution will still fail when the
826                // input being used by the opcode is locked.
827                if input.sequence == MAX_TX_IN_SEQUENCE_NUM {
828                    return Err(TxScriptError::UnsatisfiedLockTime("transaction input is finalized".to_string()));
829                }
830                Ok(())
831            }
832            _ => Err(TxScriptError::InvalidSource("LockTimeVerify only applies to transaction inputs".to_string()))
833        }
834    }
835
836    opcode OpCheckSequenceVerify<0xb1, 1>(self, vm) {
837        match vm.script_source {
838            ScriptSource::TxInput {input, tx, ..} => {
839                let [mut sequence_bytes] = vm.dstack.pop_raw()?;
840
841                // Make sure sequenceBytes is exactly 8 bytes.
842                // If more - return ErrNumberTooBig
843                // If less - pad with 0's
844                if sequence_bytes.len() > 8 {
845                    return Err(TxScriptError::NumberTooBig(format!("lockTime value represented as {sequence_bytes:x?} is longer then 8 bytes")))
846                }
847                // Don't use makeScriptNum here, since sequence is not an actual number, minimal encoding rules don't apply to it,
848                // and is more convenient to be represented as an unsigned int.
849                sequence_bytes.resize(8, 0);
850                let stack_sequence = u64::from_le_bytes(sequence_bytes.try_into().expect("ensured size checks"));
851
852                // To provide for future soft-fork extensibility, if the
853                // operand has the disabled lock-time flag set,
854                // CHECKSEQUENCEVERIFY behaves as a NOP.
855                if stack_sequence & SEQUENCE_LOCK_TIME_DISABLED != 0 {
856                    return Ok(());
857                }
858
859                // Sequence numbers with their most significant bit set are not
860                // consensus constrained. Testing that the transaction's sequence
861                // number does not have this bit set prevents using this property
862                // to get around a CHECKSEQUENCEVERIFY check.
863                if input.sequence & SEQUENCE_LOCK_TIME_DISABLED != 0 {
864                    return Err(TxScriptError::UnsatisfiedLockTime(format!("transaction sequence has sequence locktime disabled bit set: {:#x}", input.sequence)));
865                }
866
867                // Mask off non-consensus bits before doing comparisons.
868                if (stack_sequence & SEQUENCE_LOCK_TIME_MASK) > (input.sequence & SEQUENCE_LOCK_TIME_MASK) {
869                    return Err(TxScriptError::UnsatisfiedLockTime(format!("locktime requirement not satisfied -- locktime is greater than the transaction locktime: {} > {}", stack_sequence & SEQUENCE_LOCK_TIME_MASK, input.sequence & SEQUENCE_LOCK_TIME_MASK)))
870                }
871                Ok(())
872            }
873            _ => Err(TxScriptError::InvalidSource("LockTimeVerify only applies to transaction inputs".to_string()))
874        }
875    }
876
877    // Undefined opcodes.
878    opcode OpUnknown178<0xb2, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
879    opcode OpUnknown179<0xb3, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
880    opcode OpUnknown180<0xb4, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
881    opcode OpUnknown181<0xb5, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
882    opcode OpUnknown182<0xb6, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
883    opcode OpUnknown183<0xb7, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
884    opcode OpUnknown184<0xb8, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
885    opcode OpUnknown185<0xb9, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
886    opcode OpUnknown186<0xba, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
887    opcode OpUnknown187<0xbb, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
888    opcode OpUnknown188<0xbc, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
889    opcode OpUnknown189<0xbd, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
890    opcode OpUnknown190<0xbe, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
891    opcode OpUnknown191<0xbf, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
892    opcode OpUnknown192<0xc0, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
893    opcode OpUnknown193<0xc1, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
894    opcode OpUnknown194<0xc2, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
895    opcode OpUnknown195<0xc3, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
896    opcode OpUnknown196<0xc4, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
897    opcode OpUnknown197<0xc5, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
898    opcode OpUnknown198<0xc6, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
899    opcode OpUnknown199<0xc7, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
900    opcode OpUnknown200<0xc8, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
901    opcode OpUnknown201<0xc9, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
902    opcode OpUnknown202<0xca, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
903    opcode OpUnknown203<0xcb, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
904    opcode OpUnknown204<0xcc, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
905    opcode OpUnknown205<0xcd, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
906    opcode OpUnknown206<0xce, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
907    opcode OpUnknown207<0xcf, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
908    opcode OpUnknown208<0xd0, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
909    opcode OpUnknown209<0xd1, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
910    opcode OpUnknown210<0xd2, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
911    opcode OpUnknown211<0xd3, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
912    opcode OpUnknown212<0xd4, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
913    opcode OpUnknown213<0xd5, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
914    opcode OpUnknown214<0xd6, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
915    opcode OpUnknown215<0xd7, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
916    opcode OpUnknown216<0xd8, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
917    opcode OpUnknown217<0xd9, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
918    opcode OpUnknown218<0xda, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
919    opcode OpUnknown219<0xdb, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
920    opcode OpUnknown220<0xdc, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
921    opcode OpUnknown221<0xdd, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
922    opcode OpUnknown222<0xde, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
923    opcode OpUnknown223<0xdf, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
924    opcode OpUnknown224<0xe0, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
925    opcode OpUnknown225<0xe1, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
926    opcode OpUnknown226<0xe2, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
927    opcode OpUnknown227<0xe3, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
928    opcode OpUnknown228<0xe4, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
929    opcode OpUnknown229<0xe5, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
930    opcode OpUnknown230<0xe6, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
931    opcode OpUnknown231<0xe7, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
932    opcode OpUnknown232<0xe8, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
933    opcode OpUnknown233<0xe9, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
934    opcode OpUnknown234<0xea, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
935    opcode OpUnknown235<0xeb, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
936    opcode OpUnknown236<0xec, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
937    opcode OpUnknown237<0xed, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
938    opcode OpUnknown238<0xee, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
939    opcode OpUnknown239<0xef, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
940    opcode OpUnknown240<0xf0, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
941    opcode OpUnknown241<0xf1, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
942    opcode OpUnknown242<0xf2, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
943    opcode OpUnknown243<0xf3, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
944    opcode OpUnknown244<0xf4, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
945    opcode OpUnknown245<0xf5, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
946    opcode OpUnknown246<0xf6, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
947    opcode OpUnknown247<0xf7, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
948    opcode OpUnknown248<0xf8, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
949    opcode OpUnknown249<0xf9, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
950
951    opcode OpSmallInteger<0xfa, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
952    opcode OpPubKeys<0xfb, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
953    opcode OpUnknown252<0xfc, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
954    opcode OpPubKeyHash<0xfd, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
955    opcode OpPubKey<0xfe, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
956    opcode OpInvalidOpCode<0xff, 1>(self, vm) Err(TxScriptError::InvalidOpcode(format!("{self:?}")))
957}
958
959// converts an opcode from the list of Op0 to Op16 to its associated value
960#[allow(clippy::borrowed_box)]
961pub fn to_small_int<T: VerifiableTransaction>(opcode: &Box<dyn OpCodeImplementation<T>>) -> u8 {
962    let value = opcode.value();
963    if value == codes::OpFalse {
964        return 0;
965    }
966
967    assert!((codes::OpTrue..codes::Op16).contains(&value), "expected op codes between from the list of Op0 to Op16");
968    value - (codes::OpTrue - 1)
969}
970
971#[cfg(test)]
972mod test {
973    use crate::caches::Cache;
974    use crate::data_stack::Stack;
975    use crate::opcodes::{OpCodeExecution, OpCodeImplementation};
976    use crate::{opcodes, pay_to_address_script, TxScriptEngine, TxScriptError, LOCK_TIME_THRESHOLD};
977    use kaspa_addresses::{Address, Prefix, Version};
978    use kaspa_consensus_core::constants::{SOMPI_PER_KASPA, TX_VERSION};
979    use kaspa_consensus_core::hashing::sighash::SigHashReusedValues;
980    use kaspa_consensus_core::subnets::SUBNETWORK_ID_NATIVE;
981    use kaspa_consensus_core::tx::{
982        PopulatedTransaction, ScriptPublicKey, Transaction, TransactionInput, TransactionOutpoint, TransactionOutput, UtxoEntry,
983        VerifiableTransaction,
984    };
985
986    struct TestCase<'a> {
987        init: Stack,
988        code: Box<dyn OpCodeImplementation<PopulatedTransaction<'a>>>,
989        dstack: Stack,
990    }
991
992    struct ErrorTestCase<'a> {
993        init: Stack,
994        code: Box<dyn OpCodeImplementation<PopulatedTransaction<'a>>>,
995        error: TxScriptError,
996    }
997
998    fn run_success_test_cases(tests: Vec<TestCase>) {
999        let cache = Cache::new(10_000);
1000        let mut reused_values = SigHashReusedValues::new();
1001        for TestCase { init, code, dstack } in tests {
1002            let mut vm = TxScriptEngine::new(&mut reused_values, &cache);
1003            vm.dstack = init;
1004            code.execute(&mut vm).unwrap_or_else(|_| panic!("Opcode {} should not fail", code.value()));
1005            assert_eq!(*vm.dstack, dstack, "OpCode {} Pushed wrong value", code.value());
1006        }
1007    }
1008
1009    fn run_error_test_cases(tests: Vec<ErrorTestCase>) {
1010        let cache = Cache::new(10_000);
1011        let mut reused_values = SigHashReusedValues::new();
1012        for ErrorTestCase { init, code, error } in tests {
1013            let mut vm = TxScriptEngine::new(&mut reused_values, &cache);
1014            vm.dstack.clone_from(&init);
1015            assert_eq!(
1016                code.execute(&mut vm)
1017                    .expect_err(format!("Opcode {} should have errored (init: {:?})", code.value(), init.clone()).as_str()),
1018                error,
1019                "Opcode {} returned wrong error {:?}",
1020                code.value(),
1021                init
1022            );
1023        }
1024    }
1025
1026    #[test]
1027    fn test_opcode_disabled() {
1028        let tests: Vec<Box<dyn OpCodeImplementation<PopulatedTransaction>>> = vec![
1029            opcodes::OpCat::empty().expect("Should accept empty"),
1030            opcodes::OpSubStr::empty().expect("Should accept empty"),
1031            opcodes::OpLeft::empty().expect("Should accept empty"),
1032            opcodes::OpRight::empty().expect("Should accept empty"),
1033            opcodes::OpInvert::empty().expect("Should accept empty"),
1034            opcodes::OpAnd::empty().expect("Should accept empty"),
1035            opcodes::OpOr::empty().expect("Should accept empty"),
1036            opcodes::OpXor::empty().expect("Should accept empty"),
1037            opcodes::Op2Mul::empty().expect("Should accept empty"),
1038            opcodes::Op2Div::empty().expect("Should accept empty"),
1039            opcodes::OpMul::empty().expect("Should accept empty"),
1040            opcodes::OpDiv::empty().expect("Should accept empty"),
1041            opcodes::OpMod::empty().expect("Should accept empty"),
1042            opcodes::OpLShift::empty().expect("Should accept empty"),
1043            opcodes::OpRShift::empty().expect("Should accept empty"),
1044        ];
1045
1046        let cache = Cache::new(10_000);
1047        let mut reused_values = SigHashReusedValues::new();
1048        let mut vm = TxScriptEngine::new(&mut reused_values, &cache);
1049
1050        for pop in tests {
1051            match pop.execute(&mut vm) {
1052                Err(TxScriptError::OpcodeDisabled(_)) => {}
1053                _ => panic!("Opcode {pop:?} should be disabled"),
1054            }
1055        }
1056    }
1057
1058    #[test]
1059    fn test_opcode_reserved() {
1060        let tests: Vec<Box<dyn OpCodeImplementation<PopulatedTransaction>>> = vec![
1061            opcodes::OpReserved::empty().expect("Should accept empty"),
1062            opcodes::OpVer::empty().expect("Should accept empty"),
1063            opcodes::OpVerIf::empty().expect("Should accept empty"),
1064            opcodes::OpVerNotIf::empty().expect("Should accept empty"),
1065            opcodes::OpReserved1::empty().expect("Should accept empty"),
1066            opcodes::OpReserved2::empty().expect("Should accept empty"),
1067        ];
1068
1069        let cache = Cache::new(10_000);
1070        let mut reused_values = SigHashReusedValues::new();
1071        let mut vm = TxScriptEngine::new(&mut reused_values, &cache);
1072
1073        for pop in tests {
1074            match pop.execute(&mut vm) {
1075                Err(TxScriptError::OpcodeReserved(_)) => {}
1076                _ => panic!("Opcode {pop:?} should be disabled"),
1077            }
1078        }
1079    }
1080
1081    #[test]
1082    fn test_opcode_invalid() {
1083        let tests: Vec<Box<dyn OpCodeImplementation<PopulatedTransaction>>> = vec![
1084            opcodes::OpUnknown166::empty().expect("Should accept empty"),
1085            opcodes::OpUnknown167::empty().expect("Should accept empty"),
1086            opcodes::OpUnknown178::empty().expect("Should accept empty"),
1087            opcodes::OpUnknown179::empty().expect("Should accept empty"),
1088            opcodes::OpUnknown180::empty().expect("Should accept empty"),
1089            opcodes::OpUnknown181::empty().expect("Should accept empty"),
1090            opcodes::OpUnknown182::empty().expect("Should accept empty"),
1091            opcodes::OpUnknown183::empty().expect("Should accept empty"),
1092            opcodes::OpUnknown184::empty().expect("Should accept empty"),
1093            opcodes::OpUnknown185::empty().expect("Should accept empty"),
1094            opcodes::OpUnknown186::empty().expect("Should accept empty"),
1095            opcodes::OpUnknown187::empty().expect("Should accept empty"),
1096            opcodes::OpUnknown188::empty().expect("Should accept empty"),
1097            opcodes::OpUnknown189::empty().expect("Should accept empty"),
1098            opcodes::OpUnknown190::empty().expect("Should accept empty"),
1099            opcodes::OpUnknown191::empty().expect("Should accept empty"),
1100            opcodes::OpUnknown192::empty().expect("Should accept empty"),
1101            opcodes::OpUnknown193::empty().expect("Should accept empty"),
1102            opcodes::OpUnknown194::empty().expect("Should accept empty"),
1103            opcodes::OpUnknown195::empty().expect("Should accept empty"),
1104            opcodes::OpUnknown196::empty().expect("Should accept empty"),
1105            opcodes::OpUnknown197::empty().expect("Should accept empty"),
1106            opcodes::OpUnknown198::empty().expect("Should accept empty"),
1107            opcodes::OpUnknown199::empty().expect("Should accept empty"),
1108            opcodes::OpUnknown200::empty().expect("Should accept empty"),
1109            opcodes::OpUnknown201::empty().expect("Should accept empty"),
1110            opcodes::OpUnknown202::empty().expect("Should accept empty"),
1111            opcodes::OpUnknown203::empty().expect("Should accept empty"),
1112            opcodes::OpUnknown204::empty().expect("Should accept empty"),
1113            opcodes::OpUnknown205::empty().expect("Should accept empty"),
1114            opcodes::OpUnknown206::empty().expect("Should accept empty"),
1115            opcodes::OpUnknown207::empty().expect("Should accept empty"),
1116            opcodes::OpUnknown208::empty().expect("Should accept empty"),
1117            opcodes::OpUnknown209::empty().expect("Should accept empty"),
1118            opcodes::OpUnknown210::empty().expect("Should accept empty"),
1119            opcodes::OpUnknown211::empty().expect("Should accept empty"),
1120            opcodes::OpUnknown212::empty().expect("Should accept empty"),
1121            opcodes::OpUnknown213::empty().expect("Should accept empty"),
1122            opcodes::OpUnknown214::empty().expect("Should accept empty"),
1123            opcodes::OpUnknown215::empty().expect("Should accept empty"),
1124            opcodes::OpUnknown216::empty().expect("Should accept empty"),
1125            opcodes::OpUnknown217::empty().expect("Should accept empty"),
1126            opcodes::OpUnknown218::empty().expect("Should accept empty"),
1127            opcodes::OpUnknown219::empty().expect("Should accept empty"),
1128            opcodes::OpUnknown220::empty().expect("Should accept empty"),
1129            opcodes::OpUnknown221::empty().expect("Should accept empty"),
1130            opcodes::OpUnknown222::empty().expect("Should accept empty"),
1131            opcodes::OpUnknown223::empty().expect("Should accept empty"),
1132            opcodes::OpUnknown224::empty().expect("Should accept empty"),
1133            opcodes::OpUnknown225::empty().expect("Should accept empty"),
1134            opcodes::OpUnknown226::empty().expect("Should accept empty"),
1135            opcodes::OpUnknown227::empty().expect("Should accept empty"),
1136            opcodes::OpUnknown228::empty().expect("Should accept empty"),
1137            opcodes::OpUnknown229::empty().expect("Should accept empty"),
1138            opcodes::OpUnknown230::empty().expect("Should accept empty"),
1139            opcodes::OpUnknown231::empty().expect("Should accept empty"),
1140            opcodes::OpUnknown232::empty().expect("Should accept empty"),
1141            opcodes::OpUnknown233::empty().expect("Should accept empty"),
1142            opcodes::OpUnknown234::empty().expect("Should accept empty"),
1143            opcodes::OpUnknown235::empty().expect("Should accept empty"),
1144            opcodes::OpUnknown236::empty().expect("Should accept empty"),
1145            opcodes::OpUnknown237::empty().expect("Should accept empty"),
1146            opcodes::OpUnknown238::empty().expect("Should accept empty"),
1147            opcodes::OpUnknown239::empty().expect("Should accept empty"),
1148            opcodes::OpUnknown240::empty().expect("Should accept empty"),
1149            opcodes::OpUnknown241::empty().expect("Should accept empty"),
1150            opcodes::OpUnknown242::empty().expect("Should accept empty"),
1151            opcodes::OpUnknown243::empty().expect("Should accept empty"),
1152            opcodes::OpUnknown244::empty().expect("Should accept empty"),
1153            opcodes::OpUnknown245::empty().expect("Should accept empty"),
1154            opcodes::OpUnknown246::empty().expect("Should accept empty"),
1155            opcodes::OpUnknown247::empty().expect("Should accept empty"),
1156            opcodes::OpUnknown248::empty().expect("Should accept empty"),
1157            opcodes::OpUnknown249::empty().expect("Should accept empty"),
1158        ];
1159
1160        let cache = Cache::new(10_000);
1161        let mut reused_values = SigHashReusedValues::new();
1162        let mut vm = TxScriptEngine::new(&mut reused_values, &cache);
1163
1164        for pop in tests {
1165            match pop.execute(&mut vm) {
1166                Err(TxScriptError::InvalidOpcode(_)) => {}
1167                _ => panic!("Opcode {pop:?} should be disabled"),
1168            }
1169        }
1170    }
1171
1172    #[test]
1173    fn test_push_data() {
1174        run_success_test_cases(vec![
1175            TestCase { code: opcodes::OpFalse::empty().expect("Should accept empty"), dstack: vec![vec![]], init: Default::default() },
1176            TestCase {
1177                code: opcodes::OpData1::new([1u8; 1].to_vec()).expect("Valid opcode"),
1178                dstack: vec![[1u8; 1].to_vec()],
1179                init: Default::default(),
1180            },
1181            TestCase {
1182                code: opcodes::OpData2::new([1u8; 2].to_vec()).expect("Valid opcode"),
1183                dstack: vec![[1u8; 2].to_vec()],
1184                init: Default::default(),
1185            },
1186            TestCase {
1187                code: opcodes::OpData3::new([1u8; 3].to_vec()).expect("Valid opcode"),
1188                dstack: vec![[1u8; 3].to_vec()],
1189                init: Default::default(),
1190            },
1191            TestCase {
1192                code: opcodes::OpData4::new([1u8; 4].to_vec()).expect("Valid opcode"),
1193                dstack: vec![[1u8; 4].to_vec()],
1194                init: Default::default(),
1195            },
1196            TestCase {
1197                code: opcodes::OpData5::new([1u8; 5].to_vec()).expect("Valid opcode"),
1198                dstack: vec![[1u8; 5].to_vec()],
1199                init: Default::default(),
1200            },
1201            TestCase {
1202                code: opcodes::OpData6::new([1u8; 6].to_vec()).expect("Valid opcode"),
1203                dstack: vec![[1u8; 6].to_vec()],
1204                init: Default::default(),
1205            },
1206            TestCase {
1207                code: opcodes::OpData7::new([1u8; 7].to_vec()).expect("Valid opcode"),
1208                dstack: vec![[1u8; 7].to_vec()],
1209                init: Default::default(),
1210            },
1211            TestCase {
1212                code: opcodes::OpData8::new([1u8; 8].to_vec()).expect("Valid opcode"),
1213                dstack: vec![[1u8; 8].to_vec()],
1214                init: Default::default(),
1215            },
1216            TestCase {
1217                code: opcodes::OpData9::new([1u8; 9].to_vec()).expect("Valid opcode"),
1218                dstack: vec![[1u8; 9].to_vec()],
1219                init: Default::default(),
1220            },
1221            TestCase {
1222                code: opcodes::OpData10::new([1u8; 10].to_vec()).expect("Valid opcode"),
1223                dstack: vec![[1u8; 10].to_vec()],
1224                init: Default::default(),
1225            },
1226            TestCase {
1227                code: opcodes::OpData11::new([1u8; 11].to_vec()).expect("Valid opcode"),
1228                dstack: vec![[1u8; 11].to_vec()],
1229                init: Default::default(),
1230            },
1231            TestCase {
1232                code: opcodes::OpData12::new([1u8; 12].to_vec()).expect("Valid opcode"),
1233                dstack: vec![[1u8; 12].to_vec()],
1234                init: Default::default(),
1235            },
1236            TestCase {
1237                code: opcodes::OpData13::new([1u8; 13].to_vec()).expect("Valid opcode"),
1238                dstack: vec![[1u8; 13].to_vec()],
1239                init: Default::default(),
1240            },
1241            TestCase {
1242                code: opcodes::OpData14::new([1u8; 14].to_vec()).expect("Valid opcode"),
1243                dstack: vec![[1u8; 14].to_vec()],
1244                init: Default::default(),
1245            },
1246            TestCase {
1247                code: opcodes::OpData15::new([1u8; 15].to_vec()).expect("Valid opcode"),
1248                dstack: vec![[1u8; 15].to_vec()],
1249                init: Default::default(),
1250            },
1251            TestCase {
1252                code: opcodes::OpData16::new([1u8; 16].to_vec()).expect("Valid opcode"),
1253                dstack: vec![[1u8; 16].to_vec()],
1254                init: Default::default(),
1255            },
1256            TestCase {
1257                code: opcodes::OpData17::new([1u8; 17].to_vec()).expect("Valid opcode"),
1258                dstack: vec![[1u8; 17].to_vec()],
1259                init: Default::default(),
1260            },
1261            TestCase {
1262                code: opcodes::OpData18::new([1u8; 18].to_vec()).expect("Valid opcode"),
1263                dstack: vec![[1u8; 18].to_vec()],
1264                init: Default::default(),
1265            },
1266            TestCase {
1267                code: opcodes::OpData19::new([1u8; 19].to_vec()).expect("Valid opcode"),
1268                dstack: vec![[1u8; 19].to_vec()],
1269                init: Default::default(),
1270            },
1271            TestCase {
1272                code: opcodes::OpData20::new([1u8; 20].to_vec()).expect("Valid opcode"),
1273                dstack: vec![[1u8; 20].to_vec()],
1274                init: Default::default(),
1275            },
1276            TestCase {
1277                code: opcodes::OpData21::new([1u8; 21].to_vec()).expect("Valid opcode"),
1278                dstack: vec![[1u8; 21].to_vec()],
1279                init: Default::default(),
1280            },
1281            TestCase {
1282                code: opcodes::OpData22::new([1u8; 22].to_vec()).expect("Valid opcode"),
1283                dstack: vec![[1u8; 22].to_vec()],
1284                init: Default::default(),
1285            },
1286            TestCase {
1287                code: opcodes::OpData23::new([1u8; 23].to_vec()).expect("Valid opcode"),
1288                dstack: vec![[1u8; 23].to_vec()],
1289                init: Default::default(),
1290            },
1291            TestCase {
1292                code: opcodes::OpData24::new([1u8; 24].to_vec()).expect("Valid opcode"),
1293                dstack: vec![[1u8; 24].to_vec()],
1294                init: Default::default(),
1295            },
1296            TestCase {
1297                code: opcodes::OpData25::new([1u8; 25].to_vec()).expect("Valid opcode"),
1298                dstack: vec![[1u8; 25].to_vec()],
1299                init: Default::default(),
1300            },
1301            TestCase {
1302                code: opcodes::OpData26::new([1u8; 26].to_vec()).expect("Valid opcode"),
1303                dstack: vec![[1u8; 26].to_vec()],
1304                init: Default::default(),
1305            },
1306            TestCase {
1307                code: opcodes::OpData27::new([1u8; 27].to_vec()).expect("Valid opcode"),
1308                dstack: vec![[1u8; 27].to_vec()],
1309                init: Default::default(),
1310            },
1311            TestCase {
1312                code: opcodes::OpData28::new([1u8; 28].to_vec()).expect("Valid opcode"),
1313                dstack: vec![[1u8; 28].to_vec()],
1314                init: Default::default(),
1315            },
1316            TestCase {
1317                code: opcodes::OpData29::new([1u8; 29].to_vec()).expect("Valid opcode"),
1318                dstack: vec![[1u8; 29].to_vec()],
1319                init: Default::default(),
1320            },
1321            TestCase {
1322                code: opcodes::OpData30::new([1u8; 30].to_vec()).expect("Valid opcode"),
1323                dstack: vec![[1u8; 30].to_vec()],
1324                init: Default::default(),
1325            },
1326            TestCase {
1327                code: opcodes::OpData31::new([1u8; 31].to_vec()).expect("Valid opcode"),
1328                dstack: vec![[1u8; 31].to_vec()],
1329                init: Default::default(),
1330            },
1331            TestCase {
1332                code: opcodes::OpData32::new([1u8; 32].to_vec()).expect("Valid opcode"),
1333                dstack: vec![[1u8; 32].to_vec()],
1334                init: Default::default(),
1335            },
1336            TestCase {
1337                code: opcodes::OpData33::new([1u8; 33].to_vec()).expect("Valid opcode"),
1338                dstack: vec![[1u8; 33].to_vec()],
1339                init: Default::default(),
1340            },
1341            TestCase {
1342                code: opcodes::OpData34::new([1u8; 34].to_vec()).expect("Valid opcode"),
1343                dstack: vec![[1u8; 34].to_vec()],
1344                init: Default::default(),
1345            },
1346            TestCase {
1347                code: opcodes::OpData35::new([1u8; 35].to_vec()).expect("Valid opcode"),
1348                dstack: vec![[1u8; 35].to_vec()],
1349                init: Default::default(),
1350            },
1351            TestCase {
1352                code: opcodes::OpData36::new([1u8; 36].to_vec()).expect("Valid opcode"),
1353                dstack: vec![[1u8; 36].to_vec()],
1354                init: Default::default(),
1355            },
1356            TestCase {
1357                code: opcodes::OpData37::new([1u8; 37].to_vec()).expect("Valid opcode"),
1358                dstack: vec![[1u8; 37].to_vec()],
1359                init: Default::default(),
1360            },
1361            TestCase {
1362                code: opcodes::OpData38::new([1u8; 38].to_vec()).expect("Valid opcode"),
1363                dstack: vec![[1u8; 38].to_vec()],
1364                init: Default::default(),
1365            },
1366            TestCase {
1367                code: opcodes::OpData39::new([1u8; 39].to_vec()).expect("Valid opcode"),
1368                dstack: vec![[1u8; 39].to_vec()],
1369                init: Default::default(),
1370            },
1371            TestCase {
1372                code: opcodes::OpData40::new([1u8; 40].to_vec()).expect("Valid opcode"),
1373                dstack: vec![[1u8; 40].to_vec()],
1374                init: Default::default(),
1375            },
1376            TestCase {
1377                code: opcodes::OpData41::new([1u8; 41].to_vec()).expect("Valid opcode"),
1378                dstack: vec![[1u8; 41].to_vec()],
1379                init: Default::default(),
1380            },
1381            TestCase {
1382                code: opcodes::OpData42::new([1u8; 42].to_vec()).expect("Valid opcode"),
1383                dstack: vec![[1u8; 42].to_vec()],
1384                init: Default::default(),
1385            },
1386            TestCase {
1387                code: opcodes::OpData43::new([1u8; 43].to_vec()).expect("Valid opcode"),
1388                dstack: vec![[1u8; 43].to_vec()],
1389                init: Default::default(),
1390            },
1391            TestCase {
1392                code: opcodes::OpData44::new([1u8; 44].to_vec()).expect("Valid opcode"),
1393                dstack: vec![[1u8; 44].to_vec()],
1394                init: Default::default(),
1395            },
1396            TestCase {
1397                code: opcodes::OpData45::new([1u8; 45].to_vec()).expect("Valid opcode"),
1398                dstack: vec![[1u8; 45].to_vec()],
1399                init: Default::default(),
1400            },
1401            TestCase {
1402                code: opcodes::OpData46::new([1u8; 46].to_vec()).expect("Valid opcode"),
1403                dstack: vec![[1u8; 46].to_vec()],
1404                init: Default::default(),
1405            },
1406            TestCase {
1407                code: opcodes::OpData47::new([1u8; 47].to_vec()).expect("Valid opcode"),
1408                dstack: vec![[1u8; 47].to_vec()],
1409                init: Default::default(),
1410            },
1411            TestCase {
1412                code: opcodes::OpData48::new([1u8; 48].to_vec()).expect("Valid opcode"),
1413                dstack: vec![[1u8; 48].to_vec()],
1414                init: Default::default(),
1415            },
1416            TestCase {
1417                code: opcodes::OpData49::new([1u8; 49].to_vec()).expect("Valid opcode"),
1418                dstack: vec![[1u8; 49].to_vec()],
1419                init: Default::default(),
1420            },
1421            TestCase {
1422                code: opcodes::OpData50::new([1u8; 50].to_vec()).expect("Valid opcode"),
1423                dstack: vec![[1u8; 50].to_vec()],
1424                init: Default::default(),
1425            },
1426            TestCase {
1427                code: opcodes::OpData51::new([1u8; 51].to_vec()).expect("Valid opcode"),
1428                dstack: vec![[1u8; 51].to_vec()],
1429                init: Default::default(),
1430            },
1431            TestCase {
1432                code: opcodes::OpData52::new([1u8; 52].to_vec()).expect("Valid opcode"),
1433                dstack: vec![[1u8; 52].to_vec()],
1434                init: Default::default(),
1435            },
1436            TestCase {
1437                code: opcodes::OpData53::new([1u8; 53].to_vec()).expect("Valid opcode"),
1438                dstack: vec![[1u8; 53].to_vec()],
1439                init: Default::default(),
1440            },
1441            TestCase {
1442                code: opcodes::OpData54::new([1u8; 54].to_vec()).expect("Valid opcode"),
1443                dstack: vec![[1u8; 54].to_vec()],
1444                init: Default::default(),
1445            },
1446            TestCase {
1447                code: opcodes::OpData55::new([1u8; 55].to_vec()).expect("Valid opcode"),
1448                dstack: vec![[1u8; 55].to_vec()],
1449                init: Default::default(),
1450            },
1451            TestCase {
1452                code: opcodes::OpData56::new([1u8; 56].to_vec()).expect("Valid opcode"),
1453                dstack: vec![[1u8; 56].to_vec()],
1454                init: Default::default(),
1455            },
1456            TestCase {
1457                code: opcodes::OpData57::new([1u8; 57].to_vec()).expect("Valid opcode"),
1458                dstack: vec![[1u8; 57].to_vec()],
1459                init: Default::default(),
1460            },
1461            TestCase {
1462                code: opcodes::OpData58::new([1u8; 58].to_vec()).expect("Valid opcode"),
1463                dstack: vec![[1u8; 58].to_vec()],
1464                init: Default::default(),
1465            },
1466            TestCase {
1467                code: opcodes::OpData59::new([1u8; 59].to_vec()).expect("Valid opcode"),
1468                dstack: vec![[1u8; 59].to_vec()],
1469                init: Default::default(),
1470            },
1471            TestCase {
1472                code: opcodes::OpData60::new([1u8; 60].to_vec()).expect("Valid opcode"),
1473                dstack: vec![[1u8; 60].to_vec()],
1474                init: Default::default(),
1475            },
1476            TestCase {
1477                code: opcodes::OpData61::new([1u8; 61].to_vec()).expect("Valid opcode"),
1478                dstack: vec![[1u8; 61].to_vec()],
1479                init: Default::default(),
1480            },
1481            TestCase {
1482                code: opcodes::OpData62::new([1u8; 62].to_vec()).expect("Valid opcode"),
1483                dstack: vec![[1u8; 62].to_vec()],
1484                init: Default::default(),
1485            },
1486            TestCase {
1487                code: opcodes::OpData63::new([1u8; 63].to_vec()).expect("Valid opcode"),
1488                dstack: vec![[1u8; 63].to_vec()],
1489                init: Default::default(),
1490            },
1491            TestCase {
1492                code: opcodes::OpData64::new([1u8; 64].to_vec()).expect("Valid opcode"),
1493                dstack: vec![[1u8; 64].to_vec()],
1494                init: Default::default(),
1495            },
1496            TestCase {
1497                code: opcodes::OpData65::new([1u8; 65].to_vec()).expect("Valid opcode"),
1498                dstack: vec![[1u8; 65].to_vec()],
1499                init: Default::default(),
1500            },
1501            TestCase {
1502                code: opcodes::OpData66::new([1u8; 66].to_vec()).expect("Valid opcode"),
1503                dstack: vec![[1u8; 66].to_vec()],
1504                init: Default::default(),
1505            },
1506            TestCase {
1507                code: opcodes::OpData67::new([1u8; 67].to_vec()).expect("Valid opcode"),
1508                dstack: vec![[1u8; 67].to_vec()],
1509                init: Default::default(),
1510            },
1511            TestCase {
1512                code: opcodes::OpData68::new([1u8; 68].to_vec()).expect("Valid opcode"),
1513                dstack: vec![[1u8; 68].to_vec()],
1514                init: Default::default(),
1515            },
1516            TestCase {
1517                code: opcodes::OpData69::new([1u8; 69].to_vec()).expect("Valid opcode"),
1518                dstack: vec![[1u8; 69].to_vec()],
1519                init: Default::default(),
1520            },
1521            TestCase {
1522                code: opcodes::OpData70::new([1u8; 70].to_vec()).expect("Valid opcode"),
1523                dstack: vec![[1u8; 70].to_vec()],
1524                init: Default::default(),
1525            },
1526            TestCase {
1527                code: opcodes::OpData71::new([1u8; 71].to_vec()).expect("Valid opcode"),
1528                dstack: vec![[1u8; 71].to_vec()],
1529                init: Default::default(),
1530            },
1531            TestCase {
1532                code: opcodes::OpData72::new([1u8; 72].to_vec()).expect("Valid opcode"),
1533                dstack: vec![[1u8; 72].to_vec()],
1534                init: Default::default(),
1535            },
1536            TestCase {
1537                code: opcodes::OpData73::new([1u8; 73].to_vec()).expect("Valid opcode"),
1538                dstack: vec![[1u8; 73].to_vec()],
1539                init: Default::default(),
1540            },
1541            TestCase {
1542                code: opcodes::OpData74::new([1u8; 74].to_vec()).expect("Valid opcode"),
1543                dstack: vec![[1u8; 74].to_vec()],
1544                init: Default::default(),
1545            },
1546            TestCase {
1547                code: opcodes::OpData75::new([1u8; 75].to_vec()).expect("Valid opcode"),
1548                dstack: vec![[1u8; 75].to_vec()],
1549                init: Default::default(),
1550            },
1551            TestCase {
1552                code: opcodes::OpPushData1::new([1u8; 76].to_vec()).expect("Valid opcode"),
1553                dstack: vec![[1u8; 76].to_vec()],
1554                init: Default::default(),
1555            },
1556            TestCase {
1557                code: opcodes::OpPushData2::new([1u8; 0x100].to_vec()).expect("Valid opcode"),
1558                dstack: vec![[1u8; 0x100].to_vec()],
1559                init: Default::default(),
1560            },
1561            TestCase {
1562                code: opcodes::OpPushData4::new([1u8; 0x10000].to_vec()).expect("Valid opcode"),
1563                dstack: vec![[1u8; 0x10000].to_vec()],
1564                init: Default::default(),
1565            },
1566        ]);
1567    }
1568
1569    #[test]
1570    fn test_push_num() {
1571        run_success_test_cases(vec![
1572            TestCase {
1573                code: opcodes::Op1Negate::empty().expect("Should accept empty"),
1574                dstack: vec![vec![0x81]],
1575                init: Default::default(),
1576            },
1577            TestCase { code: opcodes::Op1::empty().expect("Should accept empty"), dstack: vec![vec![1]], init: Default::default() },
1578            TestCase { code: opcodes::Op2::empty().expect("Should accept empty"), dstack: vec![vec![2]], init: Default::default() },
1579            TestCase { code: opcodes::Op3::empty().expect("Should accept empty"), dstack: vec![vec![3]], init: Default::default() },
1580            TestCase { code: opcodes::Op4::empty().expect("Should accept empty"), dstack: vec![vec![4]], init: Default::default() },
1581            TestCase { code: opcodes::Op5::empty().expect("Should accept empty"), dstack: vec![vec![5]], init: Default::default() },
1582            TestCase { code: opcodes::Op6::empty().expect("Should accept empty"), dstack: vec![vec![6]], init: Default::default() },
1583            TestCase { code: opcodes::Op7::empty().expect("Should accept empty"), dstack: vec![vec![7]], init: Default::default() },
1584            TestCase { code: opcodes::Op8::empty().expect("Should accept empty"), dstack: vec![vec![8]], init: Default::default() },
1585            TestCase { code: opcodes::Op9::empty().expect("Should accept empty"), dstack: vec![vec![9]], init: Default::default() },
1586            TestCase { code: opcodes::Op10::empty().expect("Should accept empty"), dstack: vec![vec![10]], init: Default::default() },
1587            TestCase { code: opcodes::Op11::empty().expect("Should accept empty"), dstack: vec![vec![11]], init: Default::default() },
1588            TestCase { code: opcodes::Op12::empty().expect("Should accept empty"), dstack: vec![vec![12]], init: Default::default() },
1589            TestCase { code: opcodes::Op13::empty().expect("Should accept empty"), dstack: vec![vec![13]], init: Default::default() },
1590            TestCase { code: opcodes::Op14::empty().expect("Should accept empty"), dstack: vec![vec![14]], init: Default::default() },
1591            TestCase { code: opcodes::Op15::empty().expect("Should accept empty"), dstack: vec![vec![15]], init: Default::default() },
1592            TestCase { code: opcodes::Op16::empty().expect("Should accept empty"), dstack: vec![vec![16]], init: Default::default() },
1593        ]);
1594    }
1595
1596    #[test]
1597    fn test_uniary_num_ops() {
1598        run_success_test_cases(vec![
1599            TestCase { code: opcodes::Op1Add::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![vec![1]] },
1600            TestCase { code: opcodes::Op1Add::empty().expect("Should accept empty"), init: vec![vec![1]], dstack: vec![vec![2]] },
1601            TestCase {
1602                code: opcodes::Op1Add::empty().expect("Should accept empty"),
1603                init: vec![vec![2, 1]],
1604                dstack: vec![vec![3, 1]],
1605            },
1606            TestCase { code: opcodes::Op1Add::empty().expect("Should accept empty"), init: vec![vec![0x81]], dstack: vec![vec![]] },
1607            TestCase { code: opcodes::Op1Sub::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![vec![0x81]] },
1608            TestCase { code: opcodes::Op1Sub::empty().expect("Should accept empty"), init: vec![vec![1]], dstack: vec![vec![]] },
1609            TestCase { code: opcodes::Op1Sub::empty().expect("Should accept empty"), init: vec![vec![2]], dstack: vec![vec![1]] },
1610            TestCase {
1611                code: opcodes::Op1Sub::empty().expect("Should accept empty"),
1612                init: vec![vec![3, 1]],
1613                dstack: vec![vec![2, 1]],
1614            },
1615            TestCase { code: opcodes::OpNegate::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![vec![]] },
1616            TestCase { code: opcodes::OpNegate::empty().expect("Should accept empty"), init: vec![vec![1]], dstack: vec![vec![0x81]] },
1617            TestCase { code: opcodes::OpNegate::empty().expect("Should accept empty"), init: vec![vec![0x81]], dstack: vec![vec![1]] },
1618            TestCase {
1619                code: opcodes::OpNegate::empty().expect("Should accept empty"),
1620                init: vec![vec![3, 1]],
1621                dstack: vec![vec![3, 0x81]],
1622            },
1623            TestCase { code: opcodes::OpAbs::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![vec![]] },
1624            TestCase { code: opcodes::OpAbs::empty().expect("Should accept empty"), init: vec![vec![3, 1]], dstack: vec![vec![3, 1]] },
1625            TestCase {
1626                code: opcodes::OpAbs::empty().expect("Should accept empty"),
1627                init: vec![vec![3, 0x81]],
1628                dstack: vec![vec![3, 1]],
1629            },
1630            TestCase { code: opcodes::OpAbs::empty().expect("Should accept empty"), init: vec![vec![1]], dstack: vec![vec![1]] },
1631            TestCase { code: opcodes::OpAbs::empty().expect("Should accept empty"), init: vec![vec![0x81]], dstack: vec![vec![1]] },
1632            TestCase {
1633                code: opcodes::OpAbs::empty().expect("Should accept empty"),
1634                init: vec![vec![1, 1, 0x82]],
1635                dstack: vec![vec![1, 1, 2]],
1636            },
1637            TestCase { code: opcodes::OpNot::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![vec![1]] },
1638            TestCase { code: opcodes::OpNot::empty().expect("Should accept empty"), init: vec![vec![1]], dstack: vec![vec![]] },
1639            TestCase { code: opcodes::OpNot::empty().expect("Should accept empty"), init: vec![vec![1, 2, 3]], dstack: vec![vec![]] },
1640            TestCase { code: opcodes::Op0NotEqual::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![vec![]] },
1641            TestCase { code: opcodes::Op0NotEqual::empty().expect("Should accept empty"), init: vec![vec![1]], dstack: vec![vec![1]] },
1642            TestCase { code: opcodes::Op0NotEqual::empty().expect("Should accept empty"), init: vec![vec![2]], dstack: vec![vec![1]] },
1643            TestCase {
1644                code: opcodes::Op0NotEqual::empty().expect("Should accept empty"),
1645                init: vec![vec![1, 2, 3]],
1646                dstack: vec![vec![1]],
1647            },
1648        ]);
1649    }
1650
1651    #[test]
1652    fn test_binary_num_ops() {
1653        run_success_test_cases(vec![
1654            TestCase { code: opcodes::OpAdd::empty().expect("Should accept empty"), init: vec![vec![], vec![]], dstack: vec![vec![]] },
1655            TestCase {
1656                code: opcodes::OpAdd::empty().expect("Should accept empty"),
1657                init: vec![vec![], vec![1]],
1658                dstack: vec![vec![1]],
1659            },
1660            TestCase {
1661                code: opcodes::OpAdd::empty().expect("Should accept empty"),
1662                init: vec![vec![1], vec![]],
1663                dstack: vec![vec![1]],
1664            },
1665            TestCase {
1666                code: opcodes::OpAdd::empty().expect("Should accept empty"),
1667                init: vec![vec![1], vec![1]],
1668                dstack: vec![vec![2]],
1669            },
1670            TestCase {
1671                code: opcodes::OpAdd::empty().expect("Should accept empty"),
1672                init: vec![vec![0x81], vec![1]],
1673                dstack: vec![vec![]],
1674            },
1675            TestCase {
1676                code: opcodes::OpAdd::empty().expect("Should accept empty"),
1677                init: vec![vec![0x7f], vec![1]],
1678                dstack: vec![vec![0x80, 0]],
1679            },
1680            TestCase {
1681                code: opcodes::OpAdd::empty().expect("Should accept empty"),
1682                init: vec![vec![0x80, 0], vec![0x80, 0]],
1683                dstack: vec![vec![0, 1]],
1684            },
1685            TestCase {
1686                code: opcodes::OpAdd::empty().expect("Should accept empty"),
1687                init: vec![vec![0xff, 0], vec![1]],
1688                dstack: vec![vec![0, 1]],
1689            },
1690            TestCase { code: opcodes::OpSub::empty().expect("Should accept empty"), init: vec![vec![], vec![]], dstack: vec![vec![]] },
1691            TestCase {
1692                code: opcodes::OpSub::empty().expect("Should accept empty"),
1693                init: vec![vec![], vec![1]],
1694                dstack: vec![vec![0x81]],
1695            },
1696            TestCase {
1697                code: opcodes::OpSub::empty().expect("Should accept empty"),
1698                init: vec![vec![1], vec![]],
1699                dstack: vec![vec![1]],
1700            },
1701            TestCase {
1702                code: opcodes::OpSub::empty().expect("Should accept empty"),
1703                init: vec![vec![1], vec![1]],
1704                dstack: vec![vec![]],
1705            },
1706            TestCase {
1707                code: opcodes::OpSub::empty().expect("Should accept empty"),
1708                init: vec![vec![0x81], vec![1]],
1709                dstack: vec![vec![0x82]],
1710            },
1711            TestCase {
1712                code: opcodes::OpSub::empty().expect("Should accept empty"),
1713                init: vec![vec![0x80, 0], vec![1]],
1714                dstack: vec![vec![0x7f]],
1715            },
1716            TestCase {
1717                code: opcodes::OpSub::empty().expect("Should accept empty"),
1718                init: vec![vec![0, 1], vec![0x80, 0]],
1719                dstack: vec![vec![0x80, 0]],
1720            },
1721            TestCase {
1722                code: opcodes::OpSub::empty().expect("Should accept empty"),
1723                init: vec![vec![0, 1], vec![1]],
1724                dstack: vec![vec![0xff, 0]],
1725            },
1726            TestCase {
1727                code: opcodes::OpMax::empty().expect("Should accept empty"),
1728                init: vec![vec![0, 1], vec![1]],
1729                dstack: vec![vec![0, 1]],
1730            },
1731            TestCase {
1732                code: opcodes::OpMax::empty().expect("Should accept empty"),
1733                init: vec![vec![1], vec![0, 1]],
1734                dstack: vec![vec![0, 1]],
1735            },
1736            TestCase {
1737                code: opcodes::OpMax::empty().expect("Should accept empty"),
1738                init: vec![vec![0, 0x81], vec![1]],
1739                dstack: vec![vec![1]],
1740            },
1741            TestCase {
1742                code: opcodes::OpMin::empty().expect("Should accept empty"),
1743                init: vec![vec![0, 1], vec![1]],
1744                dstack: vec![vec![1]],
1745            },
1746            TestCase {
1747                code: opcodes::OpMin::empty().expect("Should accept empty"),
1748                init: vec![vec![1], vec![0, 1]],
1749                dstack: vec![vec![1]],
1750            },
1751            TestCase {
1752                code: opcodes::OpMin::empty().expect("Should accept empty"),
1753                init: vec![vec![0, 0x81], vec![1]],
1754                dstack: vec![vec![0, 0x81]],
1755            },
1756        ]);
1757    }
1758
1759    #[test]
1760    fn test_logical_ops() {
1761        run_success_test_cases(vec![
1762            TestCase {
1763                code: opcodes::OpEqual::empty().expect("Should accept empty"),
1764                init: vec![vec![], vec![]],
1765                dstack: vec![vec![1]],
1766            },
1767            TestCase {
1768                code: opcodes::OpEqual::empty().expect("Should accept empty"),
1769                init: vec![vec![0, 1, 1, 0], vec![0, 1, 1, 0]],
1770                dstack: vec![vec![1]],
1771            },
1772            TestCase {
1773                code: opcodes::OpEqual::empty().expect("Should accept empty"),
1774                init: vec![vec![], vec![0]],
1775                dstack: vec![vec![]],
1776            },
1777            TestCase {
1778                code: opcodes::OpEqual::empty().expect("Should accept empty"),
1779                init: vec![vec![0, 1, 1, 0], vec![0, 1, 1, 1]],
1780                dstack: vec![vec![]],
1781            },
1782            TestCase {
1783                code: opcodes::OpBoolAnd::empty().expect("Should accept empty"),
1784                init: vec![vec![], vec![]],
1785                dstack: vec![vec![]],
1786            },
1787            TestCase {
1788                code: opcodes::OpBoolAnd::empty().expect("Should accept empty"),
1789                init: vec![vec![1], vec![]],
1790                dstack: vec![vec![]],
1791            },
1792            TestCase {
1793                code: opcodes::OpBoolAnd::empty().expect("Should accept empty"),
1794                init: vec![vec![], vec![1]],
1795                dstack: vec![vec![]],
1796            },
1797            TestCase {
1798                code: opcodes::OpBoolAnd::empty().expect("Should accept empty"),
1799                init: vec![vec![1], vec![1]],
1800                dstack: vec![vec![1]],
1801            },
1802            TestCase {
1803                code: opcodes::OpBoolAnd::empty().expect("Should accept empty"),
1804                init: vec![vec![1], vec![0x81]],
1805                dstack: vec![vec![1]],
1806            },
1807            TestCase {
1808                code: opcodes::OpBoolOr::empty().expect("Should accept empty"),
1809                init: vec![vec![], vec![]],
1810                dstack: vec![vec![]],
1811            },
1812            TestCase {
1813                code: opcodes::OpBoolOr::empty().expect("Should accept empty"),
1814                init: vec![vec![1], vec![]],
1815                dstack: vec![vec![1]],
1816            },
1817            TestCase {
1818                code: opcodes::OpBoolOr::empty().expect("Should accept empty"),
1819                init: vec![vec![], vec![1]],
1820                dstack: vec![vec![1]],
1821            },
1822            TestCase {
1823                code: opcodes::OpBoolOr::empty().expect("Should accept empty"),
1824                init: vec![vec![1], vec![1]],
1825                dstack: vec![vec![1]],
1826            },
1827            TestCase {
1828                code: opcodes::OpBoolOr::empty().expect("Should accept empty"),
1829                init: vec![vec![0x81], vec![1]],
1830                dstack: vec![vec![1]],
1831            },
1832            TestCase {
1833                code: opcodes::OpBoolOr::empty().expect("Should accept empty"),
1834                init: vec![vec![0x81], vec![1]],
1835                dstack: vec![vec![1]],
1836            },
1837            TestCase {
1838                code: opcodes::OpNumEqual::empty().expect("Should accept empty"),
1839                init: vec![vec![1], vec![1]],
1840                dstack: vec![vec![1]],
1841            },
1842            TestCase {
1843                code: opcodes::OpNumEqual::empty().expect("Should accept empty"),
1844                init: vec![vec![], vec![1]],
1845                dstack: vec![vec![]],
1846            },
1847            TestCase {
1848                code: opcodes::OpNumEqual::empty().expect("Should accept empty"),
1849                init: vec![vec![0x81], vec![1]],
1850                dstack: vec![vec![]],
1851            },
1852            TestCase {
1853                code: opcodes::OpNumEqual::empty().expect("Should accept empty"),
1854                init: vec![vec![], vec![]],
1855                dstack: vec![vec![1]],
1856            },
1857            TestCase {
1858                code: opcodes::OpNumNotEqual::empty().expect("Should accept empty"),
1859                init: vec![vec![1], vec![1]],
1860                dstack: vec![vec![]],
1861            },
1862            TestCase {
1863                code: opcodes::OpNumNotEqual::empty().expect("Should accept empty"),
1864                init: vec![vec![], vec![1]],
1865                dstack: vec![vec![1]],
1866            },
1867            TestCase {
1868                code: opcodes::OpNumNotEqual::empty().expect("Should accept empty"),
1869                init: vec![vec![0x81], vec![1]],
1870                dstack: vec![vec![1]],
1871            },
1872            TestCase {
1873                code: opcodes::OpNumNotEqual::empty().expect("Should accept empty"),
1874                init: vec![vec![], vec![]],
1875                dstack: vec![vec![]],
1876            },
1877            TestCase {
1878                code: opcodes::OpLessThan::empty().expect("Should accept empty"),
1879                init: vec![vec![1], vec![1]],
1880                dstack: vec![vec![]],
1881            },
1882            TestCase {
1883                code: opcodes::OpLessThan::empty().expect("Should accept empty"),
1884                init: vec![vec![], vec![1]],
1885                dstack: vec![vec![1]],
1886            },
1887            TestCase {
1888                code: opcodes::OpLessThan::empty().expect("Should accept empty"),
1889                init: vec![vec![0x81], vec![1]],
1890                dstack: vec![vec![1]],
1891            },
1892            TestCase {
1893                code: opcodes::OpLessThan::empty().expect("Should accept empty"),
1894                init: vec![vec![], vec![]],
1895                dstack: vec![vec![]],
1896            },
1897            TestCase {
1898                code: opcodes::OpLessThan::empty().expect("Should accept empty"),
1899                init: vec![vec![1], vec![]],
1900                dstack: vec![vec![]],
1901            },
1902            TestCase {
1903                code: opcodes::OpLessThan::empty().expect("Should accept empty"),
1904                init: vec![vec![], vec![0x81]],
1905                dstack: vec![vec![]],
1906            },
1907            TestCase {
1908                code: opcodes::OpLessThan::empty().expect("Should accept empty"),
1909                init: vec![vec![1], vec![0x81]],
1910                dstack: vec![vec![]],
1911            },
1912            TestCase {
1913                code: opcodes::OpLessThanOrEqual::empty().expect("Should accept empty"),
1914                init: vec![vec![1], vec![1]],
1915                dstack: vec![vec![1]],
1916            },
1917            TestCase {
1918                code: opcodes::OpLessThanOrEqual::empty().expect("Should accept empty"),
1919                init: vec![vec![], vec![1]],
1920                dstack: vec![vec![1]],
1921            },
1922            TestCase {
1923                code: opcodes::OpLessThanOrEqual::empty().expect("Should accept empty"),
1924                init: vec![vec![0x81], vec![1]],
1925                dstack: vec![vec![1]],
1926            },
1927            TestCase {
1928                code: opcodes::OpLessThanOrEqual::empty().expect("Should accept empty"),
1929                init: vec![vec![], vec![]],
1930                dstack: vec![vec![1]],
1931            },
1932            TestCase {
1933                code: opcodes::OpLessThanOrEqual::empty().expect("Should accept empty"),
1934                init: vec![vec![1], vec![]],
1935                dstack: vec![vec![]],
1936            },
1937            TestCase {
1938                code: opcodes::OpLessThanOrEqual::empty().expect("Should accept empty"),
1939                init: vec![vec![], vec![0x81]],
1940                dstack: vec![vec![]],
1941            },
1942            TestCase {
1943                code: opcodes::OpLessThanOrEqual::empty().expect("Should accept empty"),
1944                init: vec![vec![1], vec![0x81]],
1945                dstack: vec![vec![]],
1946            },
1947            TestCase {
1948                code: opcodes::OpGreaterThan::empty().expect("Should accept empty"),
1949                init: vec![vec![1], vec![1]],
1950                dstack: vec![vec![]],
1951            },
1952            TestCase {
1953                code: opcodes::OpGreaterThan::empty().expect("Should accept empty"),
1954                init: vec![vec![], vec![1]],
1955                dstack: vec![vec![]],
1956            },
1957            TestCase {
1958                code: opcodes::OpGreaterThan::empty().expect("Should accept empty"),
1959                init: vec![vec![0x81], vec![1]],
1960                dstack: vec![vec![]],
1961            },
1962            TestCase {
1963                code: opcodes::OpGreaterThan::empty().expect("Should accept empty"),
1964                init: vec![vec![], vec![]],
1965                dstack: vec![vec![]],
1966            },
1967            TestCase {
1968                code: opcodes::OpGreaterThan::empty().expect("Should accept empty"),
1969                init: vec![vec![1], vec![]],
1970                dstack: vec![vec![1]],
1971            },
1972            TestCase {
1973                code: opcodes::OpGreaterThan::empty().expect("Should accept empty"),
1974                init: vec![vec![], vec![0x81]],
1975                dstack: vec![vec![1]],
1976            },
1977            TestCase {
1978                code: opcodes::OpGreaterThan::empty().expect("Should accept empty"),
1979                init: vec![vec![1], vec![0x81]],
1980                dstack: vec![vec![1]],
1981            },
1982            TestCase {
1983                code: opcodes::OpGreaterThanOrEqual::empty().expect("Should accept empty"),
1984                init: vec![vec![1], vec![1]],
1985                dstack: vec![vec![1]],
1986            },
1987            TestCase {
1988                code: opcodes::OpGreaterThanOrEqual::empty().expect("Should accept empty"),
1989                init: vec![vec![], vec![1]],
1990                dstack: vec![vec![]],
1991            },
1992            TestCase {
1993                code: opcodes::OpGreaterThanOrEqual::empty().expect("Should accept empty"),
1994                init: vec![vec![0x81], vec![1]],
1995                dstack: vec![vec![]],
1996            },
1997            TestCase {
1998                code: opcodes::OpGreaterThanOrEqual::empty().expect("Should accept empty"),
1999                init: vec![vec![], vec![]],
2000                dstack: vec![vec![1]],
2001            },
2002            TestCase {
2003                code: opcodes::OpGreaterThanOrEqual::empty().expect("Should accept empty"),
2004                init: vec![vec![1], vec![]],
2005                dstack: vec![vec![1]],
2006            },
2007            TestCase {
2008                code: opcodes::OpGreaterThanOrEqual::empty().expect("Should accept empty"),
2009                init: vec![vec![], vec![0x81]],
2010                dstack: vec![vec![1]],
2011            },
2012            TestCase {
2013                code: opcodes::OpGreaterThanOrEqual::empty().expect("Should accept empty"),
2014                init: vec![vec![1], vec![0x81]],
2015                dstack: vec![vec![1]],
2016            },
2017        ]);
2018    }
2019
2020    #[test]
2021    fn test_opdepth() {
2022        run_success_test_cases(vec![
2023            TestCase { code: opcodes::OpDepth::empty().expect("Should accept empty"), init: vec![], dstack: vec![vec![]] },
2024            TestCase {
2025                code: opcodes::OpDepth::empty().expect("Should accept empty"),
2026                init: vec![vec![]],
2027                dstack: vec![vec![], vec![1]],
2028            },
2029            TestCase {
2030                code: opcodes::OpDepth::empty().expect("Should accept empty"),
2031                init: vec![vec![1], vec![2], vec![3]],
2032                dstack: vec![vec![1], vec![2], vec![3], vec![3]],
2033            },
2034        ]);
2035    }
2036
2037    #[test]
2038    fn test_opdrop() {
2039        run_success_test_cases(vec![
2040            TestCase { code: opcodes::OpDrop::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![] },
2041            TestCase {
2042                code: opcodes::OpDrop::empty().expect("Should accept empty"),
2043                init: vec![vec![], vec![1]],
2044                dstack: vec![vec![]],
2045            },
2046            TestCase {
2047                code: opcodes::OpDrop::empty().expect("Should accept empty"),
2048                init: vec![vec![1], vec![2], vec![3], vec![3]],
2049                dstack: vec![vec![1], vec![2], vec![3]],
2050            },
2051        ]);
2052
2053        run_error_test_cases(vec![ErrorTestCase {
2054            code: opcodes::OpDrop::empty().expect("Should accept empty"),
2055            init: vec![],
2056            error: TxScriptError::InvalidStackOperation(1, 0),
2057        }])
2058    }
2059
2060    #[test]
2061    fn test_op2drop() {
2062        run_success_test_cases(vec![
2063            TestCase { code: opcodes::Op2Drop::empty().expect("Should accept empty"), init: vec![vec![], vec![1]], dstack: vec![] },
2064            TestCase {
2065                code: opcodes::Op2Drop::empty().expect("Should accept empty"),
2066                init: vec![vec![1], vec![2], vec![3], vec![3]],
2067                dstack: vec![vec![1], vec![2]],
2068            },
2069        ]);
2070
2071        run_error_test_cases(vec![
2072            ErrorTestCase {
2073                code: opcodes::Op2Drop::empty().expect("Should accept empty"),
2074                init: vec![],
2075                error: TxScriptError::InvalidStackOperation(2, 0),
2076            },
2077            ErrorTestCase {
2078                code: opcodes::Op2Drop::empty().expect("Should accept empty"),
2079                init: vec![vec![]],
2080                error: TxScriptError::InvalidStackOperation(2, 1),
2081            },
2082        ])
2083    }
2084
2085    #[test]
2086    fn test_opdup() {
2087        run_success_test_cases(vec![
2088            TestCase { code: opcodes::OpDup::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![vec![], vec![]] },
2089            TestCase {
2090                code: opcodes::OpDup::empty().expect("Should accept empty"),
2091                init: vec![vec![], vec![1]],
2092                dstack: vec![vec![], vec![1], vec![1]],
2093            },
2094            TestCase {
2095                code: opcodes::OpDup::empty().expect("Should accept empty"),
2096                init: vec![vec![1], vec![2], vec![3], vec![3]],
2097                dstack: vec![vec![1], vec![2], vec![3], vec![3], vec![3]],
2098            },
2099        ]);
2100
2101        run_error_test_cases(vec![ErrorTestCase {
2102            code: opcodes::OpDup::empty().expect("Should accept empty"),
2103            init: vec![],
2104            error: TxScriptError::InvalidStackOperation(1, 0),
2105        }])
2106    }
2107
2108    #[test]
2109    fn test_op2dup() {
2110        run_success_test_cases(vec![
2111            TestCase {
2112                code: opcodes::Op2Dup::empty().expect("Should accept empty"),
2113                init: vec![vec![], vec![1]],
2114                dstack: vec![vec![], vec![1], vec![], vec![1]],
2115            },
2116            TestCase {
2117                code: opcodes::Op2Dup::empty().expect("Should accept empty"),
2118                init: vec![vec![1], vec![2], vec![3]],
2119                dstack: vec![vec![1], vec![2], vec![3], vec![2], vec![3]],
2120            },
2121        ]);
2122
2123        run_error_test_cases(vec![
2124            ErrorTestCase {
2125                code: opcodes::Op2Dup::empty().expect("Should accept empty"),
2126                init: vec![],
2127                error: TxScriptError::InvalidStackOperation(2, 0),
2128            },
2129            ErrorTestCase {
2130                code: opcodes::Op2Dup::empty().expect("Should accept empty"),
2131                init: vec![vec![]],
2132                error: TxScriptError::InvalidStackOperation(2, 1),
2133            },
2134        ]);
2135    }
2136
2137    #[test]
2138    fn test_op3dup() {
2139        run_success_test_cases(vec![
2140            TestCase {
2141                code: opcodes::Op3Dup::empty().expect("Should accept empty"),
2142                init: vec![vec![0x81], vec![], vec![1]],
2143                dstack: vec![vec![0x81], vec![], vec![1], vec![0x81], vec![], vec![1]],
2144            },
2145            TestCase {
2146                code: opcodes::Op3Dup::empty().expect("Should accept empty"),
2147                init: vec![vec![1], vec![2], vec![3]],
2148                dstack: vec![vec![1], vec![2], vec![3], vec![1], vec![2], vec![3]],
2149            },
2150        ]);
2151
2152        run_error_test_cases(vec![
2153            ErrorTestCase {
2154                code: opcodes::Op3Dup::empty().expect("Should accept empty"),
2155                init: vec![],
2156                error: TxScriptError::InvalidStackOperation(3, 0),
2157            },
2158            ErrorTestCase {
2159                code: opcodes::Op3Dup::empty().expect("Should accept empty"),
2160                init: vec![vec![]],
2161                error: TxScriptError::InvalidStackOperation(3, 1),
2162            },
2163            ErrorTestCase {
2164                code: opcodes::Op3Dup::empty().expect("Should accept empty"),
2165                init: vec![vec![], vec![]],
2166                error: TxScriptError::InvalidStackOperation(3, 2),
2167            },
2168        ]);
2169    }
2170
2171    #[test]
2172    fn test_opnip() {
2173        run_success_test_cases(vec![
2174            TestCase {
2175                code: opcodes::OpNip::empty().expect("Should accept empty"),
2176                init: vec![vec![], vec![1]],
2177                dstack: vec![vec![1]],
2178            },
2179            TestCase {
2180                code: opcodes::OpNip::empty().expect("Should accept empty"),
2181                init: vec![vec![1], vec![]],
2182                dstack: vec![vec![]],
2183            },
2184            TestCase {
2185                code: opcodes::OpNip::empty().expect("Should accept empty"),
2186                init: vec![vec![2], vec![], vec![1]],
2187                dstack: vec![vec![2], vec![1]],
2188            },
2189        ]);
2190
2191        run_error_test_cases(vec![
2192            ErrorTestCase {
2193                code: opcodes::OpNip::empty().expect("Should accept empty"),
2194                init: vec![],
2195                error: TxScriptError::InvalidStackOperation(2, 0),
2196            },
2197            ErrorTestCase {
2198                code: opcodes::OpNip::empty().expect("Should accept empty"),
2199                init: vec![vec![]],
2200                error: TxScriptError::InvalidStackOperation(2, 1),
2201            },
2202        ]);
2203    }
2204
2205    #[test]
2206    fn test_opover() {
2207        run_success_test_cases(vec![
2208            TestCase {
2209                code: opcodes::OpOver::empty().expect("Should accept empty"),
2210                init: vec![vec![], vec![1]],
2211                dstack: vec![vec![], vec![1], vec![]],
2212            },
2213            TestCase {
2214                code: opcodes::OpOver::empty().expect("Should accept empty"),
2215                init: vec![vec![1], vec![]],
2216                dstack: vec![vec![1], vec![], vec![1]],
2217            },
2218            TestCase {
2219                code: opcodes::OpOver::empty().expect("Should accept empty"),
2220                init: vec![vec![2], vec![], vec![1]],
2221                dstack: vec![vec![2], vec![], vec![1], vec![]],
2222            },
2223        ]);
2224
2225        run_error_test_cases(vec![
2226            ErrorTestCase {
2227                code: opcodes::OpOver::empty().expect("Should accept empty"),
2228                init: vec![],
2229                error: TxScriptError::InvalidStackOperation(2, 0),
2230            },
2231            ErrorTestCase {
2232                code: opcodes::OpOver::empty().expect("Should accept empty"),
2233                init: vec![vec![]],
2234                error: TxScriptError::InvalidStackOperation(2, 1),
2235            },
2236        ]);
2237    }
2238
2239    #[test]
2240    fn test_op2over() {
2241        run_success_test_cases(vec![
2242            TestCase {
2243                code: opcodes::Op2Over::empty().expect("Should accept empty"),
2244                init: vec![vec![0x81], vec![2], vec![], vec![1]],
2245                dstack: vec![vec![0x81], vec![2], vec![], vec![1], vec![0x81], vec![2]],
2246            },
2247            TestCase {
2248                code: opcodes::Op2Over::empty().expect("Should accept empty"),
2249                init: vec![vec![], vec![0x81], vec![2], vec![], vec![1]],
2250                dstack: vec![vec![], vec![0x81], vec![2], vec![], vec![1], vec![0x81], vec![2]],
2251            },
2252        ]);
2253
2254        run_error_test_cases(vec![
2255            ErrorTestCase {
2256                code: opcodes::Op2Over::empty().expect("Should accept empty"),
2257                init: vec![],
2258                error: TxScriptError::InvalidStackOperation(4, 0),
2259            },
2260            ErrorTestCase {
2261                code: opcodes::Op2Over::empty().expect("Should accept empty"),
2262                init: vec![vec![]],
2263                error: TxScriptError::InvalidStackOperation(4, 1),
2264            },
2265            ErrorTestCase {
2266                code: opcodes::Op2Over::empty().expect("Should accept empty"),
2267                init: vec![vec![], vec![]],
2268                error: TxScriptError::InvalidStackOperation(4, 2),
2269            },
2270            ErrorTestCase {
2271                code: opcodes::Op2Over::empty().expect("Should accept empty"),
2272                init: vec![vec![], vec![], vec![]],
2273                error: TxScriptError::InvalidStackOperation(4, 3),
2274            },
2275        ]);
2276    }
2277
2278    #[test]
2279    fn test_oppick() {
2280        run_success_test_cases(vec![
2281            TestCase {
2282                code: opcodes::OpPick::empty().expect("Should accept empty"),
2283                init: vec![vec![], vec![]],
2284                dstack: vec![vec![], vec![]],
2285            },
2286            TestCase {
2287                code: opcodes::OpPick::empty().expect("Should accept empty"),
2288                init: vec![vec![2], vec![], vec![1]],
2289                dstack: vec![vec![2], vec![], vec![2]],
2290            },
2291            TestCase {
2292                code: opcodes::OpPick::empty().expect("Should accept empty"),
2293                init: vec![vec![5], vec![4], vec![3], vec![], vec![2]],
2294                dstack: vec![vec![5], vec![4], vec![3], vec![], vec![4]],
2295            },
2296        ]);
2297
2298        run_error_test_cases(vec![
2299            ErrorTestCase {
2300                code: opcodes::OpPick::empty().expect("Should accept empty"),
2301                init: vec![vec![5], vec![4], vec![3], vec![], vec![4]],
2302                error: TxScriptError::InvalidState("pick at an invalid location".to_string()),
2303            },
2304            ErrorTestCase {
2305                code: opcodes::OpPick::empty().expect("Should accept empty"),
2306                init: vec![vec![5], vec![4], vec![3], vec![], vec![0x81]],
2307                error: TxScriptError::InvalidState("pick at an invalid location".to_string()),
2308            },
2309        ])
2310    }
2311
2312    #[test]
2313    fn test_oproll() {
2314        run_success_test_cases(vec![
2315            TestCase {
2316                code: opcodes::OpRoll::empty().expect("Should accept empty"),
2317                init: vec![vec![], vec![]],
2318                dstack: vec![vec![]],
2319            },
2320            TestCase {
2321                code: opcodes::OpRoll::empty().expect("Should accept empty"),
2322                init: vec![vec![2], vec![], vec![1]],
2323                dstack: vec![vec![], vec![2]],
2324            },
2325            TestCase {
2326                code: opcodes::OpRoll::empty().expect("Should accept empty"),
2327                init: vec![vec![5], vec![4], vec![3], vec![], vec![2]],
2328                dstack: vec![vec![5], vec![3], vec![], vec![4]],
2329            },
2330        ]);
2331
2332        run_error_test_cases(vec![
2333            ErrorTestCase {
2334                code: opcodes::OpRoll::empty().expect("Should accept empty"),
2335                init: vec![vec![5], vec![4], vec![3], vec![], vec![4]],
2336                error: TxScriptError::InvalidState("roll at an invalid location".to_string()),
2337            },
2338            ErrorTestCase {
2339                code: opcodes::OpRoll::empty().expect("Should accept empty"),
2340                init: vec![vec![5], vec![4], vec![3], vec![], vec![0x81]],
2341                error: TxScriptError::InvalidState("roll at an invalid location".to_string()),
2342            },
2343        ])
2344    }
2345
2346    #[test]
2347    fn test_oprot() {
2348        run_success_test_cases(vec![
2349            TestCase {
2350                code: opcodes::OpRot::empty().expect("Should accept empty"),
2351                init: vec![vec![1], vec![2], vec![3]],
2352                dstack: vec![vec![2], vec![3], vec![1]],
2353            },
2354            TestCase {
2355                code: opcodes::OpRot::empty().expect("Should accept empty"),
2356                init: vec![vec![], vec![1], vec![2], vec![3]],
2357                dstack: vec![vec![], vec![2], vec![3], vec![1]],
2358            },
2359        ]);
2360
2361        run_error_test_cases(vec![
2362            ErrorTestCase {
2363                code: opcodes::OpRot::empty().expect("Should accept empty"),
2364                init: vec![vec![2], vec![3]],
2365                error: TxScriptError::InvalidStackOperation(3, 2),
2366            },
2367            ErrorTestCase {
2368                code: opcodes::OpRot::empty().expect("Should accept empty"),
2369                init: vec![vec![3]],
2370                error: TxScriptError::InvalidStackOperation(3, 1),
2371            },
2372            ErrorTestCase {
2373                code: opcodes::OpRot::empty().expect("Should accept empty"),
2374                init: vec![],
2375                error: TxScriptError::InvalidStackOperation(3, 0),
2376            },
2377        ]);
2378    }
2379
2380    #[test]
2381    fn test_op2rot() {
2382        run_success_test_cases(vec![
2383            TestCase {
2384                code: opcodes::Op2Rot::empty().expect("Should accept empty"),
2385                init: vec![vec![1], vec![2], vec![3], vec![4], vec![5], vec![6]],
2386                dstack: vec![vec![3], vec![4], vec![5], vec![6], vec![1], vec![2]],
2387            },
2388            TestCase {
2389                code: opcodes::Op2Rot::empty().expect("Should accept empty"),
2390                init: vec![vec![], vec![1], vec![2], vec![3], vec![4], vec![5], vec![6]],
2391                dstack: vec![vec![], vec![3], vec![4], vec![5], vec![6], vec![1], vec![2]],
2392            },
2393        ]);
2394
2395        run_error_test_cases(vec![
2396            ErrorTestCase {
2397                code: opcodes::Op2Rot::empty().expect("Should accept empty"),
2398                init: vec![vec![1], vec![2], vec![3], vec![4], vec![5]],
2399                error: TxScriptError::InvalidStackOperation(6, 5),
2400            },
2401            ErrorTestCase {
2402                code: opcodes::Op2Rot::empty().expect("Should accept empty"),
2403                init: vec![vec![1], vec![2], vec![3], vec![4]],
2404                error: TxScriptError::InvalidStackOperation(6, 4),
2405            },
2406            ErrorTestCase {
2407                code: opcodes::Op2Rot::empty().expect("Should accept empty"),
2408                init: vec![vec![1], vec![2], vec![3]],
2409                error: TxScriptError::InvalidStackOperation(6, 3),
2410            },
2411            ErrorTestCase {
2412                code: opcodes::Op2Rot::empty().expect("Should accept empty"),
2413                init: vec![vec![1], vec![2]],
2414                error: TxScriptError::InvalidStackOperation(6, 2),
2415            },
2416            ErrorTestCase {
2417                code: opcodes::Op2Rot::empty().expect("Should accept empty"),
2418                init: vec![vec![1]],
2419                error: TxScriptError::InvalidStackOperation(6, 1),
2420            },
2421            ErrorTestCase {
2422                code: opcodes::Op2Rot::empty().expect("Should accept empty"),
2423                init: vec![],
2424                error: TxScriptError::InvalidStackOperation(6, 0),
2425            },
2426        ]);
2427    }
2428
2429    #[test]
2430    fn test_opswap() {
2431        run_success_test_cases(vec![
2432            TestCase {
2433                code: opcodes::OpSwap::empty().expect("Should accept empty"),
2434                init: vec![vec![1], vec![2]],
2435                dstack: vec![vec![2], vec![1]],
2436            },
2437            TestCase {
2438                code: opcodes::OpSwap::empty().expect("Should accept empty"),
2439                init: vec![vec![], vec![1], vec![5]],
2440                dstack: vec![vec![], vec![5], vec![1]],
2441            },
2442        ]);
2443
2444        run_error_test_cases(vec![
2445            ErrorTestCase {
2446                code: opcodes::OpSwap::empty().expect("Should accept empty"),
2447                init: vec![vec![1]],
2448                error: TxScriptError::InvalidStackOperation(2, 1),
2449            },
2450            ErrorTestCase {
2451                code: opcodes::OpSwap::empty().expect("Should accept empty"),
2452                init: vec![],
2453                error: TxScriptError::InvalidStackOperation(2, 0),
2454            },
2455        ]);
2456    }
2457
2458    #[test]
2459    fn test_op2swap() {
2460        run_success_test_cases(vec![
2461            TestCase {
2462                code: opcodes::Op2Swap::empty().expect("Should accept empty"),
2463                init: vec![vec![1], vec![2], vec![3], vec![4]],
2464                dstack: vec![vec![3], vec![4], vec![1], vec![2]],
2465            },
2466            TestCase {
2467                code: opcodes::Op2Swap::empty().expect("Should accept empty"),
2468                init: vec![vec![], vec![1], vec![2], vec![3], vec![4]],
2469                dstack: vec![vec![], vec![3], vec![4], vec![1], vec![2]],
2470            },
2471        ]);
2472
2473        run_error_test_cases(vec![
2474            ErrorTestCase {
2475                code: opcodes::Op2Swap::empty().expect("Should accept empty"),
2476                init: vec![vec![], vec![2], vec![1]],
2477                error: TxScriptError::InvalidStackOperation(4, 3),
2478            },
2479            ErrorTestCase {
2480                code: opcodes::Op2Swap::empty().expect("Should accept empty"),
2481                init: vec![vec![], vec![1]],
2482                error: TxScriptError::InvalidStackOperation(4, 2),
2483            },
2484            ErrorTestCase {
2485                code: opcodes::Op2Swap::empty().expect("Should accept empty"),
2486                init: vec![vec![1]],
2487                error: TxScriptError::InvalidStackOperation(4, 1),
2488            },
2489            ErrorTestCase {
2490                code: opcodes::Op2Swap::empty().expect("Should accept empty"),
2491                init: vec![],
2492                error: TxScriptError::InvalidStackOperation(4, 0),
2493            },
2494        ]);
2495    }
2496
2497    #[test]
2498    fn test_optuck() {
2499        run_success_test_cases(vec![
2500            TestCase {
2501                code: opcodes::OpTuck::empty().expect("Should accept empty"),
2502                init: vec![vec![1], vec![2]],
2503                dstack: vec![vec![2], vec![1], vec![2]],
2504            },
2505            TestCase {
2506                code: opcodes::OpTuck::empty().expect("Should accept empty"),
2507                init: vec![vec![3], vec![9], vec![2]],
2508                dstack: vec![vec![3], vec![2], vec![9], vec![2]],
2509            },
2510        ]);
2511
2512        run_error_test_cases(vec![
2513            ErrorTestCase {
2514                code: opcodes::OpTuck::empty().expect("Should accept empty"),
2515                init: vec![vec![3]],
2516                error: TxScriptError::InvalidStackOperation(2, 1),
2517            },
2518            ErrorTestCase {
2519                code: opcodes::OpTuck::empty().expect("Should accept empty"),
2520                init: vec![],
2521                error: TxScriptError::InvalidStackOperation(2, 0),
2522            },
2523        ]);
2524    }
2525
2526    #[test]
2527    fn test_opequalverify() {
2528        run_success_test_cases(vec![
2529            TestCase {
2530                code: opcodes::OpEqualVerify::empty().expect("Should accept empty"),
2531                init: vec![vec![], vec![]],
2532                dstack: vec![],
2533            },
2534            TestCase {
2535                code: opcodes::OpEqualVerify::empty().expect("Should accept empty"),
2536                init: vec![vec![], vec![1, 0, 1], vec![1, 0, 1]],
2537                dstack: vec![vec![]],
2538            },
2539            TestCase {
2540                code: opcodes::OpNumEqualVerify::empty().expect("Should accept empty"),
2541                init: vec![vec![], vec![]],
2542                dstack: vec![],
2543            },
2544            TestCase {
2545                code: opcodes::OpNumEqualVerify::empty().expect("Should accept empty"),
2546                init: vec![vec![], vec![0, 0, 1], vec![0, 0, 1]],
2547                dstack: vec![vec![]],
2548            },
2549        ]);
2550
2551        run_error_test_cases(vec![
2552            ErrorTestCase {
2553                code: opcodes::OpEqualVerify::empty().expect("Should accept empty"),
2554                init: vec![vec![], vec![2, 0, 1], vec![1, 0, 1]],
2555                error: TxScriptError::VerifyError,
2556            },
2557            ErrorTestCase {
2558                code: opcodes::OpEqualVerify::empty().expect("Should accept empty"),
2559                init: vec![vec![1], vec![]],
2560                error: TxScriptError::VerifyError,
2561            },
2562            ErrorTestCase {
2563                code: opcodes::OpNumEqualVerify::empty().expect("Should accept empty"),
2564                init: vec![vec![], vec![2, 0, 1], vec![1, 0, 1]],
2565                error: TxScriptError::VerifyError,
2566            },
2567            ErrorTestCase {
2568                code: opcodes::OpNumEqualVerify::empty().expect("Should accept empty"),
2569                init: vec![vec![1], vec![]],
2570                error: TxScriptError::VerifyError,
2571            },
2572        ]);
2573    }
2574
2575    #[test]
2576    fn test_opsize() {
2577        run_success_test_cases(vec![
2578            TestCase {
2579                code: opcodes::OpSize::empty().expect("Should accept empty"),
2580                init: vec![vec![]],
2581                dstack: vec![vec![], vec![]],
2582            },
2583            TestCase {
2584                code: opcodes::OpSize::empty().expect("Should accept empty"),
2585                init: vec![vec![5]],
2586                dstack: vec![vec![5], vec![1]],
2587            },
2588            TestCase {
2589                code: opcodes::OpSize::empty().expect("Should accept empty"),
2590                init: vec![vec![0x80, 1]],
2591                dstack: vec![vec![0x80, 1], vec![2]],
2592            },
2593        ]);
2594
2595        run_error_test_cases(vec![ErrorTestCase {
2596            code: opcodes::OpSize::empty().expect("Should accept empty"),
2597            init: vec![],
2598            error: TxScriptError::InvalidStackOperation(1, 0),
2599        }]);
2600    }
2601
2602    #[test]
2603    fn test_opwithin() {
2604        run_success_test_cases(vec![
2605            TestCase {
2606                code: opcodes::OpWithin::empty().expect("Should accept empty"),
2607                init: vec![vec![], vec![], vec![1]],
2608                dstack: vec![vec![1]],
2609            },
2610            TestCase {
2611                code: opcodes::OpWithin::empty().expect("Should accept empty"),
2612                init: vec![vec![], vec![], vec![]],
2613                dstack: vec![vec![]],
2614            },
2615            TestCase {
2616                code: opcodes::OpWithin::empty().expect("Should accept empty"),
2617                init: vec![vec![0x81], vec![0x91], vec![1]],
2618                dstack: vec![vec![1]],
2619            },
2620        ]);
2621
2622        run_error_test_cases(vec![
2623            ErrorTestCase {
2624                code: opcodes::OpWithin::empty().expect("Should accept empty"),
2625                init: vec![vec![], vec![]],
2626                error: TxScriptError::InvalidStackOperation(3, 2),
2627            },
2628            ErrorTestCase {
2629                code: opcodes::OpWithin::empty().expect("Should accept empty"),
2630                init: vec![vec![]],
2631                error: TxScriptError::InvalidStackOperation(3, 1),
2632            },
2633            ErrorTestCase {
2634                code: opcodes::OpWithin::empty().expect("Should accept empty"),
2635                init: vec![],
2636                error: TxScriptError::InvalidStackOperation(3, 0),
2637            },
2638        ]);
2639    }
2640
2641    #[test]
2642    fn test_opsha256() {
2643        // Some test vectors from https://www.dlitz.net/crypto/shad256-test-vectors/
2644        run_success_test_cases(vec![
2645            TestCase {
2646                code: opcodes::OpSHA256::empty().expect("Should accept empty"),
2647                init: vec![vec![]],
2648                dstack: vec![b"\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55".to_vec()],
2649            },
2650            TestCase {
2651                code: opcodes::OpSHA256::empty().expect("Should accept empty"),
2652                init: vec![b"abc".to_vec()],
2653                dstack: vec![b"\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad".to_vec()],
2654            },
2655            TestCase {
2656                code: opcodes::OpSHA256::empty().expect("Should accept empty"),
2657                init: vec![b"\xde\x18\x89\x41\xa3\x37\x5d\x3a\x8a\x06\x1e\x67\x57\x6e\x92\x6d".to_vec()],
2658                dstack: vec![b"\x06\x7c\x53\x12\x69\x73\x5c\xa7\xf5\x41\xfd\xac\xa8\xf0\xdc\x76\x30\x5d\x3c\xad\xa1\x40\xf8\x93\x72\xa4\x10\xfe\x5e\xff\x6e\x4d".to_vec()],
2659            },
2660        ]);
2661
2662        run_error_test_cases(vec![ErrorTestCase {
2663            code: opcodes::OpSHA256::empty().expect("Should accept empty"),
2664            init: vec![],
2665            error: TxScriptError::InvalidStackOperation(1, 0),
2666        }]);
2667    }
2668
2669    #[test]
2670    fn test_opblake2b() {
2671        run_success_test_cases(vec![
2672            TestCase {
2673                code: opcodes::OpBlake2b::empty().expect("Should accept empty"),
2674                init: vec![b"".to_vec()],
2675                dstack: vec![b"\x0e\x57\x51\xc0\x26\xe5\x43\xb2\xe8\xab\x2e\xb0\x60\x99\xda\xa1\xd1\xe5\xdf\x47\x77\x8f\x77\x87\xfa\xab\x45\xcd\xf1\x2f\xe3\xa8".to_vec()],
2676            },
2677            TestCase {
2678                code: opcodes::OpBlake2b::empty().expect("Should accept empty"),
2679                init: vec![b"abc".to_vec()],
2680                dstack: vec![b"\xbd\xdd\x81\x3c\x63\x42\x39\x72\x31\x71\xef\x3f\xee\x98\x57\x9b\x94\x96\x4e\x3b\xb1\xcb\x3e\x42\x72\x62\xc8\xc0\x68\xd5\x23\x19".to_vec()],
2681            },
2682        ]);
2683
2684        run_error_test_cases(vec![ErrorTestCase {
2685            code: opcodes::OpBlake2b::empty().expect("Should accept empty"),
2686            init: vec![],
2687            error: TxScriptError::InvalidStackOperation(1, 0),
2688        }]);
2689    }
2690
2691    #[test]
2692    fn test_opnop() {
2693        run_success_test_cases(vec![TestCase {
2694            code: opcodes::OpNop::empty().expect("Should accept empty"),
2695            init: vec![vec![], vec![1], vec![2]],
2696            dstack: vec![vec![], vec![1], vec![2]],
2697        }]);
2698    }
2699
2700    #[derive(Clone)]
2701    struct VerifiableTransactionMock(Transaction);
2702
2703    impl VerifiableTransaction for VerifiableTransactionMock {
2704        fn tx(&self) -> &Transaction {
2705            &self.0
2706        }
2707
2708        fn populated_input(&self, _index: usize) -> (&TransactionInput, &UtxoEntry) {
2709            unimplemented!()
2710        }
2711    }
2712
2713    fn make_mock_transaction(lock_time: u64) -> (VerifiableTransactionMock, TransactionInput, UtxoEntry) {
2714        let dummy_prev_out = TransactionOutpoint::new(kaspa_hashes::Hash::from_u64_word(1), 1);
2715        let dummy_sig_script = vec![0u8; 65];
2716        let dummy_tx_input = TransactionInput::new(dummy_prev_out, dummy_sig_script, 10, 1);
2717        let addr_hash = vec![1u8; 32];
2718
2719        let addr = Address::new(Prefix::Testnet, Version::PubKey, &addr_hash);
2720        let dummy_script_public_key = pay_to_address_script(&addr);
2721        let dummy_tx_out = TransactionOutput::new(SOMPI_PER_KASPA, dummy_script_public_key);
2722
2723        let tx = VerifiableTransactionMock(Transaction::new(
2724            TX_VERSION + 1,
2725            vec![dummy_tx_input.clone()],
2726            vec![dummy_tx_out.clone()],
2727            lock_time,
2728            SUBNETWORK_ID_NATIVE,
2729            0,
2730            vec![],
2731        ));
2732        let utxo_entry = UtxoEntry::new(0, ScriptPublicKey::default(), 0, false);
2733        (tx, dummy_tx_input, utxo_entry)
2734    }
2735
2736    #[test]
2737    fn test_opchecklocktimeverify() {
2738        // Everything we need to build a script source
2739        let (base_tx, input, utxo_entry) = make_mock_transaction(1);
2740
2741        let sig_cache = Cache::new(10_000);
2742        let mut reused_values = SigHashReusedValues::new();
2743
2744        let code = opcodes::OpCheckLockTimeVerify::empty().expect("Should accept empty");
2745
2746        for (tx_lock_time, lock_time, should_fail) in [
2747            (1u64, vec![], false),                                // Case 1: 0 = locktime < txLockTime
2748            (0x800000, vec![0x7f, 0, 0], false),                  // Case 2: 0 < locktime < txLockTime
2749            (0x800000, vec![0x7f, 0, 0, 0, 0, 0, 0, 0, 0], true), // Case 3: locktime too big
2750            (LOCK_TIME_THRESHOLD * 2, vec![0x7f, 0, 0, 0], true), // Case 4: lock times are inconsistent
2751        ] {
2752            let mut tx = base_tx.clone();
2753            tx.0.lock_time = tx_lock_time;
2754            let mut vm = TxScriptEngine::from_transaction_input(&tx, &input, 0, &utxo_entry, &mut reused_values, &sig_cache)
2755                .expect("Shouldn't fail");
2756            vm.dstack = vec![lock_time.clone()];
2757            match code.execute(&mut vm) {
2758                // Message is based on the should_fail values
2759                Ok(()) => assert!(
2760                    !should_fail,
2761                    "Opcode {} must fail (tx_lock_time: {}, lock_time: {:?})",
2762                    code.value(),
2763                    tx_lock_time,
2764                    lock_time
2765                ),
2766                Err(e) => assert!(
2767                    should_fail,
2768                    "Opcode {} should not fail. Got {} (tx_lock_time: {}, lock_time: {:?})",
2769                    code.value(),
2770                    e,
2771                    tx_lock_time,
2772                    lock_time
2773                ),
2774            }
2775        }
2776    }
2777
2778    #[test]
2779    fn test_opchecksequencerify() {
2780        // Everything we need to build a script source
2781        let (tx, base_input, utxo_entry) = make_mock_transaction(1);
2782
2783        let sig_cache = Cache::new(10_000);
2784        let mut reused_values = SigHashReusedValues::new();
2785
2786        let code = opcodes::OpCheckSequenceVerify::empty().expect("Should accept empty");
2787
2788        for (tx_sequence, sequence, should_fail) in [
2789            (1u64, vec![], false),                                // Case 1: 0 = sequence < tx_sequence
2790            (0x800000, vec![0x7f, 0, 0], false),                  // Case 2: 0 < sequence < tx_sequence
2791            (0x800000, vec![0x7f, 0, 0, 0, 0, 0, 0, 0, 0], true), // Case 3: sequence too big
2792            (1 << 63, vec![0x7f, 0, 0], true),                    // Case 4: disabled
2793            ((1 << 63) | 0xffff, vec![0x7f, 0, 0], true),         // Case 5: another disabled
2794        ] {
2795            let mut input = base_input.clone();
2796            input.sequence = tx_sequence;
2797            let mut vm = TxScriptEngine::from_transaction_input(&tx, &input, 0, &utxo_entry, &mut reused_values, &sig_cache)
2798                .expect("Shouldn't fail");
2799            vm.dstack = vec![sequence.clone()];
2800            match code.execute(&mut vm) {
2801                // Message is based on the should_fail values
2802                Ok(()) => {
2803                    assert!(!should_fail, "Opcode {} must fail (tx_sequence: {}, sequence: {:?})", code.value(), tx_sequence, sequence)
2804                }
2805                Err(e) => assert!(
2806                    should_fail,
2807                    "Opcode {} should not fail. Got {} (tx_sequence: {}, sequence: {:?})",
2808                    code.value(),
2809                    e,
2810                    tx_sequence,
2811                    sequence
2812                ),
2813            }
2814        }
2815    }
2816
2817    #[test]
2818    fn test_opreturn() {
2819        run_error_test_cases(vec![ErrorTestCase {
2820            code: opcodes::OpReturn::empty().expect("Should accept empty"),
2821            init: vec![],
2822            error: TxScriptError::EarlyReturn,
2823        }]);
2824    }
2825
2826    #[test]
2827    fn test_opverify() {
2828        run_success_test_cases(vec![
2829            TestCase { code: opcodes::OpVerify::empty().expect("Should accept empty"), init: vec![vec![1]], dstack: vec![] },
2830            TestCase { code: opcodes::OpVerify::empty().expect("Should accept empty"), init: vec![vec![0x81]], dstack: vec![] },
2831            TestCase { code: opcodes::OpVerify::empty().expect("Should accept empty"), init: vec![vec![0x80, 0]], dstack: vec![] },
2832            TestCase {
2833                code: opcodes::OpVerify::empty().expect("Should accept empty"),
2834                init: vec![vec![1, 0, 0, 0, 0]],
2835                dstack: vec![],
2836            },
2837        ]);
2838
2839        run_error_test_cases(vec![
2840            ErrorTestCase {
2841                code: opcodes::OpVerify::empty().expect("Should accept empty"),
2842                init: vec![vec![0, 0, 0, 0x80]],
2843                error: TxScriptError::VerifyError,
2844            },
2845            ErrorTestCase {
2846                code: opcodes::OpVerify::empty().expect("Should accept empty"),
2847                init: vec![vec![0, 0, 0, 0]],
2848                error: TxScriptError::VerifyError,
2849            },
2850            ErrorTestCase {
2851                code: opcodes::OpVerify::empty().expect("Should accept empty"),
2852                init: vec![vec![0x80]],
2853                error: TxScriptError::VerifyError,
2854            },
2855            ErrorTestCase {
2856                code: opcodes::OpVerify::empty().expect("Should accept empty"),
2857                init: vec![vec![0]],
2858                error: TxScriptError::VerifyError,
2859            },
2860            ErrorTestCase {
2861                code: opcodes::OpVerify::empty().expect("Should accept empty"),
2862                init: vec![vec![]],
2863                error: TxScriptError::VerifyError,
2864            },
2865            ErrorTestCase {
2866                code: opcodes::OpVerify::empty().expect("Should accept empty"),
2867                init: vec![],
2868                error: TxScriptError::InvalidStackOperation(1, 0),
2869            },
2870        ])
2871    }
2872
2873    #[test]
2874    fn test_opifdup() {
2875        run_success_test_cases(vec![
2876            TestCase {
2877                code: opcodes::OpIfDup::empty().expect("Should accept empty"),
2878                init: vec![vec![1]],
2879                dstack: vec![vec![1], vec![1]],
2880            },
2881            TestCase {
2882                code: opcodes::OpIfDup::empty().expect("Should accept empty"),
2883                init: vec![vec![0x80, 0]],
2884                dstack: vec![vec![0x80, 0], vec![0x80, 0]],
2885            },
2886            TestCase { code: opcodes::OpIfDup::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![vec![]] },
2887            TestCase {
2888                code: opcodes::OpIfDup::empty().expect("Should accept empty"),
2889                init: vec![vec![0x80]],
2890                dstack: vec![vec![0x80]],
2891            },
2892            TestCase {
2893                code: opcodes::OpIfDup::empty().expect("Should accept empty"),
2894                init: vec![vec![0, 0x80]],
2895                dstack: vec![vec![0, 0x80]],
2896            },
2897            TestCase { code: opcodes::OpIfDup::empty().expect("Should accept empty"), init: vec![vec![]], dstack: vec![vec![]] },
2898        ])
2899    }
2900}