1#![allow(clippy::result_large_err)]
6use super::evaluation_error::{ExecutionContext, ScriptEvaluationError};
34use super::op::*;
35use super::script_num::ScriptNum;
36use super::{LockingScript, Script, ScriptChunk, UnlockingScript};
37use crate::primitives::bsv::sighash::{
38 compute_sighash_for_signing, SighashParams, TxInput, TxOutput, SIGHASH_FORKID,
39};
40use crate::primitives::bsv::tx_signature::TransactionSignature;
41use crate::primitives::ec::PublicKey;
42use crate::primitives::{hash160, ripemd160, sha1, sha256, sha256d, to_hex, BigNumber};
43
44const MAX_SCRIPT_ELEMENT_SIZE: usize = 1024 * 1024 * 1024;
50
51const DEFAULT_MEMORY_LIMIT: usize = 32_000_000;
53
54const MAX_MULTISIG_KEY_COUNT: i64 = i32::MAX as i64;
56
57const REQUIRE_MINIMAL_PUSH: bool = true;
59
60const REQUIRE_PUSH_ONLY_UNLOCKING: bool = true;
62
63const REQUIRE_LOW_S_SIGNATURES: bool = true;
65
66const REQUIRE_CLEAN_STACK: bool = true;
68
69lazy_static::lazy_static! {
74 static ref SCRIPTNUM_NEG_1: Vec<u8> = ScriptNum::to_bytes(&BigNumber::from_i64(-1));
76
77 static ref SCRIPTNUMS_0_TO_16: Vec<Vec<u8>> = (0..=16)
79 .map(|i| ScriptNum::to_bytes(&BigNumber::from_i64(i)))
80 .collect();
81}
82
83pub struct SpendParams {
89 pub source_txid: [u8; 32],
91 pub source_output_index: u32,
93 pub source_satoshis: u64,
95 pub locking_script: LockingScript,
97 pub transaction_version: i32,
99 pub other_inputs: Vec<TxInput>,
101 pub outputs: Vec<TxOutput>,
103 pub input_index: usize,
105 pub unlocking_script: UnlockingScript,
107 pub input_sequence: u32,
109 pub lock_time: u32,
111 pub memory_limit: Option<usize>,
113}
114
115pub struct Spend {
122 source_txid: [u8; 32],
124 source_output_index: u32,
125 source_satoshis: u64,
126 locking_script: LockingScript,
127 transaction_version: i32,
128 other_inputs: Vec<TxInput>,
129 outputs: Vec<TxOutput>,
130 input_index: usize,
131 unlocking_script: UnlockingScript,
132 input_sequence: u32,
133 lock_time: u32,
134
135 context: ExecutionContext,
137 program_counter: usize,
138 last_code_separator: Option<usize>,
139 stack: Vec<Vec<u8>>,
140 alt_stack: Vec<Vec<u8>>,
141 if_stack: Vec<bool>,
142 memory_limit: usize,
143 stack_mem: usize,
144 alt_stack_mem: usize,
145}
146
147impl Spend {
148 pub fn new(params: SpendParams) -> Self {
150 let mut spend = Self {
151 source_txid: params.source_txid,
152 source_output_index: params.source_output_index,
153 source_satoshis: params.source_satoshis,
154 locking_script: params.locking_script,
155 transaction_version: params.transaction_version,
156 other_inputs: params.other_inputs,
157 outputs: params.outputs,
158 input_index: params.input_index,
159 unlocking_script: params.unlocking_script,
160 input_sequence: params.input_sequence,
161 lock_time: params.lock_time,
162 context: ExecutionContext::UnlockingScript,
163 program_counter: 0,
164 last_code_separator: None,
165 stack: Vec::new(),
166 alt_stack: Vec::new(),
167 if_stack: Vec::new(),
168 memory_limit: params.memory_limit.unwrap_or(DEFAULT_MEMORY_LIMIT),
169 stack_mem: 0,
170 alt_stack_mem: 0,
171 };
172 spend.reset();
173 spend
174 }
175
176 pub fn reset(&mut self) {
178 self.context = ExecutionContext::UnlockingScript;
179 self.program_counter = 0;
180 self.last_code_separator = None;
181 self.stack.clear();
182 self.alt_stack.clear();
183 self.if_stack.clear();
184 self.stack_mem = 0;
185 self.alt_stack_mem = 0;
186 }
187
188 pub fn validate(&mut self) -> Result<bool, ScriptEvaluationError> {
194 if REQUIRE_PUSH_ONLY_UNLOCKING && !self.unlocking_script.is_push_only() {
196 return Err(self.error(
197 "Unlocking scripts can only contain push operations, and no other opcodes.",
198 ));
199 }
200
201 while self.step()? {
203 if self.context == ExecutionContext::LockingScript
205 && self.program_counter >= self.locking_script.chunks().len()
206 {
207 break;
208 }
209 }
210
211 if !self.if_stack.is_empty() {
213 return Err(self.error(
214 "Every OP_IF, OP_NOTIF, or OP_ELSE must be terminated with OP_ENDIF prior to the end of the script.",
215 ));
216 }
217
218 if REQUIRE_CLEAN_STACK && self.stack.len() != 1 {
220 return Err(self.error(&format!(
221 "The clean stack rule requires exactly one item to be on the stack after script execution, found {}.",
222 self.stack.len()
223 )));
224 }
225
226 if self.stack.is_empty() {
228 return Err(self.error(
229 "The top stack element must be truthy after script evaluation (stack is empty).",
230 ));
231 }
232
233 if !ScriptNum::cast_to_bool(&self.stack[self.stack.len() - 1]) {
234 return Err(self.error("The top stack element must be truthy after script evaluation."));
235 }
236
237 Ok(true)
238 }
239
240 pub fn step(&mut self) -> Result<bool, ScriptEvaluationError> {
246 if self.stack_mem > self.memory_limit {
248 return Err(self.error(&format!(
249 "Stack memory usage has exceeded {} bytes",
250 self.memory_limit
251 )));
252 }
253 if self.alt_stack_mem > self.memory_limit {
254 return Err(self.error(&format!(
255 "Alt stack memory usage has exceeded {} bytes",
256 self.memory_limit
257 )));
258 }
259
260 if self.context == ExecutionContext::UnlockingScript
262 && self.program_counter >= self.unlocking_script.chunks().len()
263 {
264 self.context = ExecutionContext::LockingScript;
265 self.program_counter = 0;
266 }
267
268 let current_chunks = match self.context {
270 ExecutionContext::UnlockingScript => self.unlocking_script.chunks(),
271 ExecutionContext::LockingScript => self.locking_script.chunks(),
272 };
273
274 if self.program_counter >= current_chunks.len() {
275 return Ok(false);
276 }
277
278 let operation = ¤t_chunks[self.program_counter];
279 let current_opcode = operation.op;
280
281 if let Some(ref data) = operation.data {
283 if data.len() > MAX_SCRIPT_ELEMENT_SIZE {
284 return Err(self.error(&format!(
285 "Data push > {} bytes (pc={})",
286 MAX_SCRIPT_ELEMENT_SIZE, self.program_counter
287 )));
288 }
289 }
290
291 let is_executing = !self.if_stack.contains(&false);
293
294 if is_executing && is_opcode_disabled(current_opcode) {
296 return Err(self.error(&format!(
297 "This opcode is currently disabled. (Opcode: {}, PC: {})",
298 opcode_to_name(current_opcode).unwrap_or("UNKNOWN"),
299 self.program_counter
300 )));
301 }
302
303 if is_executing && current_opcode <= OP_PUSHDATA4 {
305 if REQUIRE_MINIMAL_PUSH && !is_chunk_minimal_push(operation) {
307 return Err(self.error(&format!(
308 "This data is not minimally-encoded. (PC: {})",
309 self.program_counter
310 )));
311 }
312 let data = operation.data.clone().unwrap_or_default();
313 self.push_stack(data)?;
314 } else if is_executing || (OP_IF..=OP_ENDIF).contains(¤t_opcode) {
315 self.execute_opcode(current_opcode, operation)?;
317 }
318
319 self.program_counter += 1;
320 Ok(true)
321 }
322
323 fn execute_opcode(
328 &mut self,
329 opcode: u8,
330 chunk: &ScriptChunk,
331 ) -> Result<(), ScriptEvaluationError> {
332 let is_executing = !self.if_stack.contains(&false);
333
334 match opcode {
335 OP_1NEGATE => {
339 self.push_stack_copy(&SCRIPTNUM_NEG_1)?;
340 }
341 OP_0 => {
342 self.push_stack_copy(&SCRIPTNUMS_0_TO_16[0])?;
343 }
344 OP_1..=OP_16 => {
345 let n = (opcode - OP_1 + 1) as usize;
346 self.push_stack_copy(&SCRIPTNUMS_0_TO_16[n])?;
347 }
348
349 OP_NOP | OP_NOP1 | OP_NOP2 | OP_NOP3 | OP_NOP4 | OP_NOP5 | OP_NOP6 | OP_NOP7
353 | OP_NOP8 | OP_NOP9 | OP_NOP10 => {}
354 0xba..=0xff => {}
356
357 OP_IF | OP_NOTIF => {
361 let mut f_value = false;
362 if is_executing {
363 if self.stack.is_empty() {
364 return Err(self.error(
365 "OP_IF and OP_NOTIF require at least one item on the stack when they are used!",
366 ));
367 }
368 let buf = self.pop_stack()?;
369 f_value = ScriptNum::cast_to_bool(&buf);
370 if opcode == OP_NOTIF {
371 f_value = !f_value;
372 }
373 }
374 self.if_stack.push(f_value);
375 }
376 OP_ELSE => {
377 if self.if_stack.is_empty() {
378 return Err(self.error("OP_ELSE requires a preceeding OP_IF."));
379 }
380 let last = self.if_stack.len() - 1;
381 self.if_stack[last] = !self.if_stack[last];
382 }
383 OP_ENDIF => {
384 if self.if_stack.is_empty() {
385 return Err(self.error("OP_ENDIF requires a preceeding OP_IF."));
386 }
387 self.if_stack.pop();
388 }
389 OP_VERIFY => {
390 if self.stack.is_empty() {
391 return Err(
392 self.error("OP_VERIFY requires at least one item to be on the stack.")
393 );
394 }
395 let f_value = ScriptNum::cast_to_bool(self.stack_top()?);
396 if !f_value {
397 return Err(self.error("OP_VERIFY requires the top stack value to be truthy."));
398 }
399 self.pop_stack()?;
400 }
401 OP_RETURN => {
402 let end = match self.context {
404 ExecutionContext::UnlockingScript => self.unlocking_script.chunks().len(),
405 ExecutionContext::LockingScript => self.locking_script.chunks().len(),
406 };
407 self.program_counter = end;
408 self.if_stack.clear();
409 if self.program_counter > 0 {
411 self.program_counter -= 1;
412 }
413 }
414
415 OP_TOALTSTACK => {
419 if self.stack.is_empty() {
420 return Err(
421 self.error("OP_TOALTSTACK requires at least one item to be on the stack.")
422 );
423 }
424 let item = self.pop_stack()?;
425 self.push_alt_stack(item)?;
426 }
427 OP_FROMALTSTACK => {
428 if self.alt_stack.is_empty() {
429 return Err(self.error(
430 "OP_FROMALTSTACK requires at least one item to be on the alt stack.",
431 ));
432 }
433 let item = self.pop_alt_stack()?;
434 self.push_stack(item)?;
435 }
436 OP_2DROP => {
437 if self.stack.len() < 2 {
438 return Err(
439 self.error("OP_2DROP requires at least two items to be on the stack.")
440 );
441 }
442 self.pop_stack()?;
443 self.pop_stack()?;
444 }
445 OP_2DUP => {
446 if self.stack.len() < 2 {
447 return Err(
448 self.error("OP_2DUP requires at least two items to be on the stack.")
449 );
450 }
451 let buf1 = self.stack_top_n(2)?.to_vec();
452 let buf2 = self.stack_top()?.to_vec();
453 self.push_stack(buf1)?;
454 self.push_stack(buf2)?;
455 }
456 OP_3DUP => {
457 if self.stack.len() < 3 {
458 return Err(
459 self.error("OP_3DUP requires at least three items to be on the stack.")
460 );
461 }
462 let buf1 = self.stack_top_n(3)?.to_vec();
463 let buf2 = self.stack_top_n(2)?.to_vec();
464 let buf3 = self.stack_top()?.to_vec();
465 self.push_stack(buf1)?;
466 self.push_stack(buf2)?;
467 self.push_stack(buf3)?;
468 }
469 OP_2OVER => {
470 if self.stack.len() < 4 {
471 return Err(
472 self.error("OP_2OVER requires at least four items to be on the stack.")
473 );
474 }
475 let buf1 = self.stack_top_n(4)?.to_vec();
476 let buf2 = self.stack_top_n(3)?.to_vec();
477 self.push_stack(buf1)?;
478 self.push_stack(buf2)?;
479 }
480 OP_2ROT => {
481 if self.stack.len() < 6 {
482 return Err(
483 self.error("OP_2ROT requires at least six items to be on the stack.")
484 );
485 }
486 let x6 = self.pop_stack()?;
487 let x5 = self.pop_stack()?;
488 let x4 = self.pop_stack()?;
489 let x3 = self.pop_stack()?;
490 let x2 = self.pop_stack()?;
491 let x1 = self.pop_stack()?;
492 self.push_stack(x3)?;
493 self.push_stack(x4)?;
494 self.push_stack(x5)?;
495 self.push_stack(x6)?;
496 self.push_stack(x1)?;
497 self.push_stack(x2)?;
498 }
499 OP_2SWAP => {
500 if self.stack.len() < 4 {
501 return Err(
502 self.error("OP_2SWAP requires at least four items to be on the stack.")
503 );
504 }
505 let x4 = self.pop_stack()?;
506 let x3 = self.pop_stack()?;
507 let x2 = self.pop_stack()?;
508 let x1 = self.pop_stack()?;
509 self.push_stack(x3)?;
510 self.push_stack(x4)?;
511 self.push_stack(x1)?;
512 self.push_stack(x2)?;
513 }
514 OP_IFDUP => {
515 if self.stack.is_empty() {
516 return Err(
517 self.error("OP_IFDUP requires at least one item to be on the stack.")
518 );
519 }
520 let top = self.stack_top()?.to_vec();
521 if ScriptNum::cast_to_bool(&top) {
522 self.push_stack(top)?;
523 }
524 }
525 OP_DEPTH => {
526 let depth = BigNumber::from_u64(self.stack.len() as u64);
527 self.push_stack(ScriptNum::to_bytes(&depth))?;
528 }
529 OP_DROP => {
530 if self.stack.is_empty() {
531 return Err(
532 self.error("OP_DROP requires at least one item to be on the stack.")
533 );
534 }
535 self.pop_stack()?;
536 }
537 OP_DUP => {
538 if self.stack.is_empty() {
539 return Err(self.error("OP_DUP requires at least one item to be on the stack."));
540 }
541 let top = self.stack_top()?.to_vec();
542 self.push_stack(top)?;
543 }
544 OP_NIP => {
545 if self.stack.len() < 2 {
546 return Err(
547 self.error("OP_NIP requires at least two items to be on the stack.")
548 );
549 }
550 let top = self.pop_stack()?;
551 self.pop_stack()?;
552 self.push_stack(top)?;
553 }
554 OP_OVER => {
555 if self.stack.len() < 2 {
556 return Err(
557 self.error("OP_OVER requires at least two items to be on the stack.")
558 );
559 }
560 let second = self.stack_top_n(2)?.to_vec();
561 self.push_stack(second)?;
562 }
563 OP_PICK | OP_ROLL => {
564 if self.stack.len() < 2 {
565 return Err(self.error(&format!(
566 "{} requires at least two items to be on the stack.",
567 opcode_to_name(opcode).unwrap_or("OP_PICK/ROLL")
568 )));
569 }
570 let n_bytes = self.pop_stack()?;
571 let bn = ScriptNum::from_bytes(&n_bytes, REQUIRE_MINIMAL_PUSH)
572 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
573
574 let n = bn.to_i64().unwrap_or(i64::MAX);
575 if n < 0 || n >= self.stack.len() as i64 {
576 return Err(self.error(&format!(
577 "{} requires the top stack element to be 0 or a positive number less than the current size of the stack.",
578 opcode_to_name(opcode).unwrap_or("OP_PICK/ROLL")
579 )));
580 }
581
582 let n_idx = n as usize;
583 let item = self.stack[self.stack.len() - 1 - n_idx].clone();
584
585 if opcode == OP_ROLL {
586 let remove_idx = self.stack.len() - 1 - n_idx;
587 let removed = self.stack.remove(remove_idx);
588 self.stack_mem -= removed.len();
589 self.push_stack(item)?;
590 } else {
591 self.push_stack(item)?;
593 }
594 }
595 OP_ROT => {
596 if self.stack.len() < 3 {
597 return Err(
598 self.error("OP_ROT requires at least three items to be on the stack.")
599 );
600 }
601 let x3 = self.pop_stack()?;
602 let x2 = self.pop_stack()?;
603 let x1 = self.pop_stack()?;
604 self.push_stack(x2)?;
605 self.push_stack(x3)?;
606 self.push_stack(x1)?;
607 }
608 OP_SWAP => {
609 if self.stack.len() < 2 {
610 return Err(
611 self.error("OP_SWAP requires at least two items to be on the stack.")
612 );
613 }
614 let x2 = self.pop_stack()?;
615 let x1 = self.pop_stack()?;
616 self.push_stack(x2)?;
617 self.push_stack(x1)?;
618 }
619 OP_TUCK => {
620 if self.stack.len() < 2 {
621 return Err(
622 self.error("OP_TUCK requires at least two items to be on the stack.")
623 );
624 }
625 let top = self.stack_top()?.to_vec();
626 self.ensure_stack_mem(top.len())?;
627 let insert_idx = self.stack.len() - 2;
628 self.stack.insert(insert_idx, top.clone());
629 self.stack_mem += top.len();
630 }
631 OP_SIZE => {
632 if self.stack.is_empty() {
633 return Err(
634 self.error("OP_SIZE requires at least one item to be on the stack.")
635 );
636 }
637 let size = self.stack_top()?.len();
638 let bn = BigNumber::from_u64(size as u64);
639 self.push_stack(ScriptNum::to_bytes(&bn))?;
640 }
641
642 OP_CAT => {
646 if self.stack.len() < 2 {
647 return Err(
648 self.error("OP_CAT requires at least two items to be on the stack.")
649 );
650 }
651 let buf2 = self.pop_stack()?;
652 let buf1 = self.pop_stack()?;
653 let mut result = buf1;
654 result.extend(buf2);
655 if result.len() > MAX_SCRIPT_ELEMENT_SIZE {
656 return Err(self.error(&format!(
657 "It's not currently possible to push data larger than {} bytes.",
658 MAX_SCRIPT_ELEMENT_SIZE
659 )));
660 }
661 self.push_stack(result)?;
662 }
663 OP_SPLIT => {
664 if self.stack.len() < 2 {
665 return Err(
666 self.error("OP_SPLIT requires at least two items to be on the stack.")
667 );
668 }
669 let pos_bytes = self.pop_stack()?;
670 let data = self.pop_stack()?;
671
672 let pos_bn = ScriptNum::from_bytes(&pos_bytes, REQUIRE_MINIMAL_PUSH)
673 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
674 let pos = pos_bn.to_i64().unwrap_or(-1);
675
676 if pos < 0 || pos > data.len() as i64 {
677 return Err(self.error(
678 "OP_SPLIT requires the first stack item to be a non-negative number less than or equal to the size of the second-from-top stack item.",
679 ));
680 }
681
682 let split_idx = pos as usize;
683 let left = data[..split_idx].to_vec();
684 let right = data[split_idx..].to_vec();
685 self.push_stack(left)?;
686 self.push_stack(right)?;
687 }
688 OP_NUM2BIN => {
689 if self.stack.len() < 2 {
690 return Err(
691 self.error("OP_NUM2BIN requires at least two items to be on the stack.")
692 );
693 }
694 let size_bytes = self.pop_stack()?;
695 let size_bn = ScriptNum::from_bytes(&size_bytes, REQUIRE_MINIMAL_PUSH)
696 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
697 let size = size_bn.to_i64().unwrap_or(-1);
698
699 if size < 0 || size > MAX_SCRIPT_ELEMENT_SIZE as i64 {
700 return Err(self.error(&format!(
701 "It's not currently possible to push data larger than {} bytes or negative size.",
702 MAX_SCRIPT_ELEMENT_SIZE
703 )));
704 }
705 let size = size as usize;
706
707 let rawnum = self.pop_stack()?;
708 let minimal = ScriptNum::minimally_encode(&rawnum);
709
710 if minimal.len() > size {
711 return Err(self.error(
712 "OP_NUM2BIN requires that the size expressed in the top stack item is large enough to hold the value expressed in the second-from-top stack item.",
713 ));
714 }
715
716 if minimal.len() == size {
717 self.push_stack(minimal)?;
718 } else {
719 let mut result = vec![0u8; size];
721 let mut signbit = 0u8;
722
723 if !minimal.is_empty() {
724 signbit = minimal[minimal.len() - 1] & 0x80;
725 let mut minimal_copy = minimal.clone();
726 if let Some(last) = minimal_copy.last_mut() {
727 *last &= 0x7f;
728 }
729 result[..minimal_copy.len()].copy_from_slice(&minimal_copy);
730 }
731
732 if signbit != 0 {
733 result[size - 1] |= 0x80;
734 }
735 self.push_stack(result)?;
736 }
737 }
738 OP_BIN2NUM => {
739 if self.stack.is_empty() {
740 return Err(
741 self.error("OP_BIN2NUM requires at least one item to be on the stack.")
742 );
743 }
744 let buf = self.pop_stack()?;
745 let result = ScriptNum::minimally_encode(&buf);
746 if !ScriptNum::is_minimally_encoded(&result) {
747 return Err(
748 self.error("OP_BIN2NUM requires that the resulting number is valid.")
749 );
750 }
751 self.push_stack(result)?;
752 }
753
754 OP_INVERT => {
758 if self.stack.is_empty() {
759 return Err(
760 self.error("OP_INVERT requires at least one item to be on the stack.")
761 );
762 }
763 let buf = self.pop_stack()?;
764 let result: Vec<u8> = buf.iter().map(|&b| !b).collect();
765 self.push_stack(result)?;
766 }
767 OP_AND | OP_OR | OP_XOR => {
768 if self.stack.len() < 2 {
769 return Err(self.error(&format!(
770 "{} requires at least two items on the stack.",
771 opcode_to_name(opcode).unwrap_or("OP")
772 )));
773 }
774 let buf2 = self.pop_stack()?;
775 let buf1 = self.pop_stack()?;
776 if buf1.len() != buf2.len() {
777 return Err(self.error(&format!(
778 "{} requires the top two stack items to be the same size.",
779 opcode_to_name(opcode).unwrap_or("OP")
780 )));
781 }
782 let result: Vec<u8> = buf1
783 .iter()
784 .zip(buf2.iter())
785 .map(|(&a, &b)| match opcode {
786 OP_AND => a & b,
787 OP_OR => a | b,
788 _ => a ^ b, })
790 .collect();
791 self.push_stack(result)?;
792 }
793 OP_EQUAL | OP_EQUALVERIFY => {
794 if self.stack.len() < 2 {
795 return Err(self.error(&format!(
796 "{} requires at least two items to be on the stack.",
797 opcode_to_name(opcode).unwrap_or("OP_EQUAL")
798 )));
799 }
800 let buf2 = self.pop_stack()?;
801 let buf1 = self.pop_stack()?;
802 let equal = buf1 == buf2;
803 self.push_stack(if equal { vec![1] } else { vec![] })?;
804
805 if opcode == OP_EQUALVERIFY {
806 if !equal {
807 return Err(self.error(
808 "OP_EQUALVERIFY requires the top two stack items to be equal.",
809 ));
810 }
811 self.pop_stack()?;
812 }
813 }
814 OP_LSHIFT | OP_RSHIFT => {
815 if self.stack.len() < 2 {
816 return Err(self.error(&format!(
817 "{} requires at least two items to be on the stack.",
818 opcode_to_name(opcode).unwrap_or("OP")
819 )));
820 }
821 let n_bytes = self.pop_stack()?;
822 let buf = self.pop_stack()?;
823
824 let n_bn = ScriptNum::from_bytes(&n_bytes, REQUIRE_MINIMAL_PUSH)
825 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
826 let n = n_bn.to_i64().unwrap_or(-1);
827
828 if n < 0 {
829 return Err(self.error(&format!(
830 "{} requires the top item on the stack not to be negative.",
831 opcode_to_name(opcode).unwrap_or("OP")
832 )));
833 }
834
835 if buf.is_empty() {
836 self.push_stack(vec![])?;
837 } else {
838 let bn = BigNumber::from_bytes_be(&buf);
840 let n_u32 = n as u32;
841 let shifted = if opcode == OP_LSHIFT {
842 bn.mul(&BigNumber::from_u64(1u64 << n_u32.min(63)))
844 } else {
845 bn.div(&BigNumber::from_u64(1u64 << n_u32.min(63)))
847 };
848 let result = shifted.to_bytes_be(buf.len());
849 self.push_stack(result)?;
850 }
851 }
852
853 OP_1ADD | OP_1SUB | OP_NEGATE | OP_ABS | OP_NOT | OP_0NOTEQUAL => {
857 if self.stack.is_empty() {
858 return Err(self.error(&format!(
859 "{} requires at least one item to be on the stack.",
860 opcode_to_name(opcode).unwrap_or("OP")
861 )));
862 }
863 let buf = self.pop_stack()?;
864 let mut bn = ScriptNum::from_bytes(&buf, REQUIRE_MINIMAL_PUSH)
865 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
866
867 bn = match opcode {
868 OP_1ADD => bn.add(&BigNumber::one()),
869 OP_1SUB => bn.sub(&BigNumber::one()),
870 OP_NEGATE => bn.neg(),
871 OP_ABS => bn.abs(),
872 OP_NOT => {
873 if bn.is_zero() {
874 BigNumber::one()
875 } else {
876 BigNumber::zero()
877 }
878 }
879 OP_0NOTEQUAL => {
880 if bn.is_zero() {
881 BigNumber::zero()
882 } else {
883 BigNumber::one()
884 }
885 }
886 _ => bn,
887 };
888 self.push_stack(ScriptNum::to_bytes(&bn))?;
889 }
890 OP_ADD
891 | OP_SUB
892 | OP_MUL
893 | OP_DIV
894 | OP_MOD
895 | OP_BOOLAND
896 | OP_BOOLOR
897 | OP_NUMEQUAL
898 | OP_NUMEQUALVERIFY
899 | OP_NUMNOTEQUAL
900 | OP_LESSTHAN
901 | OP_GREATERTHAN
902 | OP_LESSTHANOREQUAL
903 | OP_GREATERTHANOREQUAL
904 | OP_MIN
905 | OP_MAX => {
906 if self.stack.len() < 2 {
907 return Err(self.error(&format!(
908 "{} requires at least two items to be on the stack.",
909 opcode_to_name(opcode).unwrap_or("OP")
910 )));
911 }
912 let buf2 = self.pop_stack()?;
913 let buf1 = self.pop_stack()?;
914 let bn1 = ScriptNum::from_bytes(&buf1, REQUIRE_MINIMAL_PUSH)
915 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
916 let bn2 = ScriptNum::from_bytes(&buf2, REQUIRE_MINIMAL_PUSH)
917 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
918
919 let result = match opcode {
920 OP_ADD => bn1.add(&bn2),
921 OP_SUB => bn1.sub(&bn2),
922 OP_MUL => bn1.mul(&bn2),
923 OP_DIV => {
924 if bn2.is_zero() {
925 return Err(self.error("OP_DIV cannot divide by zero!"));
926 }
927 bn1.div(&bn2)
928 }
929 OP_MOD => {
930 if bn2.is_zero() {
931 return Err(self.error("OP_MOD cannot divide by zero!"));
932 }
933 bn1.mod_floor(&bn2)
934 }
935 OP_BOOLAND => {
936 if !bn1.is_zero() && !bn2.is_zero() {
937 BigNumber::one()
938 } else {
939 BigNumber::zero()
940 }
941 }
942 OP_BOOLOR => {
943 if !bn1.is_zero() || !bn2.is_zero() {
944 BigNumber::one()
945 } else {
946 BigNumber::zero()
947 }
948 }
949 OP_NUMEQUAL | OP_NUMEQUALVERIFY => {
950 if bn1 == bn2 {
951 BigNumber::one()
952 } else {
953 BigNumber::zero()
954 }
955 }
956 OP_NUMNOTEQUAL => {
957 if bn1 != bn2 {
958 BigNumber::one()
959 } else {
960 BigNumber::zero()
961 }
962 }
963 OP_LESSTHAN => {
964 if bn1 < bn2 {
965 BigNumber::one()
966 } else {
967 BigNumber::zero()
968 }
969 }
970 OP_GREATERTHAN => {
971 if bn1 > bn2 {
972 BigNumber::one()
973 } else {
974 BigNumber::zero()
975 }
976 }
977 OP_LESSTHANOREQUAL => {
978 if bn1 <= bn2 {
979 BigNumber::one()
980 } else {
981 BigNumber::zero()
982 }
983 }
984 OP_GREATERTHANOREQUAL => {
985 if bn1 >= bn2 {
986 BigNumber::one()
987 } else {
988 BigNumber::zero()
989 }
990 }
991 OP_MIN => {
992 if bn1 < bn2 {
993 bn1
994 } else {
995 bn2
996 }
997 }
998 OP_MAX => {
999 if bn1 > bn2 {
1000 bn1
1001 } else {
1002 bn2
1003 }
1004 }
1005 _ => BigNumber::zero(),
1006 };
1007
1008 self.push_stack(ScriptNum::to_bytes(&result))?;
1009
1010 if opcode == OP_NUMEQUALVERIFY {
1011 if !ScriptNum::cast_to_bool(self.stack_top()?) {
1012 return Err(self
1013 .error("OP_NUMEQUALVERIFY requires the top stack item to be truthy."));
1014 }
1015 self.pop_stack()?;
1016 }
1017 }
1018 OP_WITHIN => {
1019 if self.stack.len() < 3 {
1020 return Err(
1021 self.error("OP_WITHIN requires at least three items to be on the stack.")
1022 );
1023 }
1024 let max_bytes = self.pop_stack()?;
1025 let min_bytes = self.pop_stack()?;
1026 let x_bytes = self.pop_stack()?;
1027 let max_bn = ScriptNum::from_bytes(&max_bytes, REQUIRE_MINIMAL_PUSH)
1028 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
1029 let min_bn = ScriptNum::from_bytes(&min_bytes, REQUIRE_MINIMAL_PUSH)
1030 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
1031 let x_bn = ScriptNum::from_bytes(&x_bytes, REQUIRE_MINIMAL_PUSH)
1032 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
1033
1034 let in_range = x_bn >= min_bn && x_bn < max_bn;
1035 self.push_stack(if in_range { vec![1] } else { vec![] })?;
1036 }
1037
1038 OP_RIPEMD160 => {
1042 if self.stack.is_empty() {
1043 return Err(
1044 self.error("OP_RIPEMD160 requires at least one item to be on the stack.")
1045 );
1046 }
1047 let buf = self.pop_stack()?;
1048 let hash = ripemd160(&buf);
1049 self.push_stack(hash.to_vec())?;
1050 }
1051 OP_SHA1 => {
1052 if self.stack.is_empty() {
1053 return Err(
1054 self.error("OP_SHA1 requires at least one item to be on the stack.")
1055 );
1056 }
1057 let buf = self.pop_stack()?;
1058 let hash = sha1(&buf);
1059 self.push_stack(hash.to_vec())?;
1060 }
1061 OP_SHA256 => {
1062 if self.stack.is_empty() {
1063 return Err(
1064 self.error("OP_SHA256 requires at least one item to be on the stack.")
1065 );
1066 }
1067 let buf = self.pop_stack()?;
1068 let hash = sha256(&buf);
1069 self.push_stack(hash.to_vec())?;
1070 }
1071 OP_HASH160 => {
1072 if self.stack.is_empty() {
1073 return Err(
1074 self.error("OP_HASH160 requires at least one item to be on the stack.")
1075 );
1076 }
1077 let buf = self.pop_stack()?;
1078 let hash = hash160(&buf);
1079 self.push_stack(hash.to_vec())?;
1080 }
1081 OP_HASH256 => {
1082 if self.stack.is_empty() {
1083 return Err(
1084 self.error("OP_HASH256 requires at least one item to be on the stack.")
1085 );
1086 }
1087 let buf = self.pop_stack()?;
1088 let hash = sha256d(&buf);
1089 self.push_stack(hash.to_vec())?;
1090 }
1091 OP_CODESEPARATOR => {
1092 self.last_code_separator = Some(self.program_counter);
1093 }
1094 OP_CHECKSIG | OP_CHECKSIGVERIFY => {
1095 if self.stack.len() < 2 {
1096 return Err(self.error(&format!(
1097 "{} requires at least two items to be on the stack.",
1098 opcode_to_name(opcode).unwrap_or("OP_CHECKSIG")
1099 )));
1100 }
1101 let pubkey_bytes = self.pop_stack()?;
1102 let sig_bytes = self.pop_stack()?;
1103
1104 self.check_signature_encoding(&sig_bytes)?;
1106 self.check_public_key_encoding(&pubkey_bytes)?;
1107
1108 let subscript = self.build_subscript(&sig_bytes)?;
1110
1111 let success = if sig_bytes.is_empty() {
1113 false
1114 } else {
1115 self.verify_signature(&sig_bytes, &pubkey_bytes, &subscript)?
1116 };
1117
1118 self.push_stack(if success { vec![1] } else { vec![] })?;
1119
1120 if opcode == OP_CHECKSIGVERIFY {
1121 if !success {
1122 return Err(self.error(
1123 "OP_CHECKSIGVERIFY requires that a valid signature is provided.",
1124 ));
1125 }
1126 self.pop_stack()?;
1127 }
1128 }
1129 OP_CHECKMULTISIG | OP_CHECKMULTISIGVERIFY => {
1130 self.op_checkmultisig(opcode)?;
1131 }
1132
1133 0x01..=0x4b => {
1137 let data = chunk.data.clone().unwrap_or_default();
1139 self.push_stack(data)?;
1140 }
1141 OP_PUSHDATA1 | OP_PUSHDATA2 | OP_PUSHDATA4 => {
1142 let data = chunk.data.clone().unwrap_or_default();
1143 self.push_stack(data)?;
1144 }
1145
1146 _ => {
1150 return Err(self.error(&format!(
1151 "Invalid opcode {} (pc={}).",
1152 opcode, self.program_counter
1153 )));
1154 }
1155 }
1156
1157 Ok(())
1158 }
1159
1160 fn op_checkmultisig(&mut self, opcode: u8) -> Result<(), ScriptEvaluationError> {
1165 if self.stack.is_empty() {
1167 return Err(self.error(&format!(
1168 "{} requires at least 1 item for nKeys.",
1169 opcode_to_name(opcode).unwrap_or("OP_CHECKMULTISIG")
1170 )));
1171 }
1172
1173 let n_keys_bytes = self.pop_stack()?;
1174 let n_keys_bn = ScriptNum::from_bytes(&n_keys_bytes, REQUIRE_MINIMAL_PUSH)
1175 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
1176 let n_keys = n_keys_bn.to_i64().unwrap_or(-1);
1177
1178 if !(0..=MAX_MULTISIG_KEY_COUNT).contains(&n_keys) {
1179 return Err(self.error(&format!(
1180 "{} requires a key count between 0 and {}.",
1181 opcode_to_name(opcode).unwrap_or("OP_CHECKMULTISIG"),
1182 MAX_MULTISIG_KEY_COUNT
1183 )));
1184 }
1185 let n_keys = n_keys as usize;
1186
1187 if self.stack.len() < n_keys {
1189 return Err(self.error(&format!(
1190 "{} stack too small for keys. Need {}, have {}.",
1191 opcode_to_name(opcode).unwrap_or("OP_CHECKMULTISIG"),
1192 n_keys,
1193 self.stack.len()
1194 )));
1195 }
1196
1197 let mut pubkeys = Vec::with_capacity(n_keys);
1198 for _ in 0..n_keys {
1199 pubkeys.push(self.pop_stack()?);
1200 }
1201
1202 if self.stack.is_empty() {
1204 return Err(self.error(&format!(
1205 "{} requires item for nSigs.",
1206 opcode_to_name(opcode).unwrap_or("OP_CHECKMULTISIG")
1207 )));
1208 }
1209
1210 let n_sigs_bytes = self.pop_stack()?;
1211 let n_sigs_bn = ScriptNum::from_bytes(&n_sigs_bytes, REQUIRE_MINIMAL_PUSH)
1212 .map_err(|e| self.error(&format!("Invalid script number: {}", e)))?;
1213 let n_sigs = n_sigs_bn.to_i64().unwrap_or(-1);
1214
1215 if n_sigs < 0 || n_sigs as usize > n_keys {
1216 return Err(self.error(&format!(
1217 "{} requires the number of signatures to be no greater than the number of keys.",
1218 opcode_to_name(opcode).unwrap_or("OP_CHECKMULTISIG")
1219 )));
1220 }
1221 let n_sigs = n_sigs as usize;
1222
1223 if self.stack.len() < n_sigs {
1225 return Err(self.error(&format!(
1226 "{} stack too small for sigs. Need {}, have {}.",
1227 opcode_to_name(opcode).unwrap_or("OP_CHECKMULTISIG"),
1228 n_sigs,
1229 self.stack.len()
1230 )));
1231 }
1232
1233 let mut sigs = Vec::with_capacity(n_sigs);
1234 for _ in 0..n_sigs {
1235 sigs.push(self.pop_stack()?);
1236 }
1237
1238 let base_script = match self.context {
1240 ExecutionContext::UnlockingScript => self.unlocking_script.as_script().clone(),
1241 ExecutionContext::LockingScript => self.locking_script.as_script().clone(),
1242 };
1243 let start_idx = self.last_code_separator.map(|i| i + 1).unwrap_or(0);
1244 let chunks = base_script.chunks();
1245 let subscript_chunks: Vec<ScriptChunk> = chunks.into_iter().skip(start_idx).collect();
1246 let mut subscript = Script::from_chunks(subscript_chunks);
1247
1248 for sig in &sigs {
1249 let sig_script = Script::new();
1250 let mut sig_script = sig_script;
1251 sig_script.write_bin(sig);
1252 subscript.find_and_delete(&sig_script);
1253 }
1254
1255 let mut success = true;
1257 let mut sig_idx = 0;
1258 let mut key_idx = 0;
1259
1260 while success && sig_idx < n_sigs {
1261 if key_idx >= n_keys {
1262 success = false;
1263 break;
1264 }
1265
1266 let sig_bytes = &sigs[sig_idx];
1267 let pubkey_bytes = &pubkeys[key_idx];
1268
1269 if self.check_signature_encoding(sig_bytes).is_err()
1271 || self.check_public_key_encoding(pubkey_bytes).is_err()
1272 {
1273 return Err(self.error(&format!(
1274 "{} requires correct encoding for the public key and signature.",
1275 opcode_to_name(opcode).unwrap_or("OP_CHECKMULTISIG")
1276 )));
1277 }
1278
1279 let sig_valid = if sig_bytes.is_empty() {
1280 false
1281 } else {
1282 self.verify_signature(sig_bytes, pubkey_bytes, &subscript)
1283 .unwrap_or(false)
1284 };
1285
1286 if sig_valid {
1287 sig_idx += 1;
1288 }
1289 key_idx += 1;
1290
1291 if n_sigs - sig_idx > n_keys - key_idx {
1292 success = false;
1293 }
1294 }
1295
1296 if self.stack.is_empty() {
1298 return Err(self.error(&format!(
1299 "{} requires an extra item (dummy) to be on the stack.",
1300 opcode_to_name(opcode).unwrap_or("OP_CHECKMULTISIG")
1301 )));
1302 }
1303 let dummy = self.pop_stack()?;
1304 if !dummy.is_empty() {
1305 return Err(self.error(&format!(
1306 "{} requires the extra stack item (dummy) to be empty.",
1307 opcode_to_name(opcode).unwrap_or("OP_CHECKMULTISIG")
1308 )));
1309 }
1310
1311 self.push_stack(if success { vec![1] } else { vec![] })?;
1312
1313 if opcode == OP_CHECKMULTISIGVERIFY {
1314 if !success {
1315 return Err(self.error(
1316 "OP_CHECKMULTISIGVERIFY requires that a sufficient number of valid signatures are provided.",
1317 ));
1318 }
1319 self.pop_stack()?;
1320 }
1321
1322 Ok(())
1323 }
1324
1325 fn check_signature_encoding(&self, sig: &[u8]) -> Result<(), ScriptEvaluationError> {
1330 if sig.is_empty() {
1331 return Ok(());
1332 }
1333
1334 if !is_valid_signature_encoding(sig) {
1336 return Err(self.error("The signature format is invalid."));
1337 }
1338
1339 let tx_sig = TransactionSignature::from_checksig_format(sig)
1341 .map_err(|_| self.error("The signature format is invalid."))?;
1342
1343 if REQUIRE_LOW_S_SIGNATURES && !tx_sig.has_low_s() {
1344 return Err(self.error("The signature must have a low S value."));
1345 }
1346
1347 if (tx_sig.scope() & SIGHASH_FORKID) == 0 {
1348 return Err(self.error("The signature must use SIGHASH_FORKID."));
1349 }
1350
1351 Ok(())
1352 }
1353
1354 fn check_public_key_encoding(&self, pubkey: &[u8]) -> Result<(), ScriptEvaluationError> {
1355 if pubkey.is_empty() {
1356 return Err(self.error("Public key is empty."));
1357 }
1358
1359 if pubkey.len() < 33 {
1360 return Err(self.error("The public key is too short, it must be at least 33 bytes."));
1361 }
1362
1363 if pubkey[0] == 0x04 {
1364 if pubkey.len() != 65 {
1365 return Err(self.error("The non-compressed public key must be 65 bytes."));
1366 }
1367 } else if pubkey[0] == 0x02 || pubkey[0] == 0x03 {
1368 if pubkey.len() != 33 {
1369 return Err(self.error("The compressed public key must be 33 bytes."));
1370 }
1371 } else {
1372 return Err(self.error("The public key is in an unknown format."));
1373 }
1374
1375 PublicKey::from_bytes(pubkey)
1377 .map_err(|_| self.error("The public key is in an unknown format."))?;
1378
1379 Ok(())
1380 }
1381
1382 fn build_subscript(&self, sig_bytes: &[u8]) -> Result<Script, ScriptEvaluationError> {
1383 let base_script = match self.context {
1384 ExecutionContext::UnlockingScript => self.unlocking_script.as_script().clone(),
1385 ExecutionContext::LockingScript => self.locking_script.as_script().clone(),
1386 };
1387
1388 let start_idx = self.last_code_separator.map(|i| i + 1).unwrap_or(0);
1389 let chunks = base_script.chunks();
1390 let subscript_chunks: Vec<ScriptChunk> = chunks.into_iter().skip(start_idx).collect();
1391 let mut subscript = Script::from_chunks(subscript_chunks);
1392
1393 let mut sig_script = Script::new();
1395 sig_script.write_bin(sig_bytes);
1396 subscript.find_and_delete(&sig_script);
1397
1398 Ok(subscript)
1399 }
1400
1401 fn verify_signature(
1402 &self,
1403 sig_bytes: &[u8],
1404 pubkey_bytes: &[u8],
1405 subscript: &Script,
1406 ) -> Result<bool, ScriptEvaluationError> {
1407 let tx_sig = match TransactionSignature::from_checksig_format(sig_bytes) {
1409 Ok(s) => s,
1410 Err(_) => return Ok(false),
1411 };
1412
1413 let pubkey = match PublicKey::from_bytes(pubkey_bytes) {
1414 Ok(p) => p,
1415 Err(_) => return Ok(false),
1416 };
1417
1418 let inputs = self.build_inputs_array();
1420
1421 let sighash = compute_sighash_for_signing(&SighashParams {
1423 version: self.transaction_version,
1424 inputs: &inputs,
1425 outputs: &self.outputs,
1426 locktime: self.lock_time,
1427 input_index: self.input_index,
1428 subscript: &subscript.to_binary(),
1429 satoshis: self.source_satoshis,
1430 scope: tx_sig.scope(),
1431 });
1432
1433 Ok(pubkey.verify(&sighash, tx_sig.signature()))
1435 }
1436
1437 fn build_inputs_array(&self) -> Vec<TxInput> {
1438 let mut inputs = Vec::with_capacity(self.other_inputs.len() + 1);
1439
1440 for (i, other) in self.other_inputs.iter().enumerate() {
1442 if i == self.input_index {
1443 inputs.push(TxInput {
1445 txid: self.source_txid,
1446 output_index: self.source_output_index,
1447 script: self.unlocking_script.to_binary(),
1448 sequence: self.input_sequence,
1449 });
1450 }
1451 inputs.push(other.clone());
1452 }
1453
1454 if self.input_index >= self.other_inputs.len() {
1456 inputs.push(TxInput {
1457 txid: self.source_txid,
1458 output_index: self.source_output_index,
1459 script: self.unlocking_script.to_binary(),
1460 sequence: self.input_sequence,
1461 });
1462 }
1463
1464 inputs
1465 }
1466
1467 fn push_stack(&mut self, item: Vec<u8>) -> Result<(), ScriptEvaluationError> {
1472 self.ensure_stack_mem(item.len())?;
1473 self.stack_mem += item.len();
1474 self.stack.push(item);
1475 Ok(())
1476 }
1477
1478 fn push_stack_copy(&mut self, item: &[u8]) -> Result<(), ScriptEvaluationError> {
1479 self.push_stack(item.to_vec())
1480 }
1481
1482 fn pop_stack(&mut self) -> Result<Vec<u8>, ScriptEvaluationError> {
1483 if self.stack.is_empty() {
1484 return Err(self.error("Attempted to pop from an empty stack."));
1485 }
1486 let item = self.stack.pop().unwrap();
1487 self.stack_mem -= item.len();
1488 Ok(item)
1489 }
1490
1491 fn stack_top(&self) -> Result<&Vec<u8>, ScriptEvaluationError> {
1492 if self.stack.is_empty() {
1493 return Err(self.error("Stack is empty."));
1494 }
1495 Ok(&self.stack[self.stack.len() - 1])
1496 }
1497
1498 fn stack_top_n(&self, n: usize) -> Result<&Vec<u8>, ScriptEvaluationError> {
1499 if self.stack.len() < n {
1500 return Err(self.error(&format!(
1501 "Stack underflow accessing element at index {}. Stack length is {}.",
1502 n,
1503 self.stack.len()
1504 )));
1505 }
1506 Ok(&self.stack[self.stack.len() - n])
1507 }
1508
1509 fn push_alt_stack(&mut self, item: Vec<u8>) -> Result<(), ScriptEvaluationError> {
1510 self.ensure_alt_stack_mem(item.len())?;
1511 self.alt_stack_mem += item.len();
1512 self.alt_stack.push(item);
1513 Ok(())
1514 }
1515
1516 fn pop_alt_stack(&mut self) -> Result<Vec<u8>, ScriptEvaluationError> {
1517 if self.alt_stack.is_empty() {
1518 return Err(self.error("Attempted to pop from an empty alt stack."));
1519 }
1520 let item = self.alt_stack.pop().unwrap();
1521 self.alt_stack_mem -= item.len();
1522 Ok(item)
1523 }
1524
1525 fn ensure_stack_mem(&self, additional: usize) -> Result<(), ScriptEvaluationError> {
1526 if self.stack_mem + additional > self.memory_limit {
1527 return Err(self.error(&format!(
1528 "Stack memory usage has exceeded {} bytes",
1529 self.memory_limit
1530 )));
1531 }
1532 Ok(())
1533 }
1534
1535 fn ensure_alt_stack_mem(&self, additional: usize) -> Result<(), ScriptEvaluationError> {
1536 if self.alt_stack_mem + additional > self.memory_limit {
1537 return Err(self.error(&format!(
1538 "Alt stack memory usage has exceeded {} bytes",
1539 self.memory_limit
1540 )));
1541 }
1542 Ok(())
1543 }
1544
1545 fn error(&self, message: &str) -> ScriptEvaluationError {
1550 ScriptEvaluationError::new(
1551 message,
1552 to_hex(&self.source_txid),
1553 self.source_output_index,
1554 self.context,
1555 self.program_counter,
1556 self.stack.clone(),
1557 self.alt_stack.clone(),
1558 self.if_stack.clone(),
1559 self.stack_mem,
1560 self.alt_stack_mem,
1561 )
1562 }
1563}
1564
1565fn is_opcode_disabled(op: u8) -> bool {
1571 matches!(op, OP_2MUL | OP_2DIV | OP_VER | OP_VERIF | OP_VERNOTIF)
1572}
1573
1574fn is_chunk_minimal_push(chunk: &ScriptChunk) -> bool {
1576 let data = match &chunk.data {
1577 Some(d) => d,
1578 None => return true,
1579 };
1580 let op = chunk.op;
1581
1582 if data.is_empty() {
1583 return op == OP_0;
1584 }
1585
1586 if data.len() == 1 && data[0] >= 1 && data[0] <= 16 {
1587 return op == OP_1 + (data[0] - 1);
1588 }
1589
1590 if data.len() == 1 && data[0] == 0x81 {
1591 return op == OP_1NEGATE;
1592 }
1593
1594 if data.len() <= 75 {
1595 return op as usize == data.len();
1596 }
1597
1598 if data.len() <= 255 {
1599 return op == OP_PUSHDATA1;
1600 }
1601
1602 if data.len() <= 65535 {
1603 return op == OP_PUSHDATA2;
1604 }
1605
1606 true
1607}
1608
1609fn is_valid_signature_encoding(sig: &[u8]) -> bool {
1611 if sig.len() < 9 || sig.len() > 73 {
1612 return false;
1613 }
1614
1615 if sig[0] != 0x30 {
1617 return false;
1618 }
1619
1620 if sig[1] as usize != sig.len() - 3 {
1622 return false;
1623 }
1624
1625 if sig[2] != 0x02 {
1627 return false;
1628 }
1629
1630 let r_len = sig[3] as usize;
1631 if r_len == 0 || 5 + r_len >= sig.len() {
1632 return false;
1633 }
1634
1635 let s_offset = 4 + r_len;
1637 if sig[s_offset] != 0x02 {
1638 return false;
1639 }
1640
1641 let s_len = sig[s_offset + 1] as usize;
1642 if s_len == 0 {
1643 return false;
1644 }
1645
1646 if r_len + s_len + 7 != sig.len() {
1648 return false;
1649 }
1650
1651 if (sig[4] & 0x80) != 0 {
1653 return false;
1654 }
1655
1656 if r_len > 1 && sig[4] == 0x00 && (sig[5] & 0x80) == 0 {
1658 return false;
1659 }
1660
1661 let s_value_offset = s_offset + 2;
1663 if (sig[s_value_offset] & 0x80) != 0 {
1664 return false;
1665 }
1666
1667 if s_len > 1 && sig[s_value_offset] == 0x00 && (sig[s_value_offset + 1] & 0x80) == 0 {
1669 return false;
1670 }
1671
1672 true
1673}
1674
1675#[cfg(test)]
1676mod tests {
1677 use super::*;
1678
1679 #[test]
1680 fn test_is_opcode_disabled() {
1681 assert!(is_opcode_disabled(OP_2MUL));
1682 assert!(is_opcode_disabled(OP_2DIV));
1683 assert!(is_opcode_disabled(OP_VER));
1684 assert!(is_opcode_disabled(OP_VERIF));
1685 assert!(is_opcode_disabled(OP_VERNOTIF));
1686
1687 assert!(!is_opcode_disabled(OP_DUP));
1688 assert!(!is_opcode_disabled(OP_MUL));
1689 assert!(!is_opcode_disabled(OP_CAT));
1690 }
1691
1692 #[test]
1693 fn test_is_chunk_minimal_push() {
1694 let chunk = ScriptChunk::new(OP_0, Some(vec![]));
1696 assert!(is_chunk_minimal_push(&chunk));
1697
1698 let chunk = ScriptChunk::new(3, Some(vec![1, 2, 3]));
1700 assert!(is_chunk_minimal_push(&chunk));
1701
1702 let chunk = ScriptChunk::new(OP_1, Some(vec![1]));
1704 assert!(is_chunk_minimal_push(&chunk));
1705
1706 let chunk = ScriptChunk::new(1, Some(vec![1]));
1708 assert!(!is_chunk_minimal_push(&chunk));
1709 }
1710
1711 #[test]
1712 fn test_simple_stack_script() {
1713 let locking = LockingScript::from_asm("OP_ADD OP_3 OP_EQUAL").unwrap();
1716 let unlocking = UnlockingScript::from_asm("OP_1 OP_2").unwrap();
1717
1718 let mut spend = Spend::new(SpendParams {
1719 source_txid: [0u8; 32],
1720 source_output_index: 0,
1721 source_satoshis: 0,
1722 locking_script: locking,
1723 transaction_version: 1,
1724 other_inputs: vec![],
1725 outputs: vec![],
1726 input_index: 0,
1727 unlocking_script: unlocking,
1728 input_sequence: 0xffffffff,
1729 lock_time: 0,
1730 memory_limit: None,
1731 });
1732
1733 let result = spend.validate();
1734 assert!(result.is_ok(), "Expected valid spend, got {:?}", result);
1735 }
1736
1737 #[test]
1738 fn test_if_else_endif() {
1739 let locking = LockingScript::from_asm("OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF").unwrap();
1742 let unlocking = UnlockingScript::from_asm("OP_1").unwrap();
1743
1744 let mut spend = Spend::new(SpendParams {
1745 source_txid: [0u8; 32],
1746 source_output_index: 0,
1747 source_satoshis: 0,
1748 locking_script: locking,
1749 transaction_version: 1,
1750 other_inputs: vec![],
1751 outputs: vec![],
1752 input_index: 0,
1753 unlocking_script: unlocking,
1754 input_sequence: 0xffffffff,
1755 lock_time: 0,
1756 memory_limit: None,
1757 });
1758
1759 let result = spend.validate();
1760 assert!(result.is_ok(), "Expected valid spend, got {:?}", result);
1761 }
1762
1763 #[test]
1764 fn test_hash_operations() {
1765 let locking = LockingScript::from_asm("OP_SHA256 OP_SIZE OP_NIP 20 OP_EQUAL").unwrap();
1769 let unlocking = UnlockingScript::from_asm("00").unwrap();
1770
1771 let mut spend = Spend::new(SpendParams {
1772 source_txid: [0u8; 32],
1773 source_output_index: 0,
1774 source_satoshis: 0,
1775 locking_script: locking,
1776 transaction_version: 1,
1777 other_inputs: vec![],
1778 outputs: vec![],
1779 input_index: 0,
1780 unlocking_script: unlocking,
1781 input_sequence: 0xffffffff,
1782 lock_time: 0,
1783 memory_limit: None,
1784 });
1785
1786 let result = spend.validate();
1787 assert!(result.is_ok(), "Expected valid spend, got {:?}", result);
1788 }
1789
1790 #[test]
1791 fn test_failing_script() {
1792 let locking = LockingScript::from_asm("OP_0").unwrap();
1794 let unlocking = UnlockingScript::new();
1795
1796 let mut spend = Spend::new(SpendParams {
1797 source_txid: [0u8; 32],
1798 source_output_index: 0,
1799 source_satoshis: 0,
1800 locking_script: locking,
1801 transaction_version: 1,
1802 other_inputs: vec![],
1803 outputs: vec![],
1804 input_index: 0,
1805 unlocking_script: unlocking,
1806 input_sequence: 0xffffffff,
1807 lock_time: 0,
1808 memory_limit: None,
1809 });
1810
1811 let result = spend.validate();
1812 assert!(result.is_err(), "Expected failed validation");
1813 }
1814}