Add phase1 type hinting checks and fix many bugs
This commit is contained in:
parent
8a54203796
commit
48e8164e28
|
@ -43,6 +43,7 @@ PHASE1_IMPORTS = '''from typing import (
|
|||
Callable,
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
Set,
|
||||
Tuple,
|
||||
)
|
||||
|
|
|
@ -184,7 +184,7 @@ class CustodyResponse(Container):
|
|||
```python
|
||||
class CustodyKeyReveal(Container):
|
||||
# Index of the validator whose key is being revealed
|
||||
revealer_index: uint64
|
||||
revealer_index: ValidatorIndex
|
||||
# Reveal (masked signature)
|
||||
reveal: Bytes96
|
||||
```
|
||||
|
@ -198,7 +198,7 @@ class EarlyDerivedSecretReveal(Container):
|
|||
# Index of the validator whose key is being revealed
|
||||
revealed_index: uint64
|
||||
# RANDAO epoch of the key that is being revealed
|
||||
epoch: uint64
|
||||
epoch: Epoch
|
||||
# Reveal (masked signature)
|
||||
reveal: Bytes96
|
||||
# Index of the validator who revealed (whistleblower)
|
||||
|
@ -251,7 +251,7 @@ class BeaconBlockBody(Container):
|
|||
### `ceillog2`
|
||||
|
||||
```python
|
||||
def ceillog2(x):
|
||||
def ceillog2(x: int) -> int:
|
||||
return x.bit_length()
|
||||
```
|
||||
|
||||
|
@ -269,7 +269,7 @@ def get_custody_chunk_count(crosslink: Crosslink) -> int:
|
|||
```python
|
||||
def get_custody_chunk_bit(key: Bytes96, chunk: bytes) -> bool:
|
||||
# TODO: Replace with something MPC-friendly, e.g. the Legendre symbol
|
||||
return get_bitfield_bit(hash(key + chunk), 0)
|
||||
return bool(get_bitfield_bit(hash(key + chunk), 0))
|
||||
```
|
||||
|
||||
### `get_chunk_bits_root`
|
||||
|
@ -288,7 +288,7 @@ def get_chunk_bits_root(chunk_bitfield: bytes) -> Bytes32:
|
|||
```python
|
||||
def get_randao_epoch_for_custody_period(period: int, validator_index: ValidatorIndex) -> Epoch:
|
||||
next_period_start = (period + 1) * EPOCHS_PER_CUSTODY_PERIOD - validator_index % EPOCHS_PER_CUSTODY_PERIOD
|
||||
return next_period_start + CUSTODY_PERIOD_TO_RANDAO_PADDING
|
||||
return Epoch(next_period_start + CUSTODY_PERIOD_TO_RANDAO_PADDING)
|
||||
```
|
||||
|
||||
### `get_validators_custody_reveal_period`
|
||||
|
@ -372,7 +372,11 @@ def process_custody_key_reveal(state: BeaconState,
|
|||
|
||||
# Reward Block Preposer
|
||||
proposer_index = get_beacon_proposer_index(state)
|
||||
increase_balance(state, proposer_index, get_base_reward(state, reveal.revealer_index) // MINOR_REWARD_QUOTIENT)
|
||||
increase_balance(
|
||||
state,
|
||||
proposer_index,
|
||||
Gwei(get_base_reward(state, reveal.revealer_index) // MINOR_REWARD_QUOTIENT)
|
||||
)
|
||||
```
|
||||
|
||||
#### Early derived secret reveals
|
||||
|
@ -433,7 +437,7 @@ def process_early_derived_secret_reveal(state: BeaconState,
|
|||
// len(get_active_validator_indices(state, get_current_epoch(state)))
|
||||
// PROPOSER_REWARD_QUOTIENT
|
||||
)
|
||||
penalty = (
|
||||
penalty = Gwei(
|
||||
max_proposer_slot_reward
|
||||
* EARLY_DERIVED_SECRET_REVEAL_SLOT_REWARD_MULTIPLE
|
||||
* (len(state.exposed_derived_secrets[derived_secret_location]) + 1)
|
||||
|
@ -442,8 +446,8 @@ def process_early_derived_secret_reveal(state: BeaconState,
|
|||
# Apply penalty
|
||||
proposer_index = get_beacon_proposer_index(state)
|
||||
whistleblower_index = reveal.masker_index
|
||||
whistleblowing_reward = penalty // WHISTLEBLOWING_REWARD_QUOTIENT
|
||||
proposer_reward = whistleblowing_reward // PROPOSER_REWARD_QUOTIENT
|
||||
whistleblowing_reward = Gwei(penalty // WHISTLEBLOWING_REWARD_QUOTIENT)
|
||||
proposer_reward = Gwei(whistleblowing_reward // PROPOSER_REWARD_QUOTIENT)
|
||||
increase_balance(state, proposer_index, proposer_reward)
|
||||
increase_balance(state, whistleblower_index, whistleblowing_reward - proposer_reward)
|
||||
decrease_balance(state, reveal.revealed_index, penalty)
|
||||
|
@ -512,7 +516,7 @@ def process_bit_challenge(state: BeaconState,
|
|||
pubkey=challenger.pubkey,
|
||||
message_hash=signing_root(challenge),
|
||||
signature=challenge.signature,
|
||||
domain=get_domain(state, get_current_epoch(state), DOMAIN_CUSTODY_BIT_CHALLENGE),
|
||||
domain=get_domain(state, DOMAIN_CUSTODY_BIT_CHALLENGE, get_current_epoch(state)),
|
||||
)
|
||||
assert is_slashable_validator(challenger, get_current_epoch(state))
|
||||
|
||||
|
@ -535,8 +539,8 @@ def process_bit_challenge(state: BeaconState,
|
|||
# Verify the responder is a valid custody key
|
||||
epoch_to_sign = get_randao_epoch_for_custody_period(
|
||||
get_validators_custody_reveal_period(
|
||||
state=state,
|
||||
index=challenge.responder_index,
|
||||
state,
|
||||
challenge.responder_index,
|
||||
epoch=slot_to_epoch(attestation.data.slot)),
|
||||
challenge.responder_index
|
||||
)
|
||||
|
@ -610,7 +614,7 @@ def process_chunk_challenge_response(state: BeaconState,
|
|||
# Verify the chunk matches the crosslink data root
|
||||
assert verify_merkle_branch(
|
||||
leaf=hash_tree_root(response.chunk),
|
||||
branch=response.data_branch,
|
||||
proof=response.data_branch,
|
||||
depth=challenge.depth,
|
||||
index=response.chunk_index,
|
||||
root=challenge.data_root,
|
||||
|
@ -620,7 +624,7 @@ def process_chunk_challenge_response(state: BeaconState,
|
|||
records[records.index(challenge)] = CustodyChunkChallengeRecord()
|
||||
# Reward the proposer
|
||||
proposer_index = get_beacon_proposer_index(state)
|
||||
increase_balance(state, proposer_index, get_base_reward(state, proposer_index) // MINOR_REWARD_QUOTIENT)
|
||||
increase_balance(state, proposer_index, Gwei(get_base_reward(state, proposer_index) // MINOR_REWARD_QUOTIENT))
|
||||
```
|
||||
|
||||
```python
|
||||
|
@ -635,7 +639,7 @@ def process_bit_challenge_response(state: BeaconState,
|
|||
# Verify the chunk matches the crosslink data root
|
||||
assert verify_merkle_branch(
|
||||
leaf=hash_tree_root(response.chunk),
|
||||
branch=response.data_branch,
|
||||
proof=response.data_branch,
|
||||
depth=ceillog2(challenge.chunk_count),
|
||||
index=response.chunk_index,
|
||||
root=challenge.data_root,
|
||||
|
@ -643,7 +647,7 @@ def process_bit_challenge_response(state: BeaconState,
|
|||
# Verify the chunk bit leaf matches the challenge data
|
||||
assert verify_merkle_branch(
|
||||
leaf=response.chunk_bits_leaf,
|
||||
branch=response.chunk_bits_branch,
|
||||
proof=response.chunk_bits_branch,
|
||||
depth=ceillog2(challenge.chunk_count) >> 8,
|
||||
index=response.chunk_index // 256,
|
||||
root=challenge.chunk_bits_merkle_root
|
||||
|
@ -671,8 +675,8 @@ Run `process_reveal_deadlines(state)` immediately after `process_registry_update
|
|||
def process_reveal_deadlines(state: BeaconState) -> None:
|
||||
for index, validator in enumerate(state.validator_registry):
|
||||
deadline = validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD)
|
||||
if get_validators_custody_reveal_period(state, index) > deadline:
|
||||
slash_validator(state, index)
|
||||
if get_validators_custody_reveal_period(state, ValidatorIndex(index)) > deadline:
|
||||
slash_validator(state, ValidatorIndex(index))
|
||||
```
|
||||
|
||||
Run `process_challenge_deadlines(state)` immediately after `process_reveal_deadlines(state)`:
|
||||
|
@ -682,17 +686,17 @@ Run `process_challenge_deadlines(state)` immediately after `process_reveal_deadl
|
|||
process_challenge_deadlines(state)
|
||||
# end insert @process_challenge_deadlines
|
||||
def process_challenge_deadlines(state: BeaconState) -> None:
|
||||
for challenge in state.custody_chunk_challenge_records:
|
||||
if get_current_epoch(state) > challenge.inclusion_epoch + CUSTODY_RESPONSE_DEADLINE:
|
||||
slash_validator(state, challenge.responder_index, challenge.challenger_index)
|
||||
records = state.custody_chunk_challenge_records
|
||||
records[records.index(challenge)] = CustodyChunkChallengeRecord()
|
||||
for custody_chunk_challenge in state.custody_chunk_challenge_records:
|
||||
if get_current_epoch(state) > custody_chunk_challenge.inclusion_epoch + CUSTODY_RESPONSE_DEADLINE:
|
||||
slash_validator(state, custody_chunk_challenge.responder_index, custody_chunk_challenge.challenger_index)
|
||||
records = state.custody_chunk_challenge
|
||||
records[records.index(custody_chunk_challenge)] = CustodyChunkChallengeRecord()
|
||||
|
||||
for challenge in state.custody_bit_challenge_records:
|
||||
if get_current_epoch(state) > challenge.inclusion_epoch + CUSTODY_RESPONSE_DEADLINE:
|
||||
slash_validator(state, challenge.responder_index, challenge.challenger_index)
|
||||
for custody_bit_challenge in state.custody_bit_challenge_records:
|
||||
if get_current_epoch(state) > custody_bit_challenge.inclusion_epoch + CUSTODY_RESPONSE_DEADLINE:
|
||||
slash_validator(state, custody_bit_challenge.responder_index, custody_bit_challenge.challenger_index)
|
||||
records = state.custody_bit_challenge_records
|
||||
records[records.index(challenge)] = CustodyBitChallengeRecord()
|
||||
records[records.index(custody_bit_challenge)] = CustodyBitChallengeRecord()
|
||||
```
|
||||
|
||||
Append this to `process_final_updates(state)`:
|
||||
|
@ -713,5 +717,5 @@ def after_process_final_updates(state: BeaconState) -> None:
|
|||
for index, validator in enumerate(state.validator_registry):
|
||||
if index not in validator_indices_in_records:
|
||||
if validator.exit_epoch != FAR_FUTURE_EPOCH and validator.withdrawable_epoch == FAR_FUTURE_EPOCH:
|
||||
validator.withdrawable_epoch = validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
||||
validator.withdrawable_epoch = Epoch(validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
|
||||
```
|
||||
|
|
|
@ -79,8 +79,8 @@ class ShardBlockBody(Container):
|
|||
```python
|
||||
class ShardAttestation(Container):
|
||||
class data(Container):
|
||||
slot: uint64
|
||||
shard: uint64
|
||||
slot: Slot
|
||||
shard: Shard
|
||||
shard_block_root: Bytes32
|
||||
aggregation_bitfield: bytes
|
||||
aggregate_signature: Bytes96
|
||||
|
@ -90,8 +90,8 @@ class ShardAttestation(Container):
|
|||
|
||||
```python
|
||||
class ShardBlock(Container):
|
||||
slot: uint64
|
||||
shard: uint64
|
||||
slot: Slot
|
||||
shard: Shard
|
||||
beacon_chain_root: Bytes32
|
||||
parent_root: Bytes32
|
||||
data: ShardBlockBody
|
||||
|
@ -104,8 +104,8 @@ class ShardBlock(Container):
|
|||
|
||||
```python
|
||||
class ShardBlockHeader(Container):
|
||||
slot: uint64
|
||||
shard: uint64
|
||||
slot: Slot
|
||||
shard: Shard
|
||||
beacon_chain_root: Bytes32
|
||||
parent_root: Bytes32
|
||||
body_root: Bytes32
|
||||
|
@ -138,8 +138,8 @@ def get_period_committee(state: BeaconState,
|
|||
### `get_switchover_epoch`
|
||||
|
||||
```python
|
||||
def get_switchover_epoch(state: BeaconState, epoch: Epoch, index: ValidatorIndex):
|
||||
earlier_start_epoch = epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD * 2
|
||||
def get_switchover_epoch(state: BeaconState, epoch: Epoch, index: ValidatorIndex) -> int:
|
||||
earlier_start_epoch = Epoch(epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD * 2)
|
||||
return (bytes_to_int(hash(generate_seed(state, earlier_start_epoch) + int_to_bytes(index, length=3)[0:8]))
|
||||
% PERSISTENT_COMMITTEE_PERIOD)
|
||||
```
|
||||
|
@ -154,19 +154,19 @@ def get_persistent_committee(state: BeaconState,
|
|||
Return the persistent committee for the given ``shard`` at the given ``slot``.
|
||||
"""
|
||||
epoch = slot_to_epoch(slot)
|
||||
earlier_start_epoch = epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD * 2
|
||||
later_start_epoch = epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD
|
||||
earlier_start_epoch = Epoch(epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD * 2)
|
||||
later_start_epoch = Epoch(epoch - (epoch % PERSISTENT_COMMITTEE_PERIOD) - PERSISTENT_COMMITTEE_PERIOD)
|
||||
|
||||
committee_count = max(
|
||||
len(get_active_validator_indices(state.validator_registry, earlier_start_epoch)) //
|
||||
len(get_active_validator_indices(state, earlier_start_epoch)) //
|
||||
(SHARD_COUNT * TARGET_COMMITTEE_SIZE),
|
||||
len(get_active_validator_indices(state.validator_registry, later_start_epoch)) //
|
||||
len(get_active_validator_indices(state, later_start_epoch)) //
|
||||
(SHARD_COUNT * TARGET_COMMITTEE_SIZE),
|
||||
) + 1
|
||||
|
||||
index = slot % committee_count
|
||||
earlier_committee = get_period_committee(state, shard, earlier_start_epoch, index, committee_count)
|
||||
later_committee = get_period_committee(state, shard, later_start_epoch, index, committee_count)
|
||||
earlier_committee = get_period_committee(state, earlier_start_epoch, shard, index, committee_count)
|
||||
later_committee = get_period_committee(state, later_start_epoch, shard, index, committee_count)
|
||||
|
||||
# Take not-yet-cycled-out validators from earlier committee and already-cycled-in validators from
|
||||
# later committee; return a sorted list of the union of the two, deduplicated
|
||||
|
@ -181,7 +181,7 @@ def get_persistent_committee(state: BeaconState,
|
|||
```python
|
||||
def get_shard_proposer_index(state: BeaconState,
|
||||
shard: Shard,
|
||||
slot: Slot) -> ValidatorIndex:
|
||||
slot: Slot) -> Optional[ValidatorIndex]:
|
||||
# Randomly shift persistent committee
|
||||
persistent_committee = get_persistent_committee(state, shard, slot)
|
||||
seed = hash(state.current_shuffling_seed + int_to_bytes(shard, length=8) + int_to_bytes(slot, length=8))
|
||||
|
@ -231,7 +231,7 @@ def verify_shard_attestation_signature(state: BeaconState,
|
|||
pubkey=bls_aggregate_pubkeys(pubkeys),
|
||||
message_hash=data.shard_block_root,
|
||||
signature=attestation.aggregate_signature,
|
||||
domain=get_domain(state, slot_to_epoch(data.slot), DOMAIN_SHARD_ATTESTER)
|
||||
domain=get_domain(state, DOMAIN_SHARD_ATTESTER, slot_to_epoch(data.slot))
|
||||
)
|
||||
```
|
||||
|
||||
|
@ -328,7 +328,7 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock],
|
|||
pubkey=beacon_state.validator_registry[proposer_index].pubkey,
|
||||
message_hash=signing_root(block),
|
||||
signature=candidate.signature,
|
||||
domain=get_domain(beacon_state, slot_to_epoch(candidate.slot), DOMAIN_SHARD_PROPOSER),
|
||||
domain=get_domain(beacon_state, DOMAIN_SHARD_PROPOSER, slot_to_epoch(candidate.slot)),
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
Loading…
Reference in New Issue