Merge branch 'dev' into SyncCommitteeSignature-to-SyncCommitteeMessage

This commit is contained in:
Hsiao-Wei Wang 2021-06-03 22:13:53 +08:00
commit 45d554aee8
No known key found for this signature in database
GPG Key ID: 1111A8A81778319E
4 changed files with 35 additions and 35 deletions

View File

@ -137,8 +137,8 @@ This patch updates a few configuration values to move penalty parameters closer
| Name | Value | Description | | Name | Value | Description |
| - | - | - | | - | - | - |
| `INACTIVITY_SCORE_BIAS` | `uint64(4)` | score points per inactive epoch | | `INACTIVITY_SCORE_BIAS` | `uint64(2**2)` (= 4) | score points per inactive epoch |
| `INACTIVITY_SCORE_RECOVERY_RATE` | `uint64(16)` | score points per recovering epoch | | `INACTIVITY_SCORE_RECOVERY_RATE` | `uint64(2**4)` (= 16) | score points per leak-free epoch |
## Containers ## Containers
@ -157,8 +157,7 @@ class BeaconBlockBody(Container):
attestations: List[Attestation, MAX_ATTESTATIONS] attestations: List[Attestation, MAX_ATTESTATIONS]
deposits: List[Deposit, MAX_DEPOSITS] deposits: List[Deposit, MAX_DEPOSITS]
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
# [New in Altair] sync_aggregate: SyncAggregate # [New in Altair]
sync_aggregate: SyncAggregate
``` ```
#### `BeaconState` #### `BeaconState`
@ -266,10 +265,7 @@ def has_flag(flags: ParticipationFlags, flag_index: int) -> bool:
```python ```python
def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]: def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorIndex]:
""" """
Return the sequence of sync committee indices (which may include duplicate indices) Return the sync committee indices, with possible duplicates, for the next sync committee.
for the next sync committee, given a ``state`` at a sync committee period boundary.
Note: Committee can contain duplicate indices for small validator sets (< SYNC_COMMITTEE_SIZE + 128)
""" """
epoch = Epoch(get_current_epoch(state) + 1) epoch = Epoch(get_current_epoch(state) + 1)
@ -292,21 +288,12 @@ def get_next_sync_committee_indices(state: BeaconState) -> Sequence[ValidatorInd
#### `get_next_sync_committee` #### `get_next_sync_committee`
*Note*: The function `get_next_sync_committee` should only be called at sync committee period boundaries.
```python ```python
def get_next_sync_committee(state: BeaconState) -> SyncCommittee: def get_next_sync_committee(state: BeaconState) -> SyncCommittee:
""" """
Return the *next* sync committee for a given ``state``. Return the next sync committee, with possible pubkey duplicates.
``SyncCommittee`` contains an aggregate pubkey that enables
resource-constrained clients to save some computation when verifying
the sync committee's signature.
``SyncCommittee`` can also contain duplicate pubkeys, when ``get_next_sync_committee_indices``
returns duplicate indices. Implementations must take care when handling
optimizations relating to aggregation and verification in the presence of duplicates.
Note: This function should only be called at sync committee period boundaries by ``process_sync_committee_updates``
as ``get_next_sync_committee_indices`` is not stable within a given period.
""" """
indices = get_next_sync_committee_indices(state) indices = get_next_sync_committee_indices(state)
pubkeys = [state.validators[index].pubkey for index in indices] pubkeys = [state.validators[index].pubkey for index in indices]
@ -325,14 +312,12 @@ def get_base_reward_per_increment(state: BeaconState) -> Gwei:
*Note*: The function `get_base_reward` is modified with the removal of `BASE_REWARDS_PER_EPOCH` and the use of increment based accounting. *Note*: The function `get_base_reward` is modified with the removal of `BASE_REWARDS_PER_EPOCH` and the use of increment based accounting.
*Note*: On average an optimally performing validator earns one base reward per epoch.
```python ```python
def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei: def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
""" """
Return the base reward for the validator defined by ``index`` with respect to the current ``state``. Return the base reward for the validator defined by ``index`` with respect to the current ``state``.
Note: An optimally performing validator can earn one base reward per epoch over a long time horizon.
This takes into account both per-epoch (e.g. attestation) and intermittent duties (e.g. block proposal
and sync committees).
""" """
increments = state.validators[index].effective_balance // EFFECTIVE_BALANCE_INCREMENT increments = state.validators[index].effective_balance // EFFECTIVE_BALANCE_INCREMENT
return Gwei(increments * get_base_reward_per_increment(state)) return Gwei(increments * get_base_reward_per_increment(state))
@ -559,6 +544,8 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
#### Sync committee processing #### Sync committee processing
*Note*: The function `process_sync_committee` is new.
```python ```python
def process_sync_committee(state: BeaconState, aggregate: SyncAggregate) -> None: def process_sync_committee(state: BeaconState, aggregate: SyncAggregate) -> None:
# Verify sync committee aggregate signature signing over the previous slot block root # Verify sync committee aggregate signature signing over the previous slot block root
@ -627,17 +614,17 @@ def process_justification_and_finalization(state: BeaconState) -> None:
```python ```python
def process_inactivity_updates(state: BeaconState) -> None: def process_inactivity_updates(state: BeaconState) -> None:
# Score updates based on previous epoch participation, skip genesis epoch # Skip the genesis epoch as score updates are based on the previous epoch participation
if get_current_epoch(state) == GENESIS_EPOCH: if get_current_epoch(state) == GENESIS_EPOCH:
return return
for index in get_eligible_validator_indices(state): for index in get_eligible_validator_indices(state):
# Increase inactivity score of inactive validators # Increase the inactivity score of inactive validators
if index in get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state)): if index in get_unslashed_participating_indices(state, TIMELY_TARGET_FLAG_INDEX, get_previous_epoch(state)):
state.inactivity_scores[index] -= min(1, state.inactivity_scores[index]) state.inactivity_scores[index] -= min(1, state.inactivity_scores[index])
else: else:
state.inactivity_scores[index] += INACTIVITY_SCORE_BIAS state.inactivity_scores[index] += INACTIVITY_SCORE_BIAS
# Decrease the score of all validators for forgiveness when not during a leak # Decrease the inactivity score of all eligible validators during a leak-free epoch
if not is_in_inactivity_leak(state): if not is_in_inactivity_leak(state):
state.inactivity_scores[index] -= min(INACTIVITY_SCORE_RECOVERY_RATE, state.inactivity_scores[index]) state.inactivity_scores[index] -= min(INACTIVITY_SCORE_RECOVERY_RATE, state.inactivity_scores[index])
``` ```

View File

@ -282,7 +282,12 @@ def get_sync_committee_message(state: BeaconState,
signing_root = compute_signing_root(block_root, domain) signing_root = compute_signing_root(block_root, domain)
signature = bls.Sign(privkey, signing_root) signature = bls.Sign(privkey, signing_root)
return SyncCommitteeMessage(slot=state.slot, validator_index=validator_index, signature=signature) return SyncCommitteeMessage(
slot=state.slot,
beacon_block_root=block_root,
validator_index=validator_index,
signature=signature,
)
``` ```
##### Broadcast sync committee message ##### Broadcast sync committee message

View File

@ -1,7 +1,7 @@
import random import random
from eth2spec.test.context import fork_transition_test from eth2spec.test.context import fork_transition_test
from eth2spec.test.helpers.constants import PHASE0, ALTAIR from eth2spec.test.helpers.constants import PHASE0, ALTAIR
from eth2spec.test.helpers.state import state_transition_and_sign_block, next_slot, next_epoch_via_block from eth2spec.test.helpers.state import state_transition_and_sign_block, next_slot, next_epoch_via_signed_block
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, build_empty_block, sign_block from eth2spec.test.helpers.block import build_empty_block_for_next_slot, build_empty_block, sign_block
from eth2spec.test.helpers.attestations import next_slots_with_attestations from eth2spec.test.helpers.attestations import next_slots_with_attestations
@ -261,12 +261,12 @@ def _run_transition_test_with_attestations(state,
assert current_epoch == spec.GENESIS_EPOCH assert current_epoch == spec.GENESIS_EPOCH
# skip genesis epoch to avoid dealing with some edge cases... # skip genesis epoch to avoid dealing with some edge cases...
block = next_epoch_via_block(spec, state) block = next_epoch_via_signed_block(spec, state)
# regular state transition until fork: # regular state transition until fork:
fill_cur_epoch = False fill_cur_epoch = False
fill_prev_epoch = True fill_prev_epoch = True
blocks = [pre_tag(sign_block(spec, state, block))] blocks = [pre_tag(block)]
current_epoch = spec.get_current_epoch(state) current_epoch = spec.get_current_epoch(state)
for _ in range(current_epoch, fork_epoch - 1): for _ in range(current_epoch, fork_epoch - 1):
_, blocks_in_epoch, state = next_slots_with_attestations( _, blocks_in_epoch, state = next_slots_with_attestations(
@ -414,8 +414,8 @@ def test_transition_with_no_attestations_until_after_fork(state, fork_epoch, spe
# continue regular state transition but add attestations # continue regular state transition but add attestations
# for enough epochs to finalize the ``fork_epoch`` # for enough epochs to finalize the ``fork_epoch``
block = next_epoch_via_block(post_spec, state) block = next_epoch_via_signed_block(post_spec, state)
blocks.append(post_tag(sign_block(post_spec, state, block))) blocks.append(post_tag(block))
for _ in range(4): for _ in range(4):
_, blocks_in_epoch, state = next_slots_with_attestations( _, blocks_in_epoch, state = next_slots_with_attestations(
post_spec, post_spec,

View File

@ -58,11 +58,19 @@ def next_epoch(spec, state):
spec.process_slots(state, slot) spec.process_slots(state, slot)
def next_epoch_via_block(spec, state): def next_epoch_via_block(spec, state, insert_state_root=False):
""" """
Transition to the start slot of the next epoch via a full block transition Transition to the start slot of the next epoch via a full block transition
""" """
return apply_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH - state.slot % spec.SLOTS_PER_EPOCH) block = apply_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH - state.slot % spec.SLOTS_PER_EPOCH)
if insert_state_root:
block.state_root = state.hash_tree_root()
return block
def next_epoch_via_signed_block(spec, state):
block = next_epoch_via_block(spec, state, insert_state_root=True)
return sign_block(spec, state, block)
def get_state_root(spec, state, slot) -> bytes: def get_state_root(spec, state, slot) -> bytes: