add previous and current crosslinks
This commit is contained in:
parent
f5c5c166af
commit
529cf4223e
|
@ -610,7 +610,8 @@ The types are defined topologically to aid in facilitating an executable version
|
|||
'finalized_root': 'bytes32',
|
||||
|
||||
# Recent state
|
||||
'latest_crosslinks': [Crosslink, SHARD_COUNT],
|
||||
'current_crosslinks': [Crosslink, SHARD_COUNT],
|
||||
'previous_crosslinks': [Crosslink, SHARD_COUNT],
|
||||
'latest_block_roots': ['bytes32', SLOTS_PER_HISTORICAL_ROOT],
|
||||
'latest_state_roots': ['bytes32', SLOTS_PER_HISTORICAL_ROOT],
|
||||
'latest_active_index_roots': ['bytes32', LATEST_ACTIVE_INDEX_ROOTS_LENGTH],
|
||||
|
@ -1554,7 +1555,8 @@ def get_genesis_beacon_state(genesis_validator_deposits: List[Deposit],
|
|||
finalized_root=ZERO_HASH,
|
||||
|
||||
# Recent state
|
||||
latest_crosslinks=Vector([Crosslink(epoch=GENESIS_EPOCH, crosslink_data_root=ZERO_HASH) for _ in range(SHARD_COUNT)]),
|
||||
current_crosslinks=Vector([Crosslink(epoch=GENESIS_EPOCH, crosslink_data_root=ZERO_HASH) for _ in range(SHARD_COUNT)]),
|
||||
previous_crosslinks=Vector([Crosslink(epoch=GENESIS_EPOCH, crosslink_data_root=ZERO_HASH) for _ in range(SHARD_COUNT)]),
|
||||
latest_block_roots=Vector([ZERO_HASH for _ in range(SLOTS_PER_HISTORICAL_ROOT)]),
|
||||
latest_state_roots=Vector([ZERO_HASH for _ in range(SLOTS_PER_HISTORICAL_ROOT)]),
|
||||
latest_active_index_roots=Vector([ZERO_HASH for _ in range(LATEST_ACTIVE_INDEX_ROOTS_LENGTH)]),
|
||||
|
@ -1758,10 +1760,14 @@ def get_previous_epoch_matching_head_attestations(state: BeaconState) -> List[Pe
|
|||
**Note**: Total balances computed for the previous epoch might be marginally different than the actual total balances during the previous epoch transition. Due to the tight bound on validator churn each epoch and small per-epoch rewards/penalties, the potential balance difference is very low and only marginally affects consensus safety.
|
||||
|
||||
```python
|
||||
def get_winning_root_and_participants(state: BeaconState, shard: Shard) -> Tuple[Bytes32, List[ValidatorIndex]]:
|
||||
def get_winning_root_and_participants(state: BeaconState, slot: Slot, shard: Shard) -> Tuple[Bytes32, List[ValidatorIndex]]:
|
||||
all_attestations = state.current_epoch_attestations + state.previous_epoch_attestations
|
||||
crosslinks = state.current_crosslinks if slot_to_epoch(slot) == get_current_epoch(state) else state.previous_crosslinks
|
||||
|
||||
valid_attestations = [
|
||||
a for a in all_attestations if a.data.previous_crosslink == state.latest_crosslinks[shard]
|
||||
a for a in all_attestations
|
||||
if a.data.previous_crosslink == crosslinks[shard] and
|
||||
a.data.shard == shard and a.data.slot == slot
|
||||
]
|
||||
all_roots = [a.data.crosslink_data_root for a in valid_attestations]
|
||||
|
||||
|
@ -1856,16 +1862,20 @@ def process_crosslinks(state: BeaconState) -> None:
|
|||
current_epoch = get_current_epoch(state)
|
||||
previous_epoch = max(current_epoch - 1, GENESIS_EPOCH)
|
||||
next_epoch = current_epoch + 1
|
||||
next_previous_crosslinks = [crosslink for crosslink in state.current_crosslinks]
|
||||
|
||||
for slot in range(get_epoch_start_slot(previous_epoch), get_epoch_start_slot(next_epoch)):
|
||||
for crosslink_committee, shard in get_crosslink_committees_at_slot(state, slot):
|
||||
winning_root, participants = get_winning_root_and_participants(state, shard)
|
||||
winning_root, participants = get_winning_root_and_participants(state, slot, shard)
|
||||
participating_balance = get_total_balance(state, participants)
|
||||
total_balance = get_total_balance(state, crosslink_committee)
|
||||
if 3 * participating_balance >= 2 * total_balance:
|
||||
state.latest_crosslinks[shard] = Crosslink(
|
||||
epoch=min(slot_to_epoch(slot), state.latest_crosslinks[shard].epoch + MAX_CROSSLINK_EPOCHS),
|
||||
crosslink_data_root=winning_root
|
||||
state.current_crosslinks[shard] = Crosslink(
|
||||
epoch=min(slot_to_epoch(slot), state.current_crosslinks[shard].epoch + MAX_CROSSLINK_EPOCHS),
|
||||
crosslink_data_root=winning_root,
|
||||
)
|
||||
|
||||
state.previous_crosslinks = next_previous_crosslinks
|
||||
```
|
||||
|
||||
#### Eth1 data
|
||||
|
@ -1972,7 +1982,7 @@ def get_crosslink_deltas(state: BeaconState) -> Tuple[List[Gwei], List[Gwei]]:
|
|||
current_epoch_start_slot = get_epoch_start_slot(get_current_epoch(state))
|
||||
for slot in range(previous_epoch_start_slot, current_epoch_start_slot):
|
||||
for crosslink_committee, shard in get_crosslink_committees_at_slot(state, slot):
|
||||
winning_root, participants = get_winning_root_and_participants(state, shard)
|
||||
winning_root, participants = get_winning_root_and_participants(state, slot, shard)
|
||||
participating_balance = get_total_balance(state, participants)
|
||||
total_balance = get_total_balance(state, crosslink_committee)
|
||||
for index in crosslink_committee:
|
||||
|
@ -2327,14 +2337,8 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
|||
|
||||
# Check crosslink data
|
||||
assert attestation.data.crosslink_data_root == ZERO_HASH # [to be removed in phase 1]
|
||||
assert state.latest_crosslinks[attestation.data.shard] in {
|
||||
attestation.data.previous_crosslink, # Case 1: latest crosslink matches previous crosslink
|
||||
Crosslink( # Case 2: latest crosslink matches current crosslink
|
||||
crosslink_data_root=attestation.data.crosslink_data_root,
|
||||
epoch=min(slot_to_epoch(attestation.data.slot),
|
||||
attestation.data.previous_crosslink.epoch + MAX_CROSSLINK_EPOCHS)
|
||||
),
|
||||
}
|
||||
crosslinks = state.current_crosslinks if slot_to_epoch(attestation.data.slot) == get_current_epoch(state) else state.previous_crosslinks
|
||||
assert crosslinks[attestation.data.shard] == attestation.data.previous_crosslink
|
||||
|
||||
# Check signature and bitfields
|
||||
assert verify_indexed_attestation(state, convert_to_indexed(state, attestation))
|
||||
|
|
|
@ -124,7 +124,7 @@ def test_bad_previous_crosslink(state):
|
|||
attestation = get_valid_attestation(state)
|
||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
state.latest_crosslinks[attestation.data.shard].epoch += 10
|
||||
state.current_crosslinks[attestation.data.shard].epoch += 10
|
||||
|
||||
pre_state, post_state = run_attestation_processing(state, attestation, False)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ from tests.phase0.helpers import (
|
|||
get_valid_proposer_slashing,
|
||||
)
|
||||
|
||||
# mark entire file as 'header'
|
||||
# mark entire file as 'proposer_slashings'
|
||||
pytestmark = pytest.mark.proposer_slashings
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@ def overwrite_spec_config(config):
|
|||
if field == "LATEST_RANDAO_MIXES_LENGTH":
|
||||
spec.BeaconState.fields['latest_randao_mixes'][1] = config[field]
|
||||
elif field == "SHARD_COUNT":
|
||||
spec.BeaconState.fields['latest_crosslinks'][1] = config[field]
|
||||
spec.BeaconState.fields['current_crosslinks'][1] = config[field]
|
||||
spec.BeaconState.fields['previous_crosslinks'][1] = config[field]
|
||||
elif field == "SLOTS_PER_HISTORICAL_ROOT":
|
||||
spec.BeaconState.fields['latest_block_roots'][1] = config[field]
|
||||
spec.BeaconState.fields['latest_state_roots'][1] = config[field]
|
||||
|
|
|
@ -95,10 +95,6 @@ def create_genesis_state(num_validators, deposit_data_leaves=None):
|
|||
|
||||
|
||||
def force_registry_change_at_next_epoch(state):
|
||||
# artificially trigger registry update at next epoch transition
|
||||
state.finalized_epoch = get_current_epoch(state) - 1
|
||||
for crosslink in state.latest_crosslinks:
|
||||
crosslink.epoch = state.finalized_epoch
|
||||
state.validator_registry_update_epoch = state.finalized_epoch - 1
|
||||
|
||||
|
||||
|
@ -149,6 +145,7 @@ def build_attestation_data(state, slot, shard):
|
|||
else:
|
||||
justified_block_root = state.current_justified_root
|
||||
|
||||
crosslinks = state.current_crosslinks if slot_to_epoch(slot) == get_current_epoch(state) else state.previous_crosslinks
|
||||
return AttestationData(
|
||||
slot=slot,
|
||||
shard=shard,
|
||||
|
@ -157,7 +154,7 @@ def build_attestation_data(state, slot, shard):
|
|||
source_root=justified_block_root,
|
||||
target_root=epoch_boundary_root,
|
||||
crosslink_data_root=spec.ZERO_HASH,
|
||||
previous_crosslink=deepcopy(state.latest_crosslinks[shard]),
|
||||
previous_crosslink=deepcopy(crosslinks[shard]),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ from build.phase0.spec import (
|
|||
advance_slot,
|
||||
cache_state,
|
||||
set_balance,
|
||||
slot_to_epoch,
|
||||
verify_merkle_branch,
|
||||
hash,
|
||||
)
|
||||
|
@ -254,6 +255,7 @@ def test_voluntary_exit(state):
|
|||
|
||||
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
|
||||
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
pre_state.finalized_epoch = slot_to_epoch(pre_state.slot) - 3
|
||||
# artificially trigger registry update at next epoch transition
|
||||
force_registry_change_at_next_epoch(pre_state)
|
||||
|
||||
|
@ -309,12 +311,12 @@ def test_no_exit_churn_too_long_since_change(state):
|
|||
#
|
||||
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
|
||||
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH
|
||||
# artificially trigger registry update at next epoch transition
|
||||
force_registry_change_at_next_epoch(pre_state)
|
||||
# make epochs since registry update greater than LATEST_SLASHED_EXIT_LENGTH
|
||||
pre_state.validator_registry_update_epoch = (
|
||||
get_current_epoch(pre_state) - spec.LATEST_SLASHED_EXIT_LENGTH
|
||||
)
|
||||
# artificially trigger registry update at next epoch transition
|
||||
force_registry_change_at_next_epoch(pre_state)
|
||||
# set validator to have previously initiated exit
|
||||
pre_state.validator_registry[validator_index].initiated_exit = True
|
||||
|
||||
|
|
Loading…
Reference in New Issue