Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add previous and current crosslinks #874

Merged
merged 33 commits into from
Apr 18, 2019
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
529cf42
add previous and current crosslinks
djrtwo Apr 2, 2019
d8df789
simplify get_winning_root logic
djrtwo Apr 2, 2019
39b4ef3
Merge branch 'dev' into prev-cur-crosslinks
djrtwo Apr 3, 2019
1fa88fb
remove previous crosslink check from process_crosslinks
djrtwo Apr 3, 2019
d1af914
Update 0_beacon-chain.md
JustinDrake Apr 3, 2019
a790afa
Update 0_beacon-chain.md
JustinDrake Apr 4, 2019
3e6dc59
Update helpers.py
JustinDrake Apr 4, 2019
dc325f7
clean up a few things from PR
djrtwo Apr 5, 2019
f677af2
Merge branch 'dev' into prev-cur-crosslinks
djrtwo Apr 5, 2019
26df4f4
Merge branch 'dev' into prev-cur-crosslinks
djrtwo Apr 7, 2019
42dc003
add previous_crosslink_root and enforce crosslinks form a chain
djrtwo Apr 7, 2019
e246c3f
source_crosslink_root to previous_crosslink_root
djrtwo Apr 8, 2019
71a28aa
fix tests
djrtwo Apr 8, 2019
0a5a5b7
Merge branch 'dev' into prev-cur-crosslinks
djrtwo Apr 13, 2019
a6b3b11
ensure no reward for crosslinks taht can't form a chain
djrtwo Apr 13, 2019
9489ae5
upate validator guide to new crosslink format
djrtwo Apr 13, 2019
eafcab7
check crosslinks validity root against previous
djrtwo Apr 13, 2019
3555ab8
Merge branch 'dev' into prev-cur-crosslinks
djrtwo Apr 14, 2019
cc68df8
Merge branch 'dev' into prev-cur-crosslinks
hwwhww Apr 17, 2019
ef14396
Merge branch 'dev' into prev-cur-crosslinks
djrtwo Apr 17, 2019
8c5f7a5
Merge branch 'dev' into prev-cur-crosslinks
djrtwo Apr 18, 2019
fbaf771
Update 0_beacon-chain.md
JustinDrake Apr 18, 2019
9ecafb2
Update 0_beacon-chain.md
JustinDrake Apr 18, 2019
40b55cf
More fixes
JustinDrake Apr 18, 2019
cae5c22
Simplify get_crosslink_committee_for_attestation and move to test hel…
JustinDrake Apr 18, 2019
964b4d3
Fix `pyspec/tests/helpers.py`
hwwhww Apr 18, 2019
743193a
nitpicks
hwwhww Apr 18, 2019
4244db9
More cleanups
JustinDrake Apr 18, 2019
2e09f1a
Merge
JustinDrake Apr 18, 2019
172e106
merge
JustinDrake Apr 18, 2019
857d9b2
Merge branch 'dev' into prev-cur-crosslinks
JustinDrake Apr 18, 2019
7a01648
Moar
JustinDrake Apr 18, 2019
741a74a
re-add crosslink tests and ensure pass
djrtwo Apr 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 77 additions & 87 deletions specs/core/0_beacon-chain.md

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions specs/core/1_custody-game.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ def process_chunk_challenge(state: BeaconState,
responder = state.validator_registry[challenge.responder_index]
assert responder.exit_epoch >= get_current_epoch(state) - MAX_CHUNK_CHALLENGE_DELAY
# Verify the responder participated in the attestation
attesters = get_attestation_participants(state, attestation.data, attestation.aggregation_bitfield)
attesters = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield)
assert challenge.responder_index in attesters
# Verify the challenge is not a duplicate
for record in state.custody_chunk_challenge_records:
Expand Down Expand Up @@ -359,9 +359,9 @@ def process_bit_challenge(state: BeaconState,
# Verify the attestation is eligible for challenging
responder = state.validator_registry[challenge.responder_index]
min_challengeable_epoch = responder.exit_epoch - EPOCHS_PER_CUSTODY_PERIOD * (1 + responder.max_reveal_lateness)
assert min_challengeable_epoch <= slot_to_epoch(challenge.attestation.data.slot)
assert min_challengeable_epoch <= slot_to_epoch(challenge.attestation.data.slot)
# Verify the responder participated in the attestation
attesters = get_attestation_participants(state, attestation.data, attestation.aggregation_bitfield)
attesters = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield)
assert challenge.responder_index in attesters
# A validator can be the challenger or responder for at most one challenge at a time
for record in state.custody_bit_challenge_records:
Expand Down
40 changes: 20 additions & 20 deletions specs/validator/0_beacon-chain-validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ __NOTICE__: This document is a work-in-progress for researchers and implementers
- [Attestations](#attestations-1)
- [Attestation data](#attestation-data)
- [Slot](#slot-1)
- [Shard](#shard)
- [Beacon block root](#beacon-block-root)
- [Target root](#target-root)
- [Crosslink data root](#crosslink-data-root)
- [Latest crosslink](#latest-crosslink)
- [Source epoch](#source-epoch)
- [Source root](#source-root)
- [Target root](#target-root)
- [Shard](#shard)
- [Previous crosslink root](#previous-crosslink-root)
- [Crosslink data root](#crosslink-data-root)
- [Construct attestation](#construct-attestation)
- [Data](#data)
- [Aggregation bitfield](#aggregation-bitfield)
Expand Down Expand Up @@ -250,14 +250,18 @@ First the validator should construct `attestation_data`, an [`AttestationData`](

Set `attestation_data.slot = head_state.slot`.

##### Shard

Set `attestation_data.shard = shard` where `shard` is the shard associated with the validator's committee defined by `get_crosslink_committees_at_slot`.

##### Beacon block root

Set `attestation_data.beacon_block_root = signing_root(head_block)`.

##### Source epoch

Set `attestation_data.source_epoch = head_state.justified_epoch`.

##### Source root

Set `attestation_data.source_root = head_state.current_justified_root`.

##### Target root

Set `attestation_data.target_root = signing_root(epoch_boundary)` where `epoch_boundary` is the block at the most recent epoch boundary.
Expand All @@ -266,23 +270,19 @@ _Note:_ This can be looked up in the state using:
* Let `epoch_start_slot = get_epoch_start_slot(get_current_epoch(head_state))`.
* Set `epoch_boundary = head if epoch_start_slot == head_state.slot else get_block_root(state, epoch_start_slot)`.

##### Crosslink data root

Set `attestation_data.crosslink_data_root = ZERO_HASH`.

_Note:_ This is a stub for phase 0.
##### Shard

##### Latest crosslink
Set `attestation_data.shard = shard` where `shard` is the shard associated with the validator's committee defined by `get_crosslink_committees_at_slot`.

Set `attestation_data.previous_crosslink = head_state.latest_crosslinks[shard]`.
##### Previous crosslink root

##### Source epoch
Set `attestation_data.previous_crosslink_root = hash_tree_root(head_state.current_crosslinks[shard])`.

Set `attestation_data.source_epoch = head_state.justified_epoch`.
##### Crosslink data root

##### Source root
Set `attestation_data.crosslink_data_root = ZERO_HASH`.

Set `attestation_data.source_root = head_state.current_justified_root`.
_Note:_ This is a stub for phase 0.

#### Construct attestation

Expand All @@ -299,7 +299,7 @@ Set `attestation.data = attestation_data` where `attestation_data` is the `Attes
* Set `aggregation_bitfield[index_into_committee // 8] |= 2 ** (index_into_committee % 8)`.
* Set `attestation.aggregation_bitfield = aggregation_bitfield`.

_Note_: Calling `get_attestation_participants(state, attestation.data, attestation.aggregation_bitfield)` should return a list of length equal to 1, containing `validator_index`.
_Note_: Calling `get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield)` should return a list of length equal to 1, containing `validator_index`.

##### Custody bitfield

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from tests.helpers import (
build_empty_block_for_next_slot,
get_valid_attestation,
next_epoch,
next_slot,
)


Expand Down Expand Up @@ -120,10 +122,12 @@ def test_non_zero_crosslink_data_root(state):


def test_bad_previous_crosslink(state):
next_epoch(state)
attestation = get_valid_attestation(state)
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY):
next_slot(state)

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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
get_valid_proposer_slashing,
)

# mark entire file as 'header'
# mark entire file as 'proposer_slashings'
pytestmark = pytest.mark.proposer_slashings


Expand Down
3 changes: 2 additions & 1 deletion test_libs/pyspec/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,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]
Expand Down
26 changes: 22 additions & 4 deletions test_libs/pyspec/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@
# functions
convert_to_indexed,
get_active_validator_indices,
get_attestation_participants,
get_attesting_indices,
get_block_root,
get_crosslink_committee_for_attestation,
get_crosslink_committees_at_slot,
get_current_epoch,
get_domain,
get_empty_block,
get_epoch_start_slot,
get_genesis_beacon_state,
get_previous_epoch,
get_shard_delta,
hash_tree_root,
slot_to_epoch,
verify_merkle_branch,
hash,
Expand Down Expand Up @@ -154,6 +155,7 @@ def build_attestation_data(state, slot, shard):

current_epoch_start_slot = get_epoch_start_slot(get_current_epoch(state))
if slot < current_epoch_start_slot:
print(slot)
epoch_boundary_root = get_block_root(state, get_epoch_start_slot(get_previous_epoch(state)))
elif slot == current_epoch_start_slot:
epoch_boundary_root = block_root
Expand All @@ -167,6 +169,7 @@ def build_attestation_data(state, slot, shard):
justified_epoch = state.current_justified_epoch
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,
Expand All @@ -175,7 +178,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_root=hash_tree_root(crosslinks[shard]),
)


Expand Down Expand Up @@ -273,6 +276,14 @@ def get_valid_attester_slashing(state):
)


def get_crosslink_committee_for_attestation(state, attestation_data):
"""
Return the crosslink committee corresponding to ``attestation_data``.
"""
crosslink_committees = get_crosslink_committees_at_slot(state, attestation_data.slot)
return [committee for committee, shard in crosslink_committees if shard == attestation_data.shard][0]


def get_valid_attestation(state, slot=None):
if slot is None:
slot = state.slot
Expand All @@ -297,7 +308,7 @@ def get_valid_attestation(state, slot=None):
custody_bitfield=custody_bitfield,
aggregate_signature=EMPTY_SIGNATURE,
)
participants = get_attestation_participants(
participants = get_attesting_indices(
state,
attestation.data,
attestation.aggregation_bitfield,
Expand Down Expand Up @@ -342,6 +353,13 @@ def fill_aggregate_attestation(state, attestation):
attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i)


def add_attestation_to_state(state, attestation, slot):
block = build_empty_block_for_next_slot(state)
block.slot = slot
block.body.attestations.append(attestation)
state_transition(state, block)


def next_slot(state):
block = build_empty_block_for_next_slot(state)
state_transition(state, block)
Expand Down
28 changes: 1 addition & 27 deletions test_libs/pyspec/tests/test_sanity.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
advance_slot,
cache_state,
set_balance,
slot_to_epoch,
verify_merkle_branch,
hash,
)
Expand Down Expand Up @@ -382,33 +383,6 @@ def test_voluntary_exit(state):
return pre_state, [initiate_exit_block, exit_block], post_state


def test_no_exit_churn_too_long_since_change(state):
pre_state = deepcopy(state)
validator_index = get_active_validator_indices(
pre_state,
get_current_epoch(pre_state)
)[-1]

#
# setup pre_state
#
# move state forward PERSISTENT_COMMITTEE_PERIOD epochs to allow for exit
pre_state.slot += spec.PERSISTENT_COMMITTEE_PERIOD * spec.SLOTS_PER_EPOCH

post_state = deepcopy(pre_state)

#
# Process registry change but ensure no exit
#
block = build_empty_block_for_next_slot(post_state)
block.slot += spec.SLOTS_PER_EPOCH
state_transition(post_state, block)

assert post_state.validator_registry[validator_index].exit_epoch == spec.FAR_FUTURE_EPOCH

return pre_state, [block], post_state


def test_transfer(state):
pre_state = deepcopy(state)
current_epoch = get_current_epoch(pre_state)
Expand Down