diff --git a/eth/vm/forks/berlin/__init__.py b/eth/vm/forks/berlin/__init__.py new file mode 100644 index 0000000000..bd750ee05e --- /dev/null +++ b/eth/vm/forks/berlin/__init__.py @@ -0,0 +1,31 @@ +from typing import ( + Type, +) + +from eth.rlp.blocks import BaseBlock +from eth.vm.forks import ( + MuirGlacierVM, +) +from eth.vm.state import BaseState + +from .blocks import BerlinBlock +from .headers import ( + compute_berlin_difficulty, + configure_berlin_header, + create_berlin_header_from_parent, +) +from .state import BerlinState + + +class BerlinVM(MuirGlacierVM): + # fork name + fork = 'berlin' + + # classes + block_class: Type[BaseBlock] = BerlinBlock + _state_class: Type[BaseState] = BerlinState + + # Methods + create_header_from_parent = staticmethod(create_berlin_header_from_parent) # type: ignore + compute_difficulty = staticmethod(compute_berlin_difficulty) # type: ignore + configure_header = configure_berlin_header diff --git a/eth/vm/forks/berlin/blocks.py b/eth/vm/forks/berlin/blocks.py new file mode 100644 index 0000000000..61df903a39 --- /dev/null +++ b/eth/vm/forks/berlin/blocks.py @@ -0,0 +1,22 @@ +from rlp.sedes import ( + CountableList, +) +from eth.rlp.headers import ( + BlockHeader, +) +from eth.vm.forks.muir_glacier.blocks import ( + MuirGlacierBlock, +) + +from .transactions import ( + BerlinTransaction, +) + + +class BerlinBlock(MuirGlacierBlock): + transaction_class = BerlinTransaction + fields = [ + ('header', BlockHeader), + ('transactions', CountableList(transaction_class)), + ('uncles', CountableList(BlockHeader)) + ] diff --git a/eth/vm/forks/berlin/computation.py b/eth/vm/forks/berlin/computation.py new file mode 100644 index 0000000000..02e43926bc --- /dev/null +++ b/eth/vm/forks/berlin/computation.py @@ -0,0 +1,20 @@ +from eth.vm.forks.muir_glacier.computation import ( + MUIR_GLACIER_PRECOMPILES +) +from eth.vm.forks.muir_glacier.computation import ( + MuirGlacierComputation, +) + +from .opcodes import BERLIN_OPCODES + +BERLIN_PRECOMPILES = MUIR_GLACIER_PRECOMPILES + + +class BerlinComputation(MuirGlacierComputation): + """ + A class for all execution computations in the ``Berlin`` fork. + Inherits from :class:`~eth.vm.forks.muir_glacier.MuirGlacierComputation` + """ + # Override + opcodes = BERLIN_OPCODES + _precompiles = BERLIN_PRECOMPILES diff --git a/eth/vm/forks/berlin/headers.py b/eth/vm/forks/berlin/headers.py new file mode 100644 index 0000000000..09352021f2 --- /dev/null +++ b/eth/vm/forks/berlin/headers.py @@ -0,0 +1,13 @@ +from eth.vm.forks.muir_glacier.headers import ( + configure_header, + create_header_from_parent, + compute_muir_glacier_difficulty, +) + + +compute_berlin_difficulty = compute_muir_glacier_difficulty + +create_berlin_header_from_parent = create_header_from_parent( + compute_berlin_difficulty +) +configure_berlin_header = configure_header(compute_berlin_difficulty) diff --git a/eth/vm/forks/berlin/opcodes.py b/eth/vm/forks/berlin/opcodes.py new file mode 100644 index 0000000000..9ea87cbd99 --- /dev/null +++ b/eth/vm/forks/berlin/opcodes.py @@ -0,0 +1,19 @@ +import copy +from typing import Dict + +from eth_utils.toolz import merge + +from eth.vm.forks.muir_glacier.opcodes import ( + MUIR_GLACIER_OPCODES, +) +from eth.vm.opcode import Opcode + + +UPDATED_OPCODES: Dict[int, Opcode] = { + # New opcodes +} + +BERLIN_OPCODES = merge( + copy.deepcopy(MUIR_GLACIER_OPCODES), + UPDATED_OPCODES, +) diff --git a/eth/vm/forks/berlin/state.py b/eth/vm/forks/berlin/state.py new file mode 100644 index 0000000000..c5e9d85ed5 --- /dev/null +++ b/eth/vm/forks/berlin/state.py @@ -0,0 +1,9 @@ +from eth.vm.forks.muir_glacier.state import ( + MuirGlacierState +) + +from .computation import BerlinComputation + + +class BerlinState(MuirGlacierState): + computation_class = BerlinComputation diff --git a/eth/vm/forks/berlin/transactions.py b/eth/vm/forks/berlin/transactions.py new file mode 100644 index 0000000000..74ee8fba8a --- /dev/null +++ b/eth/vm/forks/berlin/transactions.py @@ -0,0 +1,42 @@ +from eth_keys.datatypes import PrivateKey +from eth_typing import Address + +from eth.vm.forks.muir_glacier.transactions import ( + MuirGlacierTransaction, + MuirGlacierUnsignedTransaction, +) + +from eth._utils.transactions import ( + create_transaction_signature, +) + + +class BerlinTransaction(MuirGlacierTransaction): + @classmethod + def create_unsigned_transaction(cls, + *, + nonce: int, + gas_price: int, + gas: int, + to: Address, + value: int, + data: bytes) -> 'BerlinUnsignedTransaction': + return BerlinUnsignedTransaction(nonce, gas_price, gas, to, value, data) + + +class BerlinUnsignedTransaction(MuirGlacierUnsignedTransaction): + def as_signed_transaction(self, + private_key: PrivateKey, + chain_id: int = None) -> BerlinTransaction: + v, r, s = create_transaction_signature(self, private_key, chain_id=chain_id) + return BerlinTransaction( + nonce=self.nonce, + gas_price=self.gas_price, + gas=self.gas, + to=self.to, + value=self.value, + data=self.data, + v=v, + r=r, + s=s, + )