From a6e825d46056a4a92473e52f1ea0bcb19210e67b Mon Sep 17 00:00:00 2001 From: Justin Date: Sun, 5 May 2019 12:04:34 +0100 Subject: [PATCH 1/8] Update 0_beacon-chain.md --- specs/core/0_beacon-chain.md | 56 +++++++++++++++--------------------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 36ac927961..addaa865ee 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -279,6 +279,8 @@ The types are defined topologically to aid in facilitating an executable version ```python { + # Shard number + 'shard': 'uint64', # Epoch number 'epoch': 'uint64', # Root of the previous crosslink @@ -315,9 +317,7 @@ The types are defined topologically to aid in facilitating an executable version 'target_root': 'bytes32', # Crosslink vote - 'shard': 'uint64', - 'previous_crosslink_root': 'bytes32', - 'crosslink_data_root': 'bytes32', + 'crosslink': Crosslink, } ``` @@ -765,7 +765,7 @@ def get_epoch_start_shard(state: BeaconState, epoch: Epoch) -> Shard: def get_attestation_slot(state: BeaconState, attestation: Attestation) -> Slot: epoch = attestation.data.target_epoch committee_count = get_epoch_committee_count(state, epoch) - offset = (attestation.data.shard + SHARD_COUNT - get_epoch_start_shard(state, epoch)) % SHARD_COUNT + offset = (attestation.data.crosslink.shard + SHARD_COUNT - get_epoch_start_shard(state, epoch)) % SHARD_COUNT return get_epoch_start_slot(epoch) + offset // (committee_count // SLOTS_PER_EPOCH) ``` @@ -927,7 +927,7 @@ def get_attesting_indices(state: BeaconState, """ Return the sorted attesting indices corresponding to ``attestation_data`` and ``bitfield``. """ - committee = get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.shard) + committee = get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.crosslink.shard) assert verify_bitfield(bitfield, len(committee)) return sorted([index for i, index in enumerate(committee) if get_bitfield_bit(bitfield, i) == 0b1]) ``` @@ -1296,28 +1296,18 @@ def get_attesting_balance(state: BeaconState, attestations: List[PendingAttestat return get_total_balance(state, get_unslashed_attesting_indices(state, attestations)) ``` -```python -def get_crosslink_from_attestation_data(state: BeaconState, data: AttestationData) -> Crosslink: - return Crosslink( - epoch=min(data.target_epoch, state.current_crosslinks[data.shard].epoch + MAX_CROSSLINK_EPOCHS), - previous_crosslink_root=data.previous_crosslink_root, - crosslink_data_root=data.crosslink_data_root, - ) -``` - ```python def get_winning_crosslink_and_attesting_indices(state: BeaconState, epoch: Epoch, shard: Shard) -> Tuple[Crosslink, List[ValidatorIndex]]: - shard_attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.shard == shard] - shard_crosslinks = [get_crosslink_from_attestation_data(state, a.data) for a in shard_attestations] + shard_attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.crosslink.shard == shard] candidate_crosslinks = [ - c for c in shard_crosslinks + c for c in [a.data.crosslink for a in shard_attestations] if hash_tree_root(state.current_crosslinks[shard]) in (c.previous_crosslink_root, hash_tree_root(c)) ] if len(candidate_crosslinks) == 0: return Crosslink(), [] def get_attestations_for(crosslink: Crosslink) -> List[PendingAttestation]: - return [a for a in shard_attestations if get_crosslink_from_attestation_data(state, a.data) == crosslink] + return [a for a in shard_attestations if a.data.crosslink == crosslink] # Winning crosslink has the crosslink data root with the most balance voting for it (ties broken lexicographically) winning_crosslink = max(candidate_crosslinks, key=lambda crosslink: ( get_attesting_balance(state, get_attestations_for(crosslink)), crosslink.crosslink_data_root @@ -1705,30 +1695,30 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: attestation_slot = get_attestation_slot(state, attestation) assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH - # Check target epoch, source epoch, source root, and source crosslink data = attestation.data - assert (data.target_epoch, data.source_epoch, data.source_root, data.previous_crosslink_root) in { - (get_current_epoch(state), state.current_justified_epoch, state.current_justified_root, hash_tree_root(state.current_crosslinks[data.shard])), - (get_previous_epoch(state), state.previous_justified_epoch, state.previous_justified_root, hash_tree_root(state.previous_crosslinks[data.shard])), - } - - # Check crosslink data root - assert data.crosslink_data_root == ZERO_HASH # [to be removed in phase 1] - - # Check signature and bitfields - assert verify_indexed_attestation(state, convert_to_indexed(state, attestation)) - - # Cache pending attestation pending_attestation = PendingAttestation( data=data, aggregation_bitfield=attestation.aggregation_bitfield, inclusion_delay=state.slot - attestation_slot, proposer_index=get_beacon_proposer_index(state), ) + + assert data.target_epoch in (get_previous_epoch(state), get_current_epoch(state)) + if data.target_epoch == get_previous_epoch(state): + ffg_data = (state.previous_justified_epoch, state.previous_justified_root, get_previous_epoch(state)) + previous_crosslink = state.previous_crosslinks[data.crosslink.shard] + state.previous_epoch_attestations.append(pending_attestation) if data.target_epoch == get_current_epoch(state): + ffg_data = (state.current_justified_epoch, state.current_justified_root, get_current_epoch(state)) + previous_crosslink = state.current_crosslinks[data.crosslink.shard] state.current_epoch_attestations.append(pending_attestation) - else: - state.previous_epoch_attestations.append(pending_attestation) + + # Check FFG data, crosslink data, and signature + assert ffg_data == (data.source_epoch, data.source_root, data.target_epoch) + assert data.crosslink.epoch == min(data.target_epoch, previous_crosslink.epoch + MAX_CROSSLINK_EPOCHS) + assert data.crosslink.previous_crosslink_root == hash_tree_root(previous_crosslink) + assert data.crosslink.crosslink_data_root == ZERO_HASH # [to be removed in phase 1] + assert verify_indexed_attestation(state, convert_to_indexed(state, attestation)) ``` ##### Deposits From 5fb32fd19b780d172e8738d887fd0675df7ec3ef Mon Sep 17 00:00:00 2001 From: Justin Drake Date: Sun, 5 May 2019 12:10:39 +0100 Subject: [PATCH 2/8] Fix tests --- configs/constant_presets/mainnet.yaml | 4 ++-- configs/constant_presets/minimal.yaml | 4 ++-- specs/core/0_beacon-chain.md | 6 +++--- specs/core/1_custody-game.md | 16 ++++++++-------- specs/core/1_shard-data-chains.md | 16 ++++++++-------- specs/validator/0_beacon-chain-validator.md | 4 ++-- .../block_processing/test_process_attestation.py | 4 ++-- .../epoch_processing/test_process_crosslinks.py | 12 ++++++------ test_libs/pyspec/tests/helpers.py | 15 ++++++++++----- 9 files changed, 43 insertions(+), 38 deletions(-) diff --git a/configs/constant_presets/mainnet.yaml b/configs/constant_presets/mainnet.yaml index 72d0fdc8f2..6ac3f422f5 100644 --- a/configs/constant_presets/mainnet.yaml +++ b/configs/constant_presets/mainnet.yaml @@ -72,7 +72,7 @@ MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 # 2**11 (= 2,048) epochs 9 days PERSISTENT_COMMITTEE_PERIOD: 2048 # 2**6 (= 64) epochs ~7 hours -MAX_CROSSLINK_EPOCHS: 64 +MAX_EPOCHS_PER_CROSSLINK: 64 # 2**2 (= 4) epochs 25.6 minutes MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4 @@ -124,4 +124,4 @@ DOMAIN_RANDAO: 1 DOMAIN_ATTESTATION: 2 DOMAIN_DEPOSIT: 3 DOMAIN_VOLUNTARY_EXIT: 4 -DOMAIN_TRANSFER: 5 \ No newline at end of file +DOMAIN_TRANSFER: 5 diff --git a/configs/constant_presets/minimal.yaml b/configs/constant_presets/minimal.yaml index 0a6cab6872..caae4623ba 100644 --- a/configs/constant_presets/minimal.yaml +++ b/configs/constant_presets/minimal.yaml @@ -71,7 +71,7 @@ MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 # 2**11 (= 2,048) epochs 9 days PERSISTENT_COMMITTEE_PERIOD: 2048 # 2**6 (= 64) epochs ~7 hours -MAX_CROSSLINK_EPOCHS: 64 +MAX_EPOCHS_PER_CROSSLINK: 64 # 2**2 (= 4) epochs 25.6 minutes MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4 @@ -123,4 +123,4 @@ DOMAIN_RANDAO: 1 DOMAIN_ATTESTATION: 2 DOMAIN_DEPOSIT: 3 DOMAIN_VOLUNTARY_EXIT: 4 -DOMAIN_TRANSFER: 5 \ No newline at end of file +DOMAIN_TRANSFER: 5 diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index addaa865ee..156a2523d2 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -206,10 +206,10 @@ These configurations are updated for releases, but may be out of sync during `de | `SLOTS_PER_HISTORICAL_ROOT` | `2**13` (= 8,192) | slots | ~13 hours | | `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` | `2**8` (= 256) | epochs | ~27 hours | | `PERSISTENT_COMMITTEE_PERIOD` | `2**11` (= 2,048) | epochs | 9 days | -| `MAX_CROSSLINK_EPOCHS` | `2**6` (= 64) | epochs | ~7 hours | +| `MAX_EPOCHS_PER_CROSSLINK` | `2**6` (= 64) | epochs | ~7 hours | | `MIN_EPOCHS_TO_INACTIVITY_PENALTY` | `2**2` (= 4) | epochs | 25.6 minutes | -* `MAX_CROSSLINK_EPOCHS` should be a small constant times `SHARD_COUNT // SLOTS_PER_EPOCH` +* `MAX_EPOCHS_PER_CROSSLINK` should be a small constant times `SHARD_COUNT // SLOTS_PER_EPOCH` ### State list lengths @@ -1715,7 +1715,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: # Check FFG data, crosslink data, and signature assert ffg_data == (data.source_epoch, data.source_root, data.target_epoch) - assert data.crosslink.epoch == min(data.target_epoch, previous_crosslink.epoch + MAX_CROSSLINK_EPOCHS) + assert data.crosslink.epoch == min(data.target_epoch, previous_crosslink.epoch + MAX_EPOCHS_PER_CROSSLINK) assert data.crosslink.previous_crosslink_root == hash_tree_root(previous_crosslink) assert data.crosslink.crosslink_data_root == ZERO_HASH # [to be removed in phase 1] assert verify_indexed_attestation(state, convert_to_indexed(state, attestation)) diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index d565266110..f386ee76e5 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -265,7 +265,7 @@ The `empty` function accepts and SSZ type as input and returns an object of that def get_custody_chunk_count(attestation: Attestation) -> int: crosslink_start_epoch = attestation.data.latest_crosslink.epoch crosslink_end_epoch = slot_to_epoch(attestation.data.slot) - crosslink_crosslink_length = min(MAX_CROSSLINK_EPOCHS, end_epoch - start_epoch) + crosslink_crosslink_length = min(MAX_EPOCHS_PER_CROSSLINK, end_epoch - start_epoch) chunks_per_epoch = 2 * BYTES_PER_SHARD_BLOCK * SLOTS_PER_EPOCH // BYTES_PER_CUSTODY_CHUNK return crosslink_crosslink_length * chunks_per_epoch ``` @@ -426,10 +426,10 @@ def process_early_derived_secret_reveal(state: BeaconState, # round key slash_validator(state, reveal.revealed_index, reveal.masker_index) else: - # Only a small penalty proportional to proposer slot reward for RANDAO reveal + # Only a small penalty proportional to proposer slot reward for RANDAO reveal # that does not interfere with the custody period - # The penalty is proportional to the max proposer reward - + # The penalty is proportional to the max proposer reward + # Calculate penalty max_proposer_slot_reward = ( get_base_reward(state, reveal.revealed_index) * @@ -448,7 +448,7 @@ def process_early_derived_secret_reveal(state: BeaconState, increase_balance(state, whistleblower_index, whistleblowing_reward - proposer_reward) decrease_balance(state, reveal.revealed_index, penalty) - # Mark this derived secret as exposed so validator cannot be punished repeatedly + # Mark this derived secret as exposed so validator cannot be punished repeatedly state.exposed_derived_secrets[reveal.epoch % EARLY_DERIVED_SECRET_PENALTY_MAX_FUTURE_EPOCHS].append(reveal.revealed_index) ``` @@ -474,7 +474,7 @@ def process_chunk_challenge(state: BeaconState, # Verify the challenge is not a duplicate for record in state.custody_chunk_challenge_records: assert ( - record.crosslink_data_root != challenge.attestation.data.crosslink_data_root or + record.crosslink_data_root != challenge.attestation.data.crosslink.crosslink_data_root or record.chunk_index != challenge.chunk_index ) # Verify depth @@ -486,7 +486,7 @@ def process_chunk_challenge(state: BeaconState, challenger_index=get_beacon_proposer_index(state), responder_index=challenge.responder_index deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE, - crosslink_data_root=challenge.attestation.data.crosslink_data_root, + crosslink_data_root=challenge.attestation.data.crosslink.crosslink_data_root, depth=depth, chunk_index=challenge.chunk_index, ) @@ -564,7 +564,7 @@ def process_bit_challenge(state: BeaconState, challenger_index=challenge.challenger_index, responder_index=challenge.responder_index, deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE, - crosslink_data_root=challenge.attestation.data.crosslink_data_root, + crosslink_data_root=challenge.attestation.data.crosslink.crosslink_data_root, chunk_count=chunk_count, chunk_bits_merkle_root=merkle_root(pad_to_power_of_2((challenge.chunk_bits))), responder_key=challenge.responder_key, diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 33ef8632b0..673a64a4a7 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -215,7 +215,7 @@ def get_shard_header(block: ShardBlock) -> ShardBlockHeader: def verify_shard_attestation_signature(state: BeaconState, attestation: ShardAttestation) -> None: data = attestation.data - persistent_committee = get_persistent_committee(state, data.shard, data.slot) + persistent_committee = get_persistent_committee(state, data.crosslink.shard, data.slot) assert verify_bitfield(attestation.aggregation_bitfield, len(persistent_committee)) pubkeys = [] for i, index in enumerate(persistent_committee): @@ -225,7 +225,7 @@ def verify_shard_attestation_signature(state: BeaconState, pubkeys.append(validator.pubkey) assert bls_verify( pubkey=bls_aggregate_pubkeys(pubkeys), - message_hash=data.shard_block_root, + message_hash=data.crosslink.shard_block_root, signature=attestation.aggregate_signature, domain=get_domain(state, slot_to_epoch(data.slot), DOMAIN_SHARD_ATTESTER) ) @@ -312,7 +312,7 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], for _, attestation in enumerate(block.attestations): assert max(GENESIS_SHARD_SLOT, block.slot - SLOTS_PER_EPOCH) <= attestation.data.slot assert attestation.data.slot <= block.slot - MIN_ATTESTATION_INCLUSION_DELAY - assert attestation.data.shard == block.shard + assert attestation.data.crosslink.shard == block.shard verify_shard_attestation_signature(beacon_state, attestation) # Check signature @@ -343,11 +343,11 @@ def is_valid_shard_attestation(valid_shard_blocks: List[ShardBlock], # Check shard block shard_block = next( block for block in valid_shard_blocks if - signing_root(block) == candidate.attestation.data.shard_block_root + signing_root(block) == candidate.attestation.data.crosslink.shard_block_root , None) assert shard_block != None assert shard_block.slot == attestation.data.slot - assert shard_block.shard == attestation.data.shard + assert shard_block.shard == attestation.data.crosslink.shard # Check signature verify_shard_attestation_signature(beacon_state, attestation) @@ -382,18 +382,18 @@ def is_valid_beacon_attestation(shard: Shard, else: previous_attestation = next( attestation for attestation in valid_attestations if - attestation.data.crosslink_data_root == candidate.data.previous_crosslink.crosslink_data_root + attestation.data.crosslink.crosslink_data_root == candidate.data.previous_crosslink.crosslink_data_root , None) assert previous_attestation != None assert candidate.data.previous_attestation.epoch < slot_to_epoch(candidate.data.slot) # Check crosslink data root start_epoch = state.latest_crosslinks[shard].epoch - end_epoch = min(slot_to_epoch(candidate.data.slot) - CROSSLINK_LOOKBACK, start_epoch + MAX_CROSSLINK_EPOCHS) + end_epoch = min(slot_to_epoch(candidate.data.slot) - CROSSLINK_LOOKBACK, start_epoch + MAX_EPOCHS_PER_CROSSLINK) blocks = [] for slot in range(start_epoch * SLOTS_PER_EPOCH, end_epoch * SLOTS_PER_EPOCH): blocks.append(shard_blocks[slot]) - assert candidate.data.crosslink_data_root == compute_crosslink_data_root(blocks) + assert candidate.data.crosslink.crosslink_data_root == compute_crosslink_data_root(blocks) return True ``` diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index ca7f0eb3b3..61f80f68e2 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -271,7 +271,7 @@ _Note:_ This can be looked up in the state using: ##### Shard -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.crosslink.shard = shard` where `shard` is the shard associated with the validator's committee defined by `get_crosslink_committees_at_slot`. ##### Previous crosslink root @@ -279,7 +279,7 @@ Set `attestation_data.previous_crosslink_root = hash_tree_root(head_state.curren ##### Crosslink data root -Set `attestation_data.crosslink_data_root = ZERO_HASH`. +Set `attestation_data.crosslink.crosslink_data_root = ZERO_HASH`. _Note:_ This is a stub for phase 0. diff --git a/test_libs/pyspec/tests/block_processing/test_process_attestation.py b/test_libs/pyspec/tests/block_processing/test_process_attestation.py index bcf71376ce..24cafc2755 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/tests/block_processing/test_process_attestation.py @@ -113,7 +113,7 @@ def test_non_zero_crosslink_data_root(state): attestation = get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - attestation.data.crosslink_data_root = b'\x42' * 32 + attestation.data.crosslink.crosslink_data_root = b'\x42' * 32 pre_state, post_state = run_attestation_processing(state, attestation, False) @@ -126,7 +126,7 @@ def test_bad_previous_crosslink(state): for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY): next_slot(state) - state.current_crosslinks[attestation.data.shard].epoch += 10 + state.current_crosslinks[attestation.data.crosslink.shard].epoch += 10 pre_state, post_state = run_attestation_processing(state, attestation, False) diff --git a/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py b/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py index d6765e3a72..29e7347b12 100644 --- a/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py +++ b/test_libs/pyspec/tests/epoch_processing/test_process_crosslinks.py @@ -64,7 +64,7 @@ def test_single_crosslink_update_from_current_epoch(state): pre_state, post_state = run_process_crosslinks(state) - shard = attestation.data.shard + shard = attestation.data.crosslink.shard assert post_state.previous_crosslinks[shard] != post_state.current_crosslinks[shard] assert pre_state.current_crosslinks[shard] != post_state.current_crosslinks[shard] @@ -84,11 +84,11 @@ def test_single_crosslink_update_from_previous_epoch(state): pre_state, post_state = run_process_crosslinks(state) crosslink_deltas = get_crosslink_deltas(state) - shard = attestation.data.shard + shard = attestation.data.crosslink.shard assert post_state.previous_crosslinks[shard] != post_state.current_crosslinks[shard] assert pre_state.current_crosslinks[shard] != post_state.current_crosslinks[shard] # ensure rewarded - for index in get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.shard): + for index in get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard): assert crosslink_deltas[0][index] > 0 assert crosslink_deltas[1][index] == 0 @@ -108,7 +108,7 @@ def test_double_late_crosslink(state): for slot in range(spec.SLOTS_PER_EPOCH): attestation_2 = get_valid_attestation(state) - if attestation_2.data.shard == attestation_1.data.shard: + if attestation_2.data.crosslink.shard == attestation_1.data.crosslink.shard: break next_slot(state) fill_aggregate_attestation(state, attestation_2) @@ -124,12 +124,12 @@ def test_double_late_crosslink(state): pre_state, post_state = run_process_crosslinks(state) crosslink_deltas = get_crosslink_deltas(state) - shard = attestation_2.data.shard + shard = attestation_2.data.crosslink.shard # ensure that the current crosslinks were not updated by the second attestation assert post_state.previous_crosslinks[shard] == post_state.current_crosslinks[shard] # ensure no reward, only penalties for the failed crosslink - for index in get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.shard): + for index in get_crosslink_committee(state, attestation_2.data.target_epoch, attestation_2.data.crosslink.shard): assert crosslink_deltas[0][index] == 0 assert crosslink_deltas[1][index] > 0 diff --git a/test_libs/pyspec/tests/helpers.py b/test_libs/pyspec/tests/helpers.py index 3b9b6904d5..1ea299453d 100644 --- a/test_libs/pyspec/tests/helpers.py +++ b/test_libs/pyspec/tests/helpers.py @@ -10,6 +10,7 @@ from eth2spec.phase0.spec import ( # constants ZERO_HASH, + MAX_EPOCHS_PER_CROSSLINK, # SSZ Attestation, AttestationData, @@ -17,6 +18,7 @@ AttesterSlashing, BeaconBlock, BeaconBlockHeader, + Crosslink, Deposit, DepositData, Eth1Data, @@ -174,14 +176,17 @@ def build_attestation_data(state, slot, shard): crosslinks = state.current_crosslinks if slot_to_epoch(slot) == get_current_epoch(state) else state.previous_crosslinks return AttestationData( - shard=shard, beacon_block_root=block_root, source_epoch=justified_epoch, source_root=justified_block_root, target_epoch=slot_to_epoch(slot), target_root=epoch_boundary_root, - crosslink_data_root=spec.ZERO_HASH, - previous_crosslink_root=hash_tree_root(crosslinks[shard]), + crosslink=Crosslink( + shard=shard, + epoch=min(slot_to_epoch(slot), crosslinks[shard].epoch + MAX_EPOCHS_PER_CROSSLINK), + crosslink_data_root=spec.ZERO_HASH, + previous_crosslink_root=hash_tree_root(crosslinks[shard]), + ), ) @@ -288,7 +293,7 @@ def get_valid_attestation(state, slot=None): attestation_data = build_attestation_data(state, slot, shard) - crosslink_committee = get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.shard) + crosslink_committee = get_crosslink_committee(state, attestation_data.target_epoch, attestation_data.crosslink.shard) committee_size = len(crosslink_committee) bitfield_length = (committee_size + 7) // 8 @@ -381,7 +386,7 @@ def get_attestation_signature(state, attestation_data, privkey, custody_bit=0b0) def fill_aggregate_attestation(state, attestation): - crosslink_committee = get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.shard) + crosslink_committee = get_crosslink_committee(state, attestation.data.target_epoch, attestation.data.crosslink.shard) for i in range(len(crosslink_committee)): attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i) From b15105e1cbb4a597fea233b16eac23ae911570a6 Mon Sep 17 00:00:00 2001 From: Justin Drake Date: Mon, 6 May 2019 17:34:03 +0100 Subject: [PATCH 3/8] Address Danny's comment --- specs/core/0_beacon-chain.md | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 156a2523d2..0bd85478ec 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -1298,22 +1298,17 @@ def get_attesting_balance(state: BeaconState, attestations: List[PendingAttestat ```python def get_winning_crosslink_and_attesting_indices(state: BeaconState, epoch: Epoch, shard: Shard) -> Tuple[Crosslink, List[ValidatorIndex]]: - shard_attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.crosslink.shard == shard] - candidate_crosslinks = [ - c for c in [a.data.crosslink for a in shard_attestations] - if hash_tree_root(state.current_crosslinks[shard]) in (c.previous_crosslink_root, hash_tree_root(c)) - ] - if len(candidate_crosslinks) == 0: - return Crosslink(), [] - - def get_attestations_for(crosslink: Crosslink) -> List[PendingAttestation]: - return [a for a in shard_attestations if a.data.crosslink == crosslink] - # Winning crosslink has the crosslink data root with the most balance voting for it (ties broken lexicographically) - winning_crosslink = max(candidate_crosslinks, key=lambda crosslink: ( - get_attesting_balance(state, get_attestations_for(crosslink)), crosslink.crosslink_data_root + attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.crosslink.shard == shard] + crosslinks = list(filter( + lambda c: hash_tree_root(state.current_crosslinks[shard]) in (c.previous_crosslink_root, hash_tree_root(c)), + [a.data.crosslink for a in attestations] )) - - return winning_crosslink, get_unslashed_attesting_indices(state, get_attestations_for(winning_crosslink)) + # Winning crosslink has the crosslink data root with the most balance voting for it (ties broken lexicographically) + winning_crosslink = max(crosslinks, key=lambda c: ( + get_attesting_balance(state, [a for a in attestations if a.data.crosslink == c]), c.crosslink_data_root + ), default=Crosslink()) + winning_attestations = [a for a in attestations if a.data.crosslink == winning_crosslink] + return winning_crosslink, get_unslashed_attesting_indices(state, winning_attestations) ``` #### Justification and finalization From 8b1a2edb7c650e0e0205e11c44f44a2a578ce392 Mon Sep 17 00:00:00 2001 From: Justin Drake Date: Mon, 6 May 2019 17:53:49 +0100 Subject: [PATCH 4/8] Fix genesis bug --- specs/core/0_beacon-chain.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 9aed2001a8..04ab38e18f 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -767,7 +767,7 @@ def get_epoch_start_shard(state: BeaconState, epoch: Epoch) -> Shard: ```python def get_attestation_data_slot(state: BeaconState, data: AttestationData) -> Slot: committee_count = get_epoch_committee_count(state, data.target_epoch) - offset = (data.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 get_epoch_start_slot(data.target_epoch) + offset // (committee_count // SLOTS_PER_EPOCH) ``` @@ -1705,14 +1705,14 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: ) assert data.target_epoch in (get_previous_epoch(state), get_current_epoch(state)) - if data.target_epoch == get_previous_epoch(state): - ffg_data = (state.previous_justified_epoch, state.previous_justified_root, get_previous_epoch(state)) - previous_crosslink = state.previous_crosslinks[data.crosslink.shard] - state.previous_epoch_attestations.append(pending_attestation) if data.target_epoch == get_current_epoch(state): ffg_data = (state.current_justified_epoch, state.current_justified_root, get_current_epoch(state)) previous_crosslink = state.current_crosslinks[data.crosslink.shard] state.current_epoch_attestations.append(pending_attestation) + else: + ffg_data = (state.previous_justified_epoch, state.previous_justified_root, get_previous_epoch(state)) + previous_crosslink = state.previous_crosslinks[data.crosslink.shard] + state.previous_epoch_attestations.append(pending_attestation) # Check FFG data, crosslink data, and signature assert ffg_data == (data.source_epoch, data.source_root, data.target_epoch) From f4db9ebae00338ba336943a08271012099bcef1d Mon Sep 17 00:00:00 2001 From: Justin Drake Date: Mon, 6 May 2019 18:26:14 +0100 Subject: [PATCH 5/8] Renamings triggered by HW comment --- specs/core/0_beacon-chain.md | 26 +++++++++---------- specs/core/0_fork-choice.md | 2 +- specs/core/1_custody-game.md | 14 +++++----- specs/core/1_shard-data-chains.md | 16 ++++++------ specs/validator/0_beacon-chain-validator.md | 6 ++--- .../test_process_attestation.py | 2 +- .../test_process_block_header.py | 4 +-- test_libs/pyspec/tests/helpers.py | 12 ++++----- test_libs/pyspec/tests/test_sanity.py | 6 ++--- 9 files changed, 44 insertions(+), 44 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index 04ab38e18f..afca9eb1ba 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -287,9 +287,9 @@ The types are defined topologically to aid in facilitating an executable version # Epoch number 'epoch': 'uint64', # Root of the previous crosslink - 'previous_crosslink_root': 'bytes32', + 'parent_crosslink_root': 'bytes32', # Root of the crosslinked shard data since the previous crosslink - 'crosslink_data_root': 'bytes32', + 'data_root': 'bytes32', } ``` @@ -369,7 +369,7 @@ The types are defined topologically to aid in facilitating an executable version ```python { 'slot': 'uint64', - 'previous_block_root': 'bytes32', + 'parent_block_root': 'bytes32', 'state_root': 'bytes32', 'block_body_root': 'bytes32', 'signature': 'bytes96', @@ -536,7 +536,7 @@ The types are defined topologically to aid in facilitating an executable version { # Header 'slot': 'uint64', - 'previous_block_root': 'bytes32', + 'parent_block_root': 'bytes32', 'state_root': 'bytes32', 'body': BeaconBlockBody, 'signature': 'bytes96', @@ -1306,12 +1306,12 @@ def get_attesting_balance(state: BeaconState, attestations: List[PendingAttestat def get_winning_crosslink_and_attesting_indices(state: BeaconState, epoch: Epoch, shard: Shard) -> Tuple[Crosslink, List[ValidatorIndex]]: attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.crosslink.shard == shard] crosslinks = list(filter( - lambda c: hash_tree_root(state.current_crosslinks[shard]) in (c.previous_crosslink_root, hash_tree_root(c)), + lambda c: hash_tree_root(state.current_crosslinks[shard]) in (c.parent_crosslink_root, hash_tree_root(c)), [a.data.crosslink for a in attestations] )) # Winning crosslink has the crosslink data root with the most balance voting for it (ties broken lexicographically) winning_crosslink = max(crosslinks, key=lambda c: ( - get_attesting_balance(state, [a for a in attestations if a.data.crosslink == c]), c.crosslink_data_root + get_attesting_balance(state, [a for a in attestations if a.data.crosslink == c]), c.data_root ), default=Crosslink()) winning_attestations = [a for a in attestations if a.data.crosslink == winning_crosslink] return winning_crosslink, get_unslashed_attesting_indices(state, winning_attestations) @@ -1586,11 +1586,11 @@ def process_block_header(state: BeaconState, block: BeaconBlock) -> None: # Verify that the slots match assert block.slot == state.slot # Verify that the parent matches - assert block.previous_block_root == signing_root(state.latest_block_header) + assert block.parent_block_root == signing_root(state.latest_block_header) # Save current block as the new latest block state.latest_block_header = BeaconBlockHeader( slot=block.slot, - previous_block_root=block.previous_block_root, + parent_block_root=block.parent_block_root, block_body_root=hash_tree_root(block.body), ) # Verify proposer is not slashed @@ -1707,18 +1707,18 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: assert data.target_epoch in (get_previous_epoch(state), 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)) - previous_crosslink = state.current_crosslinks[data.crosslink.shard] + parent_crosslink = state.current_crosslinks[data.crosslink.shard] state.current_epoch_attestations.append(pending_attestation) else: ffg_data = (state.previous_justified_epoch, state.previous_justified_root, get_previous_epoch(state)) - previous_crosslink = state.previous_crosslinks[data.crosslink.shard] + parent_crosslink = state.previous_crosslinks[data.crosslink.shard] state.previous_epoch_attestations.append(pending_attestation) # Check FFG data, crosslink data, and signature assert ffg_data == (data.source_epoch, data.source_root, data.target_epoch) - assert data.crosslink.epoch == min(data.target_epoch, previous_crosslink.epoch + MAX_EPOCHS_PER_CROSSLINK) - assert data.crosslink.previous_crosslink_root == hash_tree_root(previous_crosslink) - assert data.crosslink.crosslink_data_root == ZERO_HASH # [to be removed in phase 1] + assert data.crosslink.epoch == min(data.target_epoch, parent_crosslink.epoch + MAX_EPOCHS_PER_CROSSLINK) + assert data.crosslink.parent_crosslink_root == hash_tree_root(parent_crosslink) + assert data.crosslink.data_root == ZERO_HASH # [to be removed in phase 1] assert verify_indexed_attestation(state, convert_to_indexed(state, attestation)) ``` diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 549e9e2077..891120de8e 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -38,7 +38,7 @@ All terminology, constants, functions, and protocol mechanics defined in the [Ph Processing the beacon chain is similar to processing the Ethereum 1.0 chain. Clients download and process blocks and maintain a view of what is the current "canonical chain", terminating at the current "head". For a beacon block, `block`, to be processed by a node, the following conditions must be met: -* The parent block with root `block.previous_block_root` has been processed and accepted. +* The parent block with root `block.parent_block_root` has been processed and accepted. * An Ethereum 1.0 block pointed to by the `state.latest_eth1_data.block_hash` has been processed and accepted. * The node's Unix time is greater than or equal to `state.genesis_time + block.slot * SECONDS_PER_SLOT`. diff --git a/specs/core/1_custody-game.md b/specs/core/1_custody-game.md index e259b82a55..a030c577bf 100644 --- a/specs/core/1_custody-game.md +++ b/specs/core/1_custody-game.md @@ -147,7 +147,7 @@ This document details the beacon chain additions and changes in Phase 1 of Ether 'challenger_index': ValidatorIndex, 'responder_index': ValidatorIndex, 'deadline': Epoch, - 'crosslink_data_root': Hash, + 'data_root': Hash, 'depth': 'uint64', 'chunk_index': 'uint64', } @@ -161,7 +161,7 @@ This document details the beacon chain additions and changes in Phase 1 of Ether 'challenger_index': ValidatorIndex, 'responder_index': ValidatorIndex, 'deadline': Epoch, - 'crosslink_data_root': Hash, + 'data_root': Hash, 'chunk_count': 'uint64', 'chunk_bits_merkle_root': Hash, 'responder_key': BLSSignature, @@ -474,7 +474,7 @@ def process_chunk_challenge(state: BeaconState, # Verify the challenge is not a duplicate for record in state.custody_chunk_challenge_records: assert ( - record.crosslink_data_root != challenge.attestation.data.crosslink.crosslink_data_root or + record.data_root != challenge.attestation.data.crosslink.data_root or record.chunk_index != challenge.chunk_index ) # Verify depth @@ -486,7 +486,7 @@ def process_chunk_challenge(state: BeaconState, challenger_index=get_beacon_proposer_index(state), responder_index=challenge.responder_index deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE, - crosslink_data_root=challenge.attestation.data.crosslink.crosslink_data_root, + data_root=challenge.attestation.data.crosslink.data_root, depth=depth, chunk_index=challenge.chunk_index, ) @@ -564,7 +564,7 @@ def process_bit_challenge(state: BeaconState, challenger_index=challenge.challenger_index, responder_index=challenge.responder_index, deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE, - crosslink_data_root=challenge.attestation.data.crosslink.crosslink_data_root, + data_root=challenge.attestation.data.crosslink.data_root, chunk_count=chunk_count, chunk_bits_merkle_root=merkle_root(pad_to_power_of_2((challenge.chunk_bits))), responder_key=challenge.responder_key, @@ -610,7 +610,7 @@ def process_chunk_challenge_response(state: BeaconState, branch=response.data_branch, depth=challenge.depth, index=response.chunk_index, - root=challenge.crosslink_data_root, + root=challenge.data_root, ) # Clear the challenge records = state.custody_chunk_challenge_records @@ -632,7 +632,7 @@ def process_bit_challenge_response(state: BeaconState, branch=response.data_branch, depth=math.log2(next_power_of_two(challenge.chunk_count)), index=response.chunk_index, - root=challenge.crosslink_data_root, + root=challenge.data_root, ) # Verify the chunk bit leaf matches the challenge data assert verify_merkle_branch( diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 9fbc696929..316bd0068f 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -78,7 +78,7 @@ This document describes the shard data layer and the shard fork choice rule in P 'slot': Slot, 'shard': Shard, 'beacon_chain_root': Hash, - 'previous_block_root': Hash, + 'parent_block_root': Hash, 'data': ShardBlockBody, 'state_root': Hash, 'attestations': [ShardAttestation], @@ -93,7 +93,7 @@ This document describes the shard data layer and the shard fork choice rule in P 'slot': Slot, 'shard': Shard, 'beacon_chain_root': Hash, - 'previous_block_root': Hash, + 'parent_block_root': Hash, 'body_root': Hash, 'state_root': Hash, 'attestations': [ShardAttestation], @@ -201,7 +201,7 @@ def get_shard_header(block: ShardBlock) -> ShardBlockHeader: slot: block.slot, shard: block.shard, beacon_chain_root: block.beacon_chain_root, - previous_block_root: block.previous_block_root, + parent_block_root: block.parent_block_root, body_root: hash_tree_root(block.body), state_root: block.state_root, attestations: block.attestations, @@ -296,11 +296,11 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], # Check parent block if block.slot == PHASE_1_GENESIS_SLOT: - assert candidate.previous_block_root == ZERO_HASH + assert candidate.parent_block_root == ZERO_HASH else: parent_block = next( block for block in valid_shard_blocks if - signing_root(block) == candidate.previous_block_root + signing_root(block) == candidate.parent_block_root , None) assert parent_block != None assert parent_block.shard == block.shard @@ -378,11 +378,11 @@ def is_valid_beacon_attestation(shard: Shard, # Check previous attestation if candidate.data.previous_crosslink.epoch <= PHASE_1_GENESIS_EPOCH: - assert candidate.data.previous_crosslink.crosslink_data_root == ZERO_HASH + assert candidate.data.previous_crosslink.data_root == ZERO_HASH else: previous_attestation = next( attestation for attestation in valid_attestations if - attestation.data.crosslink.crosslink_data_root == candidate.data.previous_crosslink.crosslink_data_root + attestation.data.crosslink.data_root == candidate.data.previous_crosslink.data_root , None) assert previous_attestation != None assert candidate.data.previous_attestation.epoch < slot_to_epoch(candidate.data.slot) @@ -393,7 +393,7 @@ def is_valid_beacon_attestation(shard: Shard, blocks = [] for slot in range(start_epoch * SLOTS_PER_EPOCH, end_epoch * SLOTS_PER_EPOCH): blocks.append(shard_blocks[slot]) - assert candidate.data.crosslink.crosslink_data_root == compute_crosslink_data_root(blocks) + assert candidate.data.crosslink.data_root == compute_crosslink_data_root(blocks) return True ``` diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index cfe6a8f1ff..dae9ac85f4 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -152,7 +152,7 @@ Set `block.slot = slot` where `slot` is the current slot at which the validator ##### Parent root -Set `block.previous_block_root = signing_root(parent)`. +Set `block.parent_block_root = signing_root(parent)`. ##### State root @@ -275,11 +275,11 @@ Set `attestation_data.crosslink.shard = shard` where `shard` is the shard associ ##### Previous crosslink root -Set `attestation_data.previous_crosslink_root = hash_tree_root(head_state.current_crosslinks[shard])`. +Set `attestation_data.parent_crosslink_root = hash_tree_root(head_state.current_crosslinks[shard])`. ##### Crosslink data root -Set `attestation_data.crosslink.crosslink_data_root = ZERO_HASH`. +Set `attestation_data.crosslink.data_root = ZERO_HASH`. *Note*: This is a stub for Phase 0. diff --git a/test_libs/pyspec/tests/block_processing/test_process_attestation.py b/test_libs/pyspec/tests/block_processing/test_process_attestation.py index 24cafc2755..fcbc68fe9b 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_attestation.py +++ b/test_libs/pyspec/tests/block_processing/test_process_attestation.py @@ -113,7 +113,7 @@ def test_non_zero_crosslink_data_root(state): attestation = get_valid_attestation(state) state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY - attestation.data.crosslink.crosslink_data_root = b'\x42' * 32 + attestation.data.crosslink.data_root = b'\x42' * 32 pre_state, post_state = run_attestation_processing(state, attestation, False) diff --git a/test_libs/pyspec/tests/block_processing/test_process_block_header.py b/test_libs/pyspec/tests/block_processing/test_process_block_header.py index b35b0a9c11..e4fa516b1e 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_block_header.py +++ b/test_libs/pyspec/tests/block_processing/test_process_block_header.py @@ -53,9 +53,9 @@ def test_invalid_slot(state): return pre_state, block, None -def test_invalid_previous_block_root(state): +def test_invalid_parent_block_root(state): block = build_empty_block_for_next_slot(state) - block.previous_block_root = b'\12' * 32 # invalid prev root + block.parent_block_root = b'\12' * 32 # invalid prev root pre_state, post_state = run_block_header_processing(state, block, valid=False) return pre_state, block, None diff --git a/test_libs/pyspec/tests/helpers.py b/test_libs/pyspec/tests/helpers.py index 1ea299453d..e7ee826db4 100644 --- a/test_libs/pyspec/tests/helpers.py +++ b/test_libs/pyspec/tests/helpers.py @@ -128,7 +128,7 @@ def build_empty_block_for_next_slot(state): previous_block_header = deepcopy(state.latest_block_header) if previous_block_header.state_root == spec.ZERO_HASH: previous_block_header.state_root = state.hash_tree_root() - empty_block.previous_block_root = signing_root(previous_block_header) + empty_block.parent_block_root = signing_root(previous_block_header) return empty_block @@ -155,7 +155,7 @@ def build_attestation_data(state, slot, shard): assert state.slot >= slot if slot == state.slot: - block_root = build_empty_block_for_next_slot(state).previous_block_root + block_root = build_empty_block_for_next_slot(state).parent_block_root else: block_root = get_block_root_at_slot(state, slot) @@ -184,8 +184,8 @@ def build_attestation_data(state, slot, shard): crosslink=Crosslink( shard=shard, epoch=min(slot_to_epoch(slot), crosslinks[shard].epoch + MAX_EPOCHS_PER_CROSSLINK), - crosslink_data_root=spec.ZERO_HASH, - previous_crosslink_root=hash_tree_root(crosslinks[shard]), + data_root=spec.ZERO_HASH, + parent_crosslink_root=hash_tree_root(crosslinks[shard]), ), ) @@ -240,12 +240,12 @@ def get_valid_proposer_slashing(state): header_1 = BeaconBlockHeader( slot=slot, - previous_block_root=ZERO_HASH, + parent_block_root=ZERO_HASH, state_root=ZERO_HASH, block_body_root=ZERO_HASH, ) header_2 = deepcopy(header_1) - header_2.previous_block_root = b'\x02' * 32 + header_2.parent_block_root = b'\x02' * 32 header_2.slot = slot + 1 domain = get_domain( diff --git a/test_libs/pyspec/tests/test_sanity.py b/test_libs/pyspec/tests/test_sanity.py index 1b4d20f4c5..83ba9cc113 100644 --- a/test_libs/pyspec/tests/test_sanity.py +++ b/test_libs/pyspec/tests/test_sanity.py @@ -68,7 +68,7 @@ def test_empty_block_transition(state): state_transition(test_state, block) assert len(test_state.eth1_data_votes) == len(state.eth1_data_votes) + 1 - assert get_block_root_at_slot(test_state, state.slot) == block.previous_block_root + assert get_block_root_at_slot(test_state, state.slot) == block.parent_block_root return state, [block], test_state @@ -82,7 +82,7 @@ def test_skipped_slots(state): assert test_state.slot == block.slot for slot in range(state.slot, test_state.slot): - assert get_block_root_at_slot(test_state, slot) == block.previous_block_root + assert get_block_root_at_slot(test_state, slot) == block.parent_block_root return state, [block], test_state @@ -96,7 +96,7 @@ def test_empty_epoch_transition(state): assert test_state.slot == block.slot for slot in range(state.slot, test_state.slot): - assert get_block_root_at_slot(test_state, slot) == block.previous_block_root + assert get_block_root_at_slot(test_state, slot) == block.parent_block_root return state, [block], test_state From ea60fb632c3a07d2dae29b6ca8d37cea204bc6e7 Mon Sep 17 00:00:00 2001 From: Justin Drake Date: Mon, 6 May 2019 20:49:46 +0100 Subject: [PATCH 6/8] More renaming --- specs/core/0_beacon-chain.md | 14 +++++++------- specs/core/0_fork-choice.md | 2 +- specs/core/1_shard-data-chains.md | 10 +++++----- specs/validator/0_beacon-chain-validator.md | 4 ++-- .../block_processing/test_process_block_header.py | 2 +- test_libs/pyspec/tests/helpers.py | 12 ++++++------ test_libs/pyspec/tests/test_sanity.py | 6 +++--- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index afca9eb1ba..ccba4c817d 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -287,7 +287,7 @@ The types are defined topologically to aid in facilitating an executable version # Epoch number 'epoch': 'uint64', # Root of the previous crosslink - 'parent_crosslink_root': 'bytes32', + 'parent_root': 'bytes32', # Root of the crosslinked shard data since the previous crosslink 'data_root': 'bytes32', } @@ -369,7 +369,7 @@ The types are defined topologically to aid in facilitating an executable version ```python { 'slot': 'uint64', - 'parent_block_root': 'bytes32', + 'parent_root': 'bytes32', 'state_root': 'bytes32', 'block_body_root': 'bytes32', 'signature': 'bytes96', @@ -536,7 +536,7 @@ The types are defined topologically to aid in facilitating an executable version { # Header 'slot': 'uint64', - 'parent_block_root': 'bytes32', + 'parent_root': 'bytes32', 'state_root': 'bytes32', 'body': BeaconBlockBody, 'signature': 'bytes96', @@ -1306,7 +1306,7 @@ def get_attesting_balance(state: BeaconState, attestations: List[PendingAttestat def get_winning_crosslink_and_attesting_indices(state: BeaconState, epoch: Epoch, shard: Shard) -> Tuple[Crosslink, List[ValidatorIndex]]: attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.crosslink.shard == shard] crosslinks = list(filter( - lambda c: hash_tree_root(state.current_crosslinks[shard]) in (c.parent_crosslink_root, hash_tree_root(c)), + lambda c: hash_tree_root(state.current_crosslinks[shard]) in (c.parent_root, hash_tree_root(c)), [a.data.crosslink for a in attestations] )) # Winning crosslink has the crosslink data root with the most balance voting for it (ties broken lexicographically) @@ -1586,11 +1586,11 @@ def process_block_header(state: BeaconState, block: BeaconBlock) -> None: # Verify that the slots match assert block.slot == state.slot # Verify that the parent matches - assert block.parent_block_root == signing_root(state.latest_block_header) + assert block.parent_root == signing_root(state.latest_block_header) # Save current block as the new latest block state.latest_block_header = BeaconBlockHeader( slot=block.slot, - parent_block_root=block.parent_block_root, + parent_root=block.parent_root, block_body_root=hash_tree_root(block.body), ) # Verify proposer is not slashed @@ -1717,7 +1717,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: # Check FFG data, crosslink data, and signature assert ffg_data == (data.source_epoch, data.source_root, data.target_epoch) assert data.crosslink.epoch == min(data.target_epoch, parent_crosslink.epoch + MAX_EPOCHS_PER_CROSSLINK) - assert data.crosslink.parent_crosslink_root == hash_tree_root(parent_crosslink) + assert data.crosslink.parent_root == hash_tree_root(parent_crosslink) assert data.crosslink.data_root == ZERO_HASH # [to be removed in phase 1] assert verify_indexed_attestation(state, convert_to_indexed(state, attestation)) ``` diff --git a/specs/core/0_fork-choice.md b/specs/core/0_fork-choice.md index 891120de8e..91c3e27ee4 100644 --- a/specs/core/0_fork-choice.md +++ b/specs/core/0_fork-choice.md @@ -38,7 +38,7 @@ All terminology, constants, functions, and protocol mechanics defined in the [Ph Processing the beacon chain is similar to processing the Ethereum 1.0 chain. Clients download and process blocks and maintain a view of what is the current "canonical chain", terminating at the current "head". For a beacon block, `block`, to be processed by a node, the following conditions must be met: -* The parent block with root `block.parent_block_root` has been processed and accepted. +* The parent block with root `block.parent_root` has been processed and accepted. * An Ethereum 1.0 block pointed to by the `state.latest_eth1_data.block_hash` has been processed and accepted. * The node's Unix time is greater than or equal to `state.genesis_time + block.slot * SECONDS_PER_SLOT`. diff --git a/specs/core/1_shard-data-chains.md b/specs/core/1_shard-data-chains.md index 316bd0068f..ca59c3ebc4 100644 --- a/specs/core/1_shard-data-chains.md +++ b/specs/core/1_shard-data-chains.md @@ -78,7 +78,7 @@ This document describes the shard data layer and the shard fork choice rule in P 'slot': Slot, 'shard': Shard, 'beacon_chain_root': Hash, - 'parent_block_root': Hash, + 'parent_root': Hash, 'data': ShardBlockBody, 'state_root': Hash, 'attestations': [ShardAttestation], @@ -93,7 +93,7 @@ This document describes the shard data layer and the shard fork choice rule in P 'slot': Slot, 'shard': Shard, 'beacon_chain_root': Hash, - 'parent_block_root': Hash, + 'parent_root': Hash, 'body_root': Hash, 'state_root': Hash, 'attestations': [ShardAttestation], @@ -201,7 +201,7 @@ def get_shard_header(block: ShardBlock) -> ShardBlockHeader: slot: block.slot, shard: block.shard, beacon_chain_root: block.beacon_chain_root, - parent_block_root: block.parent_block_root, + parent_root: block.parent_root, body_root: hash_tree_root(block.body), state_root: block.state_root, attestations: block.attestations, @@ -296,11 +296,11 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock], # Check parent block if block.slot == PHASE_1_GENESIS_SLOT: - assert candidate.parent_block_root == ZERO_HASH + assert candidate.parent_root == ZERO_HASH else: parent_block = next( block for block in valid_shard_blocks if - signing_root(block) == candidate.parent_block_root + signing_root(block) == candidate.parent_root , None) assert parent_block != None assert parent_block.shard == block.shard diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index dae9ac85f4..a0173ebe92 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -152,7 +152,7 @@ Set `block.slot = slot` where `slot` is the current slot at which the validator ##### Parent root -Set `block.parent_block_root = signing_root(parent)`. +Set `block.parent_root = signing_root(parent)`. ##### State root @@ -275,7 +275,7 @@ Set `attestation_data.crosslink.shard = shard` where `shard` is the shard associ ##### Previous crosslink root -Set `attestation_data.parent_crosslink_root = hash_tree_root(head_state.current_crosslinks[shard])`. +Set `attestation_data.parent_root = hash_tree_root(head_state.current_crosslinks[shard])`. ##### Crosslink data root diff --git a/test_libs/pyspec/tests/block_processing/test_process_block_header.py b/test_libs/pyspec/tests/block_processing/test_process_block_header.py index e4fa516b1e..36c7298210 100644 --- a/test_libs/pyspec/tests/block_processing/test_process_block_header.py +++ b/test_libs/pyspec/tests/block_processing/test_process_block_header.py @@ -55,7 +55,7 @@ def test_invalid_slot(state): def test_invalid_parent_block_root(state): block = build_empty_block_for_next_slot(state) - block.parent_block_root = b'\12' * 32 # invalid prev root + block.parent_root = b'\12' * 32 # invalid prev root pre_state, post_state = run_block_header_processing(state, block, valid=False) return pre_state, block, None diff --git a/test_libs/pyspec/tests/helpers.py b/test_libs/pyspec/tests/helpers.py index e7ee826db4..2024885763 100644 --- a/test_libs/pyspec/tests/helpers.py +++ b/test_libs/pyspec/tests/helpers.py @@ -128,7 +128,7 @@ def build_empty_block_for_next_slot(state): previous_block_header = deepcopy(state.latest_block_header) if previous_block_header.state_root == spec.ZERO_HASH: previous_block_header.state_root = state.hash_tree_root() - empty_block.parent_block_root = signing_root(previous_block_header) + empty_block.parent_root = signing_root(previous_block_header) return empty_block @@ -155,7 +155,7 @@ def build_attestation_data(state, slot, shard): assert state.slot >= slot if slot == state.slot: - block_root = build_empty_block_for_next_slot(state).parent_block_root + block_root = build_empty_block_for_next_slot(state).parent_root else: block_root = get_block_root_at_slot(state, slot) @@ -185,7 +185,7 @@ def build_attestation_data(state, slot, shard): shard=shard, epoch=min(slot_to_epoch(slot), crosslinks[shard].epoch + MAX_EPOCHS_PER_CROSSLINK), data_root=spec.ZERO_HASH, - parent_crosslink_root=hash_tree_root(crosslinks[shard]), + parent_root=hash_tree_root(crosslinks[shard]), ), ) @@ -240,12 +240,12 @@ def get_valid_proposer_slashing(state): header_1 = BeaconBlockHeader( slot=slot, - parent_block_root=ZERO_HASH, + parent_root=ZERO_HASH, state_root=ZERO_HASH, - block_body_root=ZERO_HASH, + body_root=ZERO_HASH, ) header_2 = deepcopy(header_1) - header_2.parent_block_root = b'\x02' * 32 + header_2.parent_root = b'\x02' * 32 header_2.slot = slot + 1 domain = get_domain( diff --git a/test_libs/pyspec/tests/test_sanity.py b/test_libs/pyspec/tests/test_sanity.py index 83ba9cc113..0cb1b9be3b 100644 --- a/test_libs/pyspec/tests/test_sanity.py +++ b/test_libs/pyspec/tests/test_sanity.py @@ -68,7 +68,7 @@ def test_empty_block_transition(state): state_transition(test_state, block) assert len(test_state.eth1_data_votes) == len(state.eth1_data_votes) + 1 - assert get_block_root_at_slot(test_state, state.slot) == block.parent_block_root + assert get_block_root_at_slot(test_state, state.slot) == block.parent_root return state, [block], test_state @@ -82,7 +82,7 @@ def test_skipped_slots(state): assert test_state.slot == block.slot for slot in range(state.slot, test_state.slot): - assert get_block_root_at_slot(test_state, slot) == block.parent_block_root + assert get_block_root_at_slot(test_state, slot) == block.parent_root return state, [block], test_state @@ -96,7 +96,7 @@ def test_empty_epoch_transition(state): assert test_state.slot == block.slot for slot in range(state.slot, test_state.slot): - assert get_block_root_at_slot(test_state, slot) == block.parent_block_root + assert get_block_root_at_slot(test_state, slot) == block.parent_root return state, [block], test_state From 964e55cd4a8b8bfecbd70e279c13e69c6c977e22 Mon Sep 17 00:00:00 2001 From: Justin Drake Date: Tue, 7 May 2019 08:52:56 +0100 Subject: [PATCH 7/8] block_body_root => body_root --- specs/core/0_beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/core/0_beacon-chain.md b/specs/core/0_beacon-chain.md index ccba4c817d..9f80fe1736 100644 --- a/specs/core/0_beacon-chain.md +++ b/specs/core/0_beacon-chain.md @@ -371,7 +371,7 @@ The types are defined topologically to aid in facilitating an executable version 'slot': 'uint64', 'parent_root': 'bytes32', 'state_root': 'bytes32', - 'block_body_root': 'bytes32', + 'body_root': 'bytes32', 'signature': 'bytes96', } ``` @@ -1591,7 +1591,7 @@ def process_block_header(state: BeaconState, block: BeaconBlock) -> None: state.latest_block_header = BeaconBlockHeader( slot=block.slot, parent_root=block.parent_root, - block_body_root=hash_tree_root(block.body), + body_root=hash_tree_root(block.body), ) # Verify proposer is not slashed proposer = state.validator_registry[get_beacon_proposer_index(state)] From 13d2ee696939e192534c0278eb271fe53510caf7 Mon Sep 17 00:00:00 2001 From: Danny Ryan Date: Tue, 7 May 2019 11:49:45 -0600 Subject: [PATCH 8/8] cleanup validator guide for crosslinks --- specs/validator/0_beacon-chain-validator.md | 53 +++++++-------------- 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/specs/validator/0_beacon-chain-validator.md b/specs/validator/0_beacon-chain-validator.md index a0173ebe92..a95052b860 100644 --- a/specs/validator/0_beacon-chain-validator.md +++ b/specs/validator/0_beacon-chain-validator.md @@ -37,14 +37,9 @@ - [Voluntary exits](#voluntary-exits) - [Attestations](#attestations-1) - [Attestation data](#attestation-data) - - [Slot](#slot-1) - - [Beacon block root](#beacon-block-root) - - [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) + - [LMD GHOST vote](#lmd-ghost-vote) + - [FFG vote](#ffg-vote) + - [Crosslink vote](#crosslink-vote) - [Construct attestation](#construct-attestation) - [Data](#data) - [Aggregation bitfield](#aggregation-bitfield) @@ -245,43 +240,29 @@ First the validator should construct `attestation_data`, an [`AttestationData`]( * Let `head_block` be the result of running the fork choice during the assigned slot. * Let `head_state` be the state of `head_block` processed through any empty slots up to the assigned slot. -##### Slot - -Set `attestation_data.slot = head_state.slot`. - -##### Beacon block root +##### LMD GHOST vote 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`. +##### FFG vote -##### Target root +* Set `attestation_data.source_epoch = head_state.justified_epoch`. +* Set `attestation_data.source_root = head_state.current_justified_root`. +* Set `attestation_data.target_epoch = get_current_epoch(head_state)` +* Set `attestation_data.target_root = signing_root(epoch_boundary_block)` where `epoch_boundary_block` is the block at the most recent epoch boundary. -Set `attestation_data.target_root = signing_root(epoch_boundary)` where `epoch_boundary` is the block at the most recent epoch boundary. - -*Note*: This can be looked up in the state using: +*Note*: `epoch_boundary_block` 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)`. - -##### Shard - -Set `attestation_data.crosslink.shard = shard` where `shard` is the shard associated with the validator's committee defined by `get_crosslink_committees_at_slot`. +* Let `epoch_boundary_block = head if epoch_start_slot == head_state.slot else get_block_root(state, epoch_start_slot)`. -##### Previous crosslink root +##### Crosslink vote -Set `attestation_data.parent_root = hash_tree_root(head_state.current_crosslinks[shard])`. +Construct `attestation_data.crosslink` via the following -##### Crosslink data root - -Set `attestation_data.crosslink.data_root = ZERO_HASH`. - -*Note*: This is a stub for Phase 0. +* Set `attestation_data.crosslink.shard = shard` where `shard` is the shard associated with the validator's committee defined by `get_crosslink_committees_at_slot`. +* Set `attestation_data.crosslink.epoch = min(attestation_data.target_epoch, head_state.current_crosslinks[shard].epoch + MAX_EPOCHS_PER_CROSSLINK)`. +* Set `attestation_data.crosslink.parent_root = hash_tree_root(head_state.current_crosslinks[shard])`. +* Set `attestation_data.crosslink.data_root = ZERO_HASH`. *Note*: This is a stub for Phase 0. #### Construct attestation