1use crate::error::ScriptError;
2use crate::hash;
3use crate::opcode::Opcode;
4use crate::stack::{is_true, Stack};
5use crate::token::Token;
6
7#[derive(Debug, Clone, Default)]
11pub struct ExecuteOpts {
12 pub sighash: Option<[u8; 32]>,
18}
19
20pub fn execute(tokens: &[Token]) -> Result<bool, ScriptError> {
30 execute_with_opts(tokens, &ExecuteOpts::default())
31}
32
33pub fn execute_with_opts(tokens: &[Token], opts: &ExecuteOpts) -> Result<bool, ScriptError> {
38 let mut stack = Stack::new();
39 execute_on_stack(tokens, &mut stack, opts)?;
40
41 if stack.is_empty() {
42 return Ok(false);
43 }
44 let top = stack.pop()?;
45 Ok(is_true(&top))
46}
47
48pub(crate) fn execute_on_stack(
53 tokens: &[Token],
54 stack: &mut Stack,
55 opts: &ExecuteOpts,
56) -> Result<(), ScriptError> {
57 let mut exec_stack: Vec<bool> = Vec::new();
58
59 for token in tokens {
60 let executing = is_executing(&exec_stack);
61
62 match token {
63 Token::Op(Opcode::OpIf) => {
65 if executing {
66 let val = stack.pop()?;
67 exec_stack.push(is_true(&val));
68 } else {
69 exec_stack.push(false);
70 }
71 }
72 Token::Op(Opcode::OpNotIf) => {
73 if executing {
74 let val = stack.pop()?;
75 exec_stack.push(!is_true(&val));
76 } else {
77 exec_stack.push(false);
78 }
79 }
80 Token::Op(Opcode::OpElse) => {
81 let top = exec_stack
82 .last_mut()
83 .ok_or(ScriptError::UnbalancedConditional)?;
84 *top = !*top;
85 }
86 Token::Op(Opcode::OpEndIf) => {
87 if exec_stack.pop().is_none() {
88 return Err(ScriptError::UnbalancedConditional);
89 }
90 }
91
92 _ if !executing => continue,
94
95 Token::PushData(data) => {
97 stack.push(data.clone());
98 }
99
100 Token::Op(Opcode::Op0) => stack.push(vec![]),
102 Token::Op(Opcode::Op1Negate) => stack.push(vec![0x81]),
103 Token::Op(Opcode::Op1) => stack.push(vec![1]),
104 Token::Op(Opcode::Op2) => stack.push(vec![2]),
105 Token::Op(Opcode::Op3) => stack.push(vec![3]),
106 Token::Op(Opcode::Op4) => stack.push(vec![4]),
107 Token::Op(Opcode::Op5) => stack.push(vec![5]),
108 Token::Op(Opcode::Op6) => stack.push(vec![6]),
109 Token::Op(Opcode::Op7) => stack.push(vec![7]),
110 Token::Op(Opcode::Op8) => stack.push(vec![8]),
111 Token::Op(Opcode::Op9) => stack.push(vec![9]),
112 Token::Op(Opcode::Op10) => stack.push(vec![10]),
113 Token::Op(Opcode::Op11) => stack.push(vec![11]),
114 Token::Op(Opcode::Op12) => stack.push(vec![12]),
115 Token::Op(Opcode::Op13) => stack.push(vec![13]),
116 Token::Op(Opcode::Op14) => stack.push(vec![14]),
117 Token::Op(Opcode::Op15) => stack.push(vec![15]),
118 Token::Op(Opcode::Op16) => stack.push(vec![16]),
119
120 Token::Op(Opcode::OpNop) => {}
122 Token::Op(Opcode::OpVerify) => {
123 let val = stack.pop()?;
124 if !is_true(&val) {
125 return Err(ScriptError::VerifyFailed);
126 }
127 }
128 Token::Op(Opcode::OpReturn) => {
129 return Err(ScriptError::OpReturnEncountered);
130 }
131
132 Token::Op(Opcode::OpDup) => {
134 let top = stack.peek()?.to_vec();
135 stack.push(top);
136 }
137 Token::Op(Opcode::OpDrop) => {
138 stack.pop()?;
139 }
140 Token::Op(Opcode::Op2Dup) => {
141 let b = stack.pop()?;
142 let a = stack.pop()?;
143 stack.push(a.clone());
144 stack.push(b.clone());
145 stack.push(a);
146 stack.push(b);
147 }
148 Token::Op(Opcode::Op2Drop) => {
149 stack.pop()?;
150 stack.pop()?;
151 }
152 Token::Op(Opcode::OpNip) => {
153 if stack.len() < 2 {
154 return Err(ScriptError::StackUnderflow);
155 }
156 stack.remove(stack.len() - 2)?;
157 }
158 Token::Op(Opcode::OpOver) => {
159 if stack.len() < 2 {
160 return Err(ScriptError::StackUnderflow);
161 }
162 let second = stack.pop()?;
163 let first = stack.peek()?.to_vec();
164 stack.push(second);
165 stack.push(first);
166 }
167 Token::Op(Opcode::OpSwap) => {
168 let b = stack.pop()?;
169 let a = stack.pop()?;
170 stack.push(b);
171 stack.push(a);
172 }
173 Token::Op(Opcode::OpTuck) => {
174 let b = stack.pop()?;
175 let a = stack.pop()?;
176 stack.push(b.clone());
177 stack.push(a);
178 stack.push(b);
179 }
180 Token::Op(Opcode::OpDepth) => {
181 let depth = stack.len();
182 stack.push(encode_num(depth as i64));
183 }
184 Token::Op(Opcode::OpSize) => {
185 let top = stack.peek()?;
186 let size = top.len();
187 stack.push(encode_num(size as i64));
188 }
189
190 Token::Op(Opcode::OpEqual) => {
192 let b = stack.pop()?;
193 let a = stack.pop()?;
194 stack.push_bool(a == b);
195 }
196 Token::Op(Opcode::OpEqualVerify) => {
197 let b = stack.pop()?;
198 let a = stack.pop()?;
199 if a != b {
200 return Err(ScriptError::VerifyFailed);
201 }
202 }
203
204 Token::Op(Opcode::OpNot) => {
206 let val = stack.pop()?;
207 if val.is_empty() || val == [0x00] {
209 stack.push(vec![0x01]);
210 } else {
211 stack.push(vec![]);
212 }
213 }
214
215 Token::Op(Opcode::OpRipemd160) => {
217 let data = stack.pop()?;
218 stack.push(hash::ripemd160(&data).to_vec());
219 }
220 Token::Op(Opcode::OpSha256) => {
221 let data = stack.pop()?;
222 stack.push(hash::sha256(&data).to_vec());
223 }
224 Token::Op(Opcode::OpHash160) => {
225 let data = stack.pop()?;
226 stack.push(hash::hash160(&data).to_vec());
227 }
228 Token::Op(Opcode::OpHash256) => {
229 let data = stack.pop()?;
230 stack.push(hash::hash256(&data).to_vec());
231 }
232 Token::Op(Opcode::OpCheckSig) => {
233 checksig(stack, opts)?;
234 }
235 Token::Op(Opcode::OpCheckSigVerify) => {
236 checksig(stack, opts)?;
237 let val = stack.pop()?;
238 if !is_true(&val) {
239 return Err(ScriptError::VerifyFailed);
240 }
241 }
242 }
243 }
244
245 if !exec_stack.is_empty() {
246 return Err(ScriptError::UnbalancedConditional);
247 }
248
249 Ok(())
250}
251
252fn is_executing(exec_stack: &[bool]) -> bool {
256 exec_stack.iter().all(|&v| v)
257}
258
259fn encode_num(n: i64) -> Vec<u8> {
261 if n == 0 {
262 return vec![];
263 }
264
265 let negative = n < 0;
266 let mut abs = if negative { (-n) as u64 } else { n as u64 };
267 let mut result = Vec::new();
268
269 while abs > 0 {
270 result.push((abs & 0xff) as u8);
271 abs >>= 8;
272 }
273
274 if result.last().map_or(false, |&b| b & 0x80 != 0) {
277 result.push(if negative { 0x80 } else { 0x00 });
278 } else if negative {
279 let len = result.len();
280 result[len - 1] |= 0x80;
281 }
282
283 result
284}
285
286fn checksig(stack: &mut Stack, opts: &ExecuteOpts) -> Result<(), ScriptError> {
291 let pubkey = stack.pop()?;
292 let sig = stack.pop()?;
293
294 #[cfg(feature = "secp256k1")]
295 {
296 if let Some(sighash) = opts.sighash {
297 let result = verify_ecdsa(&sig, &pubkey, &sighash);
298 stack.push_bool(result);
299 return Ok(());
300 }
301 }
302
303 let _ = (&pubkey, &sig, &opts);
305 stack.push(vec![0x01]);
306 Ok(())
307}
308
309#[cfg(feature = "secp256k1")]
311fn verify_ecdsa(sig_bytes: &[u8], pubkey_bytes: &[u8], sighash: &[u8; 32]) -> bool {
312 use secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1};
313
314 if sig_bytes.is_empty() {
316 return false;
317 }
318
319 let hash_type = sig_bytes[sig_bytes.len() - 1];
321 if hash_type != 0x01 {
322 return false;
324 }
325
326 let der_sig = &sig_bytes[..sig_bytes.len() - 1];
327
328 let secp = Secp256k1::verification_only();
329
330 let signature = match Signature::from_der(der_sig) {
331 Ok(s) => s,
332 Err(_) => return false,
333 };
334
335 let public_key = match PublicKey::from_slice(pubkey_bytes) {
336 Ok(k) => k,
337 Err(_) => return false,
338 };
339
340 let message = match Message::from_digest(*sighash) {
341 msg => msg,
342 };
343
344 secp.verify_ecdsa(&message, &signature, &public_key).is_ok()
345}
346
347#[cfg(test)]
348mod tests {
349 use super::*;
350 use crate::opcode::Opcode;
351 use crate::token::Token;
352
353 fn op(o: Opcode) -> Token {
355 Token::Op(o)
356 }
357
358 fn push(data: &[u8]) -> Token {
359 Token::PushData(data.to_vec())
360 }
361
362 #[test]
365 fn empty_script_returns_false() {
366 assert_eq!(execute(&[]).unwrap(), false);
367 }
368
369 #[test]
370 fn op0_is_false() {
371 assert_eq!(execute(&[op(Opcode::Op0)]).unwrap(), false);
372 }
373
374 #[test]
375 fn op1_is_true() {
376 assert_eq!(execute(&[op(Opcode::Op1)]).unwrap(), true);
377 }
378
379 #[test]
380 fn push_data_true() {
381 assert_eq!(execute(&[push(&[0x42])]).unwrap(), true);
382 }
383
384 #[test]
385 fn push_data_empty_is_false() {
386 assert_eq!(execute(&[push(&[])]).unwrap(), false);
387 }
388
389 #[test]
392 fn op1negate_pushes_0x81() {
393 let mut stack = Stack::new();
394 execute_on_stack(
395 &[op(Opcode::Op1Negate)],
396 &mut stack,
397 &ExecuteOpts::default(),
398 )
399 .unwrap();
400 assert_eq!(stack.pop().unwrap(), vec![0x81]);
401 }
402
403 #[test]
404 fn op_n_values() {
405 for n in 1u8..=16 {
406 let opcode = Opcode::from_byte(0x50 + n).unwrap();
407 let mut stack = Stack::new();
408 execute_on_stack(&[op(opcode)], &mut stack, &ExecuteOpts::default()).unwrap();
409 assert_eq!(stack.pop().unwrap(), vec![n]);
410 }
411 }
412
413 #[test]
416 fn op_nop() {
417 let tokens = [op(Opcode::Op1), op(Opcode::OpNop)];
418 assert_eq!(execute(&tokens).unwrap(), true);
419 }
420
421 #[test]
422 fn op_verify_true() {
423 let tokens = [op(Opcode::Op1), op(Opcode::OpVerify), op(Opcode::Op1)];
424 assert_eq!(execute(&tokens).unwrap(), true);
425 }
426
427 #[test]
428 fn op_verify_false() {
429 let tokens = [op(Opcode::Op0), op(Opcode::OpVerify)];
430 let err = execute(&tokens).unwrap_err();
431 assert!(matches!(err, ScriptError::VerifyFailed));
432 }
433
434 #[test]
435 fn op_return_error() {
436 let tokens = [op(Opcode::Op1), op(Opcode::OpReturn)];
437 let err = execute(&tokens).unwrap_err();
438 assert!(matches!(err, ScriptError::OpReturnEncountered));
439 }
440
441 #[test]
444 fn if_true_branch() {
445 let tokens = [
447 op(Opcode::Op1),
448 op(Opcode::OpIf),
449 op(Opcode::Op2),
450 op(Opcode::OpEndIf),
451 ];
452 let mut stack = Stack::new();
453 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
454 assert_eq!(stack.pop().unwrap(), vec![2]);
455 }
456
457 #[test]
458 fn if_false_branch() {
459 let tokens = [
461 op(Opcode::Op0),
462 op(Opcode::OpIf),
463 op(Opcode::Op2),
464 op(Opcode::OpEndIf),
465 op(Opcode::Op3),
466 ];
467 let mut stack = Stack::new();
468 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
469 assert_eq!(stack.pop().unwrap(), vec![3]);
471 assert!(stack.is_empty());
472 }
473
474 #[test]
475 fn if_else_true() {
476 let tokens = [
478 op(Opcode::Op1),
479 op(Opcode::OpIf),
480 op(Opcode::Op2),
481 op(Opcode::OpElse),
482 op(Opcode::Op3),
483 op(Opcode::OpEndIf),
484 ];
485 let mut stack = Stack::new();
486 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
487 assert_eq!(stack.pop().unwrap(), vec![2]);
488 assert!(stack.is_empty());
489 }
490
491 #[test]
492 fn if_else_false() {
493 let tokens = [
495 op(Opcode::Op0),
496 op(Opcode::OpIf),
497 op(Opcode::Op2),
498 op(Opcode::OpElse),
499 op(Opcode::Op3),
500 op(Opcode::OpEndIf),
501 ];
502 let mut stack = Stack::new();
503 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
504 assert_eq!(stack.pop().unwrap(), vec![3]);
505 assert!(stack.is_empty());
506 }
507
508 #[test]
509 fn notif_true_skips() {
510 let tokens = [
512 op(Opcode::Op1),
513 op(Opcode::OpNotIf),
514 op(Opcode::Op2),
515 op(Opcode::OpEndIf),
516 op(Opcode::Op3),
517 ];
518 let mut stack = Stack::new();
519 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
520 assert_eq!(stack.pop().unwrap(), vec![3]);
521 assert!(stack.is_empty());
522 }
523
524 #[test]
525 fn unbalanced_if() {
526 let tokens = [op(Opcode::Op1), op(Opcode::OpIf)];
527 let err = execute(&tokens).unwrap_err();
528 assert!(matches!(err, ScriptError::UnbalancedConditional));
529 }
530
531 #[test]
532 fn unbalanced_else() {
533 let tokens = [op(Opcode::OpElse)];
534 let err = execute(&tokens).unwrap_err();
535 assert!(matches!(err, ScriptError::UnbalancedConditional));
536 }
537
538 #[test]
539 fn unbalanced_endif() {
540 let tokens = [op(Opcode::OpEndIf)];
541 let err = execute(&tokens).unwrap_err();
542 assert!(matches!(err, ScriptError::UnbalancedConditional));
543 }
544
545 #[test]
548 fn op_dup() {
549 let tokens = [push(&[0xaa]), op(Opcode::OpDup)];
550 let mut stack = Stack::new();
551 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
552 assert_eq!(stack.pop().unwrap(), vec![0xaa]);
553 assert_eq!(stack.pop().unwrap(), vec![0xaa]);
554 }
555
556 #[test]
557 fn op_drop() {
558 let tokens = [op(Opcode::Op1), op(Opcode::Op2), op(Opcode::OpDrop)];
559 let mut stack = Stack::new();
560 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
561 assert_eq!(stack.pop().unwrap(), vec![1]);
562 }
563
564 #[test]
565 fn op_2dup() {
566 let tokens = [op(Opcode::Op1), op(Opcode::Op2), op(Opcode::Op2Dup)];
567 let mut stack = Stack::new();
568 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
569 assert_eq!(stack.len(), 4);
570 assert_eq!(stack.pop().unwrap(), vec![2]);
571 assert_eq!(stack.pop().unwrap(), vec![1]);
572 assert_eq!(stack.pop().unwrap(), vec![2]);
573 assert_eq!(stack.pop().unwrap(), vec![1]);
574 }
575
576 #[test]
577 fn op_2drop() {
578 let tokens = [
579 op(Opcode::Op1),
580 op(Opcode::Op2),
581 op(Opcode::Op3),
582 op(Opcode::Op2Drop),
583 ];
584 let mut stack = Stack::new();
585 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
586 assert_eq!(stack.pop().unwrap(), vec![1]);
587 }
588
589 #[test]
590 fn op_nip() {
591 let tokens = [op(Opcode::Op1), op(Opcode::Op2), op(Opcode::OpNip)];
592 let mut stack = Stack::new();
593 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
594 assert_eq!(stack.len(), 1);
595 assert_eq!(stack.pop().unwrap(), vec![2]);
596 }
597
598 #[test]
599 fn op_over() {
600 let tokens = [op(Opcode::Op1), op(Opcode::Op2), op(Opcode::OpOver)];
601 let mut stack = Stack::new();
602 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
603 assert_eq!(stack.len(), 3);
604 assert_eq!(stack.pop().unwrap(), vec![1]);
605 assert_eq!(stack.pop().unwrap(), vec![2]);
606 assert_eq!(stack.pop().unwrap(), vec![1]);
607 }
608
609 #[test]
610 fn op_swap() {
611 let tokens = [op(Opcode::Op1), op(Opcode::Op2), op(Opcode::OpSwap)];
612 let mut stack = Stack::new();
613 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
614 assert_eq!(stack.pop().unwrap(), vec![1]);
615 assert_eq!(stack.pop().unwrap(), vec![2]);
616 }
617
618 #[test]
619 fn op_tuck() {
620 let tokens = [op(Opcode::Op1), op(Opcode::Op2), op(Opcode::OpTuck)];
622 let mut stack = Stack::new();
623 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
624 assert_eq!(stack.len(), 3);
625 assert_eq!(stack.pop().unwrap(), vec![2]);
626 assert_eq!(stack.pop().unwrap(), vec![1]);
627 assert_eq!(stack.pop().unwrap(), vec![2]);
628 }
629
630 #[test]
631 fn op_depth() {
632 let tokens = [op(Opcode::Op1), op(Opcode::Op2), op(Opcode::OpDepth)];
633 let mut stack = Stack::new();
634 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
635 assert_eq!(stack.pop().unwrap(), vec![2]); }
637
638 #[test]
639 fn op_depth_empty() {
640 let tokens = [op(Opcode::OpDepth)];
641 let mut stack = Stack::new();
642 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
643 assert_eq!(stack.pop().unwrap(), vec![]); }
645
646 #[test]
647 fn op_size() {
648 let tokens = [push(&[0xaa, 0xbb, 0xcc]), op(Opcode::OpSize)];
649 let mut stack = Stack::new();
650 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
651 assert_eq!(stack.pop().unwrap(), vec![3]); assert_eq!(stack.pop().unwrap(), vec![0xaa, 0xbb, 0xcc]); }
654
655 #[test]
658 fn op_equal_true() {
659 let tokens = [
660 push(&[0x01, 0x02]),
661 push(&[0x01, 0x02]),
662 op(Opcode::OpEqual),
663 ];
664 assert_eq!(execute(&tokens).unwrap(), true);
665 }
666
667 #[test]
668 fn op_equal_false() {
669 let tokens = [push(&[0x01]), push(&[0x02]), op(Opcode::OpEqual)];
670 assert_eq!(execute(&tokens).unwrap(), false);
671 }
672
673 #[test]
674 fn op_equalverify_pass() {
675 let tokens = [
676 push(&[0xaa]),
677 push(&[0xaa]),
678 op(Opcode::OpEqualVerify),
679 op(Opcode::Op1),
680 ];
681 assert_eq!(execute(&tokens).unwrap(), true);
682 }
683
684 #[test]
685 fn op_equalverify_fail() {
686 let tokens = [push(&[0xaa]), push(&[0xbb]), op(Opcode::OpEqualVerify)];
687 let err = execute(&tokens).unwrap_err();
688 assert!(matches!(err, ScriptError::VerifyFailed));
689 }
690
691 #[test]
694 fn op_not_zero_becomes_one() {
695 let tokens = [op(Opcode::Op0), op(Opcode::OpNot)];
696 assert_eq!(execute(&tokens).unwrap(), true);
697 }
698
699 #[test]
700 fn op_not_one_becomes_zero() {
701 let tokens = [op(Opcode::Op1), op(Opcode::OpNot)];
702 assert_eq!(execute(&tokens).unwrap(), false);
703 }
704
705 #[test]
706 fn op_not_other_becomes_zero() {
707 let tokens = [op(Opcode::Op2), op(Opcode::OpNot)];
708 assert_eq!(execute(&tokens).unwrap(), false);
709 }
710
711 #[test]
714 fn op_sha256() {
715 let tokens = [push(b""), op(Opcode::OpSha256)];
716 let mut stack = Stack::new();
717 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
718 let result = stack.pop().unwrap();
719 assert_eq!(result.len(), 32);
720 assert_eq!(result, hash::sha256(b"").to_vec());
721 }
722
723 #[test]
724 fn op_hash160() {
725 let tokens = [push(b"test"), op(Opcode::OpHash160)];
726 let mut stack = Stack::new();
727 execute_on_stack(&tokens, &mut stack, &ExecuteOpts::default()).unwrap();
728 let result = stack.pop().unwrap();
729 assert_eq!(result.len(), 20);
730 assert_eq!(result, hash::hash160(b"test").to_vec());
731 }
732
733 #[test]
736 fn checksig_stub_always_true() {
737 let tokens = [push(&[0x00]), push(&[0x00]), op(Opcode::OpCheckSig)];
738 assert_eq!(execute(&tokens).unwrap(), true);
739 }
740
741 #[test]
742 fn checksigverify_stub() {
743 let tokens = [
744 push(&[0x00]),
745 push(&[0x00]),
746 op(Opcode::OpCheckSigVerify),
747 op(Opcode::Op1),
748 ];
749 assert_eq!(execute(&tokens).unwrap(), true);
750 }
751
752 #[test]
755 fn encode_num_zero() {
756 assert_eq!(encode_num(0), vec![]);
757 }
758
759 #[test]
760 fn encode_num_positive() {
761 assert_eq!(encode_num(1), vec![0x01]);
762 assert_eq!(encode_num(127), vec![0x7f]);
763 assert_eq!(encode_num(128), vec![0x80, 0x00]); assert_eq!(encode_num(255), vec![0xff, 0x00]);
765 assert_eq!(encode_num(256), vec![0x00, 0x01]);
766 }
767
768 #[test]
769 fn encode_num_negative() {
770 assert_eq!(encode_num(-1), vec![0x81]);
771 assert_eq!(encode_num(-127), vec![0xff]);
772 assert_eq!(encode_num(-128), vec![0x80, 0x80]);
773 }
774
775 #[test]
778 fn dup_empty_stack() {
779 let err = execute(&[op(Opcode::OpDup)]).unwrap_err();
780 assert!(matches!(err, ScriptError::StackUnderflow));
781 }
782
783 #[test]
784 fn equal_needs_two() {
785 let err = execute(&[op(Opcode::Op1), op(Opcode::OpEqual)]).unwrap_err();
786 assert!(matches!(err, ScriptError::StackUnderflow));
787 }
788}