mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-01-12 11:44:41 +00:00
get_attesting_indices set instead of sorted (#1225)
This commit is contained in:
parent
2739767a71
commit
dcb0244a4f
@ -866,13 +866,13 @@ def get_crosslink_committee(state: BeaconState, epoch: Epoch, shard: Shard) -> S
|
||||
### `get_attesting_indices`
|
||||
|
||||
```python
|
||||
def get_attesting_indices(state: BeaconState, data: AttestationData, bitfield: bytes) -> Sequence[ValidatorIndex]:
|
||||
def get_attesting_indices(state: BeaconState, data: AttestationData, bitfield: bytes) -> Set[ValidatorIndex]:
|
||||
"""
|
||||
Return the sorted attesting indices corresponding to ``data`` and ``bitfield``.
|
||||
Return the set of attesting indices corresponding to ``data`` and ``bitfield``.
|
||||
"""
|
||||
committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard)
|
||||
assert verify_bitfield(bitfield, len(committee))
|
||||
return sorted([index for i, index in enumerate(committee) if get_bitfield_bit(bitfield, i) == 0b1])
|
||||
return set(index for i, index in enumerate(committee) if get_bitfield_bit(bitfield, i) == 0b1)
|
||||
```
|
||||
|
||||
### `int_to_bytes`
|
||||
@ -950,12 +950,12 @@ def convert_to_indexed(state: BeaconState, attestation: Attestation) -> IndexedA
|
||||
"""
|
||||
attesting_indices = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield)
|
||||
custody_bit_1_indices = get_attesting_indices(state, attestation.data, attestation.custody_bitfield)
|
||||
assert set(custody_bit_1_indices).issubset(attesting_indices)
|
||||
custody_bit_0_indices = [index for index in attesting_indices if index not in custody_bit_1_indices]
|
||||
assert custody_bit_1_indices.issubset(attesting_indices)
|
||||
custody_bit_0_indices = attesting_indices.difference(custody_bit_1_indices)
|
||||
|
||||
return IndexedAttestation(
|
||||
custody_bit_0_indices=custody_bit_0_indices,
|
||||
custody_bit_1_indices=custody_bit_1_indices,
|
||||
custody_bit_0_indices=sorted(custody_bit_0_indices),
|
||||
custody_bit_1_indices=sorted(custody_bit_1_indices),
|
||||
data=attestation.data,
|
||||
signature=attestation.signature,
|
||||
)
|
||||
|
@ -36,7 +36,7 @@
|
||||
- [`get_custody_chunk_bit`](#get_custody_chunk_bit)
|
||||
- [`get_chunk_bits_root`](#get_chunk_bits_root)
|
||||
- [`get_randao_epoch_for_custody_period`](#get_randao_epoch_for_custody_period)
|
||||
- [`get_validators_custody_reveal_period`](#get_validators_custody_reveal_period)
|
||||
- [`get_reveal_period`](#get_reveal_period)
|
||||
- [`replace_empty_or_append`](#replace_empty_or_append)
|
||||
- [Per-block processing](#per-block-processing)
|
||||
- [Operations](#operations)
|
||||
@ -224,7 +224,7 @@ Add the following fields to the end of the specified container objects. Fields w
|
||||
class Validator(Container):
|
||||
# next_custody_reveal_period is initialised to the custody period
|
||||
# (of the particular validator) in which the validator is activated
|
||||
# = get_validators_custody_reveal_period(...)
|
||||
# = get_reveal_period(...)
|
||||
next_custody_reveal_period: uint64
|
||||
max_reveal_lateness: uint64
|
||||
```
|
||||
@ -299,17 +299,12 @@ def get_randao_epoch_for_custody_period(period: int, validator_index: ValidatorI
|
||||
return Epoch(next_period_start + CUSTODY_PERIOD_TO_RANDAO_PADDING)
|
||||
```
|
||||
|
||||
### `get_validators_custody_reveal_period`
|
||||
### `get_reveal_period`
|
||||
|
||||
```python
|
||||
def get_validators_custody_reveal_period(state: BeaconState,
|
||||
validator_index: ValidatorIndex,
|
||||
epoch: Epoch=None) -> int:
|
||||
def get_reveal_period(state: BeaconState, validator_index: ValidatorIndex, epoch: Epoch=None) -> int:
|
||||
'''
|
||||
This function returns the reveal period for a given validator.
|
||||
If no epoch is supplied, the current epoch is assumed.
|
||||
Note: This function implicitly requires that validators are not removed from the
|
||||
validator set in fewer than EPOCHS_PER_CUSTODY_PERIOD epochs
|
||||
Return the reveal period for a given validator.
|
||||
'''
|
||||
epoch = get_current_epoch(state) if epoch is None else epoch
|
||||
return (epoch + validator_index % EPOCHS_PER_CUSTODY_PERIOD) // EPOCHS_PER_CUSTODY_PERIOD
|
||||
@ -340,17 +335,15 @@ Verify that `len(block.body.custody_key_reveals) <= MAX_CUSTODY_KEY_REVEALS`.
|
||||
For each `reveal` in `block.body.custody_key_reveals`, run the following function:
|
||||
|
||||
```python
|
||||
def process_custody_key_reveal(state: BeaconState,
|
||||
reveal: CustodyKeyReveal) -> None:
|
||||
def process_custody_key_reveal(state: BeaconState, reveal: CustodyKeyReveal) -> None:
|
||||
"""
|
||||
Process ``CustodyKeyReveal`` operation.
|
||||
Note that this function mutates ``state``.
|
||||
"""
|
||||
|
||||
revealer = state.validators[reveal.revealer_index]
|
||||
epoch_to_sign = get_randao_epoch_for_custody_period(revealer.next_custody_reveal_period, reveal.revealed_index)
|
||||
|
||||
assert revealer.next_custody_reveal_period < get_validators_custody_reveal_period(state, reveal.revealed_index)
|
||||
assert revealer.next_custody_reveal_period < get_reveal_period(state, reveal.revealed_index)
|
||||
|
||||
# Revealed validator is active or exited, but not withdrawn
|
||||
assert is_slashable_validator(revealer, get_current_epoch(state))
|
||||
@ -368,11 +361,11 @@ def process_custody_key_reveal(state: BeaconState,
|
||||
)
|
||||
|
||||
# Decrement max reveal lateness if response is timely
|
||||
if revealer.next_custody_reveal_period == get_validators_custody_reveal_period(state, reveal.revealer_index) - 2:
|
||||
if revealer.next_custody_reveal_period == get_reveal_period(state, reveal.revealer_index) - 2:
|
||||
revealer.max_reveal_lateness -= MAX_REVEAL_LATENESS_DECREMENT
|
||||
revealer.max_reveal_lateness = max(
|
||||
revealer.max_reveal_lateness,
|
||||
get_validators_custody_reveal_period(state, reveal.revealed_index) - revealer.next_custody_reveal_period
|
||||
get_reveal_period(state, reveal.revealed_index) - revealer.next_custody_reveal_period
|
||||
)
|
||||
|
||||
# Process reveal
|
||||
@ -394,13 +387,11 @@ Verify that `len(block.body.early_derived_secret_reveals) <= MAX_EARLY_DERIVED_S
|
||||
For each `reveal` in `block.body.early_derived_secret_reveals`, run the following function:
|
||||
|
||||
```python
|
||||
def process_early_derived_secret_reveal(state: BeaconState,
|
||||
reveal: EarlyDerivedSecretReveal) -> None:
|
||||
def process_early_derived_secret_reveal(state: BeaconState, reveal: EarlyDerivedSecretReveal) -> None:
|
||||
"""
|
||||
Process ``EarlyDerivedSecretReveal`` operation.
|
||||
Note that this function mutates ``state``.
|
||||
"""
|
||||
|
||||
revealed_validator = state.validators[reveal.revealed_index]
|
||||
derived_secret_location = reveal.epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS
|
||||
|
||||
@ -470,8 +461,7 @@ Verify that `len(block.body.custody_chunk_challenges) <= MAX_CUSTODY_CHUNK_CHALL
|
||||
For each `challenge` in `block.body.custody_chunk_challenges`, run the following function:
|
||||
|
||||
```python
|
||||
def process_chunk_challenge(state: BeaconState,
|
||||
challenge: CustodyChunkChallenge) -> None:
|
||||
def process_chunk_challenge(state: BeaconState, challenge: CustodyChunkChallenge) -> None:
|
||||
# Verify the attestation
|
||||
validate_indexed_attestation(state, convert_to_indexed(state, challenge.attestation))
|
||||
# Verify it is not too late to challenge
|
||||
@ -514,59 +504,41 @@ Verify that `len(block.body.custody_bit_challenges) <= MAX_CUSTODY_BIT_CHALLENGE
|
||||
For each `challenge` in `block.body.custody_bit_challenges`, run the following function:
|
||||
|
||||
```python
|
||||
def process_bit_challenge(state: BeaconState,
|
||||
challenge: CustodyBitChallenge) -> None:
|
||||
def process_bit_challenge(state: BeaconState, challenge: CustodyBitChallenge) -> None:
|
||||
attestation = challenge.attestation
|
||||
epoch = slot_to_epoch(attestation.data.slot)
|
||||
shard = attestation.data.crosslink.shard
|
||||
|
||||
# Verify challenge signature
|
||||
challenger = state.validators[challenge.challenger_index]
|
||||
assert bls_verify(
|
||||
pubkey=challenger.pubkey,
|
||||
message_hash=signing_root(challenge),
|
||||
signature=challenge.signature,
|
||||
domain=get_domain(state, DOMAIN_CUSTODY_BIT_CHALLENGE, get_current_epoch(state)),
|
||||
)
|
||||
domain = get_domain(state, DOMAIN_CUSTODY_BIT_CHALLENGE, get_current_epoch(state))
|
||||
assert bls_verify(challenger.pubkey, signing_root(challenge), challenge.signature, domain)
|
||||
# Verify challenger is slashable
|
||||
assert is_slashable_validator(challenger, get_current_epoch(state))
|
||||
|
||||
# Verify the attestation
|
||||
attestation = challenge.attestation
|
||||
# Verify attestation
|
||||
validate_indexed_attestation(state, convert_to_indexed(state, attestation))
|
||||
# Verify the attestation is eligible for challenging
|
||||
# Verify attestation is eligible for challenging
|
||||
responder = state.validators[challenge.responder_index]
|
||||
assert (slot_to_epoch(attestation.data.slot) + responder.max_reveal_lateness <=
|
||||
get_validators_custody_reveal_period(state, challenge.responder_index))
|
||||
|
||||
# Verify the responder participated in the attestation
|
||||
assert epoch + responder.max_reveal_lateness <= get_reveal_period(state, challenge.responder_index)
|
||||
# Verify responder participated in the attestation
|
||||
attesters = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield)
|
||||
assert challenge.responder_index in attesters
|
||||
|
||||
# A validator can be the challenger for at most one challenge at a time
|
||||
# Verifier challenger is not already challenging
|
||||
for record in state.custody_bit_challenge_records:
|
||||
assert record.challenger_index != challenge.challenger_index
|
||||
|
||||
# Verify the responder is a valid custody key
|
||||
# Verify the responder custody key
|
||||
epoch_to_sign = get_randao_epoch_for_custody_period(
|
||||
get_validators_custody_reveal_period(
|
||||
state,
|
||||
challenge.responder_index,
|
||||
epoch=slot_to_epoch(attestation.data.slot)),
|
||||
challenge.responder_index
|
||||
get_reveal_period(state, challenge.responder_index, epoch),
|
||||
challenge.responder_index,
|
||||
)
|
||||
assert bls_verify(
|
||||
pubkey=responder.pubkey,
|
||||
message_hash=hash_tree_root(epoch_to_sign),
|
||||
signature=challenge.responder_key,
|
||||
domain=get_domain(
|
||||
state=state,
|
||||
domain_type=DOMAIN_RANDAO,
|
||||
message_epoch=epoch_to_sign,
|
||||
),
|
||||
)
|
||||
|
||||
domain = get_domain(state, DOMAIN_RANDAO, epoch_to_sign)
|
||||
assert bls_verify(responder.pubkey, hash_tree_root(epoch_to_sign), challenge.responder_key, domain)
|
||||
# Verify the chunk count
|
||||
chunk_count = get_custody_chunk_count(attestation.data.crosslink)
|
||||
assert verify_bitfield(challenge.chunk_bits, chunk_count)
|
||||
# Verify the first bit of the hash of the chunk bits does not equal the custody bit
|
||||
custody_bit = get_bitfield_bit(attestation.custody_bitfield, attesters.index(challenge.responder_index))
|
||||
committee = get_crosslink_committee(state, epoch, shard)
|
||||
custody_bit = get_bitfield_bit(attestation.custody_bitfield, committee.index(challenge.responder_index))
|
||||
assert custody_bit != get_bitfield_bit(get_chunk_bits_root(challenge.chunk_bits), 0)
|
||||
# Add new bit challenge record
|
||||
new_record = CustodyBitChallengeRecord(
|
||||
@ -581,7 +553,6 @@ def process_bit_challenge(state: BeaconState,
|
||||
)
|
||||
replace_empty_or_append(state.custody_bit_challenge_records, new_record)
|
||||
state.custody_challenge_index += 1
|
||||
|
||||
# Postpone responder withdrawability
|
||||
responder.withdrawable_epoch = FAR_FUTURE_EPOCH
|
||||
```
|
||||
@ -593,8 +564,7 @@ Verify that `len(block.body.custody_responses) <= MAX_CUSTODY_RESPONSES`.
|
||||
For each `response` in `block.body.custody_responses`, run the following function:
|
||||
|
||||
```python
|
||||
def process_custody_response(state: BeaconState,
|
||||
response: CustodyResponse) -> None:
|
||||
def process_custody_response(state: BeaconState, response: CustodyResponse) -> None:
|
||||
chunk_challenge = next((record for record in state.custody_chunk_challenge_records
|
||||
if record.challenge_index == response.challenge_index), None)
|
||||
if chunk_challenge is not None:
|
||||
@ -682,7 +652,7 @@ Run `process_reveal_deadlines(state)` immediately after `process_registry_update
|
||||
def process_reveal_deadlines(state: BeaconState) -> None:
|
||||
for index, validator in enumerate(state.validators):
|
||||
deadline = validator.next_custody_reveal_period + (CUSTODY_RESPONSE_DEADLINE // EPOCHS_PER_CUSTODY_PERIOD)
|
||||
if get_validators_custody_reveal_period(state, ValidatorIndex(index)) > deadline:
|
||||
if get_reveal_period(state, ValidatorIndex(index)) > deadline:
|
||||
slash_validator(state, ValidatorIndex(index))
|
||||
```
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user