1pub mod config;
29pub mod error;
31pub mod flags;
33mod ops_arithmetic;
34mod ops_crypto;
35mod ops_data;
36mod ops_flow;
37mod ops_stack;
38pub mod parsed_opcode;
40pub mod scriptnum;
42pub mod stack;
44pub mod thread;
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 ripemd::{Digest, Ripemd160};
188 use sha2::{Digest as D2, Sha256};
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!(
209 result.is_ok(),
210 "P2PKH-like hash verification should pass: {:?}",
211 result.err()
212 );
213 }
214
215 #[test]
216 fn test_op_if_else_endif() {
217 let unlock = Script::from_bytes(&[]);
219 let lock = Script::from_bytes(&[OP_1, OP_IF, OP_2, OP_ELSE, OP_3, OP_ENDIF]);
220 let engine = Engine::new();
223 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
224 assert!(
226 result.is_ok(),
227 "IF/ELSE/ENDIF should work: {:?}",
228 result.err()
229 );
230 }
231
232 #[test]
233 fn test_op_notif() {
234 let unlock = Script::from_bytes(&[]);
235 let lock = Script::from_bytes(&[OP_0, OP_NOTIF, OP_1, OP_ELSE, OP_0, OP_ENDIF]);
236 let engine = Engine::new();
237 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
238 assert!(
239 result.is_ok(),
240 "NOTIF with false should execute first branch"
241 );
242 }
243
244 #[test]
245 fn test_op_return_before_genesis() {
246 let unlock = Script::from_bytes(&[OP_1]);
247 let lock = Script::from_bytes(&[OP_RETURN]);
248 let engine = Engine::new();
249 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
250 assert!(result.is_err(), "OP_RETURN before genesis should fail");
251 }
252
253 #[test]
254 fn test_op_return_after_genesis() {
255 let unlock = Script::from_bytes(&[OP_1]);
256 let lock = Script::from_bytes(&[OP_1, OP_RETURN, 0x01, 0x02, 0x03]);
257 let engine = Engine::new();
258 let result = engine.execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0);
259 assert!(
260 result.is_ok(),
261 "OP_RETURN after genesis with OP_1 before should succeed: {:?}",
262 result.err()
263 );
264 }
265
266 #[test]
267 fn test_op_depth() {
268 let unlock = Script::from_bytes(&[OP_1, OP_2, OP_3]);
270 let lock = Script::from_bytes(&[OP_DEPTH, OP_3, OP_EQUAL]);
271 let engine = Engine::new();
272 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
276 assert!(result.is_ok(), "DEPTH should return 3: {:?}", result.err());
277 }
278
279 #[test]
280 fn test_op_size() {
281 let unlock = Script::from_bytes(&[0x03, 0xaa, 0xbb, 0xcc]);
283 let lock = Script::from_bytes(&[OP_SIZE, OP_3, OP_EQUALVERIFY, OP_1]);
284 let engine = Engine::new();
285 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
286 assert!(
287 result.is_ok(),
288 "SIZE of 3-byte element should be 3: {:?}",
289 result.err()
290 );
291 }
292
293 #[test]
294 fn test_op_cat() {
295 let unlock = Script::from_bytes(&[0x01, 0xaa, 0x01, 0xbb]);
297 let lock = Script::from_bytes(&[OP_CAT, 0x02, 0xaa, 0xbb, OP_EQUAL]);
298 let engine = Engine::new();
299 let result = engine.execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0);
300 assert!(result.is_ok(), "CAT should concatenate: {:?}", result.err());
301 }
302
303 #[test]
304 fn test_op_split() {
305 let unlock = Script::from_bytes(&[0x02, 0xaa, 0xbb, OP_1]);
307 let lock =
308 Script::from_bytes(&[OP_SPLIT, 0x01, 0xbb, OP_EQUALVERIFY, 0x01, 0xaa, OP_EQUAL]);
309 let engine = Engine::new();
310 let result = engine.execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0);
311 assert!(result.is_ok(), "SPLIT should work: {:?}", result.err());
312 }
313
314 #[test]
315 fn test_op_negate() {
316 let unlock = Script::from_bytes(&[OP_1]);
318 let lock = Script::from_bytes(&[OP_NEGATE, OP_1NEGATE, OP_EQUAL]);
319 let engine = Engine::new();
320 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
321 assert!(
322 result.is_ok(),
323 "NEGATE(1) should equal -1: {:?}",
324 result.err()
325 );
326 }
327
328 #[test]
329 fn test_op_abs() {
330 let unlock = Script::from_bytes(&[OP_1NEGATE]);
332 let lock = Script::from_bytes(&[OP_ABS, OP_1, OP_EQUAL]);
333 let engine = Engine::new();
334 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
335 assert!(result.is_ok(), "ABS(-1) should equal 1: {:?}", result.err());
336 }
337
338 #[test]
339 fn test_op_not() {
340 let unlock = Script::from_bytes(&[OP_0]);
342 let lock = Script::from_bytes(&[OP_NOT]);
343 let engine = Engine::new();
344 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
345 assert!(
346 result.is_ok(),
347 "NOT(0) should be 1 (truthy): {:?}",
348 result.err()
349 );
350 }
351
352 #[test]
353 fn test_op_within() {
354 let unlock = Script::from_bytes(&[OP_3, OP_2, OP_5]);
356 let lock = Script::from_bytes(&[OP_WITHIN]);
357 let engine = Engine::new();
358 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
359 assert!(
360 result.is_ok(),
361 "3 WITHIN [2,5) should be true: {:?}",
362 result.err()
363 );
364 }
365
366 #[test]
367 fn test_op_mul() {
368 let unlock = Script::from_bytes(&[OP_3, OP_4]);
370 let lock = Script::from_bytes(&[OP_MUL, OP_12, OP_EQUAL]);
371 let engine = Engine::new();
372 let result = engine.execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0);
373 assert!(result.is_ok(), "3 * 4 should equal 12: {:?}", result.err());
374 }
375
376 #[test]
377 fn test_op_div() {
378 let unlock = Script::from_bytes(&[OP_6, OP_3]);
380 let lock = Script::from_bytes(&[OP_DIV, OP_2, OP_EQUAL]);
381 let engine = Engine::new();
382 let result = engine.execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0);
383 assert!(result.is_ok(), "6 / 3 should equal 2: {:?}", result.err());
384 }
385
386 #[test]
387 fn test_op_div_by_zero() {
388 let unlock = Script::from_bytes(&[OP_6, OP_0]);
389 let lock = Script::from_bytes(&[OP_DIV]);
390 let engine = Engine::new();
391 let result = engine.execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0);
392 assert!(result.is_err(), "Division by zero should fail");
393 let err = result.unwrap_err();
394 assert_eq!(err.code, InterpreterErrorCode::DivideByZero);
395 }
396
397 #[test]
398 fn test_op_mod() {
399 let unlock = Script::from_bytes(&[OP_7, OP_3]);
401 let lock = Script::from_bytes(&[OP_MOD, OP_1, OP_EQUAL]);
402 let engine = Engine::new();
403 let result = engine.execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0);
404 assert!(result.is_ok(), "7 % 3 should equal 1: {:?}", result.err());
405 }
406
407 #[test]
408 fn test_op_booland() {
409 let unlock = Script::from_bytes(&[OP_1, OP_1]);
411 let lock = Script::from_bytes(&[OP_BOOLAND]);
412 let engine = Engine::new();
413 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
414 assert!(result.is_ok());
415
416 let unlock2 = Script::from_bytes(&[OP_1, OP_0]);
418 let lock2 = Script::from_bytes(&[OP_BOOLAND, OP_NOT]);
419 let result2 = engine.execute(&unlock2, &lock2, ScriptFlags::NONE, None, 0);
420 assert!(result2.is_ok());
421 }
422
423 #[test]
424 fn test_op_numequal() {
425 let unlock = Script::from_bytes(&[OP_5, OP_5]);
426 let lock = Script::from_bytes(&[OP_NUMEQUAL]);
427 let engine = Engine::new();
428 assert!(engine
429 .execute(&unlock, &lock, ScriptFlags::NONE, None, 0)
430 .is_ok());
431 }
432
433 #[test]
434 fn test_op_lessthan() {
435 let unlock = Script::from_bytes(&[OP_3, OP_5]);
436 let lock = Script::from_bytes(&[OP_LESSTHAN]);
437 let engine = Engine::new();
438 assert!(engine
439 .execute(&unlock, &lock, ScriptFlags::NONE, None, 0)
440 .is_ok());
441 }
442
443 #[test]
444 fn test_hash_ops() {
445 let unlock = Script::from_bytes(&[OP_0]);
447 let lock = Script::from_bytes(&[OP_SHA256, OP_SIZE, 0x01, 0x20, OP_EQUALVERIFY, OP_1]);
448 let engine = Engine::new();
449 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
450 assert!(
451 result.is_ok(),
452 "SHA256 should produce 32 bytes: {:?}",
453 result.err()
454 );
455 }
456
457 #[test]
458 fn test_op_pick_roll() {
459 let unlock = Script::from_bytes(&[OP_1, OP_2, OP_3, OP_2]);
461 let lock = Script::from_bytes(&[
462 OP_PICK,
463 OP_1,
464 OP_EQUALVERIFY,
465 OP_3,
466 OP_EQUALVERIFY,
467 OP_2,
468 OP_EQUALVERIFY,
469 OP_1,
470 ]);
471 let engine = Engine::new();
472 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
473 assert!(
474 result.is_ok(),
475 "PICK should copy element: {:?}",
476 result.err()
477 );
478 }
479
480 #[test]
481 fn test_op_toaltstack_fromaltstack() {
482 let unlock = Script::from_bytes(&[OP_5]);
483 let lock = Script::from_bytes(&[OP_TOALTSTACK, OP_FROMALTSTACK, OP_5, OP_EQUAL]);
484 let engine = Engine::new();
485 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
486 assert!(
487 result.is_ok(),
488 "TOALTSTACK/FROMALTSTACK: {:?}",
489 result.err()
490 );
491 }
492
493 #[test]
494 fn test_disabled_opcodes() {
495 let unlock = Script::from_bytes(&[OP_1]);
496 let lock = Script::from_bytes(&[OP_2MUL]);
497 let engine = Engine::new();
498 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
499 assert!(result.is_err());
500 assert_eq!(
501 result.unwrap_err().code,
502 InterpreterErrorCode::DisabledOpcode
503 );
504 }
505
506 #[test]
507 fn test_op_invert() {
508 let unlock = Script::from_bytes(&[0x01, 0x00]);
510 let lock = Script::from_bytes(&[OP_INVERT, 0x01, 0xff, OP_EQUAL]);
511 let engine = Engine::new();
512 let result = engine.execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0);
513 assert!(
514 result.is_ok(),
515 "INVERT should flip bits: {:?}",
516 result.err()
517 );
518 }
519
520 #[test]
521 fn test_op_and_or_xor() {
522 let unlock = Script::from_bytes(&[0x01, 0xff, 0x01, 0x0f]);
524 let lock = Script::from_bytes(&[OP_AND, 0x01, 0x0f, OP_EQUAL]);
525 let engine = Engine::new();
526 assert!(engine
527 .execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0,)
528 .is_ok());
529
530 let unlock2 = Script::from_bytes(&[0x01, 0xf0, 0x01, 0x0f]);
532 let lock2 = Script::from_bytes(&[OP_OR, 0x01, 0xff, OP_EQUAL]);
533 assert!(engine
534 .execute(&unlock2, &lock2, ScriptFlags::UTXO_AFTER_GENESIS, None, 0,)
535 .is_ok());
536
537 let unlock3 = Script::from_bytes(&[0x01, 0xff, 0x01, 0xff]);
539 let lock3 = Script::from_bytes(&[OP_XOR, 0x01, 0x00, OP_EQUAL]);
540 assert!(engine
541 .execute(&unlock3, &lock3, ScriptFlags::UTXO_AFTER_GENESIS, None, 0,)
542 .is_ok());
543 }
544
545 #[test]
546 fn test_op_rot() {
547 let unlock = Script::from_bytes(&[OP_1, OP_2, OP_3]);
549 let lock = Script::from_bytes(&[
550 OP_ROT,
551 OP_1,
552 OP_EQUALVERIFY, OP_3,
554 OP_EQUALVERIFY,
555 OP_2,
556 OP_EQUAL,
557 ]);
558 let engine = Engine::new();
559 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
560 assert!(result.is_ok(), "ROT should rotate: {:?}", result.err());
561 }
562
563 #[test]
564 fn test_op_tuck() {
565 let unlock = Script::from_bytes(&[OP_1, OP_2]);
567 let lock = Script::from_bytes(&[
568 OP_TUCK,
569 OP_2,
570 OP_EQUALVERIFY,
571 OP_1,
572 OP_EQUALVERIFY,
573 OP_2,
574 OP_EQUAL,
575 ]);
576 let engine = Engine::new();
577 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
578 assert!(result.is_ok(), "TUCK should work: {:?}", result.err());
579 }
580
581 #[test]
582 fn test_op_2dup() {
583 let unlock = Script::from_bytes(&[OP_1, OP_2]);
584 let lock = Script::from_bytes(&[
585 OP_2DUP,
586 OP_2,
587 OP_EQUALVERIFY,
588 OP_1,
589 OP_EQUALVERIFY,
590 OP_2,
591 OP_EQUALVERIFY,
592 OP_1,
593 OP_EQUAL,
594 ]);
595 let engine = Engine::new();
596 assert!(engine
597 .execute(&unlock, &lock, ScriptFlags::NONE, None, 0)
598 .is_ok());
599 }
600
601 #[test]
602 fn test_empty_both_scripts() {
603 let engine = Engine::new();
604 let result = engine.execute(&Script::new(), &Script::new(), ScriptFlags::NONE, None, 0);
605 assert!(result.is_err());
606 assert_eq!(result.unwrap_err().code, InterpreterErrorCode::EvalFalse);
607 }
608
609 #[test]
610 fn test_op_greaterthan() {
611 let unlock = Script::from_bytes(&[OP_5, OP_3]);
612 let lock = Script::from_bytes(&[OP_GREATERTHAN]);
613 let engine = Engine::new();
614 assert!(engine
615 .execute(&unlock, &lock, ScriptFlags::NONE, None, 0)
616 .is_ok());
617 }
618
619 #[test]
620 fn test_op_min_max() {
621 let unlock = Script::from_bytes(&[OP_3, OP_5]);
623 let lock = Script::from_bytes(&[OP_MIN, OP_3, OP_EQUAL]);
624 let engine = Engine::new();
625 assert!(engine
626 .execute(&unlock, &lock, ScriptFlags::NONE, None, 0)
627 .is_ok());
628
629 let unlock2 = Script::from_bytes(&[OP_3, OP_5]);
631 let lock2 = Script::from_bytes(&[OP_MAX, OP_5, OP_EQUAL]);
632 assert!(engine
633 .execute(&unlock2, &lock2, ScriptFlags::NONE, None, 0)
634 .is_ok());
635 }
636
637 #[test]
638 fn test_op_verify_fail() {
639 let unlock = Script::from_bytes(&[OP_0]);
640 let lock = Script::from_bytes(&[OP_VERIFY]);
641 let engine = Engine::new();
642 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
643 assert!(result.is_err());
644 assert_eq!(result.unwrap_err().code, InterpreterErrorCode::Verify);
645 }
646
647 #[test]
648 fn test_nested_if() {
649 let unlock = Script::from_bytes(&[]);
651 let lock = Script::from_bytes(&[OP_1, OP_IF, OP_1, OP_IF, OP_2, OP_ENDIF, OP_ENDIF]);
652 let engine = Engine::new();
653 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
654 assert!(result.is_ok(), "Nested IF should work: {:?}", result.err());
655 }
656
657 #[test]
658 fn test_unbalanced_if() {
659 let unlock = Script::from_bytes(&[OP_1]);
660 let lock = Script::from_bytes(&[OP_IF]);
661 let engine = Engine::new();
662 let result = engine.execute(&unlock, &lock, ScriptFlags::NONE, None, 0);
663 assert!(result.is_err());
664 assert_eq!(
665 result.unwrap_err().code,
666 InterpreterErrorCode::UnbalancedConditional
667 );
668 }
669
670 #[test]
671 fn test_op_ifdup() {
672 let unlock = Script::from_bytes(&[OP_1]);
674 let lock = Script::from_bytes(&[OP_IFDUP, OP_EQUAL]);
675 let engine = Engine::new();
676 assert!(engine
677 .execute(&unlock, &lock, ScriptFlags::NONE, None, 0)
678 .is_ok());
679 }
680
681 #[test]
682 fn test_clean_stack_without_bip16() {
683 let engine = Engine::new();
684 let result = engine.execute(
685 &Script::from_bytes(&[OP_1]),
686 &Script::from_bytes(&[OP_1]),
687 ScriptFlags::VERIFY_CLEAN_STACK,
688 None,
689 0,
690 );
691 assert!(result.is_err());
692 assert_eq!(result.unwrap_err().code, InterpreterErrorCode::InvalidFlags);
693 }
694
695 #[test]
696 fn test_lshift_rshift() {
697 let unlock = Script::from_bytes(&[0x01, 0x01, OP_1]);
701 let lock = Script::from_bytes(&[OP_LSHIFT, 0x01, 0x02, OP_EQUAL]);
702 let engine = Engine::new();
703 let result = engine.execute(&unlock, &lock, ScriptFlags::UTXO_AFTER_GENESIS, None, 0);
704 assert!(result.is_ok(), "LSHIFT should work: {:?}", result.err());
705 }
706}