add previous and current crosslinks

This commit is contained in:
Danny Ryan 2019-04-02 16:00:36 +11:00
parent f5c5c166af
commit 529cf4223e
No known key found for this signature in database
GPG Key ID: 2765A792E42CE07A
6 changed files with 31 additions and 27 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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