diff --git a/evm/logic/context.py b/evm/logic/context.py index d7ba5b004b..c0671718fd 100644 --- a/evm/logic/context.py +++ b/evm/logic/context.py @@ -189,3 +189,7 @@ def returndatacopy(computation): value = computation.return_data[returndata_start_position: returndata_start_position + size] computation.memory.write(mem_start_position, size, value) + + +def sighash(computation): + computation.stack.push(computation.msg.sig_hash) diff --git a/evm/mnemonics.py b/evm/mnemonics.py index 40e498788d..37b885e9a3 100644 --- a/evm/mnemonics.py +++ b/evm/mnemonics.py @@ -49,6 +49,7 @@ EXTCODECOPY = 'EXTCODECOPY' RETURNDATASIZE = 'RETURNDATASIZE' RETURNDATACOPY = 'RETURNDATACOPY' +SIGHASH = 'SIGHASH' # # Block Information # diff --git a/evm/opcode_values.py b/evm/opcode_values.py index 1fb198106b..0b1df665f9 100644 --- a/evm/opcode_values.py +++ b/evm/opcode_values.py @@ -55,6 +55,7 @@ EXTCODECOPY = 0x3c RETURNDATASIZE = 0x3d RETURNDATACOPY = 0x3e +SIGHASH = 0x3f # diff --git a/evm/rlp/transactions.py b/evm/rlp/transactions.py index 22ff841bdf..fbe3a65dc2 100644 --- a/evm/rlp/transactions.py +++ b/evm/rlp/transactions.py @@ -165,6 +165,11 @@ class BaseShardingTransaction(rlp.Serializable): def hash(self): return keccak(rlp.encode(self)) + @property + def sig_hash(self): + sedes = self.__class__.exclude('data') + return keccak(rlp.encode(self, sedes)) + # # Validation # diff --git a/evm/validation.py b/evm/validation.py index 6830da7e0f..46ffe24988 100644 --- a/evm/validation.py +++ b/evm/validation.py @@ -251,3 +251,8 @@ def validate_transaction_access_list(access_list, title="Access List"): def validate_access_list(access_list): for entry in access_list: validate_is_bytes(entry, "Access prefix") + + +def validate_sig_hash(sig_hash, title="Sig Hash"): + validate_is_bytes(sig_hash, title) + validate_length(sig_hash, 32, title) diff --git a/evm/vm/forks/sharding/__init__.py b/evm/vm/forks/sharding/__init__.py index 8bdf5eb3d0..440f85bfe4 100644 --- a/evm/vm/forks/sharding/__init__.py +++ b/evm/vm/forks/sharding/__init__.py @@ -30,6 +30,7 @@ from .computation import ShardingComputation from .validation import validate_sharding_transaction from .blocks import ShardingBlock +from .opcodes import SHARDING_OPCODES def _execute_sharding_transaction(vm, transaction): @@ -80,6 +81,7 @@ def _execute_sharding_transaction(vm, transaction): gas=message_gas, gas_price=transaction.gas_price, to=transaction.to, + sig_hash=transaction.sig_hash, sender=ENTRY_POINT, value=0, data=data, @@ -170,4 +172,6 @@ def _execute_sharding_transaction(vm, transaction): # Method overrides validate_transaction=validate_sharding_transaction, execute_transaction=_execute_sharding_transaction, + # opcodes + opcodes=SHARDING_OPCODES, ) diff --git a/evm/vm/forks/sharding/opcodes.py b/evm/vm/forks/sharding/opcodes.py new file mode 100644 index 0000000000..62f4e624ab --- /dev/null +++ b/evm/vm/forks/sharding/opcodes.py @@ -0,0 +1,27 @@ +import copy +from cytoolz import merge + +from evm import opcode_values +from evm import mnemonics + +from evm.opcode import as_opcode +from evm.logic import ( + context, +) + +from evm.vm.forks.byzantium import BYZANTIUM_OPCODES + + +NEW_OPCODES = { + opcode_values.SIGHASH: as_opcode( + logic_fn=context.sighash, + mnemonic=mnemonics.SIGHASH, + gas_cost=0, + ), +} + + +SHARDING_OPCODES = merge( + copy.deepcopy(BYZANTIUM_OPCODES), + NEW_OPCODES +) diff --git a/evm/vm/message.py b/evm/vm/message.py index ae4b90066c..87f3e54bcb 100644 --- a/evm/vm/message.py +++ b/evm/vm/message.py @@ -11,6 +11,7 @@ validate_uint256, validate_is_boolean, validate_access_list, + validate_sig_hash, ) @@ -148,6 +149,7 @@ def __init__(self, gas, gas_price, to, + sig_hash, sender, value, data, @@ -178,6 +180,32 @@ def __init__(self, validate_is_boolean(is_create, title="Message.is_create") self.is_create = is_create + validate_sig_hash(sig_hash, title="Message.sig_hash") + self.sig_hash = sig_hash + if access_list is not None: validate_access_list(access_list) self.access_list = access_list + + def prepare_child_message(self, + gas, + to, + value, + data, + code, + **kwargs): + kwargs.setdefault('sender', self.msg.storage_address) + + child_message = ShardingMessage( + gas=gas, + gas_price=self.msg.gas_price, + origin=self.msg.origin, + sig_hash=self.msg.sig_hash, + to=to, + value=value, + data=data, + code=code, + depth=self.msg.depth + 1, + **kwargs + ) + return child_message