Skip to content

Commit

Permalink
Move other block things from State -> VM
Browse files Browse the repository at this point in the history
  • Loading branch information
carver committed May 4, 2018
1 parent 95b68eb commit 3f24a37
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 113 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ clean-pyc:
find . -name '*~' -exec rm -f {} +

lint:
tox -elint-py36
tox -elint-py3{6,5}

test:
py.test --tb native tests
Expand Down
69 changes: 68 additions & 1 deletion evm/vm/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,40 @@ def mine_block(self, *args, **kwargs):
if block.number == 0:
return block
else:
return self.state.finalize_block(block)
return self.finalize_block(block)

#
# Finalization
#
def finalize_block(self, block):
"""
Perform any finalization steps like awarding the block mining reward.
"""
block_reward = self.get_block_reward() + (
len(block.uncles) * self.get_nephew_reward()
)

self.state.account_db.delta_balance(block.header.coinbase, block_reward)
self.logger.debug(
"BLOCK REWARD: %s -> %s",
block_reward,
block.header.coinbase,
)

for uncle in block.uncles:
uncle_reward = self.get_uncle_reward(block.number, uncle)
self.state.account_db.delta_balance(uncle.coinbase, uncle_reward)
self.logger.debug(
"UNCLE REWARD REWARD: %s -> %s",
uncle_reward,
uncle.coinbase,
)
# We need to call `persist` here since the state db batches
# all writes until we tell it to write to the underlying db
# TODO: Refactor to only use batching/journaling for tx processing
self.state.account_db.persist()

return block.copy(header=block.header.copy(state_root=self.state.state_root))

def pack_block(self, block, *args, **kwargs):
"""
Expand Down Expand Up @@ -499,6 +532,40 @@ def previous_hashes(self):
"""
return self.get_prev_hashes(self.block.header.parent_hash, self.chaindb)

@staticmethod
@abstractmethod
def get_block_reward() -> int:
"""
Return the amount in **wei** that should be given to a miner as a reward
for this block.
.. note::
This is an abstract method that must be implemented in subclasses
"""
raise NotImplementedError("Must be implemented by subclasses")

@staticmethod
@abstractmethod
def get_uncle_reward(block_number: int, uncle: BaseBlock) -> int:
"""
Return the reward which should be given to the miner of the given `uncle`.
.. note::
This is an abstract method that must be implemented in subclasses
"""
raise NotImplementedError("Must be implemented by subclasses")

@classmethod
@abstractmethod
def get_nephew_reward(cls) -> int:
"""
Return the reward which should be given to the miner of the given `nephew`.
.. note::
This is an abstract method that must be implemented in subclasses
"""
raise NotImplementedError("Must be implemented by subclasses")

#
# Headers
#
Expand Down
21 changes: 21 additions & 0 deletions evm/vm/forks/byzantium/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
from typing import ( # noqa: F401
Type,
)

from evm.constants import (
MAX_UNCLE_DEPTH,
)
from evm.rlp.blocks import BaseBlock # noqa: F401
from evm.validation import (
validate_lte,
)
from evm.vm.forks.spurious_dragon import SpuriousDragonVM
from evm.vm.forks.frontier import make_frontier_receipt
from evm.vm.state import BaseState # noqa: F401

from .blocks import ByzantiumBlock
from .constants import (
EIP649_BLOCK_REWARD,
EIP658_TRANSACTION_STATUS_CODE_FAILURE,
EIP658_TRANSACTION_STATUS_CODE_SUCCESS,
)
Expand Down Expand Up @@ -40,3 +51,13 @@ class ByzantiumVM(SpuriousDragonVM):
compute_difficulty = staticmethod(compute_byzantium_difficulty)
configure_header = configure_byzantium_header
make_receipt = staticmethod(make_byzantium_receipt)

@staticmethod
def get_block_reward():
return EIP649_BLOCK_REWARD

@staticmethod
def get_uncle_reward(block_number, uncle):
block_number_delta = block_number - uncle.block_number
validate_lte(block_number_delta, MAX_UNCLE_DEPTH)
return (8 - block_number_delta) * EIP649_BLOCK_REWARD // 8
19 changes: 0 additions & 19 deletions evm/vm/forks/byzantium/state.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,7 @@
from evm.constants import (
MAX_UNCLE_DEPTH,
)
from evm.validation import (
validate_lte,
)
from evm.vm.forks.spurious_dragon.state import SpuriousDragonState

from .computation import ByzantiumComputation
from .constants import (
EIP649_BLOCK_REWARD,
)


class ByzantiumState(SpuriousDragonState):
computation_class = ByzantiumComputation

@staticmethod
def get_block_reward():
return EIP649_BLOCK_REWARD

@staticmethod
def get_uncle_reward(block_number, uncle):
block_number_delta = block_number - uncle.block_number
validate_lte(block_number_delta, MAX_UNCLE_DEPTH)
return (8 - block_number_delta) * EIP649_BLOCK_REWARD // 8
18 changes: 18 additions & 0 deletions evm/vm/forks/frontier/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
from evm.vm.state import BaseState # noqa: F401


from evm.constants import (
BLOCK_REWARD,
UNCLE_DEPTH_PENALTY_FACTOR,
)
from evm.vm import VM
from evm.rlp.receipts import (
Receipt,
Expand Down Expand Up @@ -63,3 +67,17 @@ class FrontierVM(VM):
configure_header = configure_frontier_header
make_receipt = staticmethod(make_frontier_receipt)
validate_transaction_against_header = validate_frontier_transaction_against_header

@staticmethod
def get_block_reward():
return BLOCK_REWARD

@staticmethod
def get_uncle_reward(block_number, uncle):
return BLOCK_REWARD * (
UNCLE_DEPTH_PENALTY_FACTOR + uncle.block_number - block_number
) // UNCLE_DEPTH_PENALTY_FACTOR

@classmethod
def get_nephew_reward(cls):
return cls.get_block_reward() // 32
18 changes: 0 additions & 18 deletions evm/vm/forks/frontier/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
from eth_hash.auto import keccak

from evm import constants
from evm.constants import (
BLOCK_REWARD,
UNCLE_DEPTH_PENALTY_FACTOR,
)
from evm.db.account import (
AccountDB,
)
Expand Down Expand Up @@ -180,17 +176,3 @@ class FrontierState(BaseState, FrontierTransactionExecutor):

def validate_transaction(self, transaction):
validate_frontier_transaction(self.account_db, transaction)

@staticmethod
def get_block_reward():
return BLOCK_REWARD

@staticmethod
def get_uncle_reward(block_number, uncle):
return BLOCK_REWARD * (
UNCLE_DEPTH_PENALTY_FACTOR + uncle.block_number - block_number
) // UNCLE_DEPTH_PENALTY_FACTOR

@classmethod
def get_nephew_reward(cls):
return cls.get_block_reward() // 32
76 changes: 2 additions & 74 deletions evm/vm/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,89 +243,17 @@ def do_call(self, transaction):

return computation

def apply_transaction(
self,
transaction):
def apply_transaction(self, transaction):
"""
Apply transaction to the vm state
:param transaction: the transaction to apply
:type transaction: Transaction
:return: the computation, applied block, and the trie_data_dict
:rtype: (Computation, dict[bytes, bytes])
:return: the new state root, and the computation
"""
computation = self.execute_transaction(transaction)
self.account_db.persist()
return self.account_db.state_root, computation

#
# Finalization
#
def finalize_block(self, block):
"""
Perform any finalization steps like awarding the block mining reward.
"""
block_reward = self.get_block_reward() + (
len(block.uncles) * self.get_nephew_reward()
)

self.account_db.delta_balance(block.header.coinbase, block_reward)
self.logger.debug(
"BLOCK REWARD: %s -> %s",
block_reward,
block.header.coinbase,
)

for uncle in block.uncles:
uncle_reward = self.get_uncle_reward(block.number, uncle)
self.account_db.delta_balance(uncle.coinbase, uncle_reward)
self.logger.debug(
"UNCLE REWARD REWARD: %s -> %s",
uncle_reward,
uncle.coinbase,
)
# We need to call `persist` here since the state db batches
# all writes untill we tell it to write to the underlying db
# TODO: Refactor to only use batching/journaling for tx processing
self.account_db.persist()

return block.copy(header=block.header.copy(state_root=self.state_root))

@staticmethod
@abstractmethod
def get_block_reward():
"""
Return the amount in **wei** that should be given to a miner as a reward
for this block.
.. note::
This is an abstract method that must be implemented in subclasses
"""
raise NotImplementedError("Must be implemented by subclasses")

@staticmethod
@abstractmethod
def get_uncle_reward(block_number, uncle):
"""
Return the reward which should be given to the miner of the given `uncle`.
.. note::
This is an abstract method that must be implemented in subclasses
"""
raise NotImplementedError("Must be implemented by subclasses")

@classmethod
@abstractmethod
def get_nephew_reward(cls):
"""
Return the reward which should be given to the miner of the given `nephew`.
.. note::
This is an abstract method that must be implemented in subclasses
"""
raise NotImplementedError("Must be implemented by subclasses")


class BaseTransactionExecutor(metaclass=ABCMeta):
def execute_transaction(self, transaction):
Expand Down

0 comments on commit 3f24a37

Please sign in to comment.