Skip to content

Commit

Permalink
Implement difficulty calculation for homestead
Browse files Browse the repository at this point in the history
  • Loading branch information
gsalgado committed Jul 24, 2017
1 parent 65afb30 commit d750c6e
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 11 deletions.
1 change: 1 addition & 0 deletions evm/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
DIFFICULTY_MINIMUM = 131072

FRONTIER_DIFFICULTY_ADJUSTMENT_CUTOFF = 13
HOMESTEAD_DIFF_ADJUSTMENT_CUTOFF = 10

BOMB_EXPONENTIAL_PERIOD = 100000
BOMB_EXPONENTIAL_FREE_PERIODS = 2
Expand Down
6 changes: 6 additions & 0 deletions evm/vm/flavors/homestead/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
from .opcodes import HOMESTEAD_OPCODES
from .blocks import HomesteadBlock
from .validation import validate_homestead_transaction
from .headers import (
create_homestead_header_from_parent,
configure_homestead_header,
)


def _apply_homestead_create_message(vm, message):
Expand Down Expand Up @@ -62,4 +66,6 @@ def _apply_homestead_create_message(vm, message):
# method overrides
validate_transaction=validate_homestead_transaction,
apply_create_message=_apply_homestead_create_message,
create_header_from_parent=staticmethod(create_homestead_header_from_parent),
configure_header=configure_homestead_header,
)
11 changes: 11 additions & 0 deletions evm/vm/flavors/homestead/blocks.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
from rlp.sedes import (
CountableList,
)
from evm.rlp.headers import (
BlockHeader,
)
from evm.vm.flavors.frontier.blocks import (
FrontierBlock,
)
Expand All @@ -8,3 +14,8 @@

class HomesteadBlock(FrontierBlock):
transaction_class = HomesteadTransaction
fields = [
('header', BlockHeader),
('transactions', CountableList(HomesteadTransaction)),
('uncles', CountableList(BlockHeader))
]
58 changes: 58 additions & 0 deletions evm/vm/flavors/homestead/headers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from evm.validation import (
validate_gt,
)
from evm.constants import (
DIFFICULTY_ADJUSTMENT_DENOMINATOR,
DIFFICULTY_MINIMUM,
BOMB_EXPONENTIAL_PERIOD,
BOMB_EXPONENTIAL_FREE_PERIODS,
HOMESTEAD_DIFF_ADJUSTMENT_CUTOFF,
)

from evm.vm.flavors.frontier.headers import (
configure_frontier_header,
create_frontier_header_from_parent,
)


def compute_homestead_difficulty(parent_header, timestamp):
"""
Computes the difficulty for a homestead block based on the parent block.
"""
parent_tstamp = parent_header.timestamp
validate_gt(timestamp, parent_tstamp)
offset = parent_header.difficulty // DIFFICULTY_ADJUSTMENT_DENOMINATOR
sign = max(
1 - (timestamp - parent_tstamp) // HOMESTEAD_DIFF_ADJUSTMENT_CUTOFF,
-99)
difficulty = int(max(
parent_header.difficulty + offset * sign,
min(parent_header.difficulty, DIFFICULTY_MINIMUM)))
num_bomb_periods = (
(parent_header.block_number + 1) // BOMB_EXPONENTIAL_PERIOD
) - BOMB_EXPONENTIAL_FREE_PERIODS
if num_bomb_periods >= 0:
return max(difficulty + 2**num_bomb_periods, DIFFICULTY_MINIMUM)
else:
return difficulty


def create_homestead_header_from_parent(parent_header, **header_params):
if 'difficulty' not in header_params:
timestamp = header_params.get('timestamp', parent_header.timestamp + 1)
header_params['difficulty'] = compute_homestead_difficulty(
parent_header,
timestamp,
)
return create_frontier_header_from_parent(parent_header, **header_params)


def configure_homestead_header(vm, **header_params):
header = configure_frontier_header(vm, **header_params)
if 'timestamp' in header_params and header.block_number > 0:
parent_header = vm.block.get_parent_header()
header.difficulty = compute_homestead_difficulty(
parent_header,
header_params['timestamp'],
)
return header
28 changes: 17 additions & 11 deletions tests/json-fixtures/test_blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
keccak,
)

from evm import EVM
from evm.exceptions import (
ValidationError,
)
from evm.vm.flavors import (
HomesteadVM,
MainnetEVM,
)
from evm.rlp.headers import (
Expand All @@ -42,15 +44,17 @@
DISABLED_INDIVIDUAL_TESTS = [
"bcInvalidHeaderTest.json:ExtraData1024",
"bcInvalidHeaderTest.json:DifferentExtraData1025",
# This test alone takes more than 10 minutes to run, and that causes the
# travis build to be terminated so it's disabled until we figure out how
# to make it run faster.
"Homestead/bcSuicideIssue.json:SuicideIssue",
]

def blockchain_fixture_skip_fn(fixture_path, fixture_name, fixture):
# TODO: enable all tests
return (
":".join([fixture_path, fixture_name]) in DISABLED_INDIVIDUAL_TESTS or
fixture_path.startswith('TestNetwork') or # TODO: enable
'Homestead' in fixture_path or # TODO: enable
'Homestead' in fixture_name or # TODO: enable
'EIP150' in fixture_path or # TODO: enable
'EIP150' in fixture_name or # TODO: enable
'EIP158' in fixture_path or # TODO: enable
Expand All @@ -59,16 +63,11 @@ def blockchain_fixture_skip_fn(fixture_path, fixture_name, fixture):


SLOW_FIXTURE_NAMES = {
'GeneralStateTests/stAttackTest/ContractCreationSpam.json:ContractCreationSpam_d0g0v0_Frontier',
'GeneralStateTests/stBoundsTest/MLOAD_Bounds.json:MLOAD_Bounds_d0g0v0_Frontier',
'GeneralStateTests/stMemoryStressTest/CALLCODE_Bounds3.json:CALLCODE_Bounds3_d0g0v0_Frontier',
'GeneralStateTests/stMemoryStressTest/CALL_Bounds2.json:CALL_Bounds2_d0g0v0_Frontier',
'GeneralStateTests/stMemoryStressTest/CALL_Bounds2a.json:CALL_Bounds2a_d0g0v0_Frontier',
'GeneralStateTests/stCallCreateCallCodeTest/Call1024OOG.json:Call1024OOG_d0g0v0_Frontier',
'GeneralStateTests/stCallCreateCallCodeTest/Callcode1024OOG.json:Callcode1024OOG_d0g0v0_Frontier',
'GeneralStateTests/stCallCreateCallCodeTest/CallRecursiveBombPreCall.json:CallRecursiveBombPreCall_d0g0v0_Frontier',
'bcForkStressTest.json:ForkStressTest',
'bcWalletTest.json:walletReorganizeOwners',
'Homestead/bcExploitTest.json:DelegateCallSpam',
"Homestead/bcWalletTest.json:walletReorganizeOwners",
"Homestead/bcShanghaiLove.json:Devcon2Attack",
}


Expand Down Expand Up @@ -116,7 +115,14 @@ def test_blockchain_fixtures(fixture_name, fixture):
# assert rlp.encode(genesis_header) == fixture['genesisRLP']

db = MemoryDB()
evm = MainnetEVM.from_genesis(

evm = MainnetEVM
if fixture_name.startswith('Homestead'):
evm = EVM.configure(
'HomesteadEVM',
vm_configuration=[(0, HomesteadVM)])

evm = evm.from_genesis(
db,
genesis_params=genesis_params,
genesis_state=fixture['pre'],
Expand Down

0 comments on commit d750c6e

Please sign in to comment.