Mostly convert to using distinct Slot type (#172)

This commit is contained in:
Dustin Brody 2019-03-12 22:21:32 +00:00 committed by Jacek Sieka
parent 6dea18c140
commit 50a0948bc0
15 changed files with 133 additions and 80 deletions

View File

@ -161,13 +161,13 @@ proc slotIndex(
attestationSlot = $humaneSlotNum(attestationSlot) attestationSlot = $humaneSlotNum(attestationSlot)
pool.startingSlot = state.finalized_epoch.get_epoch_start_slot() pool.startingSlot = state.finalized_epoch.get_epoch_start_slot()
if pool.startingSlot + pool.slots.len.Slot <= attestationSlot: if pool.startingSlot + pool.slots.len.uint64 <= attestationSlot:
debug "Growing attestation pool", debug "Growing attestation pool",
attestationSlot = $humaneSlotNum(attestationSlot), attestationSlot = $humaneSlotNum(attestationSlot),
startingSlot = $humaneSlotNum(pool.startingSlot) startingSlot = $humaneSlotNum(pool.startingSlot)
# Make sure there's a pool entry for every slot, even when there's a gap # Make sure there's a pool entry for every slot, even when there's a gap
while pool.startingSlot + pool.slots.len.Slot <= attestationSlot: while pool.startingSlot + pool.slots.len.uint64 <= attestationSlot:
pool.slots.addLast(SlotData()) pool.slots.addLast(SlotData())
if pool.startingSlot < state.finalized_epoch.get_epoch_start_slot(): if pool.startingSlot < state.finalized_epoch.get_epoch_start_slot():
@ -193,7 +193,7 @@ proc add*(pool: var AttestationPool,
let let
attestationSlot = attestation.data.slot attestationSlot = attestation.data.slot
idx = pool.slotIndex(state, attestationSlot) idx = pool.slotIndex(state, attestationSlot.Slot)
slotData = addr pool.slots[idx] slotData = addr pool.slots[idx]
validation = Validation( validation = Validation(
aggregation_bitfield: attestation.aggregation_bitfield, aggregation_bitfield: attestation.aggregation_bitfield,
@ -279,11 +279,11 @@ proc getAttestationsForBlock*(pool: AttestationPool,
attestationSlot = newBlockSlot - MIN_ATTESTATION_INCLUSION_DELAY attestationSlot = newBlockSlot - MIN_ATTESTATION_INCLUSION_DELAY
if attestationSlot < pool.startingSlot or if attestationSlot < pool.startingSlot or
attestationSlot >= pool.startingSlot + pool.slots.len.Slot: attestationSlot >= pool.startingSlot + pool.slots.len.uint64:
info "No attestations", info "No attestations",
attestationSlot = humaneSlotNum(attestationSlot), attestationSlot = humaneSlotNum(attestationSlot),
startingSlot = humaneSlotNum(pool.startingSlot), startingSlot = humaneSlotNum(pool.startingSlot),
endingSlot = humaneSlotNum(pool.startingSlot + pool.slots.len.Slot) endingSlot = humaneSlotNum(pool.startingSlot + pool.slots.len.uint64)
return return

View File

@ -308,7 +308,7 @@ proc proposeBlock(node: BeaconNode,
newBlock.state_root = Eth2Digest(data: hash_tree_root(state)) newBlock.state_root = Eth2Digest(data: hash_tree_root(state))
let proposal = Proposal( let proposal = Proposal(
slot: slot, slot: slot.uint64,
shard: BEACON_CHAIN_SHARD_NUMBER, shard: BEACON_CHAIN_SHARD_NUMBER,
block_root: Eth2Digest(data: signed_root(newBlock, "signature")), block_root: Eth2Digest(data: signed_root(newBlock, "signature")),
signature: ValidatorSig(), signature: ValidatorSig(),
@ -441,7 +441,7 @@ proc scheduleEpochActions(node: BeaconNode, epoch: Epoch) =
let start = if epoch == GENESIS_EPOCH: 1.uint64 else: 0.uint64 let start = if epoch == GENESIS_EPOCH: 1.uint64 else: 0.uint64
for i in start ..< SLOTS_PER_EPOCH: for i in start ..< SLOTS_PER_EPOCH:
let slot = epoch * SLOTS_PER_EPOCH + i let slot = (epoch * SLOTS_PER_EPOCH + i).Slot
nextState.slot = slot # ugly trick, see get_beacon_proposer_index nextState.slot = slot # ugly trick, see get_beacon_proposer_index
block: # Schedule block proposals block: # Schedule block proposals

View File

@ -54,7 +54,7 @@ proc init*(T: type BlockPool, db: BeaconChainDB): BlockPool =
var blocksBySlot = initTable[uint64, seq[BlockRef]]() var blocksBySlot = initTable[uint64, seq[BlockRef]]()
for _, b in tables.pairs(blocks): for _, b in tables.pairs(blocks):
let slot = db.getBlock(b.root).get().slot let slot = db.getBlock(b.root).get().slot
blocksBySlot.mgetOrPut(slot, @[]).add(b) blocksBySlot.mgetOrPut(slot.uint64, @[]).add(b)
BlockPool( BlockPool(
pending: initTable[Eth2Digest, BeaconBlock](), pending: initTable[Eth2Digest, BeaconBlock](),
@ -146,7 +146,7 @@ proc add*(
pool.blocks[blockRoot] = blockRef pool.blocks[blockRoot] = blockRef
pool.addSlotMapping(blck.slot, blockRef) pool.addSlotMapping(blck.slot.uint64, blockRef)
# Resolved blocks should be stored in database # Resolved blocks should be stored in database
pool.db.putBlock(blockRoot, blck) pool.db.putBlock(blockRoot, blck)
@ -229,8 +229,8 @@ proc getOrResolve*(pool: var BlockPool, root: Eth2Digest): BlockRef =
if result.isNil: if result.isNil:
pool.unresolved[root] = UnresolvedBlock() pool.unresolved[root] = UnresolvedBlock()
iterator blockRootsForSlot*(pool: BlockPool, slot: uint64): Eth2Digest = iterator blockRootsForSlot*(pool: BlockPool, slot: uint64|Slot): Eth2Digest =
for br in pool.blocksBySlot.getOrDefault(slot, @[]): for br in pool.blocksBySlot.getOrDefault(slot.uint64, @[]):
yield br.root yield br.root
proc checkUnresolved*(pool: var BlockPool): seq[Eth2Digest] = proc checkUnresolved*(pool: var BlockPool): seq[Eth2Digest] =

View File

@ -280,7 +280,7 @@ func get_attestation_participants*(state: BeaconState,
## Return the participant indices at for the ``attestation_data`` and ## Return the participant indices at for the ``attestation_data`` and
## ``bitfield``. ## ``bitfield``.
let crosslink_committees = get_crosslink_committees_at_slot( let crosslink_committees = get_crosslink_committees_at_slot(
state, attestation_data.slot) state, attestation_data.slot.Slot)
doAssert anyIt( doAssert anyIt(
crosslink_committees, crosslink_committees,
it[1] == attestation_data.shard) it[1] == attestation_data.shard)
@ -367,6 +367,8 @@ proc checkAttestation*(
## at the current slot. When acting as a proposer, the same rules need to ## at the current slot. When acting as a proposer, the same rules need to
## be followed! ## be followed!
let attestation_data_slot = attestation.data.slot.Slot
if not (attestation.data.slot >= GENESIS_SLOT): if not (attestation.data.slot >= GENESIS_SLOT):
warn("Attestation predates genesis slot", warn("Attestation predates genesis slot",
attestation_slot = attestation.data.slot, attestation_slot = attestation.data.slot,
@ -386,7 +388,7 @@ proc checkAttestation*(
return return
let expected_justified_epoch = let expected_justified_epoch =
if slot_to_epoch(attestation.data.slot + 1) >= get_current_epoch(state): if slot_to_epoch(attestation.data.slot.Slot + 1) >= get_current_epoch(state):
state.justified_epoch state.justified_epoch
else: else:
state.previous_justified_epoch state.previous_justified_epoch
@ -410,12 +412,12 @@ proc checkAttestation*(
attestation.data.latest_crosslink, attestation.data.latest_crosslink,
Crosslink( Crosslink(
crosslink_data_root: attestation.data.crosslink_data_root, 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", warn("Unexpected crosslink shard",
state_latest_crosslinks_attestation_data_shard = state_latest_crosslinks_attestation_data_shard =
state.latest_crosslinks[attestation.data.shard], state.latest_crosslinks[attestation.data.shard],
attestation_data_latest_crosslink = attestation.data.latest_crosslink, attestation_data_latest_crosslink = attestation.data.latest_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) crosslink_data_root = attestation.data.crosslink_data_root)
return return
@ -423,7 +425,7 @@ proc checkAttestation*(
assert anyIt(attestation.aggregation_bitfield, it != 0) assert anyIt(attestation.aggregation_bitfield, it != 0)
let crosslink_committee = mapIt( 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.shard == attestation.data.shard),
it.committee)[0] it.committee)[0]
@ -475,7 +477,7 @@ proc checkAttestation*(
data: attestation.data, custody_bit: true)), data: attestation.data, custody_bit: true)),
], ],
attestation.aggregate_signature, attestation.aggregate_signature,
get_domain(state.fork, slot_to_epoch(attestation.data.slot), get_domain(state.fork, slot_to_epoch(attestation.data.slot.Slot),
DOMAIN_ATTESTATION), DOMAIN_ATTESTATION),
) )
@ -513,7 +515,7 @@ proc makeAttestationData*(
justified_block_root = get_block_root(state, justified_slot) justified_block_root = get_block_root(state, justified_slot)
AttestationData( AttestationData(
slot: state.slot, slot: state.slot.uint64,
shard: shard, shard: shard,
beacon_block_root: beacon_block_root, beacon_block_root: beacon_block_root,
epoch_boundary_root: epoch_boundary_root, epoch_boundary_root: epoch_boundary_root,

View File

@ -18,7 +18,7 @@
# types / composition # types / composition
import import
eth/common, math, eth/common, hashes, math,
./crypto, ./digest ./crypto, ./digest
# TODO Data types: # TODO Data types:
@ -39,6 +39,11 @@ import
# TODO Many of these constants should go into a config object that can be used # TODO Many of these constants should go into a config object that can be used
# to run.. well.. a chain with different constants! # to run.. well.. a chain with different constants!
type
Slot* = distinct uint64
Epoch* = uint64
const const
SPEC_VERSION* = "0.4.0" ## \ SPEC_VERSION* = "0.4.0" ## \
## Spec version we're aiming to be compatible with, right now ## Spec version we're aiming to be compatible with, right now
@ -103,8 +108,9 @@ const
# Initial values # Initial values
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#initial-values # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#initial-values
GENESIS_FORK_VERSION* = 0'u64 GENESIS_FORK_VERSION* = 0'u64
GENESIS_SLOT* = 2'u64^32 GENESIS_SLOT* = (2'u64^32).Slot
GENESIS_EPOCH* = GENESIS_SLOT div SLOTS_PER_EPOCH # slot_to_epoch(GENESIS_SLOT) GENESIS_EPOCH* = (GENESIS_SLOT.uint64 div SLOTS_PER_EPOCH).Epoch ##\
## slot_to_epoch(GENESIS_SLOT)
GENESIS_START_SHARD* = 0'u64 GENESIS_START_SHARD* = 0'u64
FAR_FUTURE_EPOCH* = not 0'u64 # 2^64 - 1 in spec FAR_FUTURE_EPOCH* = not 0'u64 # 2^64 - 1 in spec
ZERO_HASH* = Eth2Digest() ZERO_HASH* = Eth2Digest()
@ -172,12 +178,6 @@ const
type type
ValidatorIndex* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around ValidatorIndex* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around
## In principle, these would be better as distinct types. That's a good
## TODO eventually, but Danny has confirmed that the SSZ types will use
## primitive (uint64, etc) types and helper functions annotated ones so
## it would just create pointless casts for now.
Slot* = uint64
Epoch* = uint64
Gwei* = uint64 Gwei* = uint64
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#proposerslashing # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#proposerslashing
@ -246,7 +246,7 @@ type
latest_crosslink*: Crosslink ##\ latest_crosslink*: Crosslink ##\
## Last crosslink ## Last crosslink
justified_epoch*: uint64 ##\ justified_epoch*: Epoch ##\
## Last justified epoch in the beacon state ## Last justified epoch in the beacon state
justified_block_root*: Eth2Digest ##\ justified_block_root*: Eth2Digest ##\
@ -284,7 +284,7 @@ type
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#voluntaryexit # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#voluntaryexit
VoluntaryExit* = object VoluntaryExit* = object
# Minimum epoch for processing exit # Minimum epoch for processing exit
epoch*: uint64 epoch*: Epoch
# Index of the exiting validator # Index of the exiting validator
validator_index*: uint64 validator_index*: uint64
# Validator signature # Validator signature
@ -321,12 +321,12 @@ type
## Each block collects attestations, or votes, on past blocks, thus a chain ## Each block collects attestations, or votes, on past blocks, thus a chain
## is formed. ## is formed.
slot*: uint64 slot*: Slot
parent_root*: Eth2Digest ##\ parent_root*: Eth2Digest ##\
##\ Root hash of the previous block ##\ Root hash of the previous block
state_root*: Eth2Digest ##\ state_root*: Eth2Digest ##\
##\ The state root, _after_ this block has been processed ## The state root, _after_ this block has been processed
randao_reveal*: ValidatorSig ##\ randao_reveal*: ValidatorSig ##\
## Proposer RANDAO reveal ## Proposer RANDAO reveal
@ -375,7 +375,7 @@ type
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#beaconstate # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#beaconstate
BeaconState* = object BeaconState* = object
slot*: uint64 slot*: Slot
genesis_time*: uint64 genesis_time*: uint64
fork*: Fork ##\ fork*: Fork ##\
## For versioning hard forks ## For versioning hard forks
@ -385,7 +385,7 @@ type
validator_balances*: seq[uint64] ##\ validator_balances*: seq[uint64] ##\
## Validator balances in Gwei! ## Validator balances in Gwei!
validator_registry_update_epoch*: uint64 validator_registry_update_epoch*: Epoch
# TODO remove or conditionally compile; not in spec anymore # TODO remove or conditionally compile; not in spec anymore
validator_registry_delta_chain_tip*: Eth2Digest ##\ validator_registry_delta_chain_tip*: Eth2Digest ##\
@ -395,16 +395,16 @@ type
latest_randao_mixes*: array[LATEST_BLOCK_ROOTS_LENGTH.int, Eth2Digest] latest_randao_mixes*: array[LATEST_BLOCK_ROOTS_LENGTH.int, Eth2Digest]
previous_shuffling_start_shard*: uint64 previous_shuffling_start_shard*: uint64
current_shuffling_start_shard*: uint64 current_shuffling_start_shard*: uint64
previous_shuffling_epoch*: uint64 previous_shuffling_epoch*: Epoch
current_shuffling_epoch*: uint64 current_shuffling_epoch*: Epoch
previous_shuffling_seed*: Eth2Digest previous_shuffling_seed*: Eth2Digest
current_shuffling_seed*: Eth2Digest current_shuffling_seed*: Eth2Digest
# Finality # Finality
previous_justified_epoch*: uint64 previous_justified_epoch*: Epoch
justified_epoch*: uint64 justified_epoch*: Epoch
justification_bitfield*: uint64 justification_bitfield*: uint64
finalized_epoch*: uint64 finalized_epoch*: Epoch
# Recent state # Recent state
latest_crosslinks*: array[SHARD_COUNT, Crosslink] latest_crosslinks*: array[SHARD_COUNT, Crosslink]
@ -434,13 +434,13 @@ type
withdrawal_credentials*: Eth2Digest ##\ withdrawal_credentials*: Eth2Digest ##\
## Withdrawal credentials ## Withdrawal credentials
activation_epoch*: uint64 ##\ activation_epoch*: Epoch ##\
## Epoch when validator activated ## Epoch when validator activated
exit_epoch*: uint64 ##\ exit_epoch*: Epoch ##\
## Epoch when validator exited ## Epoch when validator exited
withdrawable_epoch*: uint64 ##\ withdrawable_epoch*: Epoch ##\
## Epoch when validator is eligible to withdraw ## Epoch when validator is eligible to withdraw
initiated_exit*: bool ##\ initiated_exit*: bool ##\
@ -451,7 +451,7 @@ type
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslink # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslink
Crosslink* = object Crosslink* = object
epoch*: uint64 ##\ epoch*: Epoch ##\
## Epoch number ## Epoch number
crosslink_data_root*: Eth2Digest ##\ crosslink_data_root*: Eth2Digest ##\
@ -462,13 +462,13 @@ type
aggregation_bitfield*: seq[byte] # Attester participation bitfield aggregation_bitfield*: seq[byte] # Attester participation bitfield
data*: AttestationData # Attestation data data*: AttestationData # Attestation data
custody_bitfield*: seq[byte] # Custody bitfield custody_bitfield*: seq[byte] # Custody bitfield
inclusion_slot*: uint64 # Inclusion slot inclusion_slot*: Slot # Inclusion slot
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#fork # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#fork
Fork* = object Fork* = object
previous_version*: uint64 # Previous fork version previous_version*: uint64 # Previous fork version
current_version*: uint64 # Current fork version current_version*: uint64 # Current fork version
epoch*: uint64 # Fork epoch number epoch*: Epoch # Fork epoch number
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#eth1data # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#eth1data
Eth1Data* = object Eth1Data* = object
@ -522,8 +522,39 @@ type
func shortValidatorKey*(state: BeaconState, validatorIdx: int): string = func shortValidatorKey*(state: BeaconState, validatorIdx: int): string =
($state.validator_registry[validatorIdx].pubkey)[0..7] ($state.validator_registry[validatorIdx].pubkey)[0..7]
func humaneSlotNum*(s: Slot): Slot = template ethTimeUnit(typ: type) =
s - GENESIS_SLOT proc `+`*(x: typ, y: uint64): typ {.borrow.}
proc `-`*(x: typ, y: uint64): typ {.borrow.}
proc `-`*(x: uint64, y: typ): typ {.borrow.}
proc `+=`*(x: var typ, y: uint64) {.borrow.}
proc `-=`*(x: var typ, y: uint64) {.borrow.}
# Not closed over type in question (Slot or Epoch)
proc `mod`*(x: typ, y: uint64): uint64 {.borrow.}
proc `div`*(x: typ, y: uint64): uint64 {.borrow.}
proc `div`*(x: uint64, y: typ): uint64 {.borrow.}
proc `-`*(x: typ, y: typ): uint64 {.borrow.}
# Comparison operators
proc `<`*(x: typ, y: typ): bool {.borrow.}
proc `<`*(x: typ, y: uint64): bool {.borrow.}
proc `<`*(x: uint64, y: typ): bool {.borrow.}
proc `<=`*(x: typ, y: typ): bool {.borrow.}
proc `<=`*(x: typ, y: uint64): bool {.borrow.}
proc `<=`*(x: uint64, y: typ): bool {.borrow.}
proc `==`*(x: typ, y: typ): bool {.borrow.}
proc `==`*(x: typ, y: uint64): bool {.borrow.}
# Nim integration
proc `$`*(x: typ): string {.borrow.}
proc hash*(x: typ): Hash {.borrow.}
ethTimeUnit(Slot)
#ethTimeUnit(Epoch)
func humaneSlotNum*(s: auto): uint64 =
s.Slot - GENESIS_SLOT
func humaneEpochNum*(e: Epoch): Epoch = func humaneEpochNum*(e: Epoch): Epoch =
e - GENESIS_EPOCH e - GENESIS_EPOCH

View File

@ -120,13 +120,13 @@ func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest =
o[1] o[1]
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slot_to_epoch # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slot_to_epoch
func slot_to_epoch*(slot: Slot): Epoch = func slot_to_epoch*(slot: Slot|uint64): Epoch =
slot div SLOTS_PER_EPOCH (slot div SLOTS_PER_EPOCH).Epoch
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_epoch_start_slot # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_epoch_start_slot
func get_epoch_start_slot*(epoch: Epoch): Slot = func get_epoch_start_slot*(epoch: Epoch): Slot =
# Return the starting slot of the given ``epoch``. # Return the starting slot of the given ``epoch``.
epoch * SLOTS_PER_EPOCH (epoch * SLOTS_PER_EPOCH).Slot
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_double_vote # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_double_vote
func is_double_vote*(attestation_data_1: AttestationData, func is_double_vote*(attestation_data_1: AttestationData,
@ -134,8 +134,9 @@ func is_double_vote*(attestation_data_1: AttestationData,
## Check if ``attestation_data_1`` and ``attestation_data_2`` have the same ## Check if ``attestation_data_1`` and ``attestation_data_2`` have the same
## target. ## target.
let let
target_epoch_1 = slot_to_epoch(attestation_data_1.slot) # RLP artifact
target_epoch_2 = slot_to_epoch(attestation_data_2.slot) target_epoch_1 = slot_to_epoch(attestation_data_1.slot.Slot)
target_epoch_2 = slot_to_epoch(attestation_data_2.slot.Slot)
target_epoch_1 == target_epoch_2 target_epoch_1 == target_epoch_2
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_surround_vote # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_surround_vote
@ -145,8 +146,9 @@ func is_surround_vote*(attestation_data_1: AttestationData,
let let
source_epoch_1 = attestation_data_1.justified_epoch source_epoch_1 = attestation_data_1.justified_epoch
source_epoch_2 = attestation_data_2.justified_epoch source_epoch_2 = attestation_data_2.justified_epoch
target_epoch_1 = slot_to_epoch(attestation_data_1.slot) # RLP artifact
target_epoch_2 = slot_to_epoch(attestation_data_2.slot) target_epoch_1 = slot_to_epoch(attestation_data_1.slot.Slot)
target_epoch_2 = slot_to_epoch(attestation_data_2.slot.Slot)
source_epoch_1 < source_epoch_2 and target_epoch_2 < target_epoch_1 source_epoch_1 < source_epoch_2 and target_epoch_2 < target_epoch_1

View File

@ -126,7 +126,7 @@ func get_previous_epoch*(state: BeaconState): Epoch =
max(get_current_epoch(state) - 1, GENESIS_EPOCH) max(get_current_epoch(state) - 1, GENESIS_EPOCH)
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot
func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot, func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
registry_change: bool = false): registry_change: bool = false):
seq[CrosslinkCommittee] = seq[CrosslinkCommittee] =
## Returns the list of ``(committee, shard)`` tuples for the ``slot``. ## Returns the list of ``(committee, shard)`` tuples for the ``slot``.

View File

@ -153,6 +153,12 @@ proc endRecord*(w: var SszWriter, memo: RecordWritingMemo) =
let finalSize = uint32(w.stream.pos - memo.initialStreamPos - 4) let finalSize = uint32(w.stream.pos - memo.initialStreamPos - 4)
memo.sizePrefixCursor.endWrite(finalSize.toBytesSSZ) memo.sizePrefixCursor.endWrite(finalSize.toBytesSSZ)
func toSSZType(x: auto): auto =
when x is Slot:
x.uint64
else:
x
proc writeValue*(w: var SszWriter, obj: auto) = proc writeValue*(w: var SszWriter, obj: auto) =
# We are not using overloads here, because this leads to # We are not using overloads here, because this leads to
# slightly better error messages when the user provides # slightly better error messages when the user provides
@ -178,10 +184,10 @@ proc writeValue*(w: var SszWriter, obj: auto) =
# for research/serialized_sizes, remove when appropriate # for research/serialized_sizes, remove when appropriate
when defined(debugFieldSizes) and obj is (BeaconState|BeaconBlock): when defined(debugFieldSizes) and obj is (BeaconState|BeaconBlock):
let start = w.stream.pos let start = w.stream.pos
w.writeValue field w.writeValue field.toSSZType
debugEcho fieldName, ": ", w.stream.pos - start debugEcho fieldName, ": ", w.stream.pos - start
else: else:
w.writeValue field w.writeValue field.toSSZType
w.endRecord(memo) w.endRecord(memo)
proc readValue*(r: var SszReader, result: var auto) = proc readValue*(r: var SszReader, result: var auto) =
@ -235,6 +241,9 @@ proc readValue*(r: var SszReader, result: var auto) =
else: else:
result.deserializeFields(fieldName, field): result.deserializeFields(fieldName, field):
when field is Slot:
field = r.readValue(uint64).Slot
else:
field = r.readValue(field.type) field = r.readValue(field.type)
if r.stream[].pos != endPos: if r.stream[].pos != endPos:
@ -303,7 +312,7 @@ func hash_tree_root*[T: object|tuple](x: T): array[32, byte] =
## Containers have their fields recursively hashed, concatenated and hashed ## Containers have their fields recursively hashed, concatenated and hashed
withHash: withHash:
for field in x.fields: for field in x.fields:
h.update hash_tree_root(field) h.update hash_tree_root(field.toSSZType)
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/simple-serialize.md#signed-roots # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/simple-serialize.md#signed-roots
func signed_root*[T: object](x: T, field_name: string): array[32, byte] = func signed_root*[T: object](x: T, field_name: string): array[32, byte] =
@ -316,7 +325,7 @@ func signed_root*[T: object](x: T, field_name: string): array[32, byte] =
if name == field_name: if name == field_name:
found_field_name = true found_field_name = true
break break
h.update hash_tree_root(field) h.update hash_tree_root(field.toSSZType)
doAssert found_field_name doAssert found_field_name

View File

@ -49,7 +49,7 @@ func verifyBlockSignature(state: BeaconState, blck: BeaconBlock): bool =
proposer = proposer =
state.validator_registry[get_beacon_proposer_index(state, state.slot)] state.validator_registry[get_beacon_proposer_index(state, state.slot)]
proposal = Proposal( proposal = Proposal(
slot: blck.slot, slot: blck.slot.uint64,
shard: BEACON_CHAIN_SHARD_NUMBER, shard: BEACON_CHAIN_SHARD_NUMBER,
block_root: Eth2Digest(data: signed_root(blck, "signature")), block_root: Eth2Digest(data: signed_root(blck, "signature")),
signature: blck.signature) signature: blck.signature)
@ -361,7 +361,8 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
let transfer_message = signed_root(transfer, "signature") let transfer_message = signed_root(transfer, "signature")
if not bls_verify( if not bls_verify(
pubkey=transfer.pubkey, transfer_message, transfer.signature, pubkey=transfer.pubkey, transfer_message, transfer.signature,
get_domain(state.fork, slot_to_epoch(transfer.slot), DOMAIN_TRANSFER)): get_domain(
state.fork, slot_to_epoch(transfer.slot), DOMAIN_TRANSFER)):
notice "Transfer: incorrect signature" notice "Transfer: incorrect signature"
return false return false
@ -611,7 +612,7 @@ func processEpoch(state: var BeaconState) =
let let
previous_epoch_head_attestations = previous_epoch_head_attestations =
previous_epoch_attestations.filterIt( previous_epoch_attestations.filterIt(
it.data.beacon_block_root == get_block_root(state, it.data.slot)) it.data.beacon_block_root == get_block_root(state, it.data.slot.Slot))
previous_epoch_head_attester_indices = previous_epoch_head_attester_indices =
toSet(get_attester_indices(state, previous_epoch_head_attestations)) toSet(get_attester_indices(state, previous_epoch_head_attestations))
@ -708,8 +709,10 @@ func processEpoch(state: var BeaconState) =
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslinks # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslinks
block: block:
for slot in get_epoch_start_slot(previous_epoch) ..< get_epoch_start_slot(next_epoch): for slot in get_epoch_start_slot(previous_epoch).uint64 ..<
let crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot) get_epoch_start_slot(next_epoch).uint64:
let crosslink_committees_at_slot =
get_crosslink_committees_at_slot(state, slot.Slot)
for crosslink_committee in crosslink_committees_at_slot: for crosslink_committee in crosslink_committees_at_slot:
if 3'u64 * total_attesting_balance(crosslink_committee) >= if 3'u64 * total_attesting_balance(crosslink_committee) >=
@ -737,7 +740,7 @@ func processEpoch(state: var BeaconState) =
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#justification-and-finalization # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#justification-and-finalization
func inclusion_distances(state: BeaconState): auto = func inclusion_distances(state: BeaconState): auto =
result = initTable[ValidatorIndex, uint64]() result = initTable[ValidatorIndex, Slot]()
for a in previous_epoch_attestations: for a in previous_epoch_attestations:
for v in get_attestation_participants( for v in get_attestation_participants(
@ -801,7 +804,7 @@ func processEpoch(state: var BeaconState) =
else: else:
## Last case will not occur. If this assumption becomes false, ## Last case will not occur. If this assumption becomes false,
## indexing into distances will fail. ## indexing into distances will fail.
initTable[ValidatorIndex, uint64]() initTable[ValidatorIndex, Slot]()
for index in active_validator_indices: for index in active_validator_indices:
if index notin previous_epoch_attester_indices: if index notin previous_epoch_attester_indices:
@ -837,7 +840,7 @@ func processEpoch(state: var BeaconState) =
## (reverse) index based on one O(n) scan of previous_epoch_attestations, ## (reverse) index based on one O(n) scan of previous_epoch_attestations,
## then perform O(n) O(1) lookups. Keep same iteration order and rules in ## then perform O(n) O(1) lookups. Keep same iteration order and rules in
## which first match wins and terminates for each ValidatorIndex. ## which first match wins and terminates for each ValidatorIndex.
var proposer_indexes = initTable[ValidatorIndex, uint64]() var proposer_indexes = initTable[ValidatorIndex, Slot]()
# This is the loop from inclusion_slot(...) # This is the loop from inclusion_slot(...)
for a in previous_epoch_attestations: for a in previous_epoch_attestations:
@ -861,8 +864,10 @@ func processEpoch(state: var BeaconState) =
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslinks-1 # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslinks-1
block: block:
for slot in get_epoch_start_slot(previous_epoch) ..< get_epoch_start_slot(current_epoch): for slot in get_epoch_start_slot(previous_epoch).uint64 ..<
let crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot) get_epoch_start_slot(current_epoch).uint64:
let crosslink_committees_at_slot =
get_crosslink_committees_at_slot(state, slot.Slot)
for crosslink_committee in crosslink_committees_at_slot: for crosslink_committee in crosslink_committees_at_slot:
let let
committee_attesting_validators = committee_attesting_validators =

View File

@ -24,7 +24,7 @@ type
func toHeader(b: BeaconBlock): BeaconBlockHeader = func toHeader(b: BeaconBlock): BeaconBlockHeader =
BeaconBlockHeader( BeaconBlockHeader(
slot: b.slot, slot: b.slot.uint64,
parent_root: b.parent_root, parent_root: b.parent_root,
state_root: b.state_root, state_root: b.state_root,
randao_reveal: b.randao_reveal, randao_reveal: b.randao_reveal,
@ -35,7 +35,7 @@ func toHeader(b: BeaconBlock): BeaconBlockHeader =
proc fromHeaderAndBody(b: var BeaconBlock, h: BeaconBlockHeader, body: BeaconBlockBody) = proc fromHeaderAndBody(b: var BeaconBlock, h: BeaconBlockHeader, body: BeaconBlockBody) =
assert(hash_tree_root_final(body) == h.body) assert(hash_tree_root_final(body) == h.body)
b.slot = h.slot b.slot = h.slot.Slot
b.parent_root = h.parent_root b.parent_root = h.parent_root
b.state_root = h.state_root b.state_root = h.state_root
b.randao_reveal = h.randao_reveal b.randao_reveal = h.randao_reveal
@ -76,7 +76,7 @@ p2pProtocol BeaconSync(version = 1,
latestFinalizedRoot: Eth2Digest # TODO latestFinalizedRoot: Eth2Digest # TODO
latestFinalizedEpoch: uint64 = node.state.data.finalized_epoch latestFinalizedEpoch: uint64 = node.state.data.finalized_epoch
bestRoot: Eth2Digest # TODO bestRoot: Eth2Digest # TODO
bestSlot: uint64 = node.state.data.slot bestSlot: uint64 = node.state.data.slot.uint64
let m = await handshake(peer, timeout = 500, let m = await handshake(peer, timeout = 500,
status(networkId, latestFinalizedRoot, status(networkId, latestFinalizedRoot,

View File

@ -15,7 +15,7 @@ proc stateSize(deposits: int, maxContent = false) =
# attestations it may hold, so we'll just add so many of them # attestations it may hold, so we'll just add so many of them
state.latest_attestations.setLen(MAX_ATTESTATIONS * SLOTS_PER_EPOCH * 2) state.latest_attestations.setLen(MAX_ATTESTATIONS * SLOTS_PER_EPOCH * 2)
let let
crosslink_committees = get_crosslink_committees_at_slot(state, 0) crosslink_committees = get_crosslink_committees_at_slot(state, 0.Slot)
validatorsPerCommittee = validatorsPerCommittee =
len(crosslink_committees[0].committee) # close enough.. len(crosslink_committees[0].committee) # close enough..
for a in state.latest_attestations.mitems(): for a in state.latest_attestations.mitems():

View File

@ -36,6 +36,8 @@ template withTimerRet(stats: var RunningStat, body: untyped): untyped =
tmp tmp
proc `%`*(x: Slot): JsonNode {.borrow.}
proc writeJson*(prefix, slot, v: auto) = proc writeJson*(prefix, slot, v: auto) =
var f: File var f: File
defer: close(f) defer: close(f)
@ -80,7 +82,7 @@ cli do(slots = 1945,
attestations[attestations_idx] = @[] attestations[attestations_idx] = @[]
let t = let t =
if (state.slot + 2.Slot) mod SLOTS_PER_EPOCH == 0: tEpoch if (state.slot + 2) mod SLOTS_PER_EPOCH == 0: tEpoch
else: tBlock else: tBlock
withTimer(timers[t]): withTimer(timers[t]):

View File

@ -57,11 +57,12 @@ suite "Beacon chain DB":
check: x == y check: x == y
let let
a0 = BeaconBlock(slot: 0) # TODO Not GENESIS_SLOT?
a0 = BeaconBlock(slot: 0.Slot)
a0r = hash_tree_root_final(a0) a0r = hash_tree_root_final(a0)
a1 = BeaconBlock(slot: 1, parent_root: a0r) a1 = BeaconBlock(slot: 1.Slot, parent_root: a0r)
a1r = hash_tree_root_final(a1) a1r = hash_tree_root_final(a1)
a2 = BeaconBlock(slot: 2, parent_root: a1r) a2 = BeaconBlock(slot: 2.Slot, parent_root: a1r)
a2r = hash_tree_root_final(a2) a2r = hash_tree_root_final(a2)
doAssert toSeq(db.getAncestors(a0r)) == [] doAssert toSeq(db.getAncestors(a0r)) == []

View File

@ -74,8 +74,9 @@ suite "Simple serialization":
SSZ.roundripTest [1, 2, 3] SSZ.roundripTest [1, 2, 3]
SSZ.roundripTest @[1, 2, 3] SSZ.roundripTest @[1, 2, 3]
SSZ.roundripTest SigKey.random().getKey() SSZ.roundripTest SigKey.random().getKey()
SSZ.roundripTest BeaconBlock(slot: 42, signature: sign(SigKey.random(), 0'u64, "")) SSZ.roundripTest BeaconBlock(
SSZ.roundripTest BeaconState(slot: 42) slot: 42.Slot, signature: sign(SigKey.random(), 0'u64, ""))
SSZ.roundripTest BeaconState(slot: 42.Slot)
suite "Tree hashing": suite "Tree hashing":
# TODO Nothing but smoke tests for now.. # TODO Nothing but smoke tests for now..

View File

@ -120,7 +120,7 @@ proc addBlock*(
# Once we've collected all the state data, we sign the block data along with # Once we've collected all the state data, we sign the block data along with
# some book-keeping values # some book-keeping values
signed_data = Proposal( signed_data = Proposal(
slot: new_block.slot, slot: new_block.slot.uint64,
shard: BEACON_CHAIN_SHARD_NUMBER, shard: BEACON_CHAIN_SHARD_NUMBER,
block_root: Eth2Digest(data: signed_root(new_block, "signature")), block_root: Eth2Digest(data: signed_root(new_block, "signature")),
signature: ValidatorSig(), signature: ValidatorSig(),