1pub mod config;
29pub mod error;
31pub mod flags;
33pub mod parsed_opcode;
35pub mod scriptnum;
37pub mod stack;
39pub mod thread;
41mod ops_arithmetic;
42mod ops_crypto;
43mod ops_data;
44mod ops_flow;
45mod ops_stack;
46
47pub use config::Config;
48pub use error::{InterpreterError, InterpreterErrorCode};
49pub use flags::ScriptFlags;
50pub use parsed_opcode::{ParsedOpcode, ParsedScript};
51pub use scriptnum::ScriptNumber;
52pub use stack::Stack;
53
54use crate::Script;
55use thread::Thread;
56
57pub trait TxContext {
63 fn verify_signature(
73 &self,
74 full_sig: &[u8],
75 pub_key: &[u8],
76 sub_script: &Script,
77 input_idx: usize,
78 sighash_flag: u32,
79 ) -> Result<bool, InterpreterError>;
80
81 fn lock_time(&self) -> u32;
83
84 fn tx_version(&self) -> u32;
86
87 fn input_sequence(&self, input_idx: usize) -> u32;
89}
90
91pub struct Engine;
93
94impl Engine {
95 pub fn new() -> Self {
97 Engine
98 }
99
100 pub fn execute(
109 &self,
110 unlocking_script: &Script,
111 locking_script: &Script,
112 flags: ScriptFlags,
113 tx_context: Option<&dyn TxContext>,
114 input_idx: usize,
115 ) -> Result<(), InterpreterError> {
116 let mut thread = Thread::new(
117 unlocking_script,
118 locking_script,
119 flags,
120 tx_context,
121 input_idx,
122 )?;
123 thread.execute()
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use crate::opcodes::*;
131
132 #[test]
133 fn test_simple_true() {
134 let unlock = Script::from_bytes(&[OP_TRUE]);
136 let lock = Script::from_bytes(&[]);
137 }
142
143 #[test]
144 fn test_op_1_op_1_op_equal() {
145 let unlock = Script::from_bytes(&[OP_1]);
147 let lock = Script::from_bytes(&[OP_1, OP_EQUAL]);
148 let engine = Engine::new();
149 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
150 assert!(result.is_ok(), "OP_1 OP_1 OP_EQUAL should succeed");
151 }
152
153 #[test]
154 fn test_op_1_op_2_op_equal_fails() {
155 let unlock = Script::from_bytes(&[OP_1]);
156 let lock = Script::from_bytes(&[OP_2, OP_EQUAL]);
157 let engine = Engine::new();
158 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
159 assert!(result.is_err(), "OP_1 OP_2 OP_EQUAL should fail");
160 }
161
162 #[test]
163 fn test_op_add() {
164 let unlock = Script::from_bytes(&[OP_2, OP_3]);
166 let lock = Script::from_bytes(&[OP_ADD, OP_5, OP_EQUAL]);
167 let engine = Engine::new();
168 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
169 assert!(result.is_ok(), "2 + 3 should equal 5");
170 }
171
172 #[test]
173 fn test_op_sub() {
174 let unlock = Script::from_bytes(&[OP_5, OP_3]);
176 let lock = Script::from_bytes(&[OP_SUB, OP_2, OP_EQUAL]);
177 let engine = Engine::new();
178 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
179 assert!(result.is_ok(), "5 - 3 should equal 2");
180 }
181
182 #[test]
183 fn test_op_dup_hash160_equalverify() {
184 use sha2::{Sha256, Digest as D2};
188 use ripemd::{Ripemd160, Digest};
189
190 let pubkey = vec![0x04; 33]; let sha = Sha256::digest(&pubkey);
192 let hash160 = Ripemd160::digest(&sha);
193
194 let mut unlock_bytes = vec![pubkey.len() as u8];
195 unlock_bytes.extend_from_slice(&pubkey);
196
197 let mut lock_bytes = vec![OP_DUP, OP_HASH160];
198 lock_bytes.push(hash160.len() as u8);
199 lock_bytes.extend_from_slice(&hash160);
200 lock_bytes.push(OP_EQUALVERIFY);
201 lock_bytes.push(OP_1);
203
204 let unlock = Script::from_bytes(&unlock_bytes);
205 let lock = Script::from_bytes(&lock_bytes);
206 let engine = Engine::new();
207 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
208 assert!(result.is_ok(), "P2PKH-like hash verification should pass: {:?}", result.err());
209 }
210
211 #[test]
212 fn test_op_if_else_endif() {
213 let unlock = Script::from_bytes(&[]);
215 let lock = Script::from_bytes(&[OP_1, OP_IF, OP_2, OP_ELSE, OP_3, OP_ENDIF]);
216 let engine = Engine::new();
219 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
220 assert!(result.is_ok(), "IF/ELSE/ENDIF should work: {:?}", result.err());
222 }
223
224 #[test]
225 fn test_op_notif() {
226 let unlock = Script::from_bytes(&[]);
227 let lock = Script::from_bytes(&[OP_0, OP_NOTIF, OP_1, OP_ELSE, OP_0, OP_ENDIF]);
228 let engine = Engine::new();
229 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
230 assert!(result.is_ok(), "NOTIF with false should execute first branch");
231 }
232
233 #[test]
234 fn test_op_return_before_genesis() {
235 let unlock = Script::from_bytes(&[OP_1]);
236 let lock = Script::from_bytes(&[OP_RETURN]);
237 let engine = Engine::new();
238 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
239 assert!(result.is_err(), "OP_RETURN before genesis should fail");
240 }
241
242 #[test]
243 fn test_op_return_after_genesis() {
244 let unlock = Script::from_bytes(&[OP_1]);
245 let lock = Script::from_bytes(&[OP_1, OP_RETURN, 0x01, 0x02, 0x03]);
246 let engine = Engine::new();
247 let result = engine.execute(
248 &unlock,
249 &lock,
250 ScriptFlags::UTXO_AFTER_GENESIS,
251 None,
252 0,
253 );
254 assert!(result.is_ok(), "OP_RETURN after genesis with OP_1 before should succeed: {:?}", result.err());
255 }
256
257 #[test]
258 fn test_op_depth() {
259 let unlock = Script::from_bytes(&[OP_1, OP_2, OP_3]);
261 let lock = Script::from_bytes(&[OP_DEPTH, OP_3, OP_EQUAL]);
262 let engine = Engine::new();
263 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
267 assert!(result.is_ok(), "DEPTH should return 3: {:?}", result.err());
268 }
269
270 #[test]
271 fn test_op_size() {
272 let unlock = Script::from_bytes(&[0x03, 0xaa, 0xbb, 0xcc]);
274 let lock = Script::from_bytes(&[OP_SIZE, OP_3, OP_EQUALVERIFY, OP_1]);
275 let engine = Engine::new();
276 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
277 assert!(result.is_ok(), "SIZE of 3-byte element should be 3: {:?}", result.err());
278 }
279
280 #[test]
281 fn test_op_cat() {
282 let unlock = Script::from_bytes(&[0x01, 0xaa, 0x01, 0xbb]);
284 let lock = Script::from_bytes(&[OP_CAT, 0x02, 0xaa, 0xbb, OP_EQUAL]);
285 let engine = Engine::new();
286 let result = engine.execute(
287 &unlock,
288 &lock,
289 ScriptFlags::UTXO_AFTER_GENESIS,
290 None,
291 0,
292 );
293 assert!(result.is_ok(), "CAT should concatenate: {:?}", result.err());
294 }
295
296 #[test]
297 fn test_op_split() {
298 let unlock = Script::from_bytes(&[0x02, 0xaa, 0xbb, OP_1]);
300 let lock = Script::from_bytes(&[OP_SPLIT, 0x01, 0xbb, OP_EQUALVERIFY, 0x01, 0xaa, OP_EQUAL]);
301 let engine = Engine::new();
302 let result = engine.execute(
303 &unlock,
304 &lock,
305 ScriptFlags::UTXO_AFTER_GENESIS,
306 None,
307 0,
308 );
309 assert!(result.is_ok(), "SPLIT should work: {:?}", result.err());
310 }
311
312 #[test]
313 fn test_op_negate() {
314 let unlock = Script::from_bytes(&[OP_1]);
316 let lock = Script::from_bytes(&[OP_NEGATE, OP_1NEGATE, OP_EQUAL]);
317 let engine = Engine::new();
318 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
319 assert!(result.is_ok(), "NEGATE(1) should equal -1: {:?}", result.err());
320 }
321
322 #[test]
323 fn test_op_abs() {
324 let unlock = Script::from_bytes(&[OP_1NEGATE]);
326 let lock = Script::from_bytes(&[OP_ABS, OP_1, OP_EQUAL]);
327 let engine = Engine::new();
328 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
329 assert!(result.is_ok(), "ABS(-1) should equal 1: {:?}", result.err());
330 }
331
332 #[test]
333 fn test_op_not() {
334 let unlock = Script::from_bytes(&[OP_0]);
336 let lock = Script::from_bytes(&[OP_NOT]);
337 let engine = Engine::new();
338 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
339 assert!(result.is_ok(), "NOT(0) should be 1 (truthy): {:?}", result.err());
340 }
341
342 #[test]
343 fn test_op_within() {
344 let unlock = Script::from_bytes(&[OP_3, OP_2, OP_5]);
346 let lock = Script::from_bytes(&[OP_WITHIN]);
347 let engine = Engine::new();
348 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
349 assert!(result.is_ok(), "3 WITHIN [2,5) should be true: {:?}", result.err());
350 }
351
352 #[test]
353 fn test_op_mul() {
354 let unlock = Script::from_bytes(&[OP_3, OP_4]);
356 let lock = Script::from_bytes(&[OP_MUL, OP_12, OP_EQUAL]);
357 let engine = Engine::new();
358 let result = engine.execute(
359 &unlock,
360 &lock,
361 ScriptFlags::UTXO_AFTER_GENESIS,
362 None,
363 0,
364 );
365 assert!(result.is_ok(), "3 * 4 should equal 12: {:?}", result.err());
366 }
367
368 #[test]
369 fn test_op_div() {
370 let unlock = Script::from_bytes(&[OP_6, OP_3]);
372 let lock = Script::from_bytes(&[OP_DIV, OP_2, OP_EQUAL]);
373 let engine = Engine::new();
374 let result = engine.execute(
375 &unlock,
376 &lock,
377 ScriptFlags::UTXO_AFTER_GENESIS,
378 None,
379 0,
380 );
381 assert!(result.is_ok(), "6 / 3 should equal 2: {:?}", result.err());
382 }
383
384 #[test]
385 fn test_op_div_by_zero() {
386 let unlock = Script::from_bytes(&[OP_6, OP_0]);
387 let lock = Script::from_bytes(&[OP_DIV]);
388 let engine = Engine::new();
389 let result = engine.execute(
390 &unlock,
391 &lock,
392 ScriptFlags::UTXO_AFTER_GENESIS,
393 None,
394 0,
395 );
396 assert!(result.is_err(), "Division by zero should fail");
397 let err = result.unwrap_err();
398 assert_eq!(err.code, InterpreterErrorCode::DivideByZero);
399 }
400
401 #[test]
402 fn test_op_mod() {
403 let unlock = Script::from_bytes(&[OP_7, OP_3]);
405 let lock = Script::from_bytes(&[OP_MOD, OP_1, OP_EQUAL]);
406 let engine = Engine::new();
407 let result = engine.execute(
408 &unlock,
409 &lock,
410 ScriptFlags::UTXO_AFTER_GENESIS,
411 None,
412 0,
413 );
414 assert!(result.is_ok(), "7 % 3 should equal 1: {:?}", result.err());
415 }
416
417 #[test]
418 fn test_op_booland() {
419 let unlock = Script::from_bytes(&[OP_1, OP_1]);
421 let lock = Script::from_bytes(&[OP_BOOLAND]);
422 let engine = Engine::new();
423 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
424 assert!(result.is_ok());
425
426 let unlock2 = Script::from_bytes(&[OP_1, OP_0]);
428 let lock2 = Script::from_bytes(&[OP_BOOLAND, OP_NOT]);
429 let result2 = engine.execute(&unlock2, &lock2, ScriptFlags::NONE, None, 0);
430 assert!(result2.is_ok());
431 }
432
433 #[test]
434 fn test_op_numequal() {
435 let unlock = Script::from_bytes(&[OP_5, OP_5]);
436 let lock = Script::from_bytes(&[OP_NUMEQUAL]);
437 let engine = Engine::new();
438 assert!(engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0).is_ok());
439 }
440
441 #[test]
442 fn test_op_lessthan() {
443 let unlock = Script::from_bytes(&[OP_3, OP_5]);
444 let lock = Script::from_bytes(&[OP_LESSTHAN]);
445 let engine = Engine::new();
446 assert!(engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0).is_ok());
447 }
448
449 #[test]
450 fn test_hash_ops() {
451 let unlock = Script::from_bytes(&[OP_0]);
453 let lock = Script::from_bytes(&[OP_SHA256, OP_SIZE, 0x01, 0x20, OP_EQUALVERIFY, OP_1]);
454 let engine = Engine::new();
455 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
456 assert!(result.is_ok(), "SHA256 should produce 32 bytes: {:?}", result.err());
457 }
458
459 #[test]
460 fn test_op_pick_roll() {
461 let unlock = Script::from_bytes(&[OP_1, OP_2, OP_3, OP_2]);
463 let lock = Script::from_bytes(&[OP_PICK, OP_1, OP_EQUALVERIFY, OP_3, OP_EQUALVERIFY, OP_2, OP_EQUALVERIFY, OP_1]);
464 let engine = Engine::new();
465 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
466 assert!(result.is_ok(), "PICK should copy element: {:?}", result.err());
467 }
468
469 #[test]
470 fn test_op_toaltstack_fromaltstack() {
471 let unlock = Script::from_bytes(&[OP_5]);
472 let lock = Script::from_bytes(&[OP_TOALTSTACK, OP_FROMALTSTACK, OP_5, OP_EQUAL]);
473 let engine = Engine::new();
474 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
475 assert!(result.is_ok(), "TOALTSTACK/FROMALTSTACK: {:?}", result.err());
476 }
477
478 #[test]
479 fn test_disabled_opcodes() {
480 let unlock = Script::from_bytes(&[OP_1]);
481 let lock = Script::from_bytes(&[OP_2MUL]);
482 let engine = Engine::new();
483 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
484 assert!(result.is_err());
485 assert_eq!(result.unwrap_err().code, InterpreterErrorCode::DisabledOpcode);
486 }
487
488 #[test]
489 fn test_op_invert() {
490 let unlock = Script::from_bytes(&[0x01, 0x00]);
492 let lock = Script::from_bytes(&[OP_INVERT, 0x01, 0xff, OP_EQUAL]);
493 let engine = Engine::new();
494 let result = engine.execute(
495 &unlock,
496 &lock,
497 ScriptFlags::UTXO_AFTER_GENESIS,
498 None,
499 0,
500 );
501 assert!(result.is_ok(), "INVERT should flip bits: {:?}", result.err());
502 }
503
504 #[test]
505 fn test_op_and_or_xor() {
506 let unlock = Script::from_bytes(&[0x01, 0xff, 0x01, 0x0f]);
508 let lock = Script::from_bytes(&[OP_AND, 0x01, 0x0f, OP_EQUAL]);
509 let engine = Engine::new();
510 assert!(engine.execute(
511 &unlock,
512 &lock,
513 ScriptFlags::UTXO_AFTER_GENESIS,
514 None,
515 0,
516 ).is_ok());
517
518 let unlock2 = Script::from_bytes(&[0x01, 0xf0, 0x01, 0x0f]);
520 let lock2 = Script::from_bytes(&[OP_OR, 0x01, 0xff, OP_EQUAL]);
521 assert!(engine.execute(
522 &unlock2,
523 &lock2,
524 ScriptFlags::UTXO_AFTER_GENESIS,
525 None,
526 0,
527 ).is_ok());
528
529 let unlock3 = Script::from_bytes(&[0x01, 0xff, 0x01, 0xff]);
531 let lock3 = Script::from_bytes(&[OP_XOR, 0x01, 0x00, OP_EQUAL]);
532 assert!(engine.execute(
533 &unlock3,
534 &lock3,
535 ScriptFlags::UTXO_AFTER_GENESIS,
536 None,
537 0,
538 ).is_ok());
539 }
540
541 #[test]
542 fn test_op_rot() {
543 let unlock = Script::from_bytes(&[OP_1, OP_2, OP_3]);
545 let lock = Script::from_bytes(&[
546 OP_ROT,
547 OP_1, OP_EQUALVERIFY, OP_3, OP_EQUALVERIFY,
549 OP_2,OP_EQUAL,
550 ]);
551 let engine = Engine::new();
552 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
553 assert!(result.is_ok(), "ROT should rotate: {:?}", result.err());
554 }
555
556 #[test]
557 fn test_op_tuck() {
558 let unlock = Script::from_bytes(&[OP_1, OP_2]);
560 let lock = Script::from_bytes(&[
561 OP_TUCK,
562 OP_2, OP_EQUALVERIFY,
563 OP_1, OP_EQUALVERIFY,
564 OP_2, OP_EQUAL,
565 ]);
566 let engine = Engine::new();
567 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
568 assert!(result.is_ok(), "TUCK should work: {:?}", result.err());
569 }
570
571 #[test]
572 fn test_op_2dup() {
573 let unlock = Script::from_bytes(&[OP_1, OP_2]);
574 let lock = Script::from_bytes(&[
575 OP_2DUP,
576 OP_2, OP_EQUALVERIFY,
577 OP_1, OP_EQUALVERIFY,
578 OP_2, OP_EQUALVERIFY,
579 OP_1, OP_EQUAL,
580 ]);
581 let engine = Engine::new();
582 assert!(engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0).is_ok());
583 }
584
585 #[test]
586 fn test_empty_both_scripts() {
587 let engine = Engine::new();
588 let result = engine.execute(
589 &Script::new(),
590 &Script::new(),
591 ScriptFlags::NONE,
592 None,
593 0,
594 );
595 assert!(result.is_err());
596 assert_eq!(result.unwrap_err().code, InterpreterErrorCode::EvalFalse);
597 }
598
599 #[test]
600 fn test_op_greaterthan() {
601 let unlock = Script::from_bytes(&[OP_5, OP_3]);
602 let lock = Script::from_bytes(&[OP_GREATERTHAN]);
603 let engine = Engine::new();
604 assert!(engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0).is_ok());
605 }
606
607 #[test]
608 fn test_op_min_max() {
609 let unlock = Script::from_bytes(&[OP_3, OP_5]);
611 let lock = Script::from_bytes(&[OP_MIN, OP_3, OP_EQUAL]);
612 let engine = Engine::new();
613 assert!(engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0).is_ok());
614
615 let unlock2 = Script::from_bytes(&[OP_3, OP_5]);
617 let lock2 = Script::from_bytes(&[OP_MAX, OP_5, OP_EQUAL]);
618 assert!(engine.execute(&unlock2, &lock2, ScriptFlags::NONE, None, 0).is_ok());
619 }
620
621 #[test]
622 fn test_op_verify_fail() {
623 let unlock = Script::from_bytes(&[OP_0]);
624 let lock = Script::from_bytes(&[OP_VERIFY]);
625 let engine = Engine::new();
626 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
627 assert!(result.is_err());
628 assert_eq!(result.unwrap_err().code, InterpreterErrorCode::Verify);
629 }
630
631 #[test]
632 fn test_nested_if() {
633 let unlock = Script::from_bytes(&[]);
635 let lock = Script::from_bytes(&[OP_1, OP_IF, OP_1, OP_IF, OP_2, OP_ENDIF, OP_ENDIF]);
636 let engine = Engine::new();
637 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
638 assert!(result.is_ok(), "Nested IF should work: {:?}", result.err());
639 }
640
641 #[test]
642 fn test_unbalanced_if() {
643 let unlock = Script::from_bytes(&[OP_1]);
644 let lock = Script::from_bytes(&[OP_IF]);
645 let engine = Engine::new();
646 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
647 assert!(result.is_err());
648 assert_eq!(
649 result.unwrap_err().code,
650 InterpreterErrorCode::UnbalancedConditional
651 );
652 }
653
654 #[test]
655 fn test_op_ifdup() {
656 let unlock = Script::from_bytes(&[OP_1]);
658 let lock = Script::from_bytes(&[OP_IFDUP, OP_EQUAL]);
659 let engine = Engine::new();
660 assert!(engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0).is_ok());
661 }
662
663 #[test]
664 fn test_clean_stack_without_bip16() {
665 let engine = Engine::new();
666 let result = engine.execute(
667 &Script::from_bytes(&[OP_1]),
668 &Script::from_bytes(&[OP_1]),
669 ScriptFlags::VERIFY_CLEAN_STACK,
670 None,
671 0,
672 );
673 assert!(result.is_err());
674 assert_eq!(result.unwrap_err().code, InterpreterErrorCode::InvalidFlags);
675 }
676
677 #[test]
678 fn test_lshift_rshift() {
679 let unlock = Script::from_bytes(&[0x01, 0x01, OP_1]);
683 let lock = Script::from_bytes(&[OP_LSHIFT, 0x01, 0x02, OP_EQUAL]);
684 let engine = Engine::new();
685 let result = engine.execute(
686 &unlock,
687 &lock,
688 ScriptFlags::UTXO_AFTER_GENESIS,
689 None,
690 0,
691 );
692 assert!(result.is_ok(), "LSHIFT should work: {:?}", result.err());
693 }
694}