Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

Commit c2ec1dc

Browse files
vubvub
authored andcommitted
Started work on new state tests
1 parent 7440dea commit c2ec1dc

File tree

4 files changed

+150
-9
lines changed

4 files changed

+150
-9
lines changed

ethereum/new_statetest_utils.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
from ethereum.state import State
2+
from ethereum.block import FakeHeader, Block
3+
from ethereum.utils import decode_hex, parse_int_or_hex, sha3, to_string, \
4+
remove_0x_head, encode_hex, big_endian_to_int
5+
from ethereum.config import default_config, Env
6+
from ethereum.exceptions import InvalidTransaction
7+
import ethereum.transactions as transactions
8+
import ethereum.state_transition as state_transition
9+
import copy
10+
11+
#from ethereum.slogging import LogRecorder, configure_logging, set_level
12+
#config_string = ':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,eth.vm.exit:trace,eth.pb.msg:trace,eth.pb.tx:debug'
13+
#configure_logging(config_string=config_string)
14+
15+
fake_headers = {}
16+
17+
def mk_fake_header(blknum):
18+
if blknum not in fake_headers:
19+
fake_headers[blknum] = FakeHeader(sha3(to_string(blknum)))
20+
return fake_headers[blknum]
21+
22+
basic_env = {
23+
"currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
24+
"currentDifficulty": "256",
25+
"currentGasLimit": "1000000000",
26+
"currentNumber": "257",
27+
"currentTimestamp": "1",
28+
"previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
29+
}
30+
31+
konfig = copy.copy(default_config)
32+
33+
konfig_spurious = copy.copy(konfig)
34+
konfig_spurious["HOMESTEAD_FORK_BLKNUM"] = 0
35+
konfig_spurious["ANTI_DOS_FORK_BLKNUM"] = 0
36+
konfig_spurious["CLEARING_FORK_BLKNUM"] = 0
37+
konfig_spurious["METROPOLIS_FORK_BLKNUM"] = 2**99
38+
39+
konfig_metropolis = copy.copy(konfig)
40+
konfig_metropolis["HOMESTEAD_FORK_BLKNUM"] = 0
41+
konfig_metropolis["ANTI_DOS_FORK_BLKNUM"] = 0
42+
konfig_metropolis["CLEARING_FORK_BLKNUM"] = 0
43+
konfig_metropolis["METROPOLIS_FORK_BLKNUM"] = 0
44+
45+
configs = {
46+
"EIP158": konfig_spurious,
47+
"Metropolis": konfig_metropolis
48+
}
49+
50+
def compute_state_test_post(test, indices=None, _configs=None):
51+
env, pre, txdata = test["env"], test["pre"], test["transaction"]
52+
# Setup env
53+
state = State(
54+
env=Env(config=konfig),
55+
block_prevhash=decode_hex(env['previousHash']),
56+
prev_headers=[mk_fake_header(i) for i in range(parse_int_or_hex(env['currentNumber']) -1,
57+
max(-1, parse_int_or_hex(env['currentNumber']) -257), -1)],
58+
block_number=parse_int_or_hex(env['currentNumber']),
59+
block_coinbase=decode_hex(env['currentCoinbase']),
60+
block_difficulty=parse_int_or_hex(env['currentDifficulty']),
61+
gas_limit=parse_int_or_hex(env['currentGasLimit']),
62+
timestamp=parse_int_or_hex(env['currentTimestamp']))
63+
64+
# Fill up pre
65+
for address, h in list(pre.items()):
66+
assert len(address) == 40
67+
address = decode_hex(address)
68+
assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage'])
69+
state.set_nonce(address, parse_int_or_hex(h['nonce']))
70+
state.set_balance(address, parse_int_or_hex(h['balance']))
71+
state.set_code(address, decode_hex(h['code'][2:]))
72+
for k, v in h['storage'].items():
73+
state.set_storage_data(address,
74+
big_endian_to_int(decode_hex(k[2:])),
75+
decode_hex(v[2:]))
76+
77+
78+
# We have an optional argument which is a list of JSONs specifying indices.
79+
# If this argument is set, we compute only those scenarios. If not, we
80+
# compute all of them.
81+
if indices is None:
82+
indices = []
83+
for data_index in range(len(txdata['data'])):
84+
for value_index in range(len(txdata['value'])):
85+
for gaslimit_index in range(len(txdata['gasLimit'])):
86+
indices.append({"data": data_index, "gas": gaslimit_index, "value": value_index})
87+
88+
o = {}
89+
for config_name in (configs.keys() if _configs is None else _configs):
90+
state.env.config = configs[config_name]
91+
output_decls = []
92+
for index_json in indices:
93+
print("Executing for indices %r" % index_json)
94+
data_index, value_index, gaslimit_index = index_json["data"], index_json["value"], index_json["gas"]
95+
try:
96+
# Create the transaction
97+
tx = transactions.Transaction(
98+
nonce=parse_int_or_hex(txdata['nonce'] or b"0"),
99+
gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"),
100+
startgas=parse_int_or_hex(txdata['gasLimit'][gaslimit_index] or b"0"),
101+
to=decode_hex(txdata['to']),
102+
value=parse_int_or_hex(txdata['value'][value_index] or b"0"),
103+
data=decode_hex(remove_0x_head(txdata['data'][data_index])))
104+
tx.sign(decode_hex(txdata['secretKey']))
105+
# Run it
106+
success, output = state_transition.apply_transaction(state, tx)
107+
print("Applied tx")
108+
except InvalidTransaction as e:
109+
print("Exception: %r" % e)
110+
success, output = False, b''
111+
state.commit()
112+
output_decl = {
113+
"hash": encode_hex(state.trie.root_hash),
114+
"indexes": index_json
115+
}
116+
output_decls.append(output_decl)
117+
o[config_name] = output_decls
118+
return o
119+
120+
def verify_state_test(test):
121+
print("Verifying state test")
122+
for config_name, result in test["post"].items():
123+
# Old protocol versions may not be supported
124+
if config_name not in configs:
125+
continue
126+
print("Testing for %s" % config_name)
127+
computed = compute_state_test_post(test, [x["indexes"] for x in result], [config_name])[config_name]
128+
supplied = test["post"][config_name]
129+
assert len(computed) == len(supplied)
130+
for c, s in zip(computed, supplied):
131+
assert c["hash"] == s["hash"]

ethereum/state_transition.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from ethereum.config import Env, default_config
2424
from ethereum.db import BaseDB, EphemDB
2525
from ethereum.exceptions import InvalidNonce, InsufficientStartGas, UnsignedTransaction, \
26-
BlockGasLimitReached, InsufficientBalance, VerificationFailed
26+
BlockGasLimitReached, InsufficientBalance, VerificationFailed, InvalidTransaction
2727
import sys
2828
if sys.version_info.major == 2:
2929
from repoze.lru import lru_cache
@@ -159,16 +159,15 @@ def config_fork_specific_validation(config, blknum, tx):
159159
tx.check_low_s_metropolis()
160160
else:
161161
if tx.sender == null_address:
162-
raise VerificationFailed("EIP86 transactions not available yet")
162+
raise InvalidTransaction("EIP86 transactions not available yet")
163163
if blknum >= config['HOMESTEAD_FORK_BLKNUM']:
164164
tx.check_low_s_homestead()
165-
print(tx.network_id, config["NETWORK_ID"])
166165
if blknum >= config["CLEARING_FORK_BLKNUM"]:
167166
if tx.network_id not in (None, config["NETWORK_ID"]):
168-
raise VerificationFailed("Wrong network ID")
167+
raise InvalidTransaction("Wrong network ID")
169168
else:
170169
if tx.network_id is not None:
171-
raise VerificationFailed("Wrong network ID")
170+
raise InvalidTransaction("Wrong network ID")
172171
return True
173172

174173
def validate_transaction(state, tx):

ethereum/tests/test_state.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22
import sys
33
import ethereum.testutils as testutils
4+
import ethereum.new_statetest_utils as new_statetest_utils
45

56
from ethereum.slogging import get_logger, configure_logging
67
logger = get_logger()
@@ -10,10 +11,16 @@
1011
configure_logging(':trace')
1112
sys.argv.remove('--trace')
1213

14+
if '--new' in sys.argv: # not default
15+
checker = new_statetest_utils.verify_state_test
16+
sys.argv.remove('--new')
17+
else:
18+
checker = testutils.check_state_test
19+
1320

1421
def test_state(filename, testname, testdata):
1522
logger.debug('running test:%r in %r' % (testname, filename))
16-
testutils.check_state_test(testutils.fixture_to_bytes(testdata))
23+
checker(testutils.fixture_to_bytes(testdata))
1724

1825

1926
def pytest_generate_tests(metafunc):
@@ -43,7 +50,7 @@ def main():
4350
for testname, testdata in list(tests.items()):
4451
if len(sys.argv) < 3 or testname == sys.argv[2]:
4552
print("Testing: %s %s" % (filename, testname))
46-
testutils.check_state_test(testdata)
53+
checker(testdata)
4754

4855

4956
if __name__ == '__main__':

ethereum/vm.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ def __init__(self, parent_memory, offset=0, size=None):
3939
def extract_all(self):
4040
d = self.data[self.offset: self.offset + self.size]
4141
d += [0] * (self.size - len(d))
42-
return b''.join([ascii_chr(x) for x in d])
42+
o = bytearray(len(d))
43+
for i, x in enumerate(d):
44+
o[i] = x
45+
return bytes(o)
4346

4447
def extract32(self, i):
4548
if i >= self.size:
@@ -147,7 +150,7 @@ def eat_gas(compustate, amount):
147150

148151

149152
def all_but_1n(x, n):
150-
return x - x / n
153+
return x - x // n
151154

152155

153156
def vm_exception(error, **kargs):
@@ -701,6 +704,7 @@ def vm_execute(ext, msg, code):
701704
# print('suiciding %s %s %d' % (msg.to, to, xfer))
702705
return 1, compustate.gas, []
703706

707+
# assert utils.is_numeric(compustate.gas)
704708
# this is slow!
705709
# for a in stk:
706710
# assert is_numeric(a), (op, stk)

0 commit comments

Comments
 (0)