Skip to content

Commit

Permalink
Merge pull request #870 from ethereum/vbuterin-patch-10
Browse files Browse the repository at this point in the history
Replace with empty instead of popping finished challenges
  • Loading branch information
djrtwo committed Apr 22, 2019
2 parents 59de05e + d4a33db commit 77af610
Showing 1 changed file with 38 additions and 8 deletions.
46 changes: 38 additions & 8 deletions specs/core/1_custody-game.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@
- [`BeaconState`](#beaconstate)
- [`BeaconBlockBody`](#beaconblockbody)
- [Helpers](#helpers)
- [`typeof`](#typeof)
- [`empty`](#empty)
- [`get_crosslink_chunk_count`](#get_crosslink_chunk_count)
- [`get_custody_chunk_bit`](#get_custody_chunk_bit)
- [`epoch_to_custody_period`](#epoch_to_custody_period)
- [`replace_empty_or_append`](#replace_empty_or_append)
- [`verify_custody_key`](#verify_custody_key)
- [Per-block processing](#per-block-processing)
- [Operations](#operations)
Expand Down Expand Up @@ -203,6 +206,14 @@ Add the following fields to the end of the specified container objects. Fields w

## Helpers

### `typeof`

The `typeof` function accepts and SSZ object as a single input and returns the corresponding SSZ type.

### `empty`

The `empty` function accepts and SSZ type as input and returns an object of that type with all fields initialized to default values.

### `get_crosslink_chunk_count`

```python
Expand All @@ -229,6 +240,18 @@ def epoch_to_custody_period(epoch: Epoch) -> int:
return epoch // EPOCHS_PER_CUSTODY_PERIOD
```

### `replace_empty_or_append`

```python
def replace_empty_or_append(list: List[Any], new_element: Any) -> int:
for i in range(len(list)):
if list[i] == empty(typeof(new_element)):
list[i] = new_element
return i
list.append(new_element)
return len(list) - 1
```

### `verify_custody_key`

```python
Expand Down Expand Up @@ -321,15 +344,17 @@ def process_chunk_challenge(state: BeaconState,
depth = math.log2(next_power_of_two(get_custody_chunk_count(challenge.attestation)))
assert challenge.chunk_index < 2**depth
# Add new chunk challenge record
state.custody_chunk_challenge_records.append(CustodyChunkChallengeRecord(
new_record = CustodyChunkChallengeRecord(
challenge_index=state.custody_challenge_index,
challenger_index=get_beacon_proposer_index(state),
responder_index=challenge.responder_index
deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE,
crosslink_data_root=challenge.attestation.data.crosslink_data_root,
depth=depth,
chunk_index=challenge.chunk_index,
))
)
replace_empty_or_append(state.custody_chunk_challenge_records, new_record)

state.custody_challenge_index += 1
# Postpone responder withdrawability
responder.withdrawable_epoch = FAR_FUTURE_EPOCH
Expand Down Expand Up @@ -385,15 +410,16 @@ def process_bit_challenge(state: BeaconState,
custody_bit = get_bitfield_bit(attestation.custody_bitfield, attesters.index(responder_index))
assert custody_bit != chunk_bits_xor
# Add new bit challenge record
state.custody_bit_challenge_records.append(CustodyBitChallengeRecord(
new_record = CustodyBitChallengeRecord(
challenge_index=state.custody_challenge_index,
challenger_index=challenge.challenger_index,
responder_index=challenge.responder_index,
deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE
crosslink_data_root=challenge.attestation.crosslink_data_root,
chunk_bits=challenge.chunk_bits,
responder_key=challenge.responder_key,
))
)
replace_empty_or_append(state.custody_bit_challenge_records, new_record)
state.custody_challenge_index += 1
# Postpone responder withdrawability
responder.withdrawable_epoch = FAR_FUTURE_EPOCH
Expand Down Expand Up @@ -434,7 +460,8 @@ def process_chunk_challenge_response(state: BeaconState,
root=challenge.crosslink_data_root,
)
# Clear the challenge
state.custody_chunk_challenge_records.remove(challenge)
records = state.custody_chunk_challenge_records
records[records.index(challenge)] = CustodyChunkChallengeRecord()
# Reward the proposer
proposer_index = get_beacon_proposer_index(state)
increase_balance(state, proposer_index, base_reward(state, index) // MINOR_REWARD_QUOTIENT)
Expand All @@ -457,7 +484,8 @@ def process_bit_challenge_response(state: BeaconState,
# Verify the chunk bit does not match the challenge chunk bit
assert get_custody_chunk_bit(challenge.responder_key, response.chunk) != get_bitfield_bit(challenge.chunk_bits, response.chunk_index)
# Clear the challenge
state.custody_bit_challenge_records.remove(challenge)
records = state.custody_bit_challenge_records
records[records.index(challenge)] = CustodyBitChallengeRecord()
# Slash challenger
slash_validator(state, challenge.challenger_index, challenge.responder_index)
```
Expand All @@ -471,12 +499,14 @@ def process_challenge_deadlines(state: BeaconState) -> None:
for challenge in state.custody_chunk_challenge_records:
if get_current_epoch(state) > challenge.deadline:
slash_validator(state, challenge.responder_index, challenge.challenger_index)
state.custody_chunk_challenge_records.remove(challenge)
records = state.custody_chunk_challenge_records
records[records.index(challenge)] = CustodyChunkChallengeRecord()

for challenge in state.custody_bit_challenge_records:
if get_current_epoch(state) > challenge.deadline:
slash_validator(state, challenge.responder_index, challenge.challenger_index)
state.custody_bit_challenge_records.remove(challenge)
records = state.custody_bit_challenge_records
records[records.index(challenge)] = CustodyBitChallengeRecord()
```

In `process_penalties_and_exits`, change the definition of `eligible` to the following (note that it is not a pure function because `state` is declared in the surrounding scope):
Expand Down

0 comments on commit 77af610

Please sign in to comment.