Skip to content

Commit 1761460

Browse files
committed
EIP-96: Add BLOCKHASH contract tests
1 parent f271d17 commit 1761460

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

EIPS/eip-96/tests/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/*.egg-info/
2+
/.cache/
3+
/__pycache__/

EIPS/eip-96/tests/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
### Usage
2+
3+
1. Setup virtualenv
4+
2. `pip install -r requirements.txt`
5+
3. `py.test`

EIPS/eip-96/tests/requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
six
2+
pytest
3+
ethereum==1.6.1
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import pytest
2+
import os
3+
from ethereum import tester, utils
4+
from ethereum.config import default_config
5+
from rlp.utils import decode_hex
6+
7+
from pprint import pprint
8+
9+
EIP_BLOCKHASH_CODE = decode_hex(
10+
b'73fffffffffffffffffffffffffffffffffffffffe33141561006a5760014303600035610100820755610100810715156100455760003561010061010083050761010001555b6201000081071515610064576000356101006201000083050761020001555b5061013e565b4360003512151561008457600060405260206040f361013d565b61010060003543031315156100a857610100600035075460605260206060f361013c565b6101006000350715156100c55762010000600035430313156100c8565b60005b156100ea576101006101006000350507610100015460805260206080f361013b565b620100006000350715156101095763010000006000354303131561010c565b60005b1561012f57610100620100006000350507610200015460a052602060a0f361013a565b600060c052602060c0f35b5b5b5b5b' # noqa
11+
)
12+
13+
BLOCKHASH_ADDR = decode_hex(b'00000000000000000000000000000000000000f0')
14+
EIP_SYSTEM_ADDR = decode_hex(b'fffffffffffffffffffffffffffffffffffffffe')
15+
16+
SYSTEM_PRIV = os.urandom(32)
17+
SYSTEM_ADDR = utils.privtoaddr(SYSTEM_PRIV)
18+
SYSTEM_GAS_LIMIT = 1000000
19+
SYSTEM_GAS_PRICE = 0
20+
BLOCKHASH_CODE = EIP_BLOCKHASH_CODE.replace(EIP_SYSTEM_ADDR, SYSTEM_ADDR, 1)
21+
NULL_HASH = b'\0' * 32
22+
23+
# Configure execution in pre-Metropolis mode.
24+
default_config['HOMESTEAD_FORK_BLKNUM'] = 0
25+
default_config['DAO_FORK_BLKNUM'] = 0
26+
default_config['ANTI_DOS_FORK_BLKNUM'] = 0
27+
default_config['CLEARING_FORK_BLKNUM'] = 0
28+
29+
30+
class State(tester.state):
31+
def exec_system(self):
32+
"""Execute BLOCKHASH contract from SYSTEM account"""
33+
34+
prev_block_hash = self.block.get_parent().hash
35+
assert len(prev_block_hash) == 32
36+
37+
gas_limit = tester.gas_limit
38+
tester.gas_limit = SYSTEM_GAS_LIMIT
39+
40+
gas_price = tester.gas_price
41+
tester.gas_price = SYSTEM_GAS_PRICE
42+
43+
output = self.send(sender=SYSTEM_PRIV, to=BLOCKHASH_ADDR, value=0,
44+
evmdata=prev_block_hash)
45+
assert len(output) == 0
46+
47+
tester.gas_limit = gas_limit
48+
tester.gas_price = gas_price
49+
50+
def get_slot(self, index):
51+
"""Get storage entry of BLOCKHASH_ADDR of given index"""
52+
int_value = self.block.get_storage_data(BLOCKHASH_ADDR, index)
53+
return utils.zpad(utils.coerce_to_bytes(int_value), 32)
54+
55+
56+
@pytest.fixture(scope='module')
57+
def state():
58+
state = State()
59+
state.block._set_acct_item(BLOCKHASH_ADDR, 'code', BLOCKHASH_CODE)
60+
61+
for i in range(257):
62+
state.mine()
63+
state.exec_system()
64+
65+
return state
66+
67+
68+
def test_setup(state):
69+
assert state.block.get_code(BLOCKHASH_ADDR) == BLOCKHASH_CODE
70+
assert state.block.get_balance(SYSTEM_ADDR) == 0
71+
assert state.block.get_nonce(SYSTEM_ADDR) > 0
72+
73+
assert state.get_slot(0) == state.blocks[256].hash
74+
for i in range(1, 256):
75+
assert state.get_slot(i) == state.blocks[i].hash
76+
77+
assert state.get_slot(256) == state.blocks[0].hash
78+
assert state.get_slot(257) == state.blocks[256].hash
79+
for i in range(258, 256 + 256):
80+
assert state.get_slot(i) == NULL_HASH
81+
82+
assert state.get_slot(512) == state.blocks[0].hash
83+
for i in range(513, 512 + 256):
84+
assert state.get_slot(i) == NULL_HASH
85+
86+
87+
def test_get_prev_block_hash(state):
88+
prev = state.block.number - 1
89+
pprint(prev)
90+
expected_hash = state.blocks[prev].hash
91+
arg = utils.zpad(utils.coerce_to_bytes(prev), 32)
92+
out = state.profile(sender=tester.k1, to=BLOCKHASH_ADDR, value=0,
93+
evmdata=arg)
94+
assert out['output'] == expected_hash
95+
assert out['gas'] == 330
96+
97+
98+
def test_get_current_block_hash(state):
99+
arg = utils.zpad(utils.coerce_to_bytes(state.block.number), 32)
100+
out = state.profile(sender=tester.k1, to=BLOCKHASH_ADDR, value=0,
101+
evmdata=arg)
102+
assert out['output'] == b'\0' * 32
103+
assert out['gas'] == 79
104+
105+
106+
def test_get_future_block_hash(state):
107+
arg = utils.zpad(utils.coerce_to_bytes(3**11 + 13), 32)
108+
out = state.profile(sender=tester.k1, to=BLOCKHASH_ADDR, value=0,
109+
evmdata=arg)
110+
assert out['output'] == b'\0' * 32
111+
assert out['gas'] == 79
112+
113+
114+
def test_first256th_slot(state):
115+
n = state.block.number
116+
state.block.number = 60000 # Allow accessing 256th block hashes
117+
118+
arg = utils.zpad(utils.coerce_to_bytes(0), 32)
119+
out = state.profile(sender=tester.k1, to=BLOCKHASH_ADDR, value=0,
120+
evmdata=arg)
121+
assert out['output'] == state.blocks[0].hash
122+
assert out['gas'] == 429
123+
124+
state.block.number = n

0 commit comments

Comments
 (0)