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)
|
||||
- [Epoch processing](#epoch-processing)
|
||||
- [`WhiskTracker`](#whisktracker)
|
||||
- [`Validator`](#validator)
|
||||
- [`BeaconState`](#beaconstate)
|
||||
- [Block processing](#block-processing)
|
||||
- [Block header](#block-header)
|
||||
|
@ -125,23 +124,6 @@ class WhiskTracker(Container):
|
|||
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`
|
||||
|
||||
```python
|
||||
|
@ -187,8 +169,11 @@ class BeaconState(Container):
|
|||
next_withdrawal_validator_index: ValidatorIndex
|
||||
# Deep history valid from Capella onwards
|
||||
historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]
|
||||
# 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_trackers: List[WhiskTracker, VALIDATOR_REGISTRY_LIMIT] # [New in Whisk]
|
||||
whisk_k_commitments: List[BLSG1Point, VALIDATOR_REGISTRY_LIMIT] # [New in Whisk]
|
||||
```
|
||||
|
||||
```python
|
||||
|
@ -204,7 +189,7 @@ def select_whisk_trackers(state: BeaconState, epoch: Epoch) -> None:
|
|||
for i in range(WHISK_CANDIDATE_TRACKERS_COUNT):
|
||||
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
|
||||
state.whisk_candidate_trackers[i] = state.validators[candidate_index].whisk_tracker
|
||||
state.whisk_candidate_trackers[i] = state.whisk_trackers[candidate_index]
|
||||
```
|
||||
|
||||
```python
|
||||
|
@ -238,7 +223,7 @@ def process_epoch(state: BeaconState) -> None:
|
|||
```python
|
||||
def process_whisk_opening_proof(state: BeaconState, block: BeaconBlock) -> None:
|
||||
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)
|
||||
```
|
||||
|
||||
|
@ -298,7 +283,7 @@ class BeaconBlockBody(capella.BeaconBlockBody):
|
|||
whisk_shuffle_proof_M_commitment: BLSG1Point # [New in Whisk]
|
||||
whisk_registration_proof: WhiskTrackerProof # [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
|
||||
|
@ -343,7 +328,7 @@ def process_shuffled_trackers(state: BeaconState, body: BeaconBlockBody) -> None
|
|||
|
||||
```python
|
||||
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
|
||||
|
@ -384,49 +369,30 @@ def process_block(state: BeaconState, block: BeaconBlock) -> None:
|
|||
|
||||
### 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
|
||||
def get_unique_whisk_k(state: BeaconState, validator_index: ValidatorIndex) -> BLSFieldElement:
|
||||
counter = 0
|
||||
while True:
|
||||
# hash `validator_index || counter`
|
||||
k = BLSFieldElement(bytes_to_bls_field(hash(uint_to_bytes(validator_index) + uint_to_bytes(uint64(counter)))))
|
||||
k = get_initial_whisk_k(validator_index, counter)
|
||||
if is_k_commitment_unique(state, BLSG1ScalarMultiply(k, BLS_G1_GENERATOR)):
|
||||
return k # unique by trial and error
|
||||
counter += 1
|
||||
```
|
||||
|
||||
```python
|
||||
def get_initial_commitments(k: BLSFieldElement) -> Tuple[BLSG1Point, WhiskTracker]:
|
||||
return (
|
||||
BLSG1ScalarMultiply(k, BLS_G1_GENERATOR),
|
||||
WhiskTracker(r_G=BLS_G1_GENERATOR, k_r_G=BLSG1ScalarMultiply(k, BLS_G1_GENERATOR))
|
||||
)
|
||||
def get_k_commitment(k: BLSFieldElement) -> BLSG1Point:
|
||||
return BLSG1ScalarMultiply(k, BLS_G1_GENERATOR)
|
||||
```
|
||||
|
||||
```python
|
||||
def get_validator_from_deposit_whisk(
|
||||
state: BeaconState,
|
||||
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
|
||||
def get_initial_tracker(k: BLSFieldElement) -> WhiskTracker:
|
||||
return WhiskTracker(r_G=BLS_G1_GENERATOR, k_r_G=BLSG1ScalarMultiply(k, BLS_G1_GENERATOR))
|
||||
```
|
||||
|
||||
```python
|
||||
|
@ -448,13 +414,16 @@ def apply_deposit(state: BeaconState,
|
|||
# Initialize validator if the deposit signature is valid
|
||||
if bls.Verify(pubkey, signing_root, signature):
|
||||
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.balances, index, amount)
|
||||
# [New in Altair]
|
||||
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.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:
|
||||
# Increase balance by deposit amount
|
||||
index = ValidatorIndex(validator_pubkeys.index(pubkey))
|
||||
|
|
|
@ -68,6 +68,11 @@ def whisk_proposer_selection(state: BeaconState, epoch: Epoch) -> None:
|
|||
|
||||
```python
|
||||
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)
|
||||
post = BeaconState(
|
||||
# Versioning
|
||||
|
@ -104,27 +109,19 @@ def upgrade_to_whisk(pre: bellatrix.BeaconState) -> BeaconState:
|
|||
current_justified_checkpoint=pre.current_justified_checkpoint,
|
||||
finalized_checkpoint=pre.finalized_checkpoint,
|
||||
# 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
|
||||
# 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)
|
||||
|
|
Loading…
Reference in New Issue