Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

implement bulk of 0.5.0 state transition function #192

Merged
merged 1 commit into from Mar 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 40 additions & 34 deletions beacon_chain/spec/beaconstate.nim
Expand Up @@ -441,73 +441,81 @@ func update_validator_registry*(state: var BeaconState) =

state.validator_registry_update_epoch = current_epoch

# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestations-1
# TODO this is https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestations now
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestations
# with last half or so still not fully converted from 0.4.0 (tag, remove when done)
proc checkAttestation*(
state: BeaconState, attestation: Attestation, flags: UpdateFlags): bool =
state: var BeaconState, attestation: Attestation, flags: UpdateFlags): bool =
## Check that an attestation follows the rules of being included in the state
## at the current slot. When acting as a proposer, the same rules need to
## be followed!

let attestation_data_slot = attestation.data.slot

# Can't submit attestations that are too far in history (or in prehistory)
if not (attestation.data.slot >= GENESIS_SLOT):
warn("Attestation predates genesis slot",
attestation_slot = attestation.data.slot,
state_slot = humaneSlotNum(state.slot))
return

if not (attestation.data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot):
warn("Attestation too new",
if not (state.slot <= attestation.data.slot + SLOTS_PER_EPOCH):
warn("Attestation too old",
attestation_slot = humaneSlotNum(attestation.data.slot),
state_slot = humaneSlotNum(state.slot))
return

if not (state.slot < attestation.data.slot + SLOTS_PER_EPOCH):
warn("Attestation too old",
# Can't submit attestations too quickly
if not (
attestation.data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot):
warn("Can't submit attestations too quickly",
attestation_slot = humaneSlotNum(attestation.data.slot),
state_slot = humaneSlotNum(state.slot))
return

let expected_justified_epoch =
if slot_to_epoch(attestation.data.slot + 1) >= get_current_epoch(state):
state.current_justified_epoch
else:
state.previous_justified_epoch

if not (attestation.data.source_epoch == expected_justified_epoch):
warn("Unexpected justified epoch",
attestation_justified_epoch =
humaneEpochNum(attestation.data.source_epoch),
expected_justified_epoch = humaneEpochNum(expected_justified_epoch))
return

let expected_justified_block_root =
get_block_root(state, get_epoch_start_slot(attestation.data.source_epoch))
if not (attestation.data.justified_block_root == expected_justified_block_root):
warn("Unexpected justified block root",
attestation_justified_block_root = attestation.data.justified_block_root,
expected_justified_block_root)
return
# # Verify that the justified epoch and root is correct
if slot_to_epoch(attestation.data.slot) >= get_current_epoch(state):
# Case 1: current epoch attestations
if not (attestation.data.source_epoch == state.current_justified_epoch):
warn("Source epoch is not current justified epoch",
attestation_slot = humaneSlotNum(attestation.data.slot),
state_slot = humaneSlotNum(state.slot))
return

if not (attestation.data.source_root == state.current_justified_root):
warn("Source root is not current justified root",
attestation_slot = humaneSlotNum(attestation.data.slot),
state_slot = humaneSlotNum(state.slot))
return
else:
# Case 2: previous epoch attestations
if not (attestation.data.source_epoch == state.previous_justified_epoch):
warn("Source epoch is not previous justified epoch",
attestation_slot = humaneSlotNum(attestation.data.slot),
state_slot = humaneSlotNum(state.slot))
return

if not (attestation.data.source_root == state.previous_justified_root):
warn("Source root is not previous justified root",
attestation_slot = humaneSlotNum(attestation.data.slot),
state_slot = humaneSlotNum(state.slot))
return

if not (state.latest_crosslinks[attestation.data.shard] in [
attestation.data.previous_crosslink,
Crosslink(
crosslink_data_root: attestation.data.crosslink_data_root,
epoch: slot_to_epoch(attestation_data_slot))]):
epoch: slot_to_epoch(attestation.data.slot))]):
warn("Unexpected crosslink shard",
state_latest_crosslinks_attestation_data_shard =
state.latest_crosslinks[attestation.data.shard],
attestation_data_previous_crosslink = attestation.data.previous_crosslink,
epoch = humaneEpochNum(slot_to_epoch(attestation_data_slot)),
epoch = humaneEpochNum(slot_to_epoch(attestation.data.slot)),
crosslink_data_root = attestation.data.crosslink_data_root)
return

doAssert allIt(attestation.custody_bitfield.bits, it == 0) #TO BE REMOVED IN PHASE 1
doAssert anyIt(attestation.aggregation_bitfield.bits, it != 0)

let crosslink_committee = mapIt(
filterIt(get_crosslink_committees_at_slot(state, attestation_data_slot),
filterIt(get_crosslink_committees_at_slot(state, attestation.data.slot),
it.shard == attestation.data.shard),
it.committee)[0]

Expand Down Expand Up @@ -585,9 +593,7 @@ proc makeAttestationData*(
slot: state.slot,
shard: shard,
beacon_block_root: beacon_block_root,
epoch_boundary_root: epoch_boundary_root,
crosslink_data_root: Eth2Digest(), # Stub in phase0
previous_crosslink: state.latest_crosslinks[shard],
source_epoch: state.current_justified_epoch,
justified_block_root: justified_block_root,
)
17 changes: 6 additions & 11 deletions beacon_chain/spec/datatypes.nim
Expand Up @@ -46,7 +46,7 @@ type
Epoch* = distinct uint64

const
SPEC_VERSION* = "0.4.0" ## \
SPEC_VERSION* = "0.5.0" ## \
## Spec version we're aiming to be compatible with, right now
## TODO: improve this scheme once we can negotiate versions in protocol

Expand Down Expand Up @@ -179,6 +179,7 @@ const
type
ValidatorIndex* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around

Shard* = uint64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe these should all be distinct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably. Given the fallout of the last distinct thing I did, I'm 100% not doing it in this PR. I agree though.

Copy link
Contributor

@mratsim mratsim Mar 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, though distinct ranges are utterly broken.

Gwei* = uint64

# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#proposerslashing
Expand Down Expand Up @@ -227,22 +228,17 @@ type
aggregate_signature*: ValidatorSig ##\
## BLS aggregate signature

# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestationdata
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestationdata
AttestationData* = object
# LMD GHOST vote
slot*: Slot
beacon_block_root*: Eth2Digest

# FFG vote
source_epoch*: Epoch
source_root*: Eth2Digest
target_root*: Eth2Digest

## TODO epoch_boundary_root and justified_block_root are creatures of new
## epoch processing and don't function quite as straightforwardly as just
## renamings, so do that as part of epoch processing change.
epoch_boundary_root*: Eth2Digest
justified_block_root*: Eth2Digest

# Crosslink vote
shard*: uint64
previous_crosslink*: Crosslink
Expand Down Expand Up @@ -620,14 +616,13 @@ func shortLog*(v: BeaconBlock): tuple[

func shortLog*(v: AttestationData): tuple[
slot: uint64, beacon_block_root: string, source_epoch: uint64,
target_root: string, epoch_boundary_root: string,
justified_block_root: string, shard: uint64,
target_root: string, source_root: string, shard: uint64,
previous_crosslink_epoch: uint64, previous_crosslink_data_root: string,
crosslink_data_root: string
] = (
humaneSlotNum(v.slot), shortLog(v.beacon_block_root),
humaneEpochNum(v.source_epoch), shortLog(v.target_root),
shortLog(v.epoch_boundary_root), shortLog(v.justified_block_root),
shortLog(v.source_root),
v.shard, humaneEpochNum(v.previous_crosslink.epoch),
shortLog(v.previous_crosslink.crosslink_data_root),
shortLog(v.crosslink_data_root)
Expand Down
11 changes: 3 additions & 8 deletions beacon_chain/spec/validator.nim
Expand Up @@ -122,10 +122,10 @@ func get_next_epoch_committee_count(state: BeaconState): uint64 =
)
get_epoch_committee_count(len(next_active_validators))

# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_previous_epoch
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_previous_epoch
func get_previous_epoch*(state: BeaconState): Epoch =
## Return the previous epoch of the given ``state``.
max(get_current_epoch(state) - 1, GENESIS_EPOCH)
get_current_epoch(state) - 1

# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot
func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
Expand All @@ -137,12 +137,7 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
## ``slot`` in the next epoch -- with and without a `registry_change`

let
# TODO: the + 1 here works around a bug, remove when upgrading to
# some more recent version:
# https://github.com/ethereum/eth2.0-specs/pull/732
# TODO remove +1 along with rest of epoch reorganization, then
# remove this 0.4.0 tag.
epoch = slot_to_epoch(slot + 1)
epoch = slot_to_epoch(slot)
current_epoch = get_current_epoch(state)
previous_epoch = get_previous_epoch(state)
next_epoch = current_epoch + 1
Expand Down