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

Commit

Permalink
Merge pull request #142 from djrtwo/warm-up
Browse files Browse the repository at this point in the history
add `warm_up_period` to `init`
  • Loading branch information
djrtwo authored May 16, 2018
2 parents eaecd40 + 822f712 commit 6a171e1
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 106 deletions.
11 changes: 8 additions & 3 deletions casper/contracts/simple_casper.v.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@
# Length of an epoch in blocks
EPOCH_LENGTH: public(int128)

# Length of warm up period in blocks
WARM_UP_PERIOD: public(int128)

# Withdrawal delay in blocks
WITHDRAWAL_DELAY: public(int128)

Expand All @@ -120,13 +123,15 @@


@public
def init(epoch_length: int128, withdrawal_delay: int128, dynasty_logout_delay: int128,
def init(epoch_length: int128, warm_up_period: int128,
withdrawal_delay: int128, dynasty_logout_delay: int128,
msg_hasher: address, purity_checker: address,
base_interest_factor: decimal, base_penalty_factor: decimal,
min_deposit_size: wei_value):

assert not self.initialized
assert epoch_length > 0 and epoch_length < 256
assert warm_up_period >= 0
assert withdrawal_delay >= 0
assert dynasty_logout_delay >= 2
assert base_interest_factor >= 0.0
Expand All @@ -136,13 +141,14 @@ def init(epoch_length: int128, withdrawal_delay: int128, dynasty_logout_delay: i
self.initialized = True

self.EPOCH_LENGTH = epoch_length
self.WARM_UP_PERIOD = warm_up_period
self.WITHDRAWAL_DELAY = withdrawal_delay
self.DYNASTY_LOGOUT_DELAY = dynasty_logout_delay
self.BASE_INTEREST_FACTOR = base_interest_factor
self.BASE_PENALTY_FACTOR = base_penalty_factor
self.MIN_DEPOSIT_SIZE = min_deposit_size

self.START_EPOCH = floor(block.number / self.EPOCH_LENGTH)
self.START_EPOCH = floor((block.number + warm_up_period) / self.EPOCH_LENGTH)

# helper contracts
self.MSG_HASHER = msg_hasher
Expand Down Expand Up @@ -460,7 +466,6 @@ def initialize_epoch(epoch: int128):
@public
@payable
def deposit(validation_addr: address, withdrawal_addr: address):
assert self.current_epoch == floor(block.number / self.EPOCH_LENGTH)
assert extract32(raw_call(self.PURITY_CHECKER, concat('\xa1\x90\x3e\xab', convert(validation_addr, 'bytes32')), gas=500000, outsize=32), 0) != convert(0, 'bytes32')
assert not self.validator_indexes[withdrawal_addr]
assert msg.value >= self.MIN_DEPOSIT_SIZE
Expand Down
29 changes: 18 additions & 11 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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

EPOCH_LENGTH = 10
WARM_UP_PERIOD = 20
DYNASTY_LOGOUT_DELAY = 5
WITHDRAWAL_DELAY = 5
BASE_INTEREST_FACTOR = 0.02
Expand Down Expand Up @@ -99,6 +100,11 @@ def epoch_length():
return EPOCH_LENGTH


@pytest.fixture
def warm_up_period():
return WARM_UP_PERIOD


@pytest.fixture
def withdrawal_delay():
return WITHDRAWAL_DELAY
Expand All @@ -125,10 +131,11 @@ def min_deposit_size():


@pytest.fixture
def casper_config(epoch_length, withdrawal_delay, dynasty_logout_delay,
def casper_config(epoch_length, warm_up_period, withdrawal_delay, dynasty_logout_delay,
base_interest_factor, base_penalty_factor, min_deposit_size):
return {
"epoch_length": epoch_length, # in blocks
"warm_up_period": warm_up_period, # in blocks
"withdrawal_delay": withdrawal_delay, # in epochs
"dynasty_logout_delay": dynasty_logout_delay, # in dynasties
"base_interest_factor": base_interest_factor,
Expand All @@ -140,8 +147,8 @@ def casper_config(epoch_length, withdrawal_delay, dynasty_logout_delay,
@pytest.fixture
def casper_args(casper_config, msg_hasher_address, purity_checker_address):
return [
casper_config["epoch_length"], casper_config["withdrawal_delay"],
casper_config["dynasty_logout_delay"],
casper_config["epoch_length"], casper_config["warm_up_period"],
casper_config["withdrawal_delay"], casper_config["dynasty_logout_delay"],
msg_hasher_address, purity_checker_address, casper_config["base_interest_factor"],
casper_config["base_penalty_factor"], casper_config["min_deposit_size"]
]
Expand Down Expand Up @@ -309,6 +316,8 @@ def get_dirs(path):
return path, extra_args


# Note: If called during "warm_up-period", new_epoch mines all the way through
# the warm up period until `initialize_epoch` can first be called
@pytest.fixture
def new_epoch(casper_chain, casper):
def new_epoch():
Expand Down Expand Up @@ -441,11 +450,10 @@ def deposit_validator(privkey, value, valcode_type="pure_ecrecover"):
@pytest.fixture
def induct_validator(casper_chain, casper, deposit_validator, new_epoch):
def induct_validator(privkey, value, valcode_type="pure_ecrecover"):
if casper.current_epoch() == 0:
new_epoch()
validator_index = deposit_validator(privkey, value, valcode_type)
new_epoch()
new_epoch()
new_epoch() # justify
new_epoch() # finalize and increment dynasty
new_epoch() # finalize and increment dynasty
return validator_index
return induct_validator

Expand All @@ -459,12 +467,11 @@ def induct_validator(privkey, value, valcode_type="pure_ecrecover"):
def induct_validators(casper_chain, casper, deposit_validator, new_epoch):
def induct_validators(privkeys, values):
start_index = casper.next_validator_index()
if casper.current_epoch() == 0:
new_epoch()
for privkey, value in zip(privkeys, values):
deposit_validator(privkey, value)
new_epoch()
new_epoch()
new_epoch() # justify
new_epoch() # finalize and increment dynasty
new_epoch() # finalize and increment dynasty
return list(range(start_index, start_index + len(privkeys)))
return induct_validators

Expand Down
8 changes: 5 additions & 3 deletions tests/test_chain_initialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ def test_msg_hasher_is_pure(


# sanity check on casper contract basic functionality
def test_init_first_epoch(casper, new_epoch):
assert casper.current_epoch() == 0
def test_init_first_epoch(casper_chain, casper, new_epoch, warm_up_period, epoch_length):
start_epoch = (casper_chain.head_state.block_number + warm_up_period) // epoch_length

assert casper.current_epoch() == start_epoch
assert casper.next_validator_index() == 1

new_epoch()

assert casper.dynasty() == 0
assert casper.next_validator_index() == 1
assert casper.current_epoch() == 1
assert casper.current_epoch() == start_epoch + 1
assert casper.total_slashed(casper.current_epoch()) == 0
33 changes: 33 additions & 0 deletions tests/test_deposit.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import pytest

from ethereum import utils


Expand Down Expand Up @@ -84,3 +86,34 @@ def test_deposit_updates_total_deposits(casper, funded_privkey, deposit_amount,

assert casper.total_curdyn_deposits_in_wei() == deposit_amount
assert casper.total_prevdyn_deposits_in_wei() == deposit_amount


@pytest.mark.parametrize(
'warm_up_period,epoch_length',
[
(10, 5),
(25, 10),
(100, 50),
]
)
def test_deposit_during_warm_up_period(casper_chain, casper, funded_privkey, deposit_amount,
deposit_validator, new_epoch, warm_up_period, epoch_length):
validator_index = deposit_validator(funded_privkey, deposit_amount)

expected_start_dynasty = casper.dynasty() + 2
assert casper.validators__start_dynasty(validator_index) == expected_start_dynasty

new_epoch() # new_epoch mines through warm_up_period on first call
casper.dynasty() == 0
new_epoch()
casper.dynasty() == 1
new_epoch()
casper.dynasty() == 2

casper.total_curdyn_deposits_in_wei() == deposit_amount
casper.total_prevdyn_deposits_in_wei() == 0

new_epoch()

casper.total_curdyn_deposits_in_wei() == deposit_amount
casper.total_prevdyn_deposits_in_wei() == deposit_amount
107 changes: 54 additions & 53 deletions tests/test_fork_choice_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def test_highest_finalized_epoch_no_validators(casper, new_epoch, min_deposits):
if min_deposits > 0:
expected_epoch = -1
else:
if casper.current_epoch() == 0:
if casper.current_epoch() == casper.START_EPOCH():
expected_epoch = -1
else:
expected_epoch = casper.last_finalized_epoch()
Expand All @@ -90,111 +90,112 @@ def test_highest_finalized_epoch_no_validators(casper, new_epoch, min_deposits):

def test_highest_justified_and_epoch(casper, funded_privkey, deposit_amount,
new_epoch, induct_validator, mk_suggested_vote):
start_epoch = casper.START_EPOCH()
validator_index = induct_validator(funded_privkey, deposit_amount)
higher_deposit = int(deposit_amount * 1.1)

assert casper.total_curdyn_deposits_in_wei() == deposit_amount
assert casper.current_epoch() == 3
assert casper.current_epoch() == start_epoch + 3 # 3 to induct first dynasty

assert casper.highest_justified_epoch(deposit_amount) == 0
assert casper.highest_finalized_epoch(deposit_amount) == -1
assert casper.highest_justified_epoch(0) == 2
assert casper.highest_finalized_epoch(0) == 2
assert casper.highest_justified_epoch(0) == start_epoch + 2
assert casper.highest_finalized_epoch(0) == start_epoch + 2
assert casper.highest_justified_epoch(higher_deposit) == 0
assert casper.highest_finalized_epoch(higher_deposit) == -1

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

assert casper.checkpoints__cur_dyn_deposits(3) == 0
assert casper.checkpoints__prev_dyn_deposits(3) == 0
assert casper.last_justified_epoch() == 3
assert casper.last_finalized_epoch() == 2
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 3) == 0
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 3) == 0
assert casper.last_justified_epoch() == start_epoch + 3
assert casper.last_finalized_epoch() == start_epoch + 2

assert casper.highest_justified_epoch(deposit_amount) == 0
assert casper.highest_finalized_epoch(deposit_amount) == -1
assert casper.highest_justified_epoch(0) == 3
assert casper.highest_finalized_epoch(0) == 2
assert casper.highest_justified_epoch(0) == start_epoch + 3
assert casper.highest_finalized_epoch(0) == start_epoch + 2
assert casper.highest_justified_epoch(higher_deposit) == 0
assert casper.highest_finalized_epoch(higher_deposit) == -1

new_epoch()
casper.vote(mk_suggested_vote(validator_index, funded_privkey))

assert casper.checkpoints__cur_dyn_deposits(4) == deposit_amount
assert casper.checkpoints__prev_dyn_deposits(4) == 0
assert casper.last_justified_epoch() == 4
assert casper.last_finalized_epoch() == 3
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 4) == deposit_amount
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 4) == 0
assert casper.last_justified_epoch() == start_epoch + 4
assert casper.last_finalized_epoch() == start_epoch + 3

assert casper.highest_justified_epoch(deposit_amount) == 0
assert casper.highest_finalized_epoch(deposit_amount) == -1
assert casper.highest_justified_epoch(0) == 4
assert casper.highest_finalized_epoch(0) == 3
assert casper.highest_justified_epoch(0) == start_epoch + 4
assert casper.highest_finalized_epoch(0) == start_epoch + 3
assert casper.highest_justified_epoch(higher_deposit) == 0
assert casper.highest_finalized_epoch(higher_deposit) == -1

new_epoch()
casper.vote(mk_suggested_vote(validator_index, funded_privkey))

assert casper.checkpoints__cur_dyn_deposits(5) == deposit_amount
assert casper.checkpoints__prev_dyn_deposits(5) == deposit_amount
assert casper.last_justified_epoch() == 5
assert casper.last_finalized_epoch() == 4
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 5) == deposit_amount
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 5) == deposit_amount
assert casper.last_justified_epoch() == start_epoch + 5
assert casper.last_finalized_epoch() == start_epoch + 4

# enough prev and cur deposits in checkpoint 5 for the justified block
assert casper.highest_justified_epoch(deposit_amount) == 5
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 5
# not enough prev and cur deposits in checkpoint 4 for the finalized block
assert casper.highest_finalized_epoch(deposit_amount) == -1
assert casper.highest_justified_epoch(0) == 5
assert casper.highest_finalized_epoch(0) == 4
assert casper.highest_justified_epoch(0) == start_epoch + 5
assert casper.highest_finalized_epoch(0) == start_epoch + 4
assert casper.highest_justified_epoch(higher_deposit) == 0
assert casper.highest_finalized_epoch(higher_deposit) == -1

new_epoch()
casper.vote(mk_suggested_vote(validator_index, funded_privkey))

assert casper.checkpoints__cur_dyn_deposits(6) > deposit_amount
assert casper.checkpoints__prev_dyn_deposits(6) > deposit_amount
assert casper.last_justified_epoch() == 6
assert casper.last_finalized_epoch() == 5
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 6) > deposit_amount
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 6) > deposit_amount
assert casper.last_justified_epoch() == start_epoch + 6
assert casper.last_finalized_epoch() == start_epoch + 5

# enough deposits in checkpoint 6 for justified and checkpoint 5 for finalized!
assert casper.highest_justified_epoch(deposit_amount) == 6
assert casper.highest_finalized_epoch(deposit_amount) == 5
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 6
assert casper.highest_finalized_epoch(deposit_amount) == start_epoch + 5
assert casper.highest_justified_epoch(higher_deposit) == 0
assert casper.highest_finalized_epoch(higher_deposit) == -1
assert casper.highest_justified_epoch(0) == 6
assert casper.highest_finalized_epoch(0) == 5
assert casper.highest_justified_epoch(0) == start_epoch + 6
assert casper.highest_finalized_epoch(0) == start_epoch + 5

new_epoch()
# no vote

assert casper.checkpoints__cur_dyn_deposits(7) > deposit_amount
assert casper.checkpoints__prev_dyn_deposits(7) > deposit_amount
assert casper.last_justified_epoch() == 6
assert casper.last_finalized_epoch() == 5
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 7) > deposit_amount
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 7) > deposit_amount
assert casper.last_justified_epoch() == start_epoch + 6
assert casper.last_finalized_epoch() == start_epoch + 5

assert casper.highest_justified_epoch(deposit_amount) == 6
assert casper.highest_finalized_epoch(deposit_amount) == 5
assert casper.highest_justified_epoch(0) == 6
assert casper.highest_finalized_epoch(0) == 5
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 6
assert casper.highest_finalized_epoch(deposit_amount) == start_epoch + 5
assert casper.highest_justified_epoch(0) == start_epoch + 6
assert casper.highest_finalized_epoch(0) == start_epoch + 5
assert casper.highest_justified_epoch(higher_deposit) == 0
assert casper.highest_finalized_epoch(higher_deposit) == -1

new_epoch()
casper.vote(mk_suggested_vote(validator_index, funded_privkey))

assert casper.checkpoints__cur_dyn_deposits(8) > deposit_amount
assert casper.checkpoints__prev_dyn_deposits(8) > deposit_amount
assert casper.checkpoints__cur_dyn_deposits(start_epoch + 8) > deposit_amount
assert casper.checkpoints__prev_dyn_deposits(start_epoch + 8) > deposit_amount
# new justified
assert casper.last_justified_epoch() == 8
assert casper.last_justified_epoch() == start_epoch + 8
# no new finalized because not sequential justified blocks
assert casper.last_finalized_epoch() == 5
assert casper.last_finalized_epoch() == start_epoch + 5

assert casper.highest_justified_epoch(deposit_amount) == 8
assert casper.highest_finalized_epoch(deposit_amount) == 5
assert casper.highest_justified_epoch(0) == 8
assert casper.highest_finalized_epoch(0) == 5
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 8
assert casper.highest_finalized_epoch(deposit_amount) == start_epoch + 5
assert casper.highest_justified_epoch(0) == start_epoch + 8
assert casper.highest_finalized_epoch(0) == start_epoch + 5
assert casper.highest_justified_epoch(higher_deposit) == 0
assert casper.highest_finalized_epoch(higher_deposit) == -1

Expand All @@ -204,12 +205,12 @@ def test_highest_justified_and_epoch(casper, funded_privkey, deposit_amount,
assert casper.checkpoints__cur_dyn_deposits(9) > deposit_amount
assert casper.checkpoints__prev_dyn_deposits(9) > deposit_amount
# new justified and finalized because sequential justified blocks
assert casper.last_justified_epoch() == 9
assert casper.last_finalized_epoch() == 8
assert casper.last_justified_epoch() == start_epoch + 9
assert casper.last_finalized_epoch() == start_epoch + 8

assert casper.highest_justified_epoch(deposit_amount) == 9
assert casper.highest_finalized_epoch(deposit_amount) == 8
assert casper.highest_justified_epoch(0) == 9
assert casper.highest_finalized_epoch(0) == 8
assert casper.highest_justified_epoch(deposit_amount) == start_epoch + 9
assert casper.highest_finalized_epoch(deposit_amount) == start_epoch + 8
assert casper.highest_justified_epoch(0) == start_epoch + 9
assert casper.highest_finalized_epoch(0) == start_epoch + 8
assert casper.highest_justified_epoch(higher_deposit) == 0
assert casper.highest_finalized_epoch(higher_deposit) == -1
Loading

0 comments on commit 6a171e1

Please sign in to comment.