Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit 6a171e1

Browse files
authored
Merge pull request #142 from djrtwo/warm-up
add `warm_up_period` to `init`
2 parents eaecd40 + 822f712 commit 6a171e1

10 files changed

+261
-106
lines changed

casper/contracts/simple_casper.v.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@
9696
# Length of an epoch in blocks
9797
EPOCH_LENGTH: public(int128)
9898

99+
# Length of warm up period in blocks
100+
WARM_UP_PERIOD: public(int128)
101+
99102
# Withdrawal delay in blocks
100103
WITHDRAWAL_DELAY: public(int128)
101104

@@ -120,13 +123,15 @@
120123

121124

122125
@public
123-
def init(epoch_length: int128, withdrawal_delay: int128, dynasty_logout_delay: int128,
126+
def init(epoch_length: int128, warm_up_period: int128,
127+
withdrawal_delay: int128, dynasty_logout_delay: int128,
124128
msg_hasher: address, purity_checker: address,
125129
base_interest_factor: decimal, base_penalty_factor: decimal,
126130
min_deposit_size: wei_value):
127131

128132
assert not self.initialized
129133
assert epoch_length > 0 and epoch_length < 256
134+
assert warm_up_period >= 0
130135
assert withdrawal_delay >= 0
131136
assert dynasty_logout_delay >= 2
132137
assert base_interest_factor >= 0.0
@@ -136,13 +141,14 @@ def init(epoch_length: int128, withdrawal_delay: int128, dynasty_logout_delay: i
136141
self.initialized = True
137142

138143
self.EPOCH_LENGTH = epoch_length
144+
self.WARM_UP_PERIOD = warm_up_period
139145
self.WITHDRAWAL_DELAY = withdrawal_delay
140146
self.DYNASTY_LOGOUT_DELAY = dynasty_logout_delay
141147
self.BASE_INTEREST_FACTOR = base_interest_factor
142148
self.BASE_PENALTY_FACTOR = base_penalty_factor
143149
self.MIN_DEPOSIT_SIZE = min_deposit_size
144150

145-
self.START_EPOCH = floor(block.number / self.EPOCH_LENGTH)
151+
self.START_EPOCH = floor((block.number + warm_up_period) / self.EPOCH_LENGTH)
146152

147153
# helper contracts
148154
self.MSG_HASHER = msg_hasher
@@ -460,7 +466,6 @@ def initialize_epoch(epoch: int128):
460466
@public
461467
@payable
462468
def deposit(validation_addr: address, withdrawal_addr: address):
463-
assert self.current_epoch == floor(block.number / self.EPOCH_LENGTH)
464469
assert extract32(raw_call(self.PURITY_CHECKER, concat('\xa1\x90\x3e\xab', convert(validation_addr, 'bytes32')), gas=500000, outsize=32), 0) != convert(0, 'bytes32')
465470
assert not self.validator_indexes[withdrawal_addr]
466471
assert msg.value >= self.MIN_DEPOSIT_SIZE

tests/conftest.py

+18-11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
PURITY_CHECKER_ABI = [{'name': 'check(address)', 'type': 'function', 'constant': True, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}, {'name': 'submit(address)', 'type': 'function', 'constant': False, 'inputs': [{'name': 'addr', 'type': 'address'}], 'outputs': [{'name': 'out', 'type': 'bool'}]}] # NOQA
2222

2323
EPOCH_LENGTH = 10
24+
WARM_UP_PERIOD = 20
2425
DYNASTY_LOGOUT_DELAY = 5
2526
WITHDRAWAL_DELAY = 5
2627
BASE_INTEREST_FACTOR = 0.02
@@ -99,6 +100,11 @@ def epoch_length():
99100
return EPOCH_LENGTH
100101

101102

103+
@pytest.fixture
104+
def warm_up_period():
105+
return WARM_UP_PERIOD
106+
107+
102108
@pytest.fixture
103109
def withdrawal_delay():
104110
return WITHDRAWAL_DELAY
@@ -125,10 +131,11 @@ def min_deposit_size():
125131

126132

127133
@pytest.fixture
128-
def casper_config(epoch_length, withdrawal_delay, dynasty_logout_delay,
134+
def casper_config(epoch_length, warm_up_period, withdrawal_delay, dynasty_logout_delay,
129135
base_interest_factor, base_penalty_factor, min_deposit_size):
130136
return {
131137
"epoch_length": epoch_length, # in blocks
138+
"warm_up_period": warm_up_period, # in blocks
132139
"withdrawal_delay": withdrawal_delay, # in epochs
133140
"dynasty_logout_delay": dynasty_logout_delay, # in dynasties
134141
"base_interest_factor": base_interest_factor,
@@ -140,8 +147,8 @@ def casper_config(epoch_length, withdrawal_delay, dynasty_logout_delay,
140147
@pytest.fixture
141148
def casper_args(casper_config, msg_hasher_address, purity_checker_address):
142149
return [
143-
casper_config["epoch_length"], casper_config["withdrawal_delay"],
144-
casper_config["dynasty_logout_delay"],
150+
casper_config["epoch_length"], casper_config["warm_up_period"],
151+
casper_config["withdrawal_delay"], casper_config["dynasty_logout_delay"],
145152
msg_hasher_address, purity_checker_address, casper_config["base_interest_factor"],
146153
casper_config["base_penalty_factor"], casper_config["min_deposit_size"]
147154
]
@@ -309,6 +316,8 @@ def get_dirs(path):
309316
return path, extra_args
310317

311318

319+
# Note: If called during "warm_up-period", new_epoch mines all the way through
320+
# the warm up period until `initialize_epoch` can first be called
312321
@pytest.fixture
313322
def new_epoch(casper_chain, casper):
314323
def new_epoch():
@@ -441,11 +450,10 @@ def deposit_validator(privkey, value, valcode_type="pure_ecrecover"):
441450
@pytest.fixture
442451
def induct_validator(casper_chain, casper, deposit_validator, new_epoch):
443452
def induct_validator(privkey, value, valcode_type="pure_ecrecover"):
444-
if casper.current_epoch() == 0:
445-
new_epoch()
446453
validator_index = deposit_validator(privkey, value, valcode_type)
447-
new_epoch()
448-
new_epoch()
454+
new_epoch() # justify
455+
new_epoch() # finalize and increment dynasty
456+
new_epoch() # finalize and increment dynasty
449457
return validator_index
450458
return induct_validator
451459

@@ -459,12 +467,11 @@ def induct_validator(privkey, value, valcode_type="pure_ecrecover"):
459467
def induct_validators(casper_chain, casper, deposit_validator, new_epoch):
460468
def induct_validators(privkeys, values):
461469
start_index = casper.next_validator_index()
462-
if casper.current_epoch() == 0:
463-
new_epoch()
464470
for privkey, value in zip(privkeys, values):
465471
deposit_validator(privkey, value)
466-
new_epoch()
467-
new_epoch()
472+
new_epoch() # justify
473+
new_epoch() # finalize and increment dynasty
474+
new_epoch() # finalize and increment dynasty
468475
return list(range(start_index, start_index + len(privkeys)))
469476
return induct_validators
470477

tests/test_chain_initialization.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@ def test_msg_hasher_is_pure(
3434

3535

3636
# sanity check on casper contract basic functionality
37-
def test_init_first_epoch(casper, new_epoch):
38-
assert casper.current_epoch() == 0
37+
def test_init_first_epoch(casper_chain, casper, new_epoch, warm_up_period, epoch_length):
38+
start_epoch = (casper_chain.head_state.block_number + warm_up_period) // epoch_length
39+
40+
assert casper.current_epoch() == start_epoch
3941
assert casper.next_validator_index() == 1
4042

4143
new_epoch()
4244

4345
assert casper.dynasty() == 0
4446
assert casper.next_validator_index() == 1
45-
assert casper.current_epoch() == 1
47+
assert casper.current_epoch() == start_epoch + 1
4648
assert casper.total_slashed(casper.current_epoch()) == 0

tests/test_deposit.py

+33
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import pytest
2+
13
from ethereum import utils
24

35

@@ -84,3 +86,34 @@ def test_deposit_updates_total_deposits(casper, funded_privkey, deposit_amount,
8486

8587
assert casper.total_curdyn_deposits_in_wei() == deposit_amount
8688
assert casper.total_prevdyn_deposits_in_wei() == deposit_amount
89+
90+
91+
@pytest.mark.parametrize(
92+
'warm_up_period,epoch_length',
93+
[
94+
(10, 5),
95+
(25, 10),
96+
(100, 50),
97+
]
98+
)
99+
def test_deposit_during_warm_up_period(casper_chain, casper, funded_privkey, deposit_amount,
100+
deposit_validator, new_epoch, warm_up_period, epoch_length):
101+
validator_index = deposit_validator(funded_privkey, deposit_amount)
102+
103+
expected_start_dynasty = casper.dynasty() + 2
104+
assert casper.validators__start_dynasty(validator_index) == expected_start_dynasty
105+
106+
new_epoch() # new_epoch mines through warm_up_period on first call
107+
casper.dynasty() == 0
108+
new_epoch()
109+
casper.dynasty() == 1
110+
new_epoch()
111+
casper.dynasty() == 2
112+
113+
casper.total_curdyn_deposits_in_wei() == deposit_amount
114+
casper.total_prevdyn_deposits_in_wei() == 0
115+
116+
new_epoch()
117+
118+
casper.total_curdyn_deposits_in_wei() == deposit_amount
119+
casper.total_prevdyn_deposits_in_wei() == deposit_amount

tests/test_fork_choice_helpers.py

+54-53
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def test_highest_finalized_epoch_no_validators(casper, new_epoch, min_deposits):
7878
if min_deposits > 0:
7979
expected_epoch = -1
8080
else:
81-
if casper.current_epoch() == 0:
81+
if casper.current_epoch() == casper.START_EPOCH():
8282
expected_epoch = -1
8383
else:
8484
expected_epoch = casper.last_finalized_epoch()
@@ -90,111 +90,112 @@ def test_highest_finalized_epoch_no_validators(casper, new_epoch, min_deposits):
9090

9191
def test_highest_justified_and_epoch(casper, funded_privkey, deposit_amount,
9292
new_epoch, induct_validator, mk_suggested_vote):
93+
start_epoch = casper.START_EPOCH()
9394
validator_index = induct_validator(funded_privkey, deposit_amount)
9495
higher_deposit = int(deposit_amount * 1.1)
9596

9697
assert casper.total_curdyn_deposits_in_wei() == deposit_amount
97-
assert casper.current_epoch() == 3
98+
assert casper.current_epoch() == start_epoch + 3 # 3 to induct first dynasty
9899

99100
assert casper.highest_justified_epoch(deposit_amount) == 0
100101
assert casper.highest_finalized_epoch(deposit_amount) == -1
101-
assert casper.highest_justified_epoch(0) == 2
102-
assert casper.highest_finalized_epoch(0) == 2
102+
assert casper.highest_justified_epoch(0) == start_epoch + 2
103+
assert casper.highest_finalized_epoch(0) == start_epoch + 2
103104
assert casper.highest_justified_epoch(higher_deposit) == 0
104105
assert casper.highest_finalized_epoch(higher_deposit) == -1
105106

106107
# justify current_epoch in contract
107108
casper.vote(mk_suggested_vote(validator_index, funded_privkey))
108109

109-
assert casper.checkpoints__cur_dyn_deposits(3) == 0
110-
assert casper.checkpoints__prev_dyn_deposits(3) == 0
111-
assert casper.last_justified_epoch() == 3
112-
assert casper.last_finalized_epoch() == 2
110+
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 3) == 0
111+
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 3) == 0
112+
assert casper.last_justified_epoch() == start_epoch + 3
113+
assert casper.last_finalized_epoch() == start_epoch + 2
113114

114115
assert casper.highest_justified_epoch(deposit_amount) == 0
115116
assert casper.highest_finalized_epoch(deposit_amount) == -1
116-
assert casper.highest_justified_epoch(0) == 3
117-
assert casper.highest_finalized_epoch(0) == 2
117+
assert casper.highest_justified_epoch(0) == start_epoch + 3
118+
assert casper.highest_finalized_epoch(0) == start_epoch + 2
118119
assert casper.highest_justified_epoch(higher_deposit) == 0
119120
assert casper.highest_finalized_epoch(higher_deposit) == -1
120121

121122
new_epoch()
122123
casper.vote(mk_suggested_vote(validator_index, funded_privkey))
123124

124-
assert casper.checkpoints__cur_dyn_deposits(4) == deposit_amount
125-
assert casper.checkpoints__prev_dyn_deposits(4) == 0
126-
assert casper.last_justified_epoch() == 4
127-
assert casper.last_finalized_epoch() == 3
125+
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 4) == deposit_amount
126+
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 4) == 0
127+
assert casper.last_justified_epoch() == start_epoch + 4
128+
assert casper.last_finalized_epoch() == start_epoch + 3
128129

129130
assert casper.highest_justified_epoch(deposit_amount) == 0
130131
assert casper.highest_finalized_epoch(deposit_amount) == -1
131-
assert casper.highest_justified_epoch(0) == 4
132-
assert casper.highest_finalized_epoch(0) == 3
132+
assert casper.highest_justified_epoch(0) == start_epoch + 4
133+
assert casper.highest_finalized_epoch(0) == start_epoch + 3
133134
assert casper.highest_justified_epoch(higher_deposit) == 0
134135
assert casper.highest_finalized_epoch(higher_deposit) == -1
135136

136137
new_epoch()
137138
casper.vote(mk_suggested_vote(validator_index, funded_privkey))
138139

139-
assert casper.checkpoints__cur_dyn_deposits(5) == deposit_amount
140-
assert casper.checkpoints__prev_dyn_deposits(5) == deposit_amount
141-
assert casper.last_justified_epoch() == 5
142-
assert casper.last_finalized_epoch() == 4
140+
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 5) == deposit_amount
141+
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 5) == deposit_amount
142+
assert casper.last_justified_epoch() == start_epoch + 5
143+
assert casper.last_finalized_epoch() == start_epoch + 4
143144

144145
# enough prev and cur deposits in checkpoint 5 for the justified block
145-
assert casper.highest_justified_epoch(deposit_amount) == 5
146+
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 5
146147
# not enough prev and cur deposits in checkpoint 4 for the finalized block
147148
assert casper.highest_finalized_epoch(deposit_amount) == -1
148-
assert casper.highest_justified_epoch(0) == 5
149-
assert casper.highest_finalized_epoch(0) == 4
149+
assert casper.highest_justified_epoch(0) == start_epoch + 5
150+
assert casper.highest_finalized_epoch(0) == start_epoch + 4
150151
assert casper.highest_justified_epoch(higher_deposit) == 0
151152
assert casper.highest_finalized_epoch(higher_deposit) == -1
152153

153154
new_epoch()
154155
casper.vote(mk_suggested_vote(validator_index, funded_privkey))
155156

156-
assert casper.checkpoints__cur_dyn_deposits(6) > deposit_amount
157-
assert casper.checkpoints__prev_dyn_deposits(6) > deposit_amount
158-
assert casper.last_justified_epoch() == 6
159-
assert casper.last_finalized_epoch() == 5
157+
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 6) > deposit_amount
158+
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 6) > deposit_amount
159+
assert casper.last_justified_epoch() == start_epoch + 6
160+
assert casper.last_finalized_epoch() == start_epoch + 5
160161

161162
# enough deposits in checkpoint 6 for justified and checkpoint 5 for finalized!
162-
assert casper.highest_justified_epoch(deposit_amount) == 6
163-
assert casper.highest_finalized_epoch(deposit_amount) == 5
163+
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 6
164+
assert casper.highest_finalized_epoch(deposit_amount) == start_epoch + 5
164165
assert casper.highest_justified_epoch(higher_deposit) == 0
165166
assert casper.highest_finalized_epoch(higher_deposit) == -1
166-
assert casper.highest_justified_epoch(0) == 6
167-
assert casper.highest_finalized_epoch(0) == 5
167+
assert casper.highest_justified_epoch(0) == start_epoch + 6
168+
assert casper.highest_finalized_epoch(0) == start_epoch + 5
168169

169170
new_epoch()
170171
# no vote
171172

172-
assert casper.checkpoints__cur_dyn_deposits(7) > deposit_amount
173-
assert casper.checkpoints__prev_dyn_deposits(7) > deposit_amount
174-
assert casper.last_justified_epoch() == 6
175-
assert casper.last_finalized_epoch() == 5
173+
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 7) > deposit_amount
174+
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 7) > deposit_amount
175+
assert casper.last_justified_epoch() == start_epoch + 6
176+
assert casper.last_finalized_epoch() == start_epoch + 5
176177

177-
assert casper.highest_justified_epoch(deposit_amount) == 6
178-
assert casper.highest_finalized_epoch(deposit_amount) == 5
179-
assert casper.highest_justified_epoch(0) == 6
180-
assert casper.highest_finalized_epoch(0) == 5
178+
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 6
179+
assert casper.highest_finalized_epoch(deposit_amount) == start_epoch + 5
180+
assert casper.highest_justified_epoch(0) == start_epoch + 6
181+
assert casper.highest_finalized_epoch(0) == start_epoch + 5
181182
assert casper.highest_justified_epoch(higher_deposit) == 0
182183
assert casper.highest_finalized_epoch(higher_deposit) == -1
183184

184185
new_epoch()
185186
casper.vote(mk_suggested_vote(validator_index, funded_privkey))
186187

187-
assert casper.checkpoints__cur_dyn_deposits(8) > deposit_amount
188-
assert casper.checkpoints__prev_dyn_deposits(8) > deposit_amount
188+
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 8) > deposit_amount
189+
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 8) > deposit_amount
189190
# new justified
190-
assert casper.last_justified_epoch() == 8
191+
assert casper.last_justified_epoch() == start_epoch + 8
191192
# no new finalized because not sequential justified blocks
192-
assert casper.last_finalized_epoch() == 5
193+
assert casper.last_finalized_epoch() == start_epoch + 5
193194

194-
assert casper.highest_justified_epoch(deposit_amount) == 8
195-
assert casper.highest_finalized_epoch(deposit_amount) == 5
196-
assert casper.highest_justified_epoch(0) == 8
197-
assert casper.highest_finalized_epoch(0) == 5
195+
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 8
196+
assert casper.highest_finalized_epoch(deposit_amount) == start_epoch + 5
197+
assert casper.highest_justified_epoch(0) == start_epoch + 8
198+
assert casper.highest_finalized_epoch(0) == start_epoch + 5
198199
assert casper.highest_justified_epoch(higher_deposit) == 0
199200
assert casper.highest_finalized_epoch(higher_deposit) == -1
200201

@@ -204,12 +205,12 @@ def test_highest_justified_and_epoch(casper, funded_privkey, deposit_amount,
204205
assert casper.checkpoints__cur_dyn_deposits(9) > deposit_amount
205206
assert casper.checkpoints__prev_dyn_deposits(9) > deposit_amount
206207
# new justified and finalized because sequential justified blocks
207-
assert casper.last_justified_epoch() == 9
208-
assert casper.last_finalized_epoch() == 8
208+
assert casper.last_justified_epoch() == start_epoch + 9
209+
assert casper.last_finalized_epoch() == start_epoch + 8
209210

210-
assert casper.highest_justified_epoch(deposit_amount) == 9
211-
assert casper.highest_finalized_epoch(deposit_amount) == 8
212-
assert casper.highest_justified_epoch(0) == 9
213-
assert casper.highest_finalized_epoch(0) == 8
211+
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 9
212+
assert casper.highest_finalized_epoch(deposit_amount) == start_epoch + 8
213+
assert casper.highest_justified_epoch(0) == start_epoch + 9
214+
assert casper.highest_finalized_epoch(0) == start_epoch + 8
214215
assert casper.highest_justified_epoch(higher_deposit) == 0
215216
assert casper.highest_finalized_epoch(higher_deposit) == -1

0 commit comments

Comments
 (0)