Merge pull request #1210 from ethereum/checkpoints

Checkpoints in beacon spec
This commit is contained in:
Danny Ryan 2019-06-27 21:26:22 -06:00 committed by GitHub
commit 1a5de80047
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 108 additions and 133 deletions

View File

@ -24,6 +24,7 @@
- [Containers](#containers) - [Containers](#containers)
- [Misc dependencies](#misc-dependencies) - [Misc dependencies](#misc-dependencies)
- [`Fork`](#fork) - [`Fork`](#fork)
- [`Checkpoint`](#checkpoint)
- [`Validator`](#validator) - [`Validator`](#validator)
- [`Crosslink`](#crosslink) - [`Crosslink`](#crosslink)
- [`AttestationData`](#attestationdata) - [`AttestationData`](#attestationdata)
@ -290,6 +291,14 @@ class Fork(Container):
epoch: Epoch # Epoch of latest fork epoch: Epoch # Epoch of latest fork
``` ```
#### `Checkpoint`
```python
class Checkpoint(Container):
epoch: Epoch
root: Hash
```
#### `Validator` #### `Validator`
```python ```python
@ -324,10 +333,8 @@ class AttestationData(Container):
# LMD GHOST vote # LMD GHOST vote
beacon_block_root: Hash beacon_block_root: Hash
# FFG vote # FFG vote
source_epoch: Epoch source: Checkpoint
source_root: Hash target: Checkpoint
target_epoch: Epoch
target_root: Hash
# Crosslink vote # Crosslink vote
crosslink: Crosslink crosslink: Crosslink
``` ```
@ -520,15 +527,11 @@ class BeaconState(Container):
# Crosslinks # Crosslinks
previous_crosslinks: Vector[Crosslink, SHARD_COUNT] # Previous epoch snapshot previous_crosslinks: Vector[Crosslink, SHARD_COUNT] # Previous epoch snapshot
current_crosslinks: Vector[Crosslink, SHARD_COUNT] current_crosslinks: Vector[Crosslink, SHARD_COUNT]
# Justification
previous_justified_epoch: Epoch # Previous epoch snapshot
previous_justified_root: Hash # Previous epoch snapshot
current_justified_epoch: Epoch
current_justified_root: Hash
justification_bitfield: uint64 # Bit set for every recent justified epoch
# Finality # Finality
finalized_epoch: Epoch justification_bitfield: uint64 # Bit set for every recent justified epoch
finalized_root: Hash previous_justified_checkpoint: Checkpoint # Previous epoch snapshot
current_justified_checkpoint: Checkpoint
finalized_checkpoint: Checkpoint
``` ```
## Helper functions ## Helper functions
@ -702,9 +705,9 @@ def get_epoch_start_shard(state: BeaconState, epoch: Epoch) -> Shard:
```python ```python
def get_attestation_data_slot(state: BeaconState, data: AttestationData) -> Slot: def get_attestation_data_slot(state: BeaconState, data: AttestationData) -> Slot:
committee_count = get_epoch_committee_count(state, data.target_epoch) committee_count = get_epoch_committee_count(state, data.target.epoch)
offset = (data.crosslink.shard + SHARD_COUNT - get_epoch_start_shard(state, data.target_epoch)) % SHARD_COUNT offset = (data.crosslink.shard + SHARD_COUNT - get_epoch_start_shard(state, data.target.epoch)) % SHARD_COUNT
return Slot(get_epoch_start_slot(data.target_epoch) + offset // (committee_count // SLOTS_PER_EPOCH)) return Slot(get_epoch_start_slot(data.target.epoch) + offset // (committee_count // SLOTS_PER_EPOCH))
``` ```
### `get_block_root_at_slot` ### `get_block_root_at_slot`
@ -863,13 +866,11 @@ def get_crosslink_committee(state: BeaconState, epoch: Epoch, shard: Shard) -> S
### `get_attesting_indices` ### `get_attesting_indices`
```python ```python
def get_attesting_indices(state: BeaconState, def get_attesting_indices(state: BeaconState, data: AttestationData, bitfield: bytes) -> Sequence[ValidatorIndex]:
attestation_data: AttestationData,
bitfield: bytes) -> Sequence[ValidatorIndex]:
""" """
Return the sorted attesting indices corresponding to ``attestation_data`` and ``bitfield``. Return the sorted attesting indices corresponding to ``data`` and ``bitfield``.
""" """
committee = get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.crosslink.shard) committee = get_crosslink_committee(state, data.target.epoch, data.crosslink.shard)
assert verify_bitfield(bitfield, len(committee)) assert verify_bitfield(bitfield, len(committee))
return sorted([index for i, index in enumerate(committee) if get_bitfield_bit(bitfield, i) == 0b1]) return sorted([index for i, index in enumerate(committee) if get_bitfield_bit(bitfield, i) == 0b1])
``` ```
@ -989,7 +990,7 @@ def validate_indexed_attestation(state: BeaconState, indexed_attestation: Indexe
hash_tree_root(AttestationDataAndCustodyBit(data=indexed_attestation.data, custody_bit=0b1)), hash_tree_root(AttestationDataAndCustodyBit(data=indexed_attestation.data, custody_bit=0b1)),
], ],
signature=indexed_attestation.signature, signature=indexed_attestation.signature,
domain=get_domain(state, DOMAIN_ATTESTATION, indexed_attestation.data.target_epoch), domain=get_domain(state, DOMAIN_ATTESTATION, indexed_attestation.data.target.epoch),
) )
``` ```
@ -1002,9 +1003,9 @@ def is_slashable_attestation_data(data_1: AttestationData, data_2: AttestationDa
""" """
return ( return (
# Double vote # Double vote
(data_1 != data_2 and data_1.target_epoch == data_2.target_epoch) or (data_1 != data_2 and data_1.target.epoch == data_2.target.epoch) or
# Surround vote # Surround vote
(data_1.source_epoch < data_2.source_epoch and data_2.target_epoch < data_1.target_epoch) (data_1.source.epoch < data_2.source.epoch and data_2.target.epoch < data_1.target.epoch)
) )
``` ```
@ -1256,7 +1257,7 @@ def get_total_active_balance(state: BeaconState) -> Gwei:
```python ```python
def get_matching_source_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]: def get_matching_source_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]:
assert epoch in (get_current_epoch(state), get_previous_epoch(state)) assert epoch in (get_previous_epoch(state), get_current_epoch(state))
return state.current_epoch_attestations if epoch == get_current_epoch(state) else state.previous_epoch_attestations return state.current_epoch_attestations if epoch == get_current_epoch(state) else state.previous_epoch_attestations
``` ```
@ -1264,7 +1265,7 @@ def get_matching_source_attestations(state: BeaconState, epoch: Epoch) -> Sequen
def get_matching_target_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]: def get_matching_target_attestations(state: BeaconState, epoch: Epoch) -> Sequence[PendingAttestation]:
return [ return [
a for a in get_matching_source_attestations(state, epoch) a for a in get_matching_source_attestations(state, epoch)
if a.data.target_root == get_block_root(state, epoch) if a.data.target.root == get_block_root(state, epoch)
] ]
``` ```
@ -1316,46 +1317,40 @@ def process_justification_and_finalization(state: BeaconState) -> None:
previous_epoch = get_previous_epoch(state) previous_epoch = get_previous_epoch(state)
current_epoch = get_current_epoch(state) current_epoch = get_current_epoch(state)
old_previous_justified_epoch = state.previous_justified_epoch old_previous_justified_checkpoint = state.previous_justified_checkpoint
old_current_justified_epoch = state.current_justified_epoch old_current_justified_checkpoint = state.current_justified_checkpoint
# Process justifications # Process justifications
state.previous_justified_epoch = state.current_justified_epoch state.previous_justified_checkpoint = state.current_justified_checkpoint
state.previous_justified_root = state.current_justified_root
state.justification_bitfield = (state.justification_bitfield << 1) % 2**64 state.justification_bitfield = (state.justification_bitfield << 1) % 2**64
previous_epoch_matching_target_balance = get_attesting_balance( previous_epoch_matching_target_balance = get_attesting_balance(
state, get_matching_target_attestations(state, previous_epoch) state, get_matching_target_attestations(state, previous_epoch)
) )
if previous_epoch_matching_target_balance * 3 >= get_total_active_balance(state) * 2: if previous_epoch_matching_target_balance * 3 >= get_total_active_balance(state) * 2:
state.current_justified_epoch = previous_epoch state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch,
state.current_justified_root = get_block_root(state, state.current_justified_epoch) root=get_block_root(state, previous_epoch))
state.justification_bitfield |= (1 << 1) state.justification_bitfield |= (1 << 1)
current_epoch_matching_target_balance = get_attesting_balance( current_epoch_matching_target_balance = get_attesting_balance(
state, get_matching_target_attestations(state, current_epoch) state, get_matching_target_attestations(state, current_epoch)
) )
if current_epoch_matching_target_balance * 3 >= get_total_active_balance(state) * 2: if current_epoch_matching_target_balance * 3 >= get_total_active_balance(state) * 2:
state.current_justified_epoch = current_epoch state.current_justified_checkpoint = Checkpoint(epoch=current_epoch, root=get_block_root(state, current_epoch))
state.current_justified_root = get_block_root(state, state.current_justified_epoch)
state.justification_bitfield |= (1 << 0) state.justification_bitfield |= (1 << 0)
# Process finalizations # Process finalizations
bitfield = state.justification_bitfield bitfield = state.justification_bitfield
# The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source # The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source
if (bitfield >> 1) % 8 == 0b111 and old_previous_justified_epoch + 3 == current_epoch: if (bitfield >> 1) % 8 == 0b111 and old_previous_justified_checkpoint.epoch + 3 == current_epoch:
state.finalized_epoch = old_previous_justified_epoch state.finalized_checkpoint = old_previous_justified_checkpoint
state.finalized_root = get_block_root(state, state.finalized_epoch)
# The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source # The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source
if (bitfield >> 1) % 4 == 0b11 and old_previous_justified_epoch + 2 == current_epoch: if (bitfield >> 1) % 4 == 0b11 and old_previous_justified_checkpoint.epoch + 2 == current_epoch:
state.finalized_epoch = old_previous_justified_epoch state.finalized_checkpoint = old_previous_justified_checkpoint
state.finalized_root = get_block_root(state, state.finalized_epoch)
# The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source # The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source
if (bitfield >> 0) % 8 == 0b111 and old_current_justified_epoch + 2 == current_epoch: if (bitfield >> 0) % 8 == 0b111 and old_current_justified_checkpoint.epoch + 2 == current_epoch:
state.finalized_epoch = old_current_justified_epoch state.finalized_checkpoint = old_current_justified_checkpoint
state.finalized_root = get_block_root(state, state.finalized_epoch)
# The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source # The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source
if (bitfield >> 0) % 4 == 0b11 and old_current_justified_epoch + 1 == current_epoch: if (bitfield >> 0) % 4 == 0b11 and old_current_justified_checkpoint.epoch + 1 == current_epoch:
state.finalized_epoch = old_current_justified_epoch state.finalized_checkpoint = old_current_justified_checkpoint
state.finalized_root = get_block_root(state, state.finalized_epoch)
``` ```
#### Crosslinks #### Crosslinks
@ -1418,7 +1413,7 @@ def get_attestation_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence
rewards[index] += Gwei(max_attester_reward * MIN_ATTESTATION_INCLUSION_DELAY // attestation.inclusion_delay) rewards[index] += Gwei(max_attester_reward * MIN_ATTESTATION_INCLUSION_DELAY // attestation.inclusion_delay)
# Inactivity penalty # Inactivity penalty
finality_delay = previous_epoch - state.finalized_epoch finality_delay = previous_epoch - state.finalized_checkpoint.epoch
if finality_delay > MIN_EPOCHS_TO_INACTIVITY_PENALTY: if finality_delay > MIN_EPOCHS_TO_INACTIVITY_PENALTY:
matching_target_attesting_indices = get_unslashed_attesting_indices(state, matching_target_attestations) matching_target_attesting_indices = get_unslashed_attesting_indices(state, matching_target_attestations)
for index in eligible_validator_indices: for index in eligible_validator_indices:
@ -1483,7 +1478,7 @@ def process_registry_updates(state: BeaconState) -> None:
activation_queue = sorted([ activation_queue = sorted([
index for index, validator in enumerate(state.validators) if index for index, validator in enumerate(state.validators) if
validator.activation_eligibility_epoch != FAR_FUTURE_EPOCH and validator.activation_eligibility_epoch != FAR_FUTURE_EPOCH and
validator.activation_epoch >= get_delayed_activation_exit_epoch(state.finalized_epoch) validator.activation_epoch >= get_delayed_activation_exit_epoch(state.finalized_checkpoint.epoch)
], key=lambda index: state.validators[index].activation_eligibility_epoch) ], key=lambda index: state.validators[index].activation_eligibility_epoch)
# Dequeued validators for activation up to churn limit (without resetting activation epoch) # Dequeued validators for activation up to churn limit (without resetting activation epoch)
for index in activation_queue[:get_churn_limit(state)]: for index in activation_queue[:get_churn_limit(state)]:
@ -1684,9 +1679,8 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
Process ``Attestation`` operation. Process ``Attestation`` operation.
""" """
data = attestation.data data = attestation.data
assert data.crosslink.shard < SHARD_COUNT assert data.crosslink.shard < SHARD_COUNT
assert data.target_epoch in (get_previous_epoch(state), get_current_epoch(state)) assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
attestation_slot = get_attestation_data_slot(state, data) attestation_slot = get_attestation_data_slot(state, data)
assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH
@ -1698,21 +1692,22 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
proposer_index=get_beacon_proposer_index(state), proposer_index=get_beacon_proposer_index(state),
) )
if data.target_epoch == get_current_epoch(state): if data.target.epoch == get_current_epoch(state):
ffg_data = (state.current_justified_epoch, state.current_justified_root, get_current_epoch(state)) assert data.source == state.current_justified_checkpoint
parent_crosslink = state.current_crosslinks[data.crosslink.shard] parent_crosslink = state.current_crosslinks[data.crosslink.shard]
state.current_epoch_attestations.append(pending_attestation) state.current_epoch_attestations.append(pending_attestation)
else: else:
ffg_data = (state.previous_justified_epoch, state.previous_justified_root, get_previous_epoch(state)) assert data.source == state.previous_justified_checkpoint
parent_crosslink = state.previous_crosslinks[data.crosslink.shard] parent_crosslink = state.previous_crosslinks[data.crosslink.shard]
state.previous_epoch_attestations.append(pending_attestation) state.previous_epoch_attestations.append(pending_attestation)
# Check FFG data, crosslink data, and signature # Check crosslink against expected parent crosslink
assert ffg_data == (data.source_epoch, data.source_root, data.target_epoch)
assert data.crosslink.start_epoch == parent_crosslink.end_epoch
assert data.crosslink.end_epoch == min(data.target_epoch, parent_crosslink.end_epoch + MAX_EPOCHS_PER_CROSSLINK)
assert data.crosslink.parent_root == hash_tree_root(parent_crosslink) assert data.crosslink.parent_root == hash_tree_root(parent_crosslink)
assert data.crosslink.start_epoch == parent_crosslink.end_epoch
assert data.crosslink.end_epoch == min(data.target.epoch, parent_crosslink.end_epoch + MAX_EPOCHS_PER_CROSSLINK)
assert data.crosslink.data_root == ZERO_HASH # [to be removed in phase 1] assert data.crosslink.data_root == ZERO_HASH # [to be removed in phase 1]
# Check signature
validate_indexed_attestation(state, convert_to_indexed(state, attestation)) validate_indexed_attestation(state, convert_to_indexed(state, attestation))
``` ```

View File

@ -55,15 +55,6 @@ The head block root associated with a `store` is defined as `get_head(store)`. A
### Helpers ### Helpers
#### `Checkpoint`
```python
@dataclass(eq=True, frozen=True)
class Checkpoint(object):
epoch: Epoch
root: Hash
```
#### `LatestMessage` #### `LatestMessage`
```python ```python
@ -73,7 +64,6 @@ class LatestMessage(object):
root: Hash root: Hash
``` ```
#### `Store` #### `Store`
```python ```python
@ -94,8 +84,8 @@ class Store(object):
def get_genesis_store(genesis_state: BeaconState) -> Store: def get_genesis_store(genesis_state: BeaconState) -> Store:
genesis_block = BeaconBlock(state_root=hash_tree_root(genesis_state)) genesis_block = BeaconBlock(state_root=hash_tree_root(genesis_state))
root = signing_root(genesis_block) root = signing_root(genesis_block)
justified_checkpoint = Checkpoint(GENESIS_EPOCH, root) justified_checkpoint = Checkpoint(epoch=GENESIS_EPOCH, root=root)
finalized_checkpoint = Checkpoint(GENESIS_EPOCH, root) finalized_checkpoint = Checkpoint(epoch=GENESIS_EPOCH, root=root)
return Store( return Store(
time=genesis_state.genesis_time, time=genesis_state.genesis_time,
justified_checkpoint=justified_checkpoint, justified_checkpoint=justified_checkpoint,
@ -179,21 +169,21 @@ def on_block(store: Store, block: BeaconBlock) -> None:
store.block_states[signing_root(block)] = state store.block_states[signing_root(block)] = state
# Update justified checkpoint # Update justified checkpoint
if state.current_justified_epoch > store.justified_checkpoint.epoch: if state.current_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
store.justified_checkpoint = Checkpoint(state.current_justified_epoch, state.current_justified_root) store.justified_checkpoint = state.current_justified_checkpoint
elif state.previous_justified_epoch > store.justified_checkpoint.epoch: elif state.previous_justified_checkpoint.epoch > store.justified_checkpoint.epoch:
store.justified_checkpoint = Checkpoint(state.previous_justified_epoch, state.previous_justified_root) store.justified_checkpoint = state.previous_justified_checkpoint
# Update finalized checkpoint # Update finalized checkpoint
if state.finalized_epoch > state.finalized_epoch: if state.finalized_checkpoint.epoch > store.finalized_checkpoint.epoch:
store.finalized_checkpoint = Checkpoint(state.finalized_epoch, state.finalized_root) store.finalized_checkpoint = state.finalized_checkpoint
``` ```
#### `on_attestation` #### `on_attestation`
```python ```python
def on_attestation(store: Store, attestation: Attestation) -> None: def on_attestation(store: Store, attestation: Attestation) -> None:
target = Checkpoint(attestation.data.target_epoch, attestation.data.target_root) target = attestation.data.target
# Cannot calculate the current shuffling if have not seen the target # Cannot calculate the current shuffling if have not seen the target
assert target.root in store.blocks assert target.root in store.blocks

View File

@ -19,7 +19,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
assert ( assert (
store.latest_messages[indexed_attestation.custody_bit_0_indices[0]] == store.latest_messages[indexed_attestation.custody_bit_0_indices[0]] ==
spec.LatestMessage( spec.LatestMessage(
epoch=attestation.data.target_epoch, epoch=attestation.data.target.epoch,
root=attestation.data.beacon_block_root, root=attestation.data.beacon_block_root,
) )
) )

View File

@ -24,11 +24,11 @@ def build_attestation_data(spec, state, slot, shard):
epoch_boundary_root = spec.get_block_root(state, spec.get_current_epoch(state)) epoch_boundary_root = spec.get_block_root(state, spec.get_current_epoch(state))
if slot < current_epoch_start_slot: if slot < current_epoch_start_slot:
justified_epoch = state.previous_justified_epoch source_epoch = state.previous_justified_checkpoint.epoch
justified_block_root = state.previous_justified_root source_root = state.previous_justified_checkpoint.root
else: else:
justified_epoch = state.current_justified_epoch source_epoch = state.current_justified_checkpoint.epoch
justified_block_root = state.current_justified_root source_root = state.current_justified_checkpoint.root
if spec.slot_to_epoch(slot) == spec.get_current_epoch(state): if spec.slot_to_epoch(slot) == spec.get_current_epoch(state):
parent_crosslink = state.current_crosslinks[shard] parent_crosslink = state.current_crosslinks[shard]
@ -37,10 +37,8 @@ def build_attestation_data(spec, state, slot, shard):
return spec.AttestationData( return spec.AttestationData(
beacon_block_root=block_root, beacon_block_root=block_root,
source_epoch=justified_epoch, source=spec.Checkpoint(epoch=source_epoch, root=source_root),
source_root=justified_block_root, target=spec.Checkpoint(epoch=spec.slot_to_epoch(slot), root=epoch_boundary_root),
target_epoch=spec.slot_to_epoch(slot),
target_root=epoch_boundary_root,
crosslink=spec.Crosslink( crosslink=spec.Crosslink(
shard=shard, shard=shard,
start_epoch=parent_crosslink.end_epoch, start_epoch=parent_crosslink.end_epoch,
@ -64,8 +62,8 @@ def get_valid_attestation(spec, state, slot=None, signed=False):
crosslink_committee = spec.get_crosslink_committee( crosslink_committee = spec.get_crosslink_committee(
state, state,
attestation_data.target_epoch, attestation_data.target.epoch,
attestation_data.crosslink.shard attestation_data.crosslink.shard,
) )
committee_size = len(crosslink_committee) committee_size = len(crosslink_committee)
@ -126,7 +124,7 @@ def get_attestation_signature(spec, state, attestation_data, privkey, custody_bi
domain=spec.get_domain( domain=spec.get_domain(
state=state, state=state,
domain_type=spec.DOMAIN_ATTESTATION, domain_type=spec.DOMAIN_ATTESTATION,
message_epoch=attestation_data.target_epoch, message_epoch=attestation_data.target.epoch,
) )
) )
@ -134,7 +132,7 @@ def get_attestation_signature(spec, state, attestation_data, privkey, custody_bi
def fill_aggregate_attestation(spec, state, attestation): def fill_aggregate_attestation(spec, state, attestation):
crosslink_committee = spec.get_crosslink_committee( crosslink_committee = spec.get_crosslink_committee(
state, state,
attestation.data.target_epoch, attestation.data.target.epoch,
attestation.data.crosslink.shard, attestation.data.crosslink.shard,
) )
for i in range(len(crosslink_committee)): for i in range(len(crosslink_committee)):

View File

@ -7,7 +7,7 @@ def get_valid_attester_slashing(spec, state, signed_1=False, signed_2=False):
attestation_1 = get_valid_attestation(spec, state, signed=signed_1) attestation_1 = get_valid_attestation(spec, state, signed=signed_1)
attestation_2 = deepcopy(attestation_1) attestation_2 = deepcopy(attestation_1)
attestation_2.data.target_root = b'\x01' * 32 attestation_2.data.target.root = b'\x01' * 32
if signed_2: if signed_2:
sign_attestation(spec, state, attestation_2) sign_attestation(spec, state, attestation_2)

View File

@ -38,7 +38,7 @@ def run_attestation_processing(spec, state, attestation, valid=True):
spec.process_attestation(state, attestation) spec.process_attestation(state, attestation)
# Make sure the attestation has been processed # Make sure the attestation has been processed
if attestation.data.target_epoch == spec.get_current_epoch(state): if attestation.data.target.epoch == spec.get_current_epoch(state):
assert len(state.current_epoch_attestations) == current_epoch_count + 1 assert len(state.current_epoch_attestations) == current_epoch_count + 1
else: else:
assert len(state.previous_epoch_attestations) == previous_epoch_count + 1 assert len(state.previous_epoch_attestations) == previous_epoch_count + 1
@ -119,16 +119,16 @@ def test_after_epoch_slots(spec, state):
@spec_state_test @spec_state_test
def test_old_source_epoch(spec, state): def test_old_source_epoch(spec, state):
state.slot = spec.SLOTS_PER_EPOCH * 5 state.slot = spec.SLOTS_PER_EPOCH * 5
state.finalized_epoch = 2 state.finalized_checkpoint.epoch = 2
state.previous_justified_epoch = 3 state.previous_justified_checkpoint.epoch = 3
state.current_justified_epoch = 4 state.current_justified_checkpoint.epoch = 4
attestation = get_valid_attestation(spec, state, slot=(spec.SLOTS_PER_EPOCH * 3) + 1) attestation = get_valid_attestation(spec, state, slot=(spec.SLOTS_PER_EPOCH * 3) + 1)
# test logic sanity check: make sure the attestation is pointing to oldest known source epoch # test logic sanity check: make sure the attestation is pointing to oldest known source epoch
assert attestation.data.source_epoch == state.previous_justified_epoch assert attestation.data.source.epoch == state.previous_justified_checkpoint.epoch
# Now go beyond that, it will be invalid # Now go beyond that, it will be invalid
attestation.data.source_epoch -= 1 attestation.data.source.epoch -= 1
sign_attestation(spec, state, attestation) sign_attestation(spec, state, attestation)
@ -154,7 +154,7 @@ def test_new_source_epoch(spec, state):
attestation = get_valid_attestation(spec, state) attestation = get_valid_attestation(spec, state)
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
attestation.data.source_epoch += 1 attestation.data.source.epoch += 1
sign_attestation(spec, state, attestation) sign_attestation(spec, state, attestation)
@ -167,7 +167,7 @@ def test_source_root_is_target_root(spec, state):
attestation = get_valid_attestation(spec, state) attestation = get_valid_attestation(spec, state)
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
attestation.data.source_root = attestation.data.target_root attestation.data.source.root = attestation.data.target.root
sign_attestation(spec, state, attestation) sign_attestation(spec, state, attestation)
@ -178,23 +178,20 @@ def test_source_root_is_target_root(spec, state):
@spec_state_test @spec_state_test
def test_invalid_current_source_root(spec, state): def test_invalid_current_source_root(spec, state):
state.slot = spec.SLOTS_PER_EPOCH * 5 state.slot = spec.SLOTS_PER_EPOCH * 5
state.finalized_epoch = 2 state.finalized_checkpoint.epoch = 2
state.previous_justified_epoch = 3 state.previous_justified_checkpoint = spec.Checkpoint(epoch=3, root=b'\x01' * 32)
state.previous_justified_root = b'\x01' * 32 state.current_justified_checkpoint = spec.Checkpoint(epoch=4, root=b'\x32' * 32)
state.current_justified_epoch = 4
state.current_justified_root = b'\xff' * 32
attestation = get_valid_attestation(spec, state, slot=(spec.SLOTS_PER_EPOCH * 3) + 1) attestation = get_valid_attestation(spec, state, slot=(spec.SLOTS_PER_EPOCH * 3) + 1)
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
# Test logic sanity checks: # Test logic sanity checks:
assert state.current_justified_root != state.previous_justified_root assert state.current_justified_checkpoint.root != state.previous_justified_checkpoint.root
assert attestation.data.source_root == state.previous_justified_root assert attestation.data.source.root == state.previous_justified_checkpoint.root
# Make attestation source root invalid: should be previous justified, not current one # Make attestation source root invalid: should be previous justified, not current one
attestation.data.source_root = state.current_justified_root attestation.data.source.root = state.current_justified_checkpoint.root
sign_attestation(spec, state, attestation) sign_attestation(spec, state, attestation)
@ -207,7 +204,7 @@ def test_bad_source_root(spec, state):
attestation = get_valid_attestation(spec, state) attestation = get_valid_attestation(spec, state)
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
attestation.data.source_root = b'\x42' * 32 attestation.data.source.root = b'\x42' * 32
sign_attestation(spec, state, attestation) sign_attestation(spec, state, attestation)

View File

@ -68,12 +68,14 @@ def test_success_surround(spec, state):
next_epoch(spec, state) next_epoch(spec, state)
apply_empty_block(spec, state) apply_empty_block(spec, state)
state.current_justified_epoch += 1 state.current_justified_checkpoint.epoch += 1
attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True)
attestation_1 = attester_slashing.attestation_1
attestation_2 = attester_slashing.attestation_2
# set attestion1 to surround attestation 2 # set attestion1 to surround attestation 2
attester_slashing.attestation_1.data.source_epoch = attester_slashing.attestation_2.data.source_epoch - 1 attestation_1.data.source.epoch = attestation_2.data.source.epoch - 1
attester_slashing.attestation_1.data.target_epoch = attester_slashing.attestation_2.data.target_epoch + 1 attestation_1.data.target.epoch = attestation_2.data.target.epoch + 1
sign_indexed_attestation(spec, state, attester_slashing.attestation_1) sign_indexed_attestation(spec, state, attester_slashing.attestation_1)
@ -120,7 +122,7 @@ def test_same_data(spec, state):
def test_no_double_or_surround(spec, state): def test_no_double_or_surround(spec, state):
attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True) attester_slashing = get_valid_attester_slashing(spec, state, signed_1=False, signed_2=True)
attester_slashing.attestation_1.data.target_epoch += 1 attester_slashing.attestation_1.data.target.epoch += 1
sign_indexed_attestation(spec, state, attester_slashing.attestation_1) sign_indexed_attestation(spec, state, attester_slashing.attestation_1)
yield from run_attester_slashing_processing(spec, state, attester_slashing, False) yield from run_attester_slashing_processing(spec, state, attester_slashing, False)

View File

@ -96,7 +96,7 @@ def test_single_crosslink_update_from_previous_epoch(spec, state):
# ensure rewarded # ensure rewarded
for index in spec.get_crosslink_committee( for index in spec.get_crosslink_committee(
state, state,
attestation.data.target_epoch, attestation.data.target.epoch,
attestation.data.crosslink.shard): attestation.data.crosslink.shard):
assert crosslink_deltas[0][index] > 0 assert crosslink_deltas[0][index] > 0
assert crosslink_deltas[1][index] == 0 assert crosslink_deltas[1][index] == 0
@ -148,7 +148,7 @@ def test_double_late_crosslink(spec, state):
# ensure no reward, only penalties for the failed crosslink # ensure no reward, only penalties for the failed crosslink
for index in spec.get_crosslink_committee( for index in spec.get_crosslink_committee(
state, state,
attestation_2.data.target_epoch, attestation_2.data.target.epoch,
attestation_2.data.crosslink.shard): attestation_2.data.crosslink.shard):
assert crosslink_deltas[0][index] == 0 assert crosslink_deltas[0][index] == 0
assert crosslink_deltas[1][index] > 0 assert crosslink_deltas[1][index] > 0

View File

@ -13,25 +13,22 @@ def check_finality(spec,
previous_justified_changed, previous_justified_changed,
finalized_changed): finalized_changed):
if current_justified_changed: if current_justified_changed:
assert state.current_justified_epoch > prev_state.current_justified_epoch assert state.current_justified_checkpoint.epoch > prev_state.current_justified_checkpoint.epoch
assert state.current_justified_root != prev_state.current_justified_root assert state.current_justified_checkpoint.root != prev_state.current_justified_checkpoint.root
else: else:
assert state.current_justified_epoch == prev_state.current_justified_epoch assert state.current_justified_checkpoint == prev_state.current_justified_checkpoint
assert state.current_justified_root == prev_state.current_justified_root
if previous_justified_changed: if previous_justified_changed:
assert state.previous_justified_epoch > prev_state.previous_justified_epoch assert state.previous_justified_checkpoint.epoch > prev_state.previous_justified_checkpoint.epoch
assert state.previous_justified_root != prev_state.previous_justified_root assert state.previous_justified_checkpoint.root != prev_state.previous_justified_checkpoint.root
else: else:
assert state.previous_justified_epoch == prev_state.previous_justified_epoch assert state.previous_justified_checkpoint == prev_state.previous_justified_checkpoint
assert state.previous_justified_root == prev_state.previous_justified_root
if finalized_changed: if finalized_changed:
assert state.finalized_epoch > prev_state.finalized_epoch assert state.finalized_checkpoint.epoch > prev_state.finalized_checkpoint.epoch
assert state.finalized_root != prev_state.finalized_root assert state.finalized_checkpoint.root != prev_state.finalized_checkpoint.root
else: else:
assert state.finalized_epoch == prev_state.finalized_epoch assert state.finalized_checkpoint == prev_state.finalized_checkpoint
assert state.finalized_root == prev_state.finalized_root
def next_epoch_with_attestations(spec, def next_epoch_with_attestations(spec,
@ -107,8 +104,7 @@ def test_finality_rule_4(spec, state):
elif epoch == 1: elif epoch == 1:
# rule 4 of finality # rule 4 of finality
check_finality(spec, state, prev_state, True, True, True) check_finality(spec, state, prev_state, True, True, True)
assert state.finalized_epoch == prev_state.current_justified_epoch assert state.finalized_checkpoint == prev_state.current_justified_checkpoint
assert state.finalized_root == prev_state.current_justified_root
yield 'blocks', blocks yield 'blocks', blocks
yield 'post', state yield 'post', state
@ -138,8 +134,7 @@ def test_finality_rule_1(spec, state):
elif epoch == 2: elif epoch == 2:
# finalized by rule 1 # finalized by rule 1
check_finality(spec, state, prev_state, True, True, True) check_finality(spec, state, prev_state, True, True, True)
assert state.finalized_epoch == prev_state.previous_justified_epoch assert state.finalized_checkpoint == prev_state.previous_justified_checkpoint
assert state.finalized_root == prev_state.previous_justified_root
yield 'blocks', blocks yield 'blocks', blocks
yield 'post', state yield 'post', state
@ -169,8 +164,7 @@ def test_finality_rule_2(spec, state):
prev_state, new_blocks, state = next_epoch_with_attestations(spec, state, False, True) prev_state, new_blocks, state = next_epoch_with_attestations(spec, state, False, True)
# finalized by rule 2 # finalized by rule 2
check_finality(spec, state, prev_state, True, False, True) check_finality(spec, state, prev_state, True, False, True)
assert state.finalized_epoch == prev_state.previous_justified_epoch assert state.finalized_checkpoint == prev_state.previous_justified_checkpoint
assert state.finalized_root == prev_state.previous_justified_root
blocks += new_blocks blocks += new_blocks
@ -221,8 +215,7 @@ def test_finality_rule_3(spec, state):
blocks += new_blocks blocks += new_blocks
# rule 3 # rule 3
check_finality(spec, state, prev_state, True, True, True) check_finality(spec, state, prev_state, True, True, True)
assert state.finalized_epoch == prev_state.current_justified_epoch assert state.finalized_checkpoint == prev_state.current_justified_checkpoint
assert state.finalized_root == prev_state.current_justified_root
yield 'blocks', blocks yield 'blocks', blocks
yield 'post', state yield 'post', state