Whisk: Move validator whisk trackers and commitments to state (#3407)
* Move validator whisk trackers and commitments to state * Move comment
This commit is contained in:
parent
0ab160bc28
commit
65a28b6d69
|
@ -15,7 +15,6 @@
|
||||||
- [Curdleproofs and opening proofs](#curdleproofs-and-opening-proofs)
|
- [Curdleproofs and opening proofs](#curdleproofs-and-opening-proofs)
|
||||||
- [Epoch processing](#epoch-processing)
|
- [Epoch processing](#epoch-processing)
|
||||||
- [`WhiskTracker`](#whisktracker)
|
- [`WhiskTracker`](#whisktracker)
|
||||||
- [`Validator`](#validator)
|
|
||||||
- [`BeaconState`](#beaconstate)
|
- [`BeaconState`](#beaconstate)
|
||||||
- [Block processing](#block-processing)
|
- [Block processing](#block-processing)
|
||||||
- [Block header](#block-header)
|
- [Block header](#block-header)
|
||||||
|
@ -125,23 +124,6 @@ class WhiskTracker(Container):
|
||||||
k_r_G: BLSG1Point # k * r * G
|
k_r_G: BLSG1Point # k * r * G
|
||||||
```
|
```
|
||||||
|
|
||||||
### `Validator`
|
|
||||||
|
|
||||||
```python
|
|
||||||
class Validator(Container):
|
|
||||||
pubkey: BLSPubkey
|
|
||||||
withdrawal_credentials: Bytes32 # Commitment to pubkey for withdrawals
|
|
||||||
effective_balance: Gwei # Balance at stake
|
|
||||||
slashed: boolean
|
|
||||||
# Status epochs
|
|
||||||
activation_eligibility_epoch: Epoch # When criteria for activation were met
|
|
||||||
activation_epoch: Epoch
|
|
||||||
exit_epoch: Epoch
|
|
||||||
withdrawable_epoch: Epoch # When validator can withdraw funds
|
|
||||||
whisk_tracker: WhiskTracker # Whisk tracker (r * G, k * r * G) [New in Whisk]
|
|
||||||
whisk_k_commitment: BLSG1Point # Whisk k commitment k * BLS_G1_GENERATOR [New in Whisk]
|
|
||||||
```
|
|
||||||
|
|
||||||
### `BeaconState`
|
### `BeaconState`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -187,8 +169,11 @@ class BeaconState(Container):
|
||||||
next_withdrawal_validator_index: ValidatorIndex
|
next_withdrawal_validator_index: ValidatorIndex
|
||||||
# Deep history valid from Capella onwards
|
# Deep history valid from Capella onwards
|
||||||
historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]
|
historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]
|
||||||
|
# Whisk
|
||||||
whisk_candidate_trackers: Vector[WhiskTracker, WHISK_CANDIDATE_TRACKERS_COUNT] # [New in Whisk]
|
whisk_candidate_trackers: Vector[WhiskTracker, WHISK_CANDIDATE_TRACKERS_COUNT] # [New in Whisk]
|
||||||
whisk_proposer_trackers: Vector[WhiskTracker, WHISK_PROPOSER_TRACKERS_COUNT] # [New in Whisk]
|
whisk_proposer_trackers: Vector[WhiskTracker, WHISK_PROPOSER_TRACKERS_COUNT] # [New in Whisk]
|
||||||
|
whisk_trackers: List[WhiskTracker, VALIDATOR_REGISTRY_LIMIT] # [New in Whisk]
|
||||||
|
whisk_k_commitments: List[BLSG1Point, VALIDATOR_REGISTRY_LIMIT] # [New in Whisk]
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -204,7 +189,7 @@ def select_whisk_trackers(state: BeaconState, epoch: Epoch) -> None:
|
||||||
for i in range(WHISK_CANDIDATE_TRACKERS_COUNT):
|
for i in range(WHISK_CANDIDATE_TRACKERS_COUNT):
|
||||||
seed = hash(get_seed(state, epoch, DOMAIN_WHISK_CANDIDATE_SELECTION) + uint_to_bytes(i))
|
seed = hash(get_seed(state, epoch, DOMAIN_WHISK_CANDIDATE_SELECTION) + uint_to_bytes(i))
|
||||||
candidate_index = compute_proposer_index(state, active_validator_indices, seed) # sample by effective balance
|
candidate_index = compute_proposer_index(state, active_validator_indices, seed) # sample by effective balance
|
||||||
state.whisk_candidate_trackers[i] = state.validators[candidate_index].whisk_tracker
|
state.whisk_candidate_trackers[i] = state.whisk_trackers[candidate_index]
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -238,7 +223,7 @@ def process_epoch(state: BeaconState) -> None:
|
||||||
```python
|
```python
|
||||||
def process_whisk_opening_proof(state: BeaconState, block: BeaconBlock) -> None:
|
def process_whisk_opening_proof(state: BeaconState, block: BeaconBlock) -> None:
|
||||||
tracker = state.whisk_proposer_trackers[state.slot % WHISK_PROPOSER_TRACKERS_COUNT]
|
tracker = state.whisk_proposer_trackers[state.slot % WHISK_PROPOSER_TRACKERS_COUNT]
|
||||||
k_commitment = state.validators[block.proposer_index].whisk_k_commitment
|
k_commitment = state.whisk_k_commitments[block.proposer_index]
|
||||||
assert IsValidWhiskOpeningProof(tracker, k_commitment, block.body.whisk_opening_proof)
|
assert IsValidWhiskOpeningProof(tracker, k_commitment, block.body.whisk_opening_proof)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -298,7 +283,7 @@ class BeaconBlockBody(capella.BeaconBlockBody):
|
||||||
whisk_shuffle_proof_M_commitment: BLSG1Point # [New in Whisk]
|
whisk_shuffle_proof_M_commitment: BLSG1Point # [New in Whisk]
|
||||||
whisk_registration_proof: WhiskTrackerProof # [New in Whisk]
|
whisk_registration_proof: WhiskTrackerProof # [New in Whisk]
|
||||||
whisk_tracker: WhiskTracker # [New in Whisk]
|
whisk_tracker: WhiskTracker # [New in Whisk]
|
||||||
whisk_k_commitment: BLSG1Point # [New in Whisk]
|
whisk_k_commitment: BLSG1Point # k * BLS_G1_GENERATOR [New in Whisk]
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -343,7 +328,7 @@ def process_shuffled_trackers(state: BeaconState, body: BeaconBlockBody) -> None
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def is_k_commitment_unique(state: BeaconState, k_commitment: BLSG1Point) -> bool:
|
def is_k_commitment_unique(state: BeaconState, k_commitment: BLSG1Point) -> bool:
|
||||||
return all([validator.whisk_k_commitment != k_commitment for validator in state.validators])
|
return all([whisk_k_commitment != k_commitment for whisk_k_commitment in state.whisk_k_commitments])
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -384,49 +369,30 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
||||||
|
|
||||||
### Deposits
|
### Deposits
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_initial_whisk_k(validator_index: ValidatorIndex, counter: int) -> BLSFieldElement:
|
||||||
|
# hash `validator_index || counter`
|
||||||
|
return BLSFieldElement(bytes_to_bls_field(hash(uint_to_bytes(validator_index) + uint_to_bytes(uint64(counter)))))
|
||||||
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_unique_whisk_k(state: BeaconState, validator_index: ValidatorIndex) -> BLSFieldElement:
|
def get_unique_whisk_k(state: BeaconState, validator_index: ValidatorIndex) -> BLSFieldElement:
|
||||||
counter = 0
|
counter = 0
|
||||||
while True:
|
while True:
|
||||||
# hash `validator_index || counter`
|
k = get_initial_whisk_k(validator_index, counter)
|
||||||
k = BLSFieldElement(bytes_to_bls_field(hash(uint_to_bytes(validator_index) + uint_to_bytes(uint64(counter)))))
|
|
||||||
if is_k_commitment_unique(state, BLSG1ScalarMultiply(k, BLS_G1_GENERATOR)):
|
if is_k_commitment_unique(state, BLSG1ScalarMultiply(k, BLS_G1_GENERATOR)):
|
||||||
return k # unique by trial and error
|
return k # unique by trial and error
|
||||||
counter += 1
|
counter += 1
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_initial_commitments(k: BLSFieldElement) -> Tuple[BLSG1Point, WhiskTracker]:
|
def get_k_commitment(k: BLSFieldElement) -> BLSG1Point:
|
||||||
return (
|
return BLSG1ScalarMultiply(k, BLS_G1_GENERATOR)
|
||||||
BLSG1ScalarMultiply(k, BLS_G1_GENERATOR),
|
|
||||||
WhiskTracker(r_G=BLS_G1_GENERATOR, k_r_G=BLSG1ScalarMultiply(k, BLS_G1_GENERATOR))
|
|
||||||
)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_validator_from_deposit_whisk(
|
def get_initial_tracker(k: BLSFieldElement) -> WhiskTracker:
|
||||||
state: BeaconState,
|
return WhiskTracker(r_G=BLS_G1_GENERATOR, k_r_G=BLSG1ScalarMultiply(k, BLS_G1_GENERATOR))
|
||||||
pubkey: BLSPubkey,
|
|
||||||
withdrawal_credentials: Bytes32,
|
|
||||||
amount: uint64
|
|
||||||
) -> Validator:
|
|
||||||
effective_balance = min(amount - amount % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
|
|
||||||
k = get_unique_whisk_k(state, ValidatorIndex(len(state.validators)))
|
|
||||||
whisk_k_commitment, whisk_tracker = get_initial_commitments(k)
|
|
||||||
|
|
||||||
validator = Validator(
|
|
||||||
pubkey=pubkey,
|
|
||||||
withdrawal_credentials=withdrawal_credentials,
|
|
||||||
activation_eligibility_epoch=FAR_FUTURE_EPOCH,
|
|
||||||
activation_epoch=FAR_FUTURE_EPOCH,
|
|
||||||
exit_epoch=FAR_FUTURE_EPOCH,
|
|
||||||
withdrawable_epoch=FAR_FUTURE_EPOCH,
|
|
||||||
effective_balance=effective_balance,
|
|
||||||
# Whisk fields
|
|
||||||
whisk_tracker=whisk_tracker,
|
|
||||||
whisk_k_commitment=whisk_k_commitment,
|
|
||||||
)
|
|
||||||
return validator
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -448,13 +414,16 @@ def apply_deposit(state: BeaconState,
|
||||||
# Initialize validator if the deposit signature is valid
|
# Initialize validator if the deposit signature is valid
|
||||||
if bls.Verify(pubkey, signing_root, signature):
|
if bls.Verify(pubkey, signing_root, signature):
|
||||||
index = get_index_for_new_validator(state)
|
index = get_index_for_new_validator(state)
|
||||||
validator = get_validator_from_deposit_whisk(state, pubkey, withdrawal_credentials, amount)
|
validator = get_validator_from_deposit(pubkey, withdrawal_credentials, amount)
|
||||||
set_or_append_list(state.validators, index, validator)
|
set_or_append_list(state.validators, index, validator)
|
||||||
set_or_append_list(state.balances, index, amount)
|
set_or_append_list(state.balances, index, amount)
|
||||||
# [New in Altair]
|
|
||||||
set_or_append_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000))
|
set_or_append_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000))
|
||||||
set_or_append_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000))
|
set_or_append_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000))
|
||||||
set_or_append_list(state.inactivity_scores, index, uint64(0))
|
set_or_append_list(state.inactivity_scores, index, uint64(0))
|
||||||
|
# [New in Whisk]
|
||||||
|
k = get_unique_whisk_k(state, ValidatorIndex(len(state.validators) - 1))
|
||||||
|
state.whisk_trackers.append(get_initial_tracker(k))
|
||||||
|
state.whisk_k_commitments.append(get_k_commitment(k))
|
||||||
else:
|
else:
|
||||||
# Increase balance by deposit amount
|
# Increase balance by deposit amount
|
||||||
index = ValidatorIndex(validator_pubkeys.index(pubkey))
|
index = ValidatorIndex(validator_pubkeys.index(pubkey))
|
||||||
|
|
|
@ -68,6 +68,11 @@ def whisk_proposer_selection(state: BeaconState, epoch: Epoch) -> None:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def upgrade_to_whisk(pre: bellatrix.BeaconState) -> BeaconState:
|
def upgrade_to_whisk(pre: bellatrix.BeaconState) -> BeaconState:
|
||||||
|
# Compute initial unsafe trackers for all validators
|
||||||
|
ks = [get_initial_whisk_k(ValidatorIndex(validator_index), 0) for validator_index in range(len(pre.validators))]
|
||||||
|
whisk_k_commitments = [get_k_commitment(k) for k in ks]
|
||||||
|
whisk_trackers = [get_initial_tracker(k) for k in ks]
|
||||||
|
|
||||||
epoch = bellatrix.get_current_epoch(pre)
|
epoch = bellatrix.get_current_epoch(pre)
|
||||||
post = BeaconState(
|
post = BeaconState(
|
||||||
# Versioning
|
# Versioning
|
||||||
|
@ -104,27 +109,19 @@ def upgrade_to_whisk(pre: bellatrix.BeaconState) -> BeaconState:
|
||||||
current_justified_checkpoint=pre.current_justified_checkpoint,
|
current_justified_checkpoint=pre.current_justified_checkpoint,
|
||||||
finalized_checkpoint=pre.finalized_checkpoint,
|
finalized_checkpoint=pre.finalized_checkpoint,
|
||||||
# Inactivity
|
# Inactivity
|
||||||
inactivity_scores=pre.inactivity_Scores,
|
inactivity_scores=pre.inactivity_scores,
|
||||||
|
# Sync
|
||||||
|
current_sync_committee=pre.current_sync_committee,
|
||||||
|
next_sync_committee=pre.next_sync_committee,
|
||||||
|
# Execution-layer
|
||||||
|
latest_execution_payload_header=pre.latest_execution_payload_header,
|
||||||
|
# Whisk
|
||||||
|
whisk_proposer_trackers=[WhiskTracker() for _ in range(WHISK_PROPOSER_TRACKERS_COUNT)], # [New in Whisk]
|
||||||
|
whisk_candidate_trackers=[WhiskTracker() for _ in range(WHISK_CANDIDATE_TRACKERS_COUNT)], # [New in Whisk]
|
||||||
|
whisk_trackers=whisk_trackers, # [New in Whisk]
|
||||||
|
whisk_k_commitments=whisk_k_commitments, # [New in Whisk]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Initialize all validators with predictable commitments
|
|
||||||
for val_index, pre_validator in enumerate(pre.validators):
|
|
||||||
whisk_commitment, whisk_tracker = get_initial_commitments(get_unique_whisk_k(post, ValidatorIndex(val_index)))
|
|
||||||
|
|
||||||
post_validator = Validator(
|
|
||||||
pubkey=pre_validator.pubkey,
|
|
||||||
withdrawal_credentials=pre_validator.withdrawal_credentials,
|
|
||||||
effective_balance=pre_validator.effective_balance,
|
|
||||||
slashed=pre_validator.slashed,
|
|
||||||
activation_eligibility_epoch=pre_validator.activation_eligibility_epoch,
|
|
||||||
activation_epoch=pre_validator.activation_epoch,
|
|
||||||
exit_epoch=pre_validator.exit_epoch,
|
|
||||||
withdrawable_epoch=pre_validator.withdrawable_epoch,
|
|
||||||
whisk_commitment=whisk_commitment,
|
|
||||||
whisk_tracker=whisk_tracker,
|
|
||||||
)
|
|
||||||
post.validators.append(post_validator)
|
|
||||||
|
|
||||||
# Do a candidate selection followed by a proposer selection so that we have proposers for the upcoming day
|
# Do a candidate selection followed by a proposer selection so that we have proposers for the upcoming day
|
||||||
# Use an old epoch when selecting candidates so that we don't get the same seed as in the next candidate selection
|
# Use an old epoch when selecting candidates so that we don't get the same seed as in the next candidate selection
|
||||||
whisk_candidate_selection(post, epoch - WHISK_PROPOSER_SELECTION_GAP - 1)
|
whisk_candidate_selection(post, epoch - WHISK_PROPOSER_SELECTION_GAP - 1)
|
||||||
|
|
Loading…
Reference in New Issue