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

Commit 8577d94

Browse files
author
Jan Xie
committed
Merge branch 'state_revamp' into state_revamp_for_pyethapp
2 parents 2209f33 + 9725a73 commit 8577d94

12 files changed

+26923
-145
lines changed

ethereum/casper_contract.py

Lines changed: 135 additions & 61 deletions
Large diffs are not rendered by default.

ethereum/casper_utils.py

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
rlp_decoder_path = os.path.join(mydir, 'rlp_decoder_contract.py')
2121
hash_without_ed_path = os.path.join(mydir, 'hash_without_ed_contract.py')
2222
finalizer_path = os.path.join(mydir, 'finalizer_contract.py')
23-
validator_sizes = [64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072]
2423

2524

2625
# Get the final saved code of a contract from the init code
@@ -100,7 +99,7 @@ def get_parent(self, val):
10099
assert utils.sha3(o) == origval
101100
return o
102101
val = utils.sha3(val)
103-
raise Exception("parent not found")
102+
raise Exception("Randao parent not found")
104103

105104
# Create the validation code for a given address
106105
def generate_validation_code(addr):
@@ -131,19 +130,19 @@ def call_casper(state, fun, args=[], gas=1000000, value=0):
131130

132131
# Get the number of skips needed to make a block on the current
133132
# parent
134-
def get_skips_and_block_making_time(chain, my_indices, max_lookup=100):
133+
def get_skips_and_block_making_time(state, vchash, max_lookup=100):
135134
skips = 0
136135
while skips < max_lookup:
137-
indices = call_casper(chain.state, 'getValidator', [skips])
138-
if indices and (my_indices[0], my_indices[1]) == (indices[0], indices[1]):
139-
return skips, call_casper(chain.state, 'getMinTimestamp', [skips]) + 3
136+
vchash2 = call_casper(state, 'getValidator', [skips])
137+
if vchash2 and vchash2 == vchash:
138+
return skips, call_casper(state, 'getMinTimestamp', [skips]) + 3
140139
skips += 1
141140
return None, None
142141

143142
# Check a particular count of skips
144-
def check_skips(chain, my_indices, skips):
145-
indices = call_casper(chain.state, 'getValidator', [skips])
146-
return indices and (my_indices[0], my_indices[1]) == (indices[0], indices[1])
143+
def check_skips(chain, vchash, skips):
144+
vchash2 = call_casper(chain.state, 'getValidator', [skips])
145+
return vchash2 and vchash2 == vchash
147146

148147
# Get timestamp given a particular number of skips
149148
def get_timestamp(chain, skips):
@@ -152,12 +151,11 @@ def get_timestamp(chain, skips):
152151
return call_casper(chain.state, 'getMinTimestamp', [skips]) + 3
153152

154153
# Add a signature to a block
155-
def sign_block(block, key, randao_parent, indices, skips):
154+
def sign_block(block, key, randao_parent, vchash, skips):
156155
block.header.extra_data = \
157156
randao_parent + \
158157
utils.zpad(utils.encode_int(skips), 32) + \
159-
utils.zpad(utils.encode_int(indices[0]), 32) + \
160-
utils.zpad(utils.encode_int(indices[1]), 32)
158+
vchash
161159
for val in utils.ecsign(block.header.signing_hash, key):
162160
block.header.extra_data += utils.zpad(utils.encode_int(val), 32)
163161
return block
@@ -176,12 +174,12 @@ def casper_contract_bootstrap(state, timestamp=0, epoch_length=100, number=0, ga
176174
success = apply_transaction(state, t)
177175
assert success
178176

179-
def validator_inject(state, vcode, deposit_size, randao_commitment, nonce=0, ct=None):
177+
def validator_inject(state, vcode, deposit_size, randao_commitment, address, nonce=0, ct=None):
180178
if not ct:
181179
ct = get_casper_ct()
182180
state.set_balance(utils.int_to_addr(1), deposit_size)
183181
t = Transaction(nonce, 0, 10**8, casper_config['CASPER_ADDR'], deposit_size,
184-
ct.encode('deposit', [vcode, randao_commitment]))
182+
ct.encode('deposit', [vcode, randao_commitment, address]))
185183
t._sender = utils.int_to_addr(1)
186184
success = apply_transaction(state, t)
187185
assert success
@@ -215,14 +213,14 @@ def make_casper_genesis(validators, alloc, timestamp=0, epoch_length=100):
215213
casper_contract_bootstrap(state, ct=ct)
216214

217215
# Add validators
218-
for i, (vcode, deposit_size, randao_commitment) in enumerate(validators):
219-
validator_inject(state, vcode, deposit_size, randao_commitment, i, ct)
216+
for i, (vcode, deposit_size, randao_commitment, address) in enumerate(validators):
217+
validator_inject(state, vcode, deposit_size, randao_commitment, address, i, ct)
220218

221219
# Start the first epoch
222220
casper_start_epoch(state)
223221

224222
assert call_casper(state, 'getEpoch', []) == 0
225-
assert call_casper(state, 'getTotalDeposits', []) == sum([d for a,d,r in validators])
223+
assert call_casper(state, 'getTotalDeposits', []) == sum([d for a,d,r,a in validators])
226224
state.commit()
227225
return state
228226

@@ -233,21 +231,6 @@ def casper_start_epoch(state):
233231
t._sender = casper_config['CASPER_ADDR']
234232
apply_transaction(state, t)
235233

236-
def find_indices(state, vcode):
237-
for i in range(len(validator_sizes)):
238-
epoch = state.block_number // call_casper(state, 'getEpochLength', [])
239-
valcount = call_casper(state, 'getValidatorCount', [i])
240-
for j in range(valcount):
241-
valcode = call_casper(state, 'getValidationCode', [i, j])
242-
if valcode == vcode:
243-
start = call_casper(state, 'getStartEpoch', [i, j])
244-
end = call_casper(state, 'getEndEpoch', [i, j])
245-
if start <= epoch < end:
246-
return [i, j, True]
247-
else:
248-
return [i, j, False]
249-
return [None, None, False]
250-
251234

252235
def get_dunkle_candidates(chain, state, scan_limit=10):
253236
blknumber = call_casper(state, 'getBlockNumber')

ethereum/chain.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ def add_block(self, block):
225225
while i < len(self.time_queue) and block.timestamp > self.time_queue[i].timestamp:
226226
i += 1
227227
self.time_queue.insert(i, block)
228-
log.info('Block received too early. Delaying for %d seconds' % (block.header.timestamp - now))
228+
log.info('Block received too early (%d vs %d). Delaying for %d seconds' %
229+
(now, block.header.timestamp, block.header.timestamp - now))
229230
return False
230231
if block.header.prevhash == self.head_hash:
231232
log.info('Adding to head', head=encode_hex(block.header.prevhash))

ethereum/state_transition.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,12 @@ def rp(what, actual, target):
279279
if not state.is_METROPOLIS() and not SKIP_MEDSTATES:
280280
state.commit()
281281
r = mk_receipt(state, state.logs)
282+
_logs = list(state.logs)
282283
state.logs = []
283284
state.add_to_list('receipts', r)
284285
state.set_param('bloom', state.bloom | r.bloom)
285286
state.set_param('txindex', state.txindex + 1)
286-
return success
287+
return success, output
287288

288289

289290
def mk_receipt_sha(receipts):

ethereum/tests/test_difficulty.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from ethereum import tester, blocks
1+
from ethereum import tester
22
import ethereum.utils as utils
33
import rlp
44
import ethereum.testutils as testutils

ethereum/tests/test_genesis.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import os
22
import pytest
33
import json
4-
import ethereum.blocks as blocks
54
import ethereum.testutils as testutils
65
from ethereum.testutils import fixture_to_bytes
76
import ethereum.utils as utils
@@ -11,6 +10,10 @@
1110
logger = get_logger()
1211

1312

13+
def blocks_genesis(*args): # FIXME!
14+
pass
15+
16+
1417
@pytest.fixture(scope="module")
1518
def genesis_fixture():
1619
"""
@@ -29,22 +32,22 @@ def genesis_fixture():
2932

3033
@pytest.mark.xfail # code not in sync with genesis fixtures
3134
def test_genesis_state_root(genesis_fixture):
32-
genesis = blocks.genesis(new_env())
35+
genesis = blocks_genesis(new_env())
3336
assert encode_hex(genesis.state_root) == utils.to_string(genesis_fixture['genesis_state_root'])
3437

3538

3639
def test_genesis_initial_alloc(genesis_fixture):
3740
env = new_env()
38-
genesis = blocks.genesis(env)
41+
genesis = blocks_genesis(env)
3942
for k, v in list(env.config['GENESIS_INITIAL_ALLOC'].items()):
4043
assert genesis.get_balance(k) == v.get("balance", 0) or v.get("wei", 0)
4144

4245

4346
@pytest.mark.xfail # code not in sync with genesis fixtures
4447
def test_genesis_hash(genesis_fixture):
45-
genesis = blocks.genesis(new_env())
48+
genesis = blocks_genesis(new_env())
4649
assert genesis.hex_hash() == utils.to_string(genesis_fixture['genesis_hash'])
4750

4851

4952
if __name__ == '__main__':
50-
print('current genesis:', blocks.genesis(new_env()).hex_hash())
53+
print('current genesis:', blocks_genesis(new_env()).hex_hash())

ethereum/tests/test_pos.py

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
from ethereum.parse_genesis_declaration import mk_basic_state
88
from ethereum import abi
99
from ethereum.casper_utils import RandaoManager, generate_validation_code, call_casper, \
10-
get_skips_and_block_making_time, sign_block, get_casper_ct, make_casper_genesis, \
11-
validator_sizes, find_indices, get_timestamp, make_withdrawal_signature, \
12-
casper_config
10+
get_skips_and_block_making_time, sign_block, get_contract_code, \
11+
casper_config, get_casper_ct, get_casper_code, get_rlp_decoder_code, \
12+
get_hash_without_ed_code, make_casper_genesis, get_timestamp, \
13+
make_withdrawal_signature
1314
from ethereum.block_creation import make_head_candidate
1415
from ethereum.transaction_queue import TransactionQueue
1516
from ethereum.slogging import LogRecorder, configure_logging, set_level
@@ -24,67 +25,73 @@
2425
configure_logging(config_string=config_string)
2526

2627
NUM_PARTICIPANTS = 10
28+
BLOCK_MAKING_PPB = 10
2729

2830
print 'Initializing privkeys, addresses and randaos for validators'
2931
privkeys = [utils.sha3(str(i)) for i in range(NUM_PARTICIPANTS)]
3032
addrs = [utils.privtoaddr(k) for k in privkeys]
3133
randaos = [RandaoManager(utils.sha3(str(i))) for i in range(NUM_PARTICIPANTS)]
32-
deposit_sizes = [256] * (NUM_PARTICIPANTS // 4) + [128] * (NUM_PARTICIPANTS - (NUM_PARTICIPANTS // 4))
33-
assert len(privkeys) == len(addrs) == len(randaos) == len(deposit_sizes) == NUM_PARTICIPANTS
34+
deposit_sizes = [i * 500 + 500 for i in range(NUM_PARTICIPANTS)]
35+
vcodes = [generate_validation_code(a) for a in addrs]
36+
vchashes = [utils.sha3(c) for c in vcodes]
37+
assert len(privkeys) == len(addrs) == len(randaos) == len(deposit_sizes) == len(vcodes) == len(vchashes) == NUM_PARTICIPANTS
3438

3539
# Creating casper contract translator
3640
ct = get_casper_ct()
3741
assert ct
3842
print 'Constructing genesis'
39-
s = make_casper_genesis(validators=[(generate_validation_code(a), ds * 10**18, r.get(9999))
43+
s = make_casper_genesis(validators=[(generate_validation_code(a), ds * 10**18, r.get(9999), a)
4044
for a, ds, r in zip(addrs, deposit_sizes, randaos)][:-1],
4145
alloc={a: {'balance': 10**18} for a in addrs},
4246
timestamp=int(time.time() - 99999),
4347
epoch_length=100)
4448
print 'Genesis constructed successfully'
4549
chains = [Chain(s.to_snapshot(), env=s.env) for i in range(NUM_PARTICIPANTS)]
50+
withdrawal_time_1 = call_casper(chains[0].state, 'getLockDuration', [vchashes[0]])
51+
52+
# List of validator IDs that created each block
53+
vids = []
4654

4755
# Create and sign a block
48-
def make_block(chain, key, randao, indices, skips):
56+
def make_block(chain, key, randao, vchash, skips):
4957
h = make_head_candidate(chain, TransactionQueue(), timestamp=get_timestamp(chain, skips))
50-
return sign_block(h, key, randao.get_parent(call_casper(chain.state, 'getRandao', [indices[0], indices[1]])), indices, skips)
58+
return sign_block(h, key, randao.get_parent(call_casper(chain.state, 'getRandao', [vchash])), vchash, skips)
5159

5260
next_validator = call_casper(s, 'getValidator', [0])
53-
print 'Next validator:', next_validator
54-
indices = [find_indices(s, generate_validation_code(addrs[i]))[:2] for i in range(len(addrs) - 1)]
55-
print indices, next_validator
56-
next_validator_id = indices.index(next_validator)
57-
58-
print 'Index in set:', next_validator_id
61+
print 'Next validator:', next_validator.encode('hex')
62+
next_validator_id = vchashes.index(next_validator)
63+
print 'Next validator index:', next_validator_id
5964

60-
skip_count, timestamp = get_skips_and_block_making_time(chains[next_validator_id], indices[next_validator_id])
65+
skip_count, timestamp = get_skips_and_block_making_time(chains[0].state, next_validator)
6166
assert skip_count == 0
6267
b = make_block(chains[0], privkeys[next_validator_id],
63-
randaos[next_validator_id], indices[next_validator_id], skip_count)
68+
randaos[next_validator_id], vchashes[next_validator_id], skip_count)
6469
# Validate it
6570
print 'Block timestamp:', b.header.timestamp
6671
initialize(s, b)
6772
print 'Validating block'
6873
assert validate_block_header(s, b.header)
6974
print 'Validation successful'
7075
assert chains[0].add_block(b)
76+
vids.append(next_validator_id)
7177
print 'Block added to chain'
7278
# Make another block
7379
next_validator = call_casper(chains[0].state, 'getValidator', [0])
74-
next_validator_id = indices.index(next_validator)
75-
skip_count, timestamp = get_skips_and_block_making_time(chains[0], next_validator)
80+
next_validator_id = vchashes.index(next_validator)
81+
skip_count, timestamp = get_skips_and_block_making_time(chains[0].state, next_validator)
7682
assert skip_count == 0
7783
b2 = make_block(chains[0], privkeys[next_validator_id],
78-
randaos[next_validator_id], indices[next_validator_id], skip_count)
84+
randaos[next_validator_id], vchashes[next_validator_id], skip_count)
7985
assert chains[0].add_block(b2)
86+
vids.append(next_validator_id)
8087
print 'Second block added to chain'
8188
# Make a dunkle and include it in a transaction
8289
next_validator = call_casper(chains[1].state, 'getValidator', [1])
83-
next_validator_id = indices.index(next_validator)
84-
skip_count, timestamp = get_skips_and_block_making_time(chains[next_validator_id], next_validator)
90+
next_validator_id = vchashes.index(next_validator)
91+
skip_count, timestamp = get_skips_and_block_making_time(chains[1].state, next_validator)
8592
assert skip_count == 1
8693
b3 = make_block(chains[1], privkeys[next_validator_id],
87-
randaos[next_validator_id], indices[next_validator_id], skip_count)
94+
randaos[next_validator_id], vchashes[next_validator_id], skip_count)
8895
print 'Dunkle produced'
8996
t = Transaction(0, 0, 10**6, casper_config['CASPER_ADDR'], 0, ct.encode('includeDunkle', [rlp.encode(b3.header)])).sign(privkeys[0])
9097
apply_transaction(chains[0].state, t)
@@ -104,51 +111,61 @@ def make_block(chain, key, randao, indices, skips):
104111
t2 = Transaction(chains[0].state.get_nonce(a), 0, 1000000, casper_config['CASPER_ADDR'],
105112
ds * 10**18, ct.encode('deposit', [vc, r.get(9999)])).sign(k)
106113
apply_transaction(chains[0].state, t2)
107-
indices.append(find_indices(chains[0].state, vc)[:2])
108-
assert indices[-1]
109-
assert call_casper(chains[0].state, 'getStartEpoch', indices[-1]) == 2
114+
assert call_casper(chains[0].state, 'getStartEpoch', [vchashes[-1]]) == 2
110115
chains[0].state.commit()
111-
print 'Added new validator "in-flight", indices:', indices[-1]
116+
print 'Added new validator "in-flight", indices:', vchashes[-1].encode('hex')
112117
# Create some blocks
113-
vids = []
114118
bn = call_casper(chains[0].state, 'getBlockNumber')
115119
for i in range(bn + 1, 200):
116120
next_validator = call_casper(chains[0].state, 'getValidator', [0])
117-
next_validator_id = indices.index(next_validator)
121+
next_validator_id = vchashes.index(next_validator)
118122
b = make_block(chains[0], privkeys[next_validator_id], randaos[next_validator_id],
119-
indices[next_validator_id], 0)
123+
vchashes[next_validator_id], 0)
120124
assert chains[0].add_block(b)
121125
vids.append(next_validator_id)
122126
print 'Created 200 blocks before any deposits/widthdraws, created by validators:', vids
123-
assert len(indices) - 1 not in vids
127+
assert len(vchashes) - 1 not in vids
124128
assert 0 in vids
125129
# Remove a validator
126130
sigdata = make_withdrawal_signature(privkeys[0])
127-
txdata = ct.encode('startWithdrawal', [indices[0][0], indices[0][1], sigdata])
131+
txdata = ct.encode('startWithdrawal', [vchashes[0], sigdata])
128132
t3 = Transaction(chains[0].state.get_nonce(addrs[0]), 0, 1000000, casper_config['CASPER_ADDR'], 0, txdata).sign(privkeys[0])
129133
apply_transaction(chains[0].state, t3)
130-
assert call_casper(chains[0].state, 'getEndEpoch', indices[0]) == 4
134+
assert call_casper(chains[0].state, 'getEndEpoch', [vchashes[0]]) == 4
131135
chains[0].state.commit()
132136
print 'Withdrew a validator'
137+
print '%d blocks before ETH becomes available' % withdrawal_time_1
133138
for i in range(200, 400):
134139
next_validator = call_casper(chains[0].state, 'getValidator', [0])
135-
next_validator_id = indices.index(next_validator)
140+
next_validator_id = vchashes.index(next_validator)
136141
b = make_block(chains[0], privkeys[next_validator_id], randaos[next_validator_id],
137-
indices[next_validator_id], 0)
142+
vchashes[next_validator_id], 0)
138143
assert b.header.number == i
139144
assert chains[0].add_block(b)
140145
vids.append(next_validator_id)
141146
print 'Created 200 blocks after the deposit, created by validators:', vids[-200:]
142-
assert len(indices) - 1 in vids
147+
assert len(vchashes) - 1 in vids
143148
assert 0 in vids
144-
for i in range(400, 600):
149+
for i in range(400, 400 + withdrawal_time_1 + 1):
145150
next_validator = call_casper(chains[0].state, 'getValidator', [0])
146-
next_validator_id = indices.index(next_validator)
151+
next_validator_id = vchashes.index(next_validator)
147152
b = make_block(chains[0], privkeys[next_validator_id], randaos[next_validator_id],
148-
indices[next_validator_id], 0)
153+
vchashes[next_validator_id], 0)
149154
assert chains[0].add_block(b)
150155
vids.append(next_validator_id)
151-
print 'Created 200 blocks after the withdrawal, created by validators:', vids[-200:]
152-
assert len(indices) - 1 in vids
156+
print 'Created %d blocks after the withdrawal, created by validators:' % (withdrawal_time_1 + 1), vids[-200:]
157+
assert len(vchashes) - 1 in vids
153158
assert 0 not in vids[-200:]
159+
pre_bal = chains[0].state.get_balance(addrs[0])
160+
txdata = ct.encode('withdraw', [vchashes[0]])
161+
t4 = Transaction(chains[0].state.get_nonce(addrs[0]), 0, 1000000, casper_config['CASPER_ADDR'], 0, txdata).sign(privkeys[0])
162+
apply_transaction(chains[0].state, t4)
163+
post_bal = chains[0].state.get_balance(addrs[0])
164+
print 'Wei withdrawn:', post_bal - pre_bal
165+
blocks_by_v0_in_stage1 = len([x for x in vids[:200] if x == 0])
166+
expected_revenue_in_stage1 = blocks_by_v0_in_stage1 * max(sum(deposit_sizes[:-1]), 1000000) * 10**18 * BLOCK_MAKING_PPB / 10**9
167+
blocks_by_v0_in_stage2 = len([x for x in vids[200:400] if x == 0])
168+
expected_revenue_in_stage2 = blocks_by_v0_in_stage2 * max(sum(deposit_sizes), 1000000) * 10**18 * BLOCK_MAKING_PPB / 10**9
169+
170+
assert post_bal - pre_bal == deposit_sizes[0] * 10**18 + expected_revenue_in_stage1 + expected_revenue_in_stage2
154171
print 'PoS test fully passed'

ethereum/tests/test_transactions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def test_transaction(filename, testname, testdata):
2626
tx = rlp.decode(rlpdata, transactions.Transaction)
2727
blknum = int(testdata["blocknumber"])
2828
if blknum >= 1000000: # config.default_config["HOMESTEAD_FORK_BLKNUM"]:
29-
tx.check_low_s()
29+
tx.check_low_s_homestead()
3030
o["sender"] = tx.sender
3131
o["transaction"] = {
3232
"data": b'0x' * (len(tx.data) > 0) + encode_hex(tx.data),

0 commit comments

Comments
 (0)