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

Commit 7440dea

Browse files
vubvub
authored andcommitted
Added checksums, also passing EIP86 transaction tests
1 parent 237df71 commit 7440dea

File tree

9 files changed

+88
-68
lines changed

9 files changed

+88
-68
lines changed

ethereum/config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
GASLIMIT_ADJMAX_FACTOR=1024,
2727
BLKLIM_FACTOR_NOM=3,
2828
BLKLIM_FACTOR_DEN=2,
29+
# Network ID
30+
NETWORK_ID=1,
2931
# Block reward
3032
BLOCK_REWARD=5000 * utils.denoms.finney,
3133
NEPHEW_REWARD=5000 * utils.denoms.finney // 32, # BLOCK_REWARD / 32
@@ -51,7 +53,6 @@
5153
HOMESTEAD_DIFF_ADJUSTMENT_CUTOFF=10,
5254
# Metropolis fork
5355
METROPOLIS_FORK_BLKNUM=2**99,
54-
METROPOLIS_ENTRY_POINT=utils.int_to_addr(2**160 - 1),
5556
METROPOLIS_STATEROOT_STORE=0x10,
5657
METROPOLIS_BLOCKHASH_STORE=0x20,
5758
METROPOLIS_WRAPAROUND=65536,

ethereum/processblock.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def create_contract(ext, msg):
142142
# assert not ext.get_code(msg.to)
143143
msg.data = vm.CallData([], 0, 0)
144144
snapshot = ext.snapshot()
145-
ext.set_nonce(msg.to, 1)
145+
ext.set_nonce(msg.to, 1 if ext.post_clearing_hardfork() else 0)
146146
res, gas, dat = _apply_msg(ext, msg, code)
147147
assert utils.is_numeric(gas)
148148
log_msg.debug('CONTRACT CREATION FINISHED', res=res, gas=gas, dat=dat)
@@ -151,7 +151,7 @@ def create_contract(ext, msg):
151151
if not len(dat):
152152
return 1, gas, msg.to
153153
gcost = len(dat) * opcodes.GCONTRACTBYTE
154-
if gas >= gcost:
154+
if gas >= gcost and len(dat) < 24000:
155155
gas -= gcost
156156
else:
157157
dat = []
@@ -160,7 +160,7 @@ def create_contract(ext, msg):
160160
ext.revert(snapshot)
161161
return 0, 0, b''
162162
ext.set_code(msg.to, b''.join(map(ascii_chr, dat)))
163-
log_msg.debug('SETTING CODE', addr=encode_hex(msg.to))
163+
log_msg.debug('SETTING CODE', addr=encode_hex(msg.to), lendat=len(dat))
164164
return 1, gas, msg.to
165165
else:
166166
ext.revert(snapshot)

ethereum/state_transition.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
from functools import lru_cache
3232
from ethereum.slogging import get_logger
3333

34+
null_address = b'\xff' * 20
35+
3436
log = get_logger('eth.block')
3537
log_tx = get_logger('eth.pb.tx')
3638
log_msg = get_logger('eth.pb.msg')
@@ -150,21 +152,35 @@ def verify_execution_results(state, block):
150152
(block.header.gas_used, state.gas_used))
151153
return True
152154

155+
def config_fork_specific_validation(config, blknum, tx):
156+
# (1) The transaction signature is valid;
157+
_ = tx.sender
158+
if blknum >= config['METROPOLIS_FORK_BLKNUM']:
159+
tx.check_low_s_metropolis()
160+
else:
161+
if tx.sender == null_address:
162+
raise VerificationFailed("EIP86 transactions not available yet")
163+
if blknum >= config['HOMESTEAD_FORK_BLKNUM']:
164+
tx.check_low_s_homestead()
165+
print(tx.network_id, config["NETWORK_ID"])
166+
if blknum >= config["CLEARING_FORK_BLKNUM"]:
167+
if tx.network_id not in (None, config["NETWORK_ID"]):
168+
raise VerificationFailed("Wrong network ID")
169+
else:
170+
if tx.network_id is not None:
171+
raise VerificationFailed("Wrong network ID")
172+
return True
173+
153174
def validate_transaction(state, tx):
154175

155176
def rp(what, actual, target):
156177
return '%r: %r actual:%r target:%r' % (tx, what, actual, target)
157178

158179
# (1) The transaction signature is valid;
159180
if not tx.sender: # sender is set and validated on Transaction initialization
160-
if state.is_METROPOLIS():
161-
tx._sender = normalize_address(state.config["METROPOLIS_ENTRY_POINT"])
162-
else:
163-
raise UnsignedTransaction(tx)
164-
if state.is_METROPOLIS():
165-
tx.check_low_s_metropolis()
166-
elif state.is_HOMESTEAD():
167-
tx.check_low_s_homestead()
181+
raise UnsignedTransaction(tx)
182+
183+
assert config_fork_specific_validation(state.config, state.block_number, tx)
168184

169185
# (2) the transaction nonce is valid (equivalent to the
170186
# sender account's current nonce);

ethereum/tests/test_contracts.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,7 +1533,7 @@ def test_abi_logging():
15331533
o.pop()
15341534
c.test_chicken(tester.a0)
15351535
assert o == [{"_event_type": b"chicken",
1536-
"m": utils.encode_hex(tester.a0)}]
1536+
"m": "0x"+utils.encode_hex(tester.a0)}]
15371537
o.pop()
15381538

15391539

@@ -1578,8 +1578,8 @@ def test_abi_address_output():
15781578
c.register(123, b'1212121212121212121212121212121212121212')
15791579
c.register(123, b'3434343434343434343434343434343434343434')
15801580
c.register(125, b'5656565656565656565656565656565656565656')
1581-
assert c.get_address(123) == b'1212121212121212121212121212121212121212'
1582-
assert c.get_address(125) == b'5656565656565656565656565656565656565656'
1581+
assert c.get_address(123) == '0x1212121212121212121212121212121212121212'
1582+
assert c.get_address(125) == '0x5656565656565656565656565656565656565656'
15831583

15841584
filename5 = 'abi_output_tester_1264876521746198724124'
15851585

@@ -1605,8 +1605,8 @@ def test_inner_abi_address_output():
16051605
c.register(123, b'1212121212121212121212121212121212121212')
16061606
c.register(123, b'3434343434343434343434343434343434343434')
16071607
c.register(125, b'5656565656565656565656565656565656565656')
1608-
assert c.get_address(123) == b'1212121212121212121212121212121212121212'
1609-
assert c.get_address(125) == b'5656565656565656565656565656565656565656'
1608+
assert c.get_address(123) == '0x1212121212121212121212121212121212121212'
1609+
assert c.get_address(125) == '0x5656565656565656565656565656565656565656'
16101610

16111611

16121612
string_logging_code = """

ethereum/tests/test_transactions.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44
from rlp.utils import decode_hex, encode_hex, str_to_bytes
55
import ethereum.testutils as testutils
66
from ethereum.testutils import fixture_to_bytes
7+
from ethereum.state_transition import config_fork_specific_validation
78
import ethereum.config as config
89
import sys
910
import json
11+
import copy
12+
konfig = copy.copy(config.default_config)
13+
konfig['METROPOLIS_FORK_BLKNUM'] = 3000000
1014

1115
from ethereum.slogging import get_logger
1216
logger = get_logger()
@@ -25,29 +29,32 @@ def test_transaction(filename, testname, testdata):
2529
o = {}
2630
tx = rlp.decode(rlpdata, transactions.Transaction)
2731
blknum = int(testdata["blocknumber"])
28-
if blknum >= 1000000: # config.default_config["HOMESTEAD_FORK_BLKNUM"]:
29-
tx.check_low_s_homestead()
32+
#if blknum >= 1000000: # config.default_config["HOMESTEAD_FORK_BLKNUM"]:
33+
# tx.check_low_s_homestead()
34+
assert config_fork_specific_validation(konfig, blknum, tx)
3035
o["sender"] = tx.sender
3136
o["transaction"] = {
32-
"data": b'0x' * (len(tx.data) > 0) + encode_hex(tx.data),
33-
"gasLimit": str_to_bytes(str(tx.startgas)),
34-
"gasPrice": str_to_bytes(str(tx.gasprice)),
35-
"nonce": str_to_bytes(str(tx.nonce)),
36-
"r": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.r), 32)),
37-
"s": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.s), 32)),
38-
"v": str_to_bytes(str(tx.v)),
39-
"value": str_to_bytes(str(tx.value)),
37+
"data": '0x' * (len(tx.data) > 0) + encode_hex(tx.data),
38+
"gasLimit": str(tx.startgas),
39+
"gasPrice": str(tx.gasprice),
40+
"nonce": str(tx.nonce),
41+
"r": '0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.r), 32)),
42+
"s": '0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.s), 32)),
43+
"v": str(tx.v),
44+
"value": str(tx.value),
4045
"to": encode_hex(tx.to),
4146
}
4247
except Exception as e:
4348
tx = None
4449
sys.stderr.write(str(e))
4550
if 'transaction' not in testdata: # expected to fail
51+
print(testdata)
4652
assert tx is None
4753
else:
54+
print(testdata)
4855
assert set(o['transaction'].keys()) == set(testdata.get("transaction", dict()).keys())
4956
o.get("transaction", None) == testdata.get("transaction", None)
50-
assert encode_hex(o.get("sender", '')) == testdata.get("sender", '')
57+
assert str_to_bytes(encode_hex(o.get("sender", ''))) == testdata.get("sender", '')
5158

5259

5360
def pytest_generate_tests(metafunc):

ethereum/testutils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from ethereum.config import default_config
1616
from ethereum.parse_genesis_declaration import state_from_genesis_declaration
1717
from ethereum import state_transition
18-
from state import State
18+
from ethereum.state import State
1919
import json
2020
import os
2121
import time

ethereum/transactions.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
# in the yellow paper it is specified that s should be smaller than secpk1n (eq.205)
1818
secpk1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337
19+
null_address = b'\xff' * 20
1920

2021

2122
class Transaction(rlp.Serializable):
@@ -59,6 +60,7 @@ def __init__(self, nonce, gasprice, startgas, to, value, data, v=0, r=0, s=0):
5960
assert len(to) == 20 or len(to) == 0
6061
super(Transaction, self).__init__(nonce, gasprice, startgas, to, value, data, v, r, s)
6162
self.logs = []
63+
self.network_id = None
6264

6365
if self.gasprice >= TT256 or self.startgas >= TT256 or \
6466
self.value >= TT256 or self.nonce >= TT256:
@@ -73,30 +75,28 @@ def sender(self):
7375

7476
if not self._sender:
7577
# Determine sender
76-
if self.v:
77-
if self.r >= N or self.s >= N or self.v not in (27, 28, 37, 38, 41, 42) \
78-
or self.r == 0 or self.s == 0:
79-
raise InvalidTransaction("Invalid signature values!")
80-
log.debug('reco< 27 or self.v > 28 \vering sender')
78+
if self.r == 0 and self.s == 0:
79+
self.network_id = self.v
80+
self._sender = null_address
81+
else:
8182
if self.v in (27, 28):
82-
rlpdata = rlp.encode(self, UnsignedTransaction)
83-
rawhash = utils.sha3(rlpdata)
84-
v = self.v
85-
elif self.v in (37, 38):
86-
rlpdata = rlp.encode(rlp.infer_sedes(self).serialize(self)[:-3] + ['\x01', '', ''])
87-
rawhash = utils.sha3(rlpdata)
88-
v = self.v - 10
89-
elif self.v in (41, 42):
90-
rlpdata = rlp.encode(rlp.infer_sedes(self).serialize(self)[:-3] + ['\x03', '', ''])
91-
rawhash = utils.sha3(rlpdata)
92-
v = self.v - 14
93-
pub = ecrecover_to_pub(rawhash, v, self.r, self.s)
83+
self.network_id = None
84+
vee = self.v
85+
sighash = utils.sha3(rlp.encode(self, UnsignedTransaction))
86+
elif self.v >= 37:
87+
self.network_id = ((self.v - 1) // 2) - 17
88+
vee = self.v - self.network_id * 2 - 8
89+
assert vee in (27, 28)
90+
rlpdata = rlp.encode(rlp.infer_sedes(self).serialize(self)[:-3] + [self.network_id, '', ''])
91+
sighash = utils.sha3(rlpdata)
92+
else:
93+
raise InvalidTransaction("Invalid V value")
94+
if self.r >= N or self.s >= N or self.r == 0 or self.s == 0:
95+
raise InvalidTransaction("Invalid signature values!")
96+
pub = ecrecover_to_pub(sighash, vee, self.r, self.s)
9497
if pub == b"\x00" * 64:
9598
raise InvalidTransaction("Invalid signature (zero privkey cannot sign)")
9699
self._sender = utils.sha3(pub)[-20:]
97-
assert self.sender == self._sender
98-
else:
99-
self._sender = 0
100100
return self._sender
101101

102102
@sender.setter

ethereum/utils.py

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -173,26 +173,22 @@ def sha3(seed):
173173
assert encode_hex(sha3(b'')) == 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
174174

175175

176-
def privtoaddr(x, extended=False):
176+
def privtoaddr(x):
177177
if len(x) > 32:
178178
x = decode_hex(x)
179-
o = sha3(privtopub(x)[1:])[12:]
180-
return add_checksum(o) if extended else o
181-
182-
183-
def add_checksum(x):
184-
if len(x) in (40, 48):
185-
x = decode_hex(x)
186-
if len(x) == 24:
187-
return x
188-
return x + sha3(x)[:4]
189-
190-
191-
def check_and_strip_checksum(x):
192-
if len(x) in (40, 48):
193-
x = decode_hex(x)
194-
assert len(x) == 24 and sha3(x[:20])[:4] == x[-4:]
195-
return x[:20]
179+
return sha3(privtopub(x)[1:])[12:]
180+
181+
182+
def checksum_encode(addr): # Takes a 20-byte binary address as input
183+
addr = normalize_address(addr)
184+
o = ''
185+
v = big_endian_to_int(sha3(encode_hex(addr)))
186+
for i, c in enumerate(addr.hex()):
187+
if c in '0123456789':
188+
o += c
189+
else:
190+
o += c.upper() if (v & (2**(255 - 4*i))) else c.lower()
191+
return '0x'+o
196192

197193

198194
def normalize_address(x, allow_blank=False):

fixtures

Submodule fixtures updated 5813 files

0 commit comments

Comments
 (0)