Merge pull request #1044 from ethereum/JustinDrake-patch-21
Crosslink in AttestationData
This commit is contained in:
commit
af2bb7d6f6
|
@ -72,7 +72,7 @@ MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
|
||||||
# 2**11 (= 2,048) epochs 9 days
|
# 2**11 (= 2,048) epochs 9 days
|
||||||
PERSISTENT_COMMITTEE_PERIOD: 2048
|
PERSISTENT_COMMITTEE_PERIOD: 2048
|
||||||
# 2**6 (= 64) epochs ~7 hours
|
# 2**6 (= 64) epochs ~7 hours
|
||||||
MAX_CROSSLINK_EPOCHS: 64
|
MAX_EPOCHS_PER_CROSSLINK: 64
|
||||||
# 2**2 (= 4) epochs 25.6 minutes
|
# 2**2 (= 4) epochs 25.6 minutes
|
||||||
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
|
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
|
||||||
# 2**11 (= 2,048) epochs 9 days
|
# 2**11 (= 2,048) epochs 9 days
|
||||||
PERSISTENT_COMMITTEE_PERIOD: 2048
|
PERSISTENT_COMMITTEE_PERIOD: 2048
|
||||||
# 2**6 (= 64) epochs ~7 hours
|
# 2**6 (= 64) epochs ~7 hours
|
||||||
MAX_CROSSLINK_EPOCHS: 64
|
MAX_EPOCHS_PER_CROSSLINK: 64
|
||||||
# 2**2 (= 4) epochs 25.6 minutes
|
# 2**2 (= 4) epochs 25.6 minutes
|
||||||
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
|
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
|
||||||
|
|
||||||
|
|
|
@ -209,10 +209,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 |
|
| `SLOTS_PER_HISTORICAL_ROOT` | `2**13` (= 8,192) | slots | ~13 hours |
|
||||||
| `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` | `2**8` (= 256) | epochs | ~27 hours |
|
| `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` | `2**8` (= 256) | epochs | ~27 hours |
|
||||||
| `PERSISTENT_COMMITTEE_PERIOD` | `2**11` (= 2,048) | epochs | 9 days |
|
| `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 |
|
| `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
|
### State list lengths
|
||||||
|
|
||||||
|
@ -282,12 +282,14 @@ The types are defined topologically to aid in facilitating an executable version
|
||||||
|
|
||||||
```python
|
```python
|
||||||
{
|
{
|
||||||
|
# Shard number
|
||||||
|
'shard': 'uint64',
|
||||||
# Epoch number
|
# Epoch number
|
||||||
'epoch': 'uint64',
|
'epoch': 'uint64',
|
||||||
# Root of the previous crosslink
|
# Root of the previous crosslink
|
||||||
'previous_crosslink_root': 'bytes32',
|
'parent_root': 'bytes32',
|
||||||
# Root of the crosslinked shard data since the previous crosslink
|
# Root of the crosslinked shard data since the previous crosslink
|
||||||
'crosslink_data_root': 'bytes32',
|
'data_root': 'bytes32',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -318,9 +320,7 @@ The types are defined topologically to aid in facilitating an executable version
|
||||||
'target_root': 'bytes32',
|
'target_root': 'bytes32',
|
||||||
|
|
||||||
# Crosslink vote
|
# Crosslink vote
|
||||||
'shard': 'uint64',
|
'crosslink': Crosslink,
|
||||||
'previous_crosslink_root': 'bytes32',
|
|
||||||
'crosslink_data_root': 'bytes32',
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -369,9 +369,9 @@ The types are defined topologically to aid in facilitating an executable version
|
||||||
```python
|
```python
|
||||||
{
|
{
|
||||||
'slot': 'uint64',
|
'slot': 'uint64',
|
||||||
'previous_block_root': 'bytes32',
|
'parent_root': 'bytes32',
|
||||||
'state_root': 'bytes32',
|
'state_root': 'bytes32',
|
||||||
'block_body_root': 'bytes32',
|
'body_root': 'bytes32',
|
||||||
'signature': 'bytes96',
|
'signature': 'bytes96',
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -536,7 +536,7 @@ The types are defined topologically to aid in facilitating an executable version
|
||||||
{
|
{
|
||||||
# Header
|
# Header
|
||||||
'slot': 'uint64',
|
'slot': 'uint64',
|
||||||
'previous_block_root': 'bytes32',
|
'parent_root': 'bytes32',
|
||||||
'state_root': 'bytes32',
|
'state_root': 'bytes32',
|
||||||
'body': BeaconBlockBody,
|
'body': BeaconBlockBody,
|
||||||
'signature': 'bytes96',
|
'signature': 'bytes96',
|
||||||
|
@ -767,7 +767,7 @@ 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.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)
|
return get_epoch_start_slot(data.target_epoch) + offset // (committee_count // SLOTS_PER_EPOCH)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -929,7 +929,7 @@ def get_attesting_indices(state: BeaconState,
|
||||||
"""
|
"""
|
||||||
Return the sorted attesting indices corresponding to ``attestation_data`` and ``bitfield``.
|
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))
|
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])
|
||||||
```
|
```
|
||||||
|
@ -1305,34 +1305,19 @@ def get_attesting_balance(state: BeaconState, attestations: List[PendingAttestat
|
||||||
return get_total_balance(state, get_unslashed_attesting_indices(state, attestations))
|
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
|
```python
|
||||||
def get_winning_crosslink_and_attesting_indices(state: BeaconState, epoch: Epoch, shard: Shard) -> Tuple[Crosslink, List[ValidatorIndex]]:
|
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]
|
attestations = [a for a in get_matching_source_attestations(state, epoch) if a.data.crosslink.shard == shard]
|
||||||
shard_crosslinks = [get_crosslink_from_attestation_data(state, a.data) for a in shard_attestations]
|
crosslinks = list(filter(
|
||||||
candidate_crosslinks = [
|
lambda c: hash_tree_root(state.current_crosslinks[shard]) in (c.parent_root, hash_tree_root(c)),
|
||||||
c for c in shard_crosslinks
|
[a.data.crosslink for a in 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]
|
|
||||||
# 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
|
|
||||||
))
|
))
|
||||||
|
# Winning crosslink has the crosslink data root with the most balance voting for it (ties broken lexicographically)
|
||||||
return winning_crosslink, get_unslashed_attesting_indices(state, get_attestations_for(winning_crosslink))
|
winning_crosslink = max(crosslinks, key=lambda c: (
|
||||||
|
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)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Justification and finalization
|
#### Justification and finalization
|
||||||
|
@ -1604,12 +1589,12 @@ def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
|
||||||
# Verify that the slots match
|
# Verify that the slots match
|
||||||
assert block.slot == state.slot
|
assert block.slot == state.slot
|
||||||
# Verify that the parent matches
|
# Verify that the parent matches
|
||||||
assert block.previous_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
|
# Save current block as the new latest block
|
||||||
state.latest_block_header = BeaconBlockHeader(
|
state.latest_block_header = BeaconBlockHeader(
|
||||||
slot=block.slot,
|
slot=block.slot,
|
||||||
previous_block_root=block.previous_block_root,
|
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
|
# Verify proposer is not slashed
|
||||||
proposer = state.validator_registry[get_beacon_proposer_index(state)]
|
proposer = state.validator_registry[get_beacon_proposer_index(state)]
|
||||||
|
@ -1715,29 +1700,29 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||||
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
|
||||||
|
|
||||||
# Check target epoch, source epoch, source root, and source crosslink
|
|
||||||
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(
|
pending_attestation = PendingAttestation(
|
||||||
data=data,
|
data=data,
|
||||||
aggregation_bitfield=attestation.aggregation_bitfield,
|
aggregation_bitfield=attestation.aggregation_bitfield,
|
||||||
inclusion_delay=state.slot - attestation_slot,
|
inclusion_delay=state.slot - attestation_slot,
|
||||||
proposer_index=get_beacon_proposer_index(state),
|
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_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))
|
||||||
|
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))
|
||||||
|
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
|
||||||
|
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_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))
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Deposits
|
##### Deposits
|
||||||
|
|
|
@ -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:
|
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_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.
|
* 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`.
|
* The node's Unix time is greater than or equal to `state.genesis_time + block.slot * SECONDS_PER_SLOT`.
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ This document details the beacon chain additions and changes in Phase 1 of Ether
|
||||||
'challenger_index': ValidatorIndex,
|
'challenger_index': ValidatorIndex,
|
||||||
'responder_index': ValidatorIndex,
|
'responder_index': ValidatorIndex,
|
||||||
'deadline': Epoch,
|
'deadline': Epoch,
|
||||||
'crosslink_data_root': Hash,
|
'data_root': Hash,
|
||||||
'depth': 'uint64',
|
'depth': 'uint64',
|
||||||
'chunk_index': '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,
|
'challenger_index': ValidatorIndex,
|
||||||
'responder_index': ValidatorIndex,
|
'responder_index': ValidatorIndex,
|
||||||
'deadline': Epoch,
|
'deadline': Epoch,
|
||||||
'crosslink_data_root': Hash,
|
'data_root': Hash,
|
||||||
'chunk_count': 'uint64',
|
'chunk_count': 'uint64',
|
||||||
'chunk_bits_merkle_root': Hash,
|
'chunk_bits_merkle_root': Hash,
|
||||||
'responder_key': BLSSignature,
|
'responder_key': BLSSignature,
|
||||||
|
@ -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:
|
def get_custody_chunk_count(attestation: Attestation) -> int:
|
||||||
crosslink_start_epoch = attestation.data.latest_crosslink.epoch
|
crosslink_start_epoch = attestation.data.latest_crosslink.epoch
|
||||||
crosslink_end_epoch = slot_to_epoch(attestation.data.slot)
|
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
|
chunks_per_epoch = 2 * BYTES_PER_SHARD_BLOCK * SLOTS_PER_EPOCH // BYTES_PER_CUSTODY_CHUNK
|
||||||
return crosslink_crosslink_length * chunks_per_epoch
|
return crosslink_crosslink_length * chunks_per_epoch
|
||||||
```
|
```
|
||||||
|
@ -474,7 +474,7 @@ def process_chunk_challenge(state: BeaconState,
|
||||||
# Verify the challenge is not a duplicate
|
# Verify the challenge is not a duplicate
|
||||||
for record in state.custody_chunk_challenge_records:
|
for record in state.custody_chunk_challenge_records:
|
||||||
assert (
|
assert (
|
||||||
record.crosslink_data_root != challenge.attestation.data.crosslink_data_root or
|
record.data_root != challenge.attestation.data.crosslink.data_root or
|
||||||
record.chunk_index != challenge.chunk_index
|
record.chunk_index != challenge.chunk_index
|
||||||
)
|
)
|
||||||
# Verify depth
|
# Verify depth
|
||||||
|
@ -486,7 +486,7 @@ def process_chunk_challenge(state: BeaconState,
|
||||||
challenger_index=get_beacon_proposer_index(state),
|
challenger_index=get_beacon_proposer_index(state),
|
||||||
responder_index=challenge.responder_index
|
responder_index=challenge.responder_index
|
||||||
deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE,
|
deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE,
|
||||||
crosslink_data_root=challenge.attestation.data.crosslink_data_root,
|
data_root=challenge.attestation.data.crosslink.data_root,
|
||||||
depth=depth,
|
depth=depth,
|
||||||
chunk_index=challenge.chunk_index,
|
chunk_index=challenge.chunk_index,
|
||||||
)
|
)
|
||||||
|
@ -564,7 +564,7 @@ def process_bit_challenge(state: BeaconState,
|
||||||
challenger_index=challenge.challenger_index,
|
challenger_index=challenge.challenger_index,
|
||||||
responder_index=challenge.responder_index,
|
responder_index=challenge.responder_index,
|
||||||
deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE,
|
deadline=get_current_epoch(state) + CUSTODY_RESPONSE_DEADLINE,
|
||||||
crosslink_data_root=challenge.attestation.data.crosslink_data_root,
|
data_root=challenge.attestation.data.crosslink.data_root,
|
||||||
chunk_count=chunk_count,
|
chunk_count=chunk_count,
|
||||||
chunk_bits_merkle_root=merkle_root(pad_to_power_of_2((challenge.chunk_bits))),
|
chunk_bits_merkle_root=merkle_root(pad_to_power_of_2((challenge.chunk_bits))),
|
||||||
responder_key=challenge.responder_key,
|
responder_key=challenge.responder_key,
|
||||||
|
@ -610,7 +610,7 @@ def process_chunk_challenge_response(state: BeaconState,
|
||||||
branch=response.data_branch,
|
branch=response.data_branch,
|
||||||
depth=challenge.depth,
|
depth=challenge.depth,
|
||||||
index=response.chunk_index,
|
index=response.chunk_index,
|
||||||
root=challenge.crosslink_data_root,
|
root=challenge.data_root,
|
||||||
)
|
)
|
||||||
# Clear the challenge
|
# Clear the challenge
|
||||||
records = state.custody_chunk_challenge_records
|
records = state.custody_chunk_challenge_records
|
||||||
|
@ -632,7 +632,7 @@ def process_bit_challenge_response(state: BeaconState,
|
||||||
branch=response.data_branch,
|
branch=response.data_branch,
|
||||||
depth=math.log2(next_power_of_two(challenge.chunk_count)),
|
depth=math.log2(next_power_of_two(challenge.chunk_count)),
|
||||||
index=response.chunk_index,
|
index=response.chunk_index,
|
||||||
root=challenge.crosslink_data_root,
|
root=challenge.data_root,
|
||||||
)
|
)
|
||||||
# Verify the chunk bit leaf matches the challenge data
|
# Verify the chunk bit leaf matches the challenge data
|
||||||
assert verify_merkle_branch(
|
assert verify_merkle_branch(
|
||||||
|
|
|
@ -78,7 +78,7 @@ This document describes the shard data layer and the shard fork choice rule in P
|
||||||
'slot': Slot,
|
'slot': Slot,
|
||||||
'shard': Shard,
|
'shard': Shard,
|
||||||
'beacon_chain_root': Hash,
|
'beacon_chain_root': Hash,
|
||||||
'previous_block_root': Hash,
|
'parent_root': Hash,
|
||||||
'data': ShardBlockBody,
|
'data': ShardBlockBody,
|
||||||
'state_root': Hash,
|
'state_root': Hash,
|
||||||
'attestations': [ShardAttestation],
|
'attestations': [ShardAttestation],
|
||||||
|
@ -93,7 +93,7 @@ This document describes the shard data layer and the shard fork choice rule in P
|
||||||
'slot': Slot,
|
'slot': Slot,
|
||||||
'shard': Shard,
|
'shard': Shard,
|
||||||
'beacon_chain_root': Hash,
|
'beacon_chain_root': Hash,
|
||||||
'previous_block_root': Hash,
|
'parent_root': Hash,
|
||||||
'body_root': Hash,
|
'body_root': Hash,
|
||||||
'state_root': Hash,
|
'state_root': Hash,
|
||||||
'attestations': [ShardAttestation],
|
'attestations': [ShardAttestation],
|
||||||
|
@ -201,7 +201,7 @@ def get_shard_header(block: ShardBlock) -> ShardBlockHeader:
|
||||||
slot: block.slot,
|
slot: block.slot,
|
||||||
shard: block.shard,
|
shard: block.shard,
|
||||||
beacon_chain_root: block.beacon_chain_root,
|
beacon_chain_root: block.beacon_chain_root,
|
||||||
previous_block_root: block.previous_block_root,
|
parent_root: block.parent_root,
|
||||||
body_root: hash_tree_root(block.body),
|
body_root: hash_tree_root(block.body),
|
||||||
state_root: block.state_root,
|
state_root: block.state_root,
|
||||||
attestations: block.attestations,
|
attestations: block.attestations,
|
||||||
|
@ -215,7 +215,7 @@ def get_shard_header(block: ShardBlock) -> ShardBlockHeader:
|
||||||
def verify_shard_attestation_signature(state: BeaconState,
|
def verify_shard_attestation_signature(state: BeaconState,
|
||||||
attestation: ShardAttestation) -> None:
|
attestation: ShardAttestation) -> None:
|
||||||
data = attestation.data
|
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))
|
assert verify_bitfield(attestation.aggregation_bitfield, len(persistent_committee))
|
||||||
pubkeys = []
|
pubkeys = []
|
||||||
for i, index in enumerate(persistent_committee):
|
for i, index in enumerate(persistent_committee):
|
||||||
|
@ -225,7 +225,7 @@ def verify_shard_attestation_signature(state: BeaconState,
|
||||||
pubkeys.append(validator.pubkey)
|
pubkeys.append(validator.pubkey)
|
||||||
assert bls_verify(
|
assert bls_verify(
|
||||||
pubkey=bls_aggregate_pubkeys(pubkeys),
|
pubkey=bls_aggregate_pubkeys(pubkeys),
|
||||||
message_hash=data.shard_block_root,
|
message_hash=data.crosslink.shard_block_root,
|
||||||
signature=attestation.aggregate_signature,
|
signature=attestation.aggregate_signature,
|
||||||
domain=get_domain(state, slot_to_epoch(data.slot), DOMAIN_SHARD_ATTESTER)
|
domain=get_domain(state, slot_to_epoch(data.slot), DOMAIN_SHARD_ATTESTER)
|
||||||
)
|
)
|
||||||
|
@ -296,11 +296,11 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock],
|
||||||
|
|
||||||
# Check parent block
|
# Check parent block
|
||||||
if block.slot == PHASE_1_GENESIS_SLOT:
|
if block.slot == PHASE_1_GENESIS_SLOT:
|
||||||
assert candidate.previous_block_root == ZERO_HASH
|
assert candidate.parent_root == ZERO_HASH
|
||||||
else:
|
else:
|
||||||
parent_block = next(
|
parent_block = next(
|
||||||
block for block in valid_shard_blocks if
|
block for block in valid_shard_blocks if
|
||||||
signing_root(block) == candidate.previous_block_root
|
signing_root(block) == candidate.parent_root
|
||||||
, None)
|
, None)
|
||||||
assert parent_block != None
|
assert parent_block != None
|
||||||
assert parent_block.shard == block.shard
|
assert parent_block.shard == block.shard
|
||||||
|
@ -312,7 +312,7 @@ def is_valid_shard_block(beacon_blocks: List[BeaconBlock],
|
||||||
for _, attestation in enumerate(block.attestations):
|
for _, attestation in enumerate(block.attestations):
|
||||||
assert max(GENESIS_SHARD_SLOT, block.slot - SLOTS_PER_EPOCH) <= attestation.data.slot
|
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.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)
|
verify_shard_attestation_signature(beacon_state, attestation)
|
||||||
|
|
||||||
# Check signature
|
# Check signature
|
||||||
|
@ -343,11 +343,11 @@ def is_valid_shard_attestation(valid_shard_blocks: List[ShardBlock],
|
||||||
# Check shard block
|
# Check shard block
|
||||||
shard_block = next(
|
shard_block = next(
|
||||||
block for block in valid_shard_blocks if
|
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)
|
, None)
|
||||||
assert shard_block != None
|
assert shard_block != None
|
||||||
assert shard_block.slot == attestation.data.slot
|
assert shard_block.slot == attestation.data.slot
|
||||||
assert shard_block.shard == attestation.data.shard
|
assert shard_block.shard == attestation.data.crosslink.shard
|
||||||
|
|
||||||
# Check signature
|
# Check signature
|
||||||
verify_shard_attestation_signature(beacon_state, attestation)
|
verify_shard_attestation_signature(beacon_state, attestation)
|
||||||
|
@ -378,22 +378,22 @@ def is_valid_beacon_attestation(shard: Shard,
|
||||||
|
|
||||||
# Check previous attestation
|
# Check previous attestation
|
||||||
if candidate.data.previous_crosslink.epoch <= PHASE_1_GENESIS_EPOCH:
|
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:
|
else:
|
||||||
previous_attestation = next(
|
previous_attestation = next(
|
||||||
attestation for attestation in valid_attestations if
|
attestation for attestation in valid_attestations if
|
||||||
attestation.data.crosslink_data_root == candidate.data.previous_crosslink.crosslink_data_root
|
attestation.data.crosslink.data_root == candidate.data.previous_crosslink.data_root
|
||||||
, None)
|
, None)
|
||||||
assert previous_attestation != None
|
assert previous_attestation != None
|
||||||
assert candidate.data.previous_attestation.epoch < slot_to_epoch(candidate.data.slot)
|
assert candidate.data.previous_attestation.epoch < slot_to_epoch(candidate.data.slot)
|
||||||
|
|
||||||
# Check crosslink data root
|
# Check crosslink data root
|
||||||
start_epoch = state.latest_crosslinks[shard].epoch
|
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 = []
|
blocks = []
|
||||||
for slot in range(start_epoch * SLOTS_PER_EPOCH, end_epoch * SLOTS_PER_EPOCH):
|
for slot in range(start_epoch * SLOTS_PER_EPOCH, end_epoch * SLOTS_PER_EPOCH):
|
||||||
blocks.append(shard_blocks[slot])
|
blocks.append(shard_blocks[slot])
|
||||||
assert candidate.data.crosslink_data_root == compute_crosslink_data_root(blocks)
|
assert candidate.data.crosslink.data_root == compute_crosslink_data_root(blocks)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
```
|
```
|
||||||
|
|
|
@ -37,14 +37,9 @@
|
||||||
- [Voluntary exits](#voluntary-exits)
|
- [Voluntary exits](#voluntary-exits)
|
||||||
- [Attestations](#attestations-1)
|
- [Attestations](#attestations-1)
|
||||||
- [Attestation data](#attestation-data)
|
- [Attestation data](#attestation-data)
|
||||||
- [Slot](#slot-1)
|
- [LMD GHOST vote](#lmd-ghost-vote)
|
||||||
- [Beacon block root](#beacon-block-root)
|
- [FFG vote](#ffg-vote)
|
||||||
- [Source epoch](#source-epoch)
|
- [Crosslink vote](#crosslink-vote)
|
||||||
- [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)
|
- [Construct attestation](#construct-attestation)
|
||||||
- [Data](#data)
|
- [Data](#data)
|
||||||
- [Aggregation bitfield](#aggregation-bitfield)
|
- [Aggregation bitfield](#aggregation-bitfield)
|
||||||
|
@ -152,7 +147,7 @@ Set `block.slot = slot` where `slot` is the current slot at which the validator
|
||||||
|
|
||||||
##### Parent root
|
##### Parent root
|
||||||
|
|
||||||
Set `block.previous_block_root = signing_root(parent)`.
|
Set `block.parent_root = signing_root(parent)`.
|
||||||
|
|
||||||
##### State root
|
##### State root
|
||||||
|
|
||||||
|
@ -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_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.
|
* Let `head_state` be the state of `head_block` processed through any empty slots up to the assigned slot.
|
||||||
|
|
||||||
##### Slot
|
##### LMD GHOST vote
|
||||||
|
|
||||||
Set `attestation_data.slot = head_state.slot`.
|
|
||||||
|
|
||||||
##### Beacon block root
|
|
||||||
|
|
||||||
Set `attestation_data.beacon_block_root = signing_root(head_block)`.
|
Set `attestation_data.beacon_block_root = signing_root(head_block)`.
|
||||||
|
|
||||||
##### Source epoch
|
##### FFG vote
|
||||||
|
|
||||||
Set `attestation_data.source_epoch = head_state.justified_epoch`.
|
* 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.
|
||||||
|
|
||||||
##### Source root
|
*Note*: `epoch_boundary_block` can be looked up in the state using:
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
*Note*: This can be looked up in the state using:
|
|
||||||
* Let `epoch_start_slot = get_epoch_start_slot(get_current_epoch(head_state))`.
|
* 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)`.
|
* Let `epoch_boundary_block = head if epoch_start_slot == head_state.slot else get_block_root(state, epoch_start_slot)`.
|
||||||
|
|
||||||
##### Shard
|
##### Crosslink vote
|
||||||
|
|
||||||
Set `attestation_data.shard = shard` where `shard` is the shard associated with the validator's committee defined by `get_crosslink_committees_at_slot`.
|
Construct `attestation_data.crosslink` via the following
|
||||||
|
|
||||||
##### Previous crosslink root
|
* 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.previous_crosslink_root = hash_tree_root(head_state.current_crosslinks[shard])`.
|
* 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.
|
||||||
##### Crosslink data root
|
|
||||||
|
|
||||||
Set `attestation_data.crosslink_data_root = ZERO_HASH`.
|
|
||||||
|
|
||||||
*Note*: This is a stub for Phase 0.
|
|
||||||
|
|
||||||
#### Construct attestation
|
#### Construct attestation
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ def test_non_zero_crosslink_data_root(state):
|
||||||
attestation = get_valid_attestation(state)
|
attestation = get_valid_attestation(state)
|
||||||
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
state.slot += spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||||
|
|
||||||
attestation.data.crosslink_data_root = b'\x42' * 32
|
attestation.data.crosslink.data_root = b'\x42' * 32
|
||||||
|
|
||||||
pre_state, post_state = run_attestation_processing(state, attestation, False)
|
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):
|
for _ in range(spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
||||||
next_slot(state)
|
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)
|
pre_state, post_state = run_attestation_processing(state, attestation, False)
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,9 @@ def test_invalid_slot(state):
|
||||||
return pre_state, block, None
|
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 = build_empty_block_for_next_slot(state)
|
||||||
block.previous_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)
|
pre_state, post_state = run_block_header_processing(state, block, valid=False)
|
||||||
return pre_state, block, None
|
return pre_state, block, None
|
||||||
|
|
|
@ -64,7 +64,7 @@ def test_single_crosslink_update_from_current_epoch(state):
|
||||||
|
|
||||||
pre_state, post_state = run_process_crosslinks(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 post_state.previous_crosslinks[shard] != post_state.current_crosslinks[shard]
|
||||||
assert pre_state.current_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)
|
pre_state, post_state = run_process_crosslinks(state)
|
||||||
crosslink_deltas = get_crosslink_deltas(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 post_state.previous_crosslinks[shard] != post_state.current_crosslinks[shard]
|
||||||
assert pre_state.current_crosslinks[shard] != post_state.current_crosslinks[shard]
|
assert pre_state.current_crosslinks[shard] != post_state.current_crosslinks[shard]
|
||||||
# ensure rewarded
|
# 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[0][index] > 0
|
||||||
assert crosslink_deltas[1][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):
|
for slot in range(spec.SLOTS_PER_EPOCH):
|
||||||
attestation_2 = get_valid_attestation(state)
|
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
|
break
|
||||||
next_slot(state)
|
next_slot(state)
|
||||||
fill_aggregate_attestation(state, attestation_2)
|
fill_aggregate_attestation(state, attestation_2)
|
||||||
|
@ -124,12 +124,12 @@ def test_double_late_crosslink(state):
|
||||||
pre_state, post_state = run_process_crosslinks(state)
|
pre_state, post_state = run_process_crosslinks(state)
|
||||||
crosslink_deltas = get_crosslink_deltas(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
|
# ensure that the current crosslinks were not updated by the second attestation
|
||||||
assert post_state.previous_crosslinks[shard] == post_state.current_crosslinks[shard]
|
assert post_state.previous_crosslinks[shard] == post_state.current_crosslinks[shard]
|
||||||
# ensure no reward, only penalties for the failed crosslink
|
# 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[0][index] == 0
|
||||||
assert crosslink_deltas[1][index] > 0
|
assert crosslink_deltas[1][index] > 0
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ from eth2spec.utils.minimal_ssz import signing_root
|
||||||
from eth2spec.phase0.spec import (
|
from eth2spec.phase0.spec import (
|
||||||
# constants
|
# constants
|
||||||
ZERO_HASH,
|
ZERO_HASH,
|
||||||
|
MAX_EPOCHS_PER_CROSSLINK,
|
||||||
# SSZ
|
# SSZ
|
||||||
Attestation,
|
Attestation,
|
||||||
AttestationData,
|
AttestationData,
|
||||||
|
@ -17,6 +18,7 @@ from eth2spec.phase0.spec import (
|
||||||
AttesterSlashing,
|
AttesterSlashing,
|
||||||
BeaconBlock,
|
BeaconBlock,
|
||||||
BeaconBlockHeader,
|
BeaconBlockHeader,
|
||||||
|
Crosslink,
|
||||||
Deposit,
|
Deposit,
|
||||||
DepositData,
|
DepositData,
|
||||||
Eth1Data,
|
Eth1Data,
|
||||||
|
@ -126,7 +128,7 @@ def build_empty_block_for_next_slot(state):
|
||||||
previous_block_header = deepcopy(state.latest_block_header)
|
previous_block_header = deepcopy(state.latest_block_header)
|
||||||
if previous_block_header.state_root == spec.ZERO_HASH:
|
if previous_block_header.state_root == spec.ZERO_HASH:
|
||||||
previous_block_header.state_root = state.hash_tree_root()
|
previous_block_header.state_root = state.hash_tree_root()
|
||||||
empty_block.previous_block_root = signing_root(previous_block_header)
|
empty_block.parent_root = signing_root(previous_block_header)
|
||||||
return empty_block
|
return empty_block
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,7 +155,7 @@ def build_attestation_data(state, slot, shard):
|
||||||
assert state.slot >= slot
|
assert state.slot >= slot
|
||||||
|
|
||||||
if slot == state.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_root
|
||||||
else:
|
else:
|
||||||
block_root = get_block_root_at_slot(state, slot)
|
block_root = get_block_root_at_slot(state, slot)
|
||||||
|
|
||||||
|
@ -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
|
crosslinks = state.current_crosslinks if slot_to_epoch(slot) == get_current_epoch(state) else state.previous_crosslinks
|
||||||
return AttestationData(
|
return AttestationData(
|
||||||
shard=shard,
|
|
||||||
beacon_block_root=block_root,
|
beacon_block_root=block_root,
|
||||||
source_epoch=justified_epoch,
|
source_epoch=justified_epoch,
|
||||||
source_root=justified_block_root,
|
source_root=justified_block_root,
|
||||||
target_epoch=slot_to_epoch(slot),
|
target_epoch=slot_to_epoch(slot),
|
||||||
target_root=epoch_boundary_root,
|
target_root=epoch_boundary_root,
|
||||||
crosslink_data_root=spec.ZERO_HASH,
|
crosslink=Crosslink(
|
||||||
previous_crosslink_root=hash_tree_root(crosslinks[shard]),
|
shard=shard,
|
||||||
|
epoch=min(slot_to_epoch(slot), crosslinks[shard].epoch + MAX_EPOCHS_PER_CROSSLINK),
|
||||||
|
data_root=spec.ZERO_HASH,
|
||||||
|
parent_root=hash_tree_root(crosslinks[shard]),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -235,12 +240,12 @@ def get_valid_proposer_slashing(state):
|
||||||
|
|
||||||
header_1 = BeaconBlockHeader(
|
header_1 = BeaconBlockHeader(
|
||||||
slot=slot,
|
slot=slot,
|
||||||
previous_block_root=ZERO_HASH,
|
parent_root=ZERO_HASH,
|
||||||
state_root=ZERO_HASH,
|
state_root=ZERO_HASH,
|
||||||
block_body_root=ZERO_HASH,
|
body_root=ZERO_HASH,
|
||||||
)
|
)
|
||||||
header_2 = deepcopy(header_1)
|
header_2 = deepcopy(header_1)
|
||||||
header_2.previous_block_root = b'\x02' * 32
|
header_2.parent_root = b'\x02' * 32
|
||||||
header_2.slot = slot + 1
|
header_2.slot = slot + 1
|
||||||
|
|
||||||
domain = get_domain(
|
domain = get_domain(
|
||||||
|
@ -288,7 +293,7 @@ def get_valid_attestation(state, slot=None):
|
||||||
|
|
||||||
attestation_data = build_attestation_data(state, slot, shard)
|
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)
|
committee_size = len(crosslink_committee)
|
||||||
bitfield_length = (committee_size + 7) // 8
|
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):
|
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)):
|
for i in range(len(crosslink_committee)):
|
||||||
attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i)
|
attestation.aggregation_bitfield = set_bitfield_bit(attestation.aggregation_bitfield, i)
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ def test_empty_block_transition(state):
|
||||||
state_transition(test_state, block)
|
state_transition(test_state, block)
|
||||||
|
|
||||||
assert len(test_state.eth1_data_votes) == len(state.eth1_data_votes) + 1
|
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_root
|
||||||
|
|
||||||
return state, [block], test_state
|
return state, [block], test_state
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ def test_skipped_slots(state):
|
||||||
|
|
||||||
assert test_state.slot == block.slot
|
assert test_state.slot == block.slot
|
||||||
for slot in range(state.slot, test_state.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_root
|
||||||
|
|
||||||
return state, [block], test_state
|
return state, [block], test_state
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ def test_empty_epoch_transition(state):
|
||||||
|
|
||||||
assert test_state.slot == block.slot
|
assert test_state.slot == block.slot
|
||||||
for slot in range(state.slot, test_state.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_root
|
||||||
|
|
||||||
return state, [block], test_state
|
return state, [block], test_state
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue