Skip to content

Commit

Permalink
Added....
Browse files Browse the repository at this point in the history
* Machinery for publishing old subkeys
* Inability to withdraw until you published all subkeys
* After a validator exits the queue there's still a minimum 1-day delay before they can withdraw (in the future this delay will be used as an opportunity to start a PoC challenge game)
  • Loading branch information
vbuterin authored Feb 9, 2019
1 parent 10a3e1b commit c7891c8
Showing 1 changed file with 83 additions and 21 deletions.
104 changes: 83 additions & 21 deletions specs/core/1_shard-data-chains.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Phase 1 depends upon all of the constants defined in [Phase 0](0_beacon-chain.md
| `MAX_BRANCH_RESPONSES` | 2**4 (= 16) | | |
| `MAX_EARLY_SUBKEY_REVEALS` | 2**4 (= 16) | | |
| `CUSTODY_PERIOD_LENGTH` | 2**11 (= 2048) | epochs | 9 days |
| `MINOR_REWARD_QUOTIENT` | 2**8 (= 256) | | |

### Flags, domains, etc.

Expand Down Expand Up @@ -134,12 +135,24 @@ The fork choice rule for any shard is LMD GHOST using the validators currently a

## Data structures

Add a member value to the end of the `Validator` object (initialized to `[]`):
Add member values to the end of the `Validator` object:

```python
'open_branch_challenges': [BranchChallengeRecord],
'next_subkey_to_reveal': 'uint64',
'reveal_max_periods_late': 'uint64'
```

And the initializers:

```python
'open_branch_challenges': [],
'next_subkey_to_reveal': 0,
'reveal_max_periods_late': 0,
```

Rename `withdrawal_epoch` to `withdrawable_epoch`.

Define a `BranchChallengeRecord` as follows:

```python
Expand All @@ -152,26 +165,12 @@ Define a `BranchChallengeRecord` as follows:
}
```

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):

```python
def eligible(index):
validator = state.validator_registry[index]
if len(validator.open_branch_challenges) > 0:
return False
elif validator.penalized_epoch <= current_epoch:
penalized_withdrawal_epochs = LATEST_PENALIZED_EXIT_LENGTH // 2
return current_epoch >= validator.penalized_epoch + penalized_withdrawal_epochs
else:
return current_epoch >= validator.exit_epoch + MIN_VALIDATOR_WITHDRAWAL_EPOCHS
```

Add two member values to the `BeaconBlockBody` structure:

```python
'branch_challenges': [BranchChallenge],
'branch_responses': [BranchResponse],
'early_subkey_reveals': [EarlySubkeyReveal],
'subkey_reveals': [SubkeyReveal],
```

Define a `BranchChallenge` as follows:
Expand All @@ -196,7 +195,7 @@ Define a `BranchResponse` as follows:
}
```

Define a `EarlySubkeyReveal` as follows:
Define a `SubkeyReveal` as follows:

```python
{
Expand Down Expand Up @@ -227,6 +226,38 @@ def verify_custody_subkey(pubkey: bytes48, subkey: bytes96, period: int) -> bool
)
```

Change the definition of `prepare_validator_for_withdrawal` as follows:

```python
def prepare_validator_for_withdrawal(state: BeaconState, index: ValidatorIndex) -> None:
"""
Set the validator with the given ``index`` with ``WITHDRAWABLE`` flag.
Note that this function mutates ``state``.
"""
validator = state.validator_registry[index]
validator.withdrawable_epoch = get_current_epoch(state) + MIN_VALIDATOR_WITHDRAWAL_EPOCHS
```

Change the definition of `penalize_validator` as follows:

```python
def penalize_validator(state: BeaconState, index: ValidatorIndex) -> None:
"""
Penalize the validator of the given ``index``.
Note that this function mutates ``state``.
"""
exit_validator(state, index)
validator = state.validator_registry[index]
state.latest_penalized_balances[get_current_epoch(state) % LATEST_PENALIZED_EXIT_LENGTH] += get_effective_balance(state, index)

whistleblower_index = get_beacon_proposer_index(state, state.slot)
whistleblower_reward = get_effective_balance(state, index) // WHISTLEBLOWER_REWARD_QUOTIENT
state.validator_balances[whistleblower_index] += whistleblower_reward
state.validator_balances[index] -= whistleblower_reward
validator.penalized_epoch = get_current_epoch(state)
validator.withdrawable_epoch = get_current_epoch(state) + LATEST_PENALIZED_EXIT_LENGTH
```

## Per-slot processing

Add two object processing categories to the per-slot processing, in order given below and lower than all other objects (specifically, right below exits) as follows.
Expand Down Expand Up @@ -257,19 +288,31 @@ For each `response` in `block.body.branch_responses`:
* Verify that `verify_merkle_branch(leaf=response.data, branch=response.branch, depth=record.depth, index=record.data_index, root=record.root) is True.
* Verify that `get_current_epoch(state) >= record.inclusion_epoch + ENTRY_EXIT_DELAY`.
* Remove the `record` from `state.validator_registry[response.responder_index].open_branch_challenges`
* Determine the proposer `proposer_index = get_beacon_proposer_index(state, state.slot)` and set `state.validator_balances[proposer_index] += base_reward(state, index) // INCLUDER_REWARD_QUOTIENT // MAX_BRANCH_CHALLENGES`.
* Determine the proposer `proposer_index = get_beacon_proposer_index(state, state.slot)` and set `state.validator_balances[proposer_index] += base_reward(state, index) // MINOR_REWARD_QUOTIENT`.
### Early subkey reveals
### Subkey reveals
Verify that `len(block.body.early_subkey_reveals) <= MAX_EARLY_SUBKEY_REVEALS`.
For each `reveal` in `block.body.early_subkey_reveals`:
* Verify that `state.validator_registry[reveal.validator_index].penalized_epoch > get_current_epoch(state) + ENTRY_EXIT_DELAY`.
* Verify that `verify_custody_subkey(state.validator_registry[reveal.validator_index].pubkey, reveal.subkey, reveal.period)` returns `True`.
* Verify that `reveal.period >= get_current_custody_period(state)`.
* Let `is_early_reveal = reveal.period > get_current_custody_period(state) or (reveal.period == get_current_custody_period(state) and state.validator_registry[reveal.validator_index].exit_epoch > get_current_epoch(state))` (ie. either the reveal is of a future period, or it's of the current period and the validator is still active)
* Verify that one of the following is true:
* (i) `is_early_reveal` is `True`
* (ii) `is_early_reveal` is `False` and `reveal.period == state.validator_registry[reveal.validator_index].next_subkey_to_reveal` (revealing a past subkey, or a current subkey for a validator that has exited)
In case (i):
* Verify that `state.validator_registry[reveal.validator_index].penalized_epoch > get_current_epoch(state) + ENTRY_EXIT_DELAY`.
* Run `penalize_validator(state, reveal.validator_index)`.
In case (ii):
* Determine the proposer `proposer_index = get_beacon_proposer_index(state, state.slot)` and set `state.validator_balances[proposer_index] += base_reward(state, index) // MINOR_REWARD_QUOTIENT`.
* Set `state.validator_registry[reveal.validator_index].next_subkey_to_reveal += 1`
* Set `state.validator_registry[reveal.validator_index].reveal_max_periods_late = max(state.validator_registry[reveal.validator_index].reveal_max_periods_late, get_current_period(state) - reveal.period)`.
## Per-epoch processing
Add the following loop immediately below the `process_ejections` loop:
Expand All @@ -284,3 +327,22 @@ def process_challenge_absences(state: BeaconState) -> None:
if len(validator.open_branch_challenges) > 0 and get_current_epoch(state) > validator.open_branch_challenges[0].inclusion_epoch + CHALLENGE_RESPONSE_DEADLINE:
penalize_validator(state, index)
```
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):
```python
def eligible(index):
validator = state.validator_registry[index]
# Cannot exit if there are still open branch challenges
if len(validator.open_branch_challenges) > 0:
return False
# Cannot exit if you have not revealed all of your subkeys
elif validator.next_subkey_to_reveal <= validator.exit_epoch // CUSTODY_PERIOD_LENGTH:
return False
# Cannot exit if you already have
elif validator.withdrawable_epoch < FAR_FUTURE_EPOCH:
return False
# Return minimum time
else:
return current_epoch >= validator.exit_epoch + MIN_VALIDATOR_WITHDRAWAL_EPOCHS
```

0 comments on commit c7891c8

Please sign in to comment.