Skip to content

Commit

Permalink
Merge pull request #81 from djrtwo/bugfix/dynasty_wei_delta_in_slashing
Browse files Browse the repository at this point in the history
[bugfix] dynasty_wei_delta errors in slashing
  • Loading branch information
djrtwo authored Apr 11, 2018
2 parents 0142319 + 12d9f18 commit b00004a
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 7 deletions.
17 changes: 10 additions & 7 deletions casper/contracts/simple_casper.v.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,13 +481,16 @@ def slash(vote_msg_1: bytes <= 1024, vote_msg_2: bytes <= 1024):
# Log slashing
log.Slash(msg.sender, self.validators[validator_index_1].withdrawal_addr, validator_index_1, slashing_bounty, deposit_destroyed)

deposit: decimal(wei/m) = self.validators[validator_index_1].deposit
self.dynasty_wei_delta[self.dynasty + 1] -= deposit

# if validator had already initialized logout remove his deposit
# from next dynasty rather than from his end_dynasty
if self.validators[validator_index_1].end_dynasty < self.default_end_dynasty:
self.dynasty_wei_delta[self.validators[validator_index_1].end_dynasty] += deposit
# if validator not logged out yet, remove total from next dynasty
end_dynasty: int128 = self.validators[validator_index_1].end_dynasty
if self.dynasty < end_dynasty:
deposit: decimal(wei/m) = self.validators[validator_index_1].deposit
self.dynasty_wei_delta[self.dynasty + 1] -= deposit

# if validator was already staged for logout at end_dynasty,
# ensure that we don't doubly remove from total
if end_dynasty < self.default_end_dynasty:
self.dynasty_wei_delta[end_dynasty] += deposit

self.delete_validator(validator_index_1)
send(msg.sender, slashing_bounty)
Expand Down
21 changes: 21 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,27 @@ def mk_suggested_vote(validator_index, privkey):
return mk_suggested_vote


@pytest.fixture
def mk_slash_votes(casper, mk_vote, fake_hash):
def mk_slash_votes(validator_index, privkey):
vote_1 = mk_vote(
validator_index,
casper.recommended_target_hash(),
casper.current_epoch(),
casper.recommended_source_epoch(),
privkey
)
vote_2 = mk_vote(
validator_index,
fake_hash,
casper.current_epoch(),
casper.recommended_source_epoch(),
privkey
)
return vote_1, vote_2
return mk_slash_votes


@pytest.fixture
def mk_logout():
def mk_logout(validator_index, epoch, key):
Expand Down
70 changes: 70 additions & 0 deletions tests/test_slashing.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,73 @@ def test_slash_no_surround(casper, funded_privkey, deposit_amount, new_epoch,
assert casper.deposit_size(validator_index) == 0
assert casper.dynasty_wei_delta(next_dynasty) == \
(-deposit_amount / casper.deposit_scale_factor())


def test_slash_after_logout_delay(casper, funded_privkey, deposit_amount, get_last_log,
induct_validator, mk_suggested_vote, mk_slash_votes,
new_epoch, fake_hash, logout_validator):
validator_index = induct_validator(funded_privkey, deposit_amount)
scaled_deposit_size = casper.validators__deposit(validator_index)

assert casper.total_curdyn_deposits_scaled() == deposit_amount

logout_validator(validator_index, funded_privkey)
end_dynasty = casper.validators__end_dynasty(validator_index)

assert casper.dynasty_wei_delta(end_dynasty) == -scaled_deposit_size

# step past validator's end_dynasty
dynasty_logout_delay = casper.dynasty_logout_delay()
for _ in range(dynasty_logout_delay + 1):
casper.vote(mk_suggested_vote(validator_index, funded_privkey))
new_epoch()

new_scaled_deposit_size = casper.validators__deposit(validator_index)
# should have a bit more from rewards
assert new_scaled_deposit_size > scaled_deposit_size

assert casper.dynasty() == casper.validators__end_dynasty(validator_index) + 1
assert casper.dynasty_wei_delta(casper.dynasty() + 1) == 0

vote_1, vote_2 = mk_slash_votes(validator_index, funded_privkey)
casper.slash(vote_1, vote_2)

assert casper.deposit_size(validator_index) == 0

# validator already out of current deposits. should not change dynasty_wei_delta
assert casper.dynasty_wei_delta(end_dynasty) == -new_scaled_deposit_size
assert casper.dynasty_wei_delta(casper.dynasty() + 1) == 0


def test_slash_after_logout_before_logout_delay(casper, funded_privkey, deposit_amount,
get_last_log, induct_validator,
mk_suggested_vote, mk_slash_votes,
new_epoch, fake_hash, logout_validator):
validator_index = induct_validator(funded_privkey, deposit_amount)
scaled_deposit_size = casper.validators__deposit(validator_index)

assert casper.total_curdyn_deposits_scaled() == deposit_amount

logout_validator(validator_index, funded_privkey)
end_dynasty = casper.validators__end_dynasty(validator_index)

assert casper.dynasty_wei_delta(end_dynasty) == -scaled_deposit_size

# step forward but not up to end_dynasty
casper.vote(mk_suggested_vote(validator_index, funded_privkey))
new_epoch()

new_scaled_deposit_size = casper.validators__deposit(validator_index)

assert casper.dynasty() < end_dynasty - 1
assert casper.dynasty_wei_delta(casper.dynasty() + 1) == 0
assert casper.dynasty_wei_delta(end_dynasty) == -new_scaled_deposit_size

vote_1, vote_2 = mk_slash_votes(validator_index, funded_privkey)
casper.slash(vote_1, vote_2)

assert casper.deposit_size(validator_index) == 0

# remove deposit from next dynasty rather than end_dynasty
assert casper.dynasty_wei_delta(end_dynasty) == 0
assert casper.dynasty_wei_delta(casper.dynasty() + 1) == -new_scaled_deposit_size

0 comments on commit b00004a

Please sign in to comment.