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:
Lion - dapplion 2023-06-14 18:58:57 +03:00 committed by GitHub
parent 0ab160bc28
commit 65a28b6d69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 73 deletions

View File

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

View File

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