15
15
import datetime
16
16
import struct
17
17
from enum import IntEnum
18
- from typing import Callable
19
18
20
19
from cryptography .exceptions import InvalidSignature
21
20
from cryptography .hazmat .primitives import hashes
46
45
get_data_value ,
47
46
get_script_op ,
48
47
)
48
+ from hathor .transaction .scripts .script_context import ScriptContext
49
49
50
50
51
51
class Opcode (IntEnum ):
@@ -157,7 +157,7 @@ def op_pushdata1(position: int, full_data: bytes, stack: Stack) -> int:
157
157
return new_pos
158
158
159
159
160
- def op_dup (stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
160
+ def op_dup (stack : Stack ) -> None :
161
161
"""Duplicates item on top of stack
162
162
163
163
:param stack: the stack used when evaluating the script
@@ -170,7 +170,7 @@ def op_dup(stack: Stack, log: list[str], extras: ScriptExtras) -> None:
170
170
stack .append (stack [- 1 ])
171
171
172
172
173
- def op_greaterthan_timestamp (stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
173
+ def op_greaterthan_timestamp (stack : Stack , extras : ScriptExtras ) -> None :
174
174
"""Check whether transaction's timestamp is greater than the top of stack
175
175
176
176
The top of stack must be a big-endian u32int.
@@ -190,7 +190,7 @@ def op_greaterthan_timestamp(stack: Stack, log: list[str], extras: ScriptExtras)
190
190
datetime .datetime .fromtimestamp (timelock ).strftime ("%m/%d/%Y %I:%M:%S %p" )))
191
191
192
192
193
- def op_equalverify (stack : Stack , log : list [str ], extras : ScriptExtras ) -> None :
193
+ def op_equalverify (stack : Stack , log : list [str ]) -> None :
194
194
"""Verifies top 2 elements from stack are equal
195
195
196
196
:param stack: the stack used when evaluating the script
@@ -201,13 +201,13 @@ def op_equalverify(stack: Stack, log: list[str], extras: ScriptExtras) -> None:
201
201
"""
202
202
if len (stack ) < 2 :
203
203
raise MissingStackItems ('OP_EQUALVERIFY: need 2 elements on stack, currently {}' .format (len (stack )))
204
- op_equal (stack , log , extras )
204
+ op_equal (stack , log )
205
205
is_equal = stack .pop ()
206
206
if not is_equal :
207
207
raise EqualVerifyFailed ('Failed to verify if elements are equal' )
208
208
209
209
210
- def op_equal (stack : Stack , log : list [str ], extras : ScriptExtras ) -> None :
210
+ def op_equal (stack : Stack , log : list [str ]) -> None :
211
211
"""Verifies top 2 elements from stack are equal
212
212
213
213
In case they are the same, we push 1 to the stack and push 0 if they are different
@@ -265,7 +265,7 @@ def op_checksig(stack: Stack, log: list[str], extras: ScriptExtras) -> None:
265
265
log .append ('OP_CHECKSIG: failed' )
266
266
267
267
268
- def op_hash160 (stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
268
+ def op_hash160 (stack : Stack ) -> None :
269
269
"""Top stack item is hashed twice: first with SHA-256 and then with RIPEMD-160.
270
270
Result is pushed back to stack.
271
271
@@ -282,7 +282,7 @@ def op_hash160(stack: Stack, log: list[str], extras: ScriptExtras) -> None:
282
282
stack .append (new_elem )
283
283
284
284
285
- def op_checkdatasig (stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
285
+ def op_checkdatasig (stack : Stack ) -> None :
286
286
"""Verifies public key, signature and data match. Expects public key to be on top of stack, followed
287
287
by signature and data. If they match, put data on stack; otherwise, fail.
288
288
@@ -316,7 +316,7 @@ def op_checkdatasig(stack: Stack, log: list[str], extras: ScriptExtras) -> None:
316
316
raise OracleChecksigFailed from e
317
317
318
318
319
- def op_data_strequal (stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
319
+ def op_data_strequal (stack : Stack ) -> None :
320
320
"""Equivalent to an OP_GET_DATA_STR followed by an OP_EQUALVERIFY.
321
321
322
322
Consumes three parameters from stack: <data> <k> <value>. Gets the kth value
@@ -347,7 +347,7 @@ def op_data_strequal(stack: Stack, log: list[str], extras: ScriptExtras) -> None
347
347
stack .append (data )
348
348
349
349
350
- def op_data_greaterthan (stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
350
+ def op_data_greaterthan (stack : Stack ) -> None :
351
351
"""Equivalent to an OP_GET_DATA_INT followed by an OP_GREATERTHAN.
352
352
353
353
Consumes three parameters from stack: <data> <k> <n>. Gets the kth value
@@ -383,7 +383,7 @@ def op_data_greaterthan(stack: Stack, log: list[str], extras: ScriptExtras) -> N
383
383
stack .append (data )
384
384
385
385
386
- def op_data_match_interval (stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
386
+ def op_data_match_interval (stack : Stack ) -> None :
387
387
"""Equivalent to an OP_GET_DATA_INT followed by an OP_MATCH_INTERVAL.
388
388
389
389
:param stack: the stack used when evaluating the script
@@ -435,7 +435,7 @@ def op_data_match_interval(stack: Stack, log: list[str], extras: ScriptExtras) -
435
435
stack .append (last_pubkey )
436
436
437
437
438
- def op_data_match_value (stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
438
+ def op_data_match_value (stack : Stack ) -> None :
439
439
"""Equivalent to an OP_GET_DATA_STR followed by an OP_MATCH_VALUE.
440
440
441
441
:param stack: the stack used when evaluating the script
@@ -484,7 +484,7 @@ def op_data_match_value(stack: Stack, log: list[str], extras: ScriptExtras) -> N
484
484
stack .append (winner_pubkey )
485
485
486
486
487
- def op_find_p2pkh (stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
487
+ def op_find_p2pkh (stack : Stack , extras : ScriptExtras ) -> None :
488
488
"""Checks whether the current transaction has an output with a P2PKH script with
489
489
the given public key hash and the same amount as the input.
490
490
@@ -604,7 +604,7 @@ def op_checkmultisig(stack: Stack, log: list[str], extras: ScriptExtras) -> None
604
604
stack .append (1 )
605
605
606
606
607
- def op_integer (opcode : int , stack : Stack , log : list [ str ], extras : ScriptExtras ) -> None :
607
+ def op_integer (opcode : int , stack : Stack ) -> None :
608
608
""" Appends an integer to the stack
609
609
We get the opcode comparing to all integers opcodes
610
610
@@ -624,17 +624,34 @@ def op_integer(opcode: int, stack: Stack, log: list[str], extras: ScriptExtras)
624
624
raise ScriptError (e ) from e
625
625
626
626
627
- MAP_OPCODE_TO_FN : dict [int , Callable [[Stack , list [str ], ScriptExtras ], None ]] = {
628
- Opcode .OP_DUP : op_dup ,
629
- Opcode .OP_EQUAL : op_equal ,
630
- Opcode .OP_EQUALVERIFY : op_equalverify ,
631
- Opcode .OP_CHECKSIG : op_checksig ,
632
- Opcode .OP_HASH160 : op_hash160 ,
633
- Opcode .OP_GREATERTHAN_TIMESTAMP : op_greaterthan_timestamp ,
634
- Opcode .OP_CHECKMULTISIG : op_checkmultisig ,
635
- Opcode .OP_DATA_STREQUAL : op_data_strequal ,
636
- Opcode .OP_DATA_GREATERTHAN : op_data_greaterthan ,
637
- Opcode .OP_DATA_MATCH_VALUE : op_data_match_value ,
638
- Opcode .OP_CHECKDATASIG : op_checkdatasig ,
639
- Opcode .OP_FIND_P2PKH : op_find_p2pkh ,
640
- }
627
+ def execute_op_code (
628
+ opcode : Opcode ,
629
+ stack : Stack ,
630
+ log : list [str ],
631
+ extras : ScriptExtras ,
632
+ context : ScriptContext ,
633
+ ) -> None :
634
+ """
635
+ Execute a function opcode.
636
+
637
+ Args:
638
+ opcode: the opcode to be executed.
639
+ stack: the stack to be manipulated.
640
+ log: the log list to be appended.
641
+ extras: auxiliary opcode arguments.
642
+ context: the script context to be manipulated.
643
+ """
644
+ match opcode :
645
+ case Opcode .OP_DUP : op_dup (stack )
646
+ case Opcode .OP_EQUAL : op_equal (stack , log )
647
+ case Opcode .OP_EQUALVERIFY : op_equalverify (stack , log )
648
+ case Opcode .OP_CHECKSIG : op_checksig (stack , log , extras )
649
+ case Opcode .OP_HASH160 : op_hash160 (stack )
650
+ case Opcode .OP_GREATERTHAN_TIMESTAMP : op_greaterthan_timestamp (stack , extras )
651
+ case Opcode .OP_CHECKMULTISIG : op_checkmultisig (stack , log , extras )
652
+ case Opcode .OP_DATA_STREQUAL : op_data_strequal (stack )
653
+ case Opcode .OP_DATA_GREATERTHAN : op_data_greaterthan (stack )
654
+ case Opcode .OP_DATA_MATCH_VALUE : op_data_match_value (stack )
655
+ case Opcode .OP_CHECKDATASIG : op_checkdatasig (stack )
656
+ case Opcode .OP_FIND_P2PKH : op_find_p2pkh (stack , extras )
657
+ case _: raise ScriptError (f'unknown opcode: { opcode } ' )
0 commit comments