spec 0.3.0 updates: EPOCH_LENGTH -> SLOTS_PER_EPOCH, SlotNumber -> Slot, EpochNumber -> Epoch (#127)

* spec 0.3.0 updates: EPOCH_LENGTH -> SLOTS_PER_EPOCH, SlotNumber -> Slot, EpochNumber -> Epoch
This commit is contained in:
Dustin Brody 2019-02-20 01:33:58 +00:00 committed by Jacek Sieka
parent 4670d6c98a
commit 132f1147a2
21 changed files with 112 additions and 114 deletions

View File

@ -50,7 +50,7 @@ type
## We keep one item per slot such that indexing matches slot number
## together with startingSlot
startingSlot*: SlotNumber ## \
startingSlot*: Slot ## \
## Generally, we keep attestations only until a slot has been finalized -
## after that, they may no longer affect fork choice.
@ -206,13 +206,13 @@ proc add*(pool: var AttestationPool,
attestationSlot = $humaneSlotNum(attestationSlot)
pool.startingSlot = attestationSlot
if pool.startingSlot + pool.slots.len.SlotNumber <= attestationSlot:
if pool.startingSlot + pool.slots.len.Slot <= attestationSlot:
debug "Growing attestation pool",
attestationSlot = $humaneSlotNum(attestationSlot),
startingSlot = $humaneSlotNum(pool.startingSlot)
# Make sure there's a pool entry for every slot, even when there's a gap
while pool.startingSlot + pool.slots.len.SlotNumber <= attestationSlot:
while pool.startingSlot + pool.slots.len.Slot <= attestationSlot:
pool.slots.addLast(SlotData())
if pool.startingSlot < state.finalized_epoch.get_epoch_start_slot():
@ -267,7 +267,7 @@ proc add*(pool: var AttestationPool,
proc getAttestationsForBlock*(pool: AttestationPool,
lastState: BeaconState,
newBlockSlot: SlotNumber): seq[Attestation] =
newBlockSlot: Slot): seq[Attestation] =
if newBlockSlot - GENESIS_SLOT < MIN_ATTESTATION_INCLUSION_DELAY:
debug "Too early for attestations",
newBlockSlot = humaneSlotNum(newBlockSlot)
@ -287,11 +287,11 @@ proc getAttestationsForBlock*(pool: AttestationPool,
attestationSlot = newBlockSlot - MIN_ATTESTATION_INCLUSION_DELAY
if attestationSlot < pool.startingSlot or
attestationSlot >= pool.startingSlot + pool.slots.len.SlotNumber:
attestationSlot >= pool.startingSlot + pool.slots.len.Slot:
info "No attestations",
attestationSlot = humaneSlotNum(attestationSlot),
startingSlot = humaneSlotNum(pool.startingSlot),
endingSlot = humaneSlotNum(pool.startingSlot + pool.slots.len.SlotNumber)
endingSlot = humaneSlotNum(pool.startingSlot + pool.slots.len.Slot)
return

View File

@ -23,11 +23,11 @@ proc hashToBlockKey(h: Eth2Digest): array[32 + 1, byte] =
result[0] = byte ord(kHashToBlock)
result[1 .. ^1] = h.data
proc slotToBlockHashKey(s: SlotNumber): array[sizeof(SlotNumber) + 1, byte] =
proc slotToBlockHashKey(s: Slot): array[sizeof(Slot) + 1, byte] =
result[0] = byte ord(kSlotToBlockHash)
copyMem(addr result[1], unsafeAddr(s), sizeof(s))
proc slotToStateKey(s: SlotNumber): array[sizeof(SlotNumber) + 1, byte] =
proc slotToStateKey(s: Slot): array[sizeof(Slot) + 1, byte] =
result[0] = byte ord(kSlotToState)
copyMem(addr result[1], unsafeAddr(s), sizeof(s))

View File

@ -17,7 +17,7 @@ type
attachedValidators: ValidatorPool
attestationPool: AttestationPool
mainchainMonitor: MainchainMonitor
lastScheduledEpoch: EpochNumber
lastScheduledEpoch: Epoch
headBlock: BeaconBlock
headBlockRoot: Eth2Digest
blocksChildren: Table[Eth2Digest, seq[Eth2Digest]]
@ -29,7 +29,7 @@ const
topicBeaconBlocks = "ethereum/2.1/beacon_chain/blocks"
topicAttestations = "ethereum/2.1/beacon_chain/attestations"
stateStoragePeriod = EPOCH_LENGTH.uint64 * 10 # Save states once per this number of slots. TODO: Find a good number.
stateStoragePeriod = SLOTS_PER_EPOCH.uint64 * 10 # Save states once per this number of slots. TODO: Find a good number.
func shortHash(x: auto): string =
($x)[0..7]
@ -153,7 +153,7 @@ proc getAttachedValidator(node: BeaconNode, idx: int): AttachedValidator =
proc makeAttestation(node: BeaconNode,
validator: AttachedValidator,
slot: SlotNumber,
slot: Slot,
shard: uint64,
committeeLen: int,
indexInCommittee: int) {.async.} =
@ -210,7 +210,7 @@ proc makeAttestation(node: BeaconNode,
proc proposeBlock(node: BeaconNode,
validator: AttachedValidator,
slot: SlotNumber) {.async.} =
slot: Slot) {.async.} =
doAssert node != nil
doAssert validator != nil
doAssert validator.idx < node.beaconState.validator_registry.len
@ -260,7 +260,7 @@ proc proposeBlock(node: BeaconNode,
idx = validator.idx
proc scheduleBlockProposal(node: BeaconNode,
slot: SlotNumber,
slot: Slot,
validator: AttachedValidator) =
# TODO:
# This function exists only to hide a bug with Nim's closures.
@ -289,7 +289,7 @@ proc scheduleBlockProposal(node: BeaconNode,
proc scheduleAttestation(node: BeaconNode,
validator: AttachedValidator,
slot: SlotNumber,
slot: Slot,
shard: uint64,
committeeLen: int,
indexInCommittee: int) =
@ -317,7 +317,7 @@ proc scheduleAttestation(node: BeaconNode,
asyncCheck makeAttestation(node, validator, slot,
shard, committeeLen, indexInCommittee)
proc scheduleEpochActions(node: BeaconNode, epoch: EpochNumber) =
proc scheduleEpochActions(node: BeaconNode, epoch: Epoch) =
## This schedules the required block proposals and
## attestations from our attached validators.
doAssert node != nil
@ -332,8 +332,8 @@ proc scheduleEpochActions(node: BeaconNode, epoch: EpochNumber) =
let start = if epoch == GENESIS_EPOCH: 1.uint64 else: 0.uint64
for i in start ..< EPOCH_LENGTH:
let slot = epoch * EPOCH_LENGTH + i
for i in start ..< SLOTS_PER_EPOCH:
let slot = epoch * SLOTS_PER_EPOCH + i
nextState.slot = slot # ugly trick, see get_beacon_proposer_index
block: # Schedule block proposals
@ -359,7 +359,7 @@ proc scheduleEpochActions(node: BeaconNode, epoch: EpochNumber) =
node.lastScheduledEpoch = epoch
let
nextEpoch = epoch + 1
at = node.beaconState.slotMiddle(nextEpoch * EPOCH_LENGTH)
at = node.beaconState.slotMiddle(nextEpoch * SLOTS_PER_EPOCH)
info "Scheduling next epoch update",
fromNow = (at - fastEpochTime()) div 1000,
@ -439,7 +439,7 @@ proc processBlocks*(node: BeaconNode) =
node.attestationPool.add(a, node.beaconState)
let epoch = node.beaconState.getSlotFromTime div EPOCH_LENGTH
let epoch = node.beaconState.getSlotFromTime div SLOTS_PER_EPOCH
node.scheduleEpochActions(epoch)
runForever()
@ -479,7 +479,7 @@ when isMainModule:
slotsSinceFinalization = node.beaconState.slotDistanceFromNow(),
stateSlot = humaneSlotNum(node.beaconState.slot),
SHARD_COUNT,
EPOCH_LENGTH,
SLOTS_PER_EPOCH,
SECONDS_PER_SLOT,
SPEC_VERSION

View File

@ -18,7 +18,7 @@ import
# the processing of which sets `B` as finalized.)
# * Let `justified_head` be the descendant of `finalized_head`
# with the highest slot number that has been justified
# for at least `EPOCH_LENGTH` slots.
# for at least `SLOTS_PER_EPOCH` slots.
# (A block `B` is justified if there is a descendant of `B` in `store`
# the processing of which sets `B` as justified.)
# If no such descendant exists set `justified_head` to `finalized_head`.
@ -47,7 +47,7 @@ proc get_parent(db: BeaconChainDB, blck: Eth2Digest): Eth2Digest =
db.getBlock(blck).parent_root
proc get_ancestor(
store: BeaconChainDB, blck: Eth2Digest, slot: SlotNumber): Eth2Digest =
store: BeaconChainDB, blck: Eth2Digest, slot: Slot): Eth2Digest =
## Find the ancestor with a specific slot number
let blk = store.getBlock(blck)
if blk.slot == slot:
@ -65,7 +65,7 @@ func getVoteCount(aggregation_bitfield: openarray[byte]): int =
result += int aggregation_bitfield.get_bitfield_bit(validatorIdx)
func getAttestationVoteCount(
pool: AttestationPool, current_slot: SlotNumber): CountTable[Eth2Digest] =
pool: AttestationPool, current_slot: Slot): CountTable[Eth2Digest] =
## Returns all blocks more recent that the current slot
## that were attested and their vote count
# This replaces:

View File

@ -85,7 +85,7 @@ func process_deposit(state: var BeaconState,
state.validator_balances[index] += amount
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_entry_exit_effect_epoch
func get_entry_exit_effect_epoch*(epoch: EpochNumber): EpochNumber =
func get_entry_exit_effect_epoch*(epoch: Epoch): Epoch =
## An entry or exit triggered in the ``epoch`` given by the input takes effect at
## the epoch given by the output.
epoch + 1 + ACTIVATION_EXIT_DELAY
@ -171,11 +171,11 @@ func get_initial_beacon_state*(
## must be calculated before creating the genesis block.
# Induct validators
# Not in spec: the system doesn't work unless there are at least EPOCH_LENGTH
# Not in spec: the system doesn't work unless there are at least SLOTS_PER_EPOCH
# validators - there needs to be at least one member in each committee -
# good to know for testing, though arguably the system is not that useful at
# at that point :)
assert initial_validator_deposits.len >= EPOCH_LENGTH
assert initial_validator_deposits.len >= SLOTS_PER_EPOCH
var state = BeaconState(
# Misc
@ -230,7 +230,7 @@ func get_initial_beacon_state*(
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_block_root
func get_block_root*(state: BeaconState,
slot: SlotNumber): Eth2Digest =
slot: Slot): Eth2Digest =
# Return the block root at a recent ``slot``.
doAssert state.slot <= slot + LATEST_BLOCK_ROOTS_LENGTH
@ -348,7 +348,7 @@ proc checkAttestation*(
return
if not (state.slot - MIN_ATTESTATION_INCLUSION_DELAY <
attestation.data.slot + EPOCH_LENGTH):
attestation.data.slot + SLOTS_PER_EPOCH):
warn("Attestation too old",
attestation_slot = attestation.data.slot, state_slot = state.slot)
return

View File

@ -57,7 +57,7 @@ const
## For the safety of crosslinks `TARGET_COMMITTEE_SIZE` exceeds
## [the recommended minimum committee size of 111](https://vitalik.ca/files/Ithaca201807_Sharding.pdf);
## with sufficient active validators (at least
## `EPOCH_LENGTH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures
## `SLOTS_PER_EPOCH * TARGET_COMMITTEE_SIZE`), the shuffling algorithm ensures
## committee sizes at least `TARGET_COMMITTEE_SIZE`. (Unbiasable randomness
## with a Verifiable Delay Function (VDF) will improve committee robustness
## and lower the safe minimum committee size.)
@ -96,17 +96,17 @@ const
## the validator pool
# Time parameter, here so that GENESIS_EPOCH can access it
EPOCH_LENGTH* {.intdefine.} = 64 ##\
SLOTS_PER_EPOCH* {.intdefine.} = 64 ##\
## (~6.4 minutes)
## slots that make up an epoch, at the end of which more heavy
## processing is done
## Compile with -d:EPOCH_LENGTH=4 for shorter epochs
## Compile with -d:SLOTS_PER_EPOCH=4 for shorter epochs
# Initial values
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#initial-values
GENESIS_FORK_VERSION* = 0'u64
GENESIS_SLOT* = 2'u64^63
GENESIS_EPOCH* = GENESIS_SLOT div EPOCH_LENGTH # slot_to_epoch(GENESIS_SLOT)
GENESIS_EPOCH* = GENESIS_SLOT div SLOTS_PER_EPOCH # slot_to_epoch(GENESIS_SLOT)
GENESIS_START_SHARD* = 0'u64
FAR_FUTURE_EPOCH* = not 0'u64 # 2^64 - 1 in spec
ZERO_HASH* = Eth2Digest()
@ -130,9 +130,6 @@ const
## wait towards the end of the slot and still have time to publish the
## attestation.
SLOTS_PER_EPOCH* = 2^6 ##\
## 6.4 minutes
MIN_SEED_LOOKAHEAD* = 1 ##\
## epochs (~6.4 minutes)
@ -185,8 +182,8 @@ type
## 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.
SlotNumber* = uint64
EpochNumber* = uint64
Slot* = uint64
Epoch* = uint64
Gwei* = uint64
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#proposerslashing
@ -497,7 +494,7 @@ type
CrosslinkCommittee* = tuple[committee: seq[ValidatorIndex], shard: uint64]
template epoch*(slot: int|uint64): auto =
slot div EPOCH_LENGTH
slot div SLOTS_PER_EPOCH
when true:
# TODO: Remove these once RLP serialization is no longer used
@ -525,10 +522,10 @@ when true:
func shortValidatorKey*(state: BeaconState, validatorIdx: int): string =
($state.validator_registry[validatorIdx].pubkey)[0..7]
func humaneSlotNum*(s: SlotNumber): SlotNumber =
func humaneSlotNum*(s: Slot): Slot =
s - GENESIS_SLOT
func humaneEpochNum*(e: EpochNumber): EpochNumber =
func humaneEpochNum*(e: Epoch): Epoch =
e - GENESIS_EPOCH
export

View File

@ -34,7 +34,7 @@ func verify_bitfield*(bitfield: openarray[byte], committee_size: int): bool =
true
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#split
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#split
func split*[T](lst: openArray[T], N: Positive): seq[seq[T]] =
## split lst in N pieces, with each piece having `len(lst) div N` or
## `len(lst) div N + 1` pieces
@ -68,7 +68,7 @@ func integer_squareroot*(n: SomeInteger): SomeInteger =
x
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_fork_version
func get_fork_version*(fork: Fork, epoch: EpochNumber): uint64 =
func get_fork_version*(fork: Fork, epoch: Epoch): uint64 =
## Return the fork version of the given ``epoch``.
if epoch < fork.epoch:
fork.previous_version
@ -77,7 +77,7 @@ func get_fork_version*(fork: Fork, epoch: EpochNumber): uint64 =
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_domain
func get_domain*(
fork: Fork, epoch: EpochNumber, domain_type: SignatureDomain): uint64 =
fork: Fork, epoch: Epoch, domain_type: SignatureDomain): uint64 =
# TODO Slot overflow? Or is slot 32 bits for all intents and purposes?
# Get the domain number that represents the fork meta and signature domain.
(get_fork_version(fork, epoch) shl 32) + domain_type.uint32
@ -98,14 +98,14 @@ func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest =
#TODO
discard
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#slot_to_epoch
func slot_to_epoch*(slot: SlotNumber): EpochNumber =
slot div EPOCH_LENGTH
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#slot_to_epoch
func slot_to_epoch*(slot: Slot): Epoch =
slot div SLOTS_PER_EPOCH
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_epoch_start_slot
func get_epoch_start_slot*(epoch: EpochNumber): SlotNumber =
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_epoch_start_slot
func get_epoch_start_slot*(epoch: Epoch): Slot =
# Return the starting slot of the given ``epoch``.
epoch * EPOCH_LENGTH
epoch * SLOTS_PER_EPOCH
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#is_double_vote
func is_double_vote*(attestation_data_1: AttestationData,
@ -129,25 +129,25 @@ func is_surround_vote*(attestation_data_1: AttestationData,
source_epoch_1 < source_epoch_2 and target_epoch_2 < target_epoch_1
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#is_active_validator
func is_active_validator*(validator: Validator, epoch: EpochNumber): bool =
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#is_active_validator
func is_active_validator*(validator: Validator, epoch: Epoch): bool =
### Checks if validator is active
validator.activation_epoch <= epoch and epoch < validator.exit_epoch
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_active_validator_indices
func get_active_validator_indices*(validators: openArray[Validator], epoch: EpochNumber): seq[ValidatorIndex] =
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_active_validator_indices
func get_active_validator_indices*(validators: openArray[Validator], epoch: Epoch): seq[ValidatorIndex] =
## Gets indices of active validators from validators
for idx, val in validators:
if is_active_validator(val, epoch):
result.add idx.ValidatorIndex
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_epoch_committee_count
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_epoch_committee_count
func get_epoch_committee_count*(active_validator_count: int): uint64 =
clamp(
active_validator_count div EPOCH_LENGTH div TARGET_COMMITTEE_SIZE,
1, SHARD_COUNT div EPOCH_LENGTH).uint64 * EPOCH_LENGTH
active_validator_count div SLOTS_PER_EPOCH div TARGET_COMMITTEE_SIZE,
1, SHARD_COUNT div SLOTS_PER_EPOCH).uint64 * SLOTS_PER_EPOCH
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_current_epoch_committee_count
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_current_epoch_committee_count
func get_current_epoch_committee_count*(state: BeaconState): uint64 =
# Return the number of committees in the current epoch of the given ``state``.
let current_active_validators = get_active_validator_indices(
@ -156,15 +156,15 @@ func get_current_epoch_committee_count*(state: BeaconState): uint64 =
)
get_epoch_committee_count(len(current_active_validators))
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_current_epoch
func get_current_epoch*(state: BeaconState): EpochNumber =
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_current_epoch
func get_current_epoch*(state: BeaconState): Epoch =
# Return the current epoch of the given ``state``.
doAssert state.slot >= GENESIS_SLOT, $state.slot
slot_to_epoch(state.slot)
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_randao_mix
func get_randao_mix*(state: BeaconState,
epoch: EpochNumber): Eth2Digest =
epoch: Epoch): Eth2Digest =
## Returns the randao mix at a recent ``epoch``.
# Cannot underflow, since GENESIS_EPOCH > LATEST_RANDAO_MIXES_LENGTH
@ -174,7 +174,7 @@ func get_randao_mix*(state: BeaconState,
state.latest_randao_mixes[epoch mod LATEST_RANDAO_MIXES_LENGTH]
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_active_index_root
func get_active_index_root(state: BeaconState, epoch: EpochNumber): Eth2Digest =
func get_active_index_root(state: BeaconState, epoch: Epoch): Eth2Digest =
# Returns the index root at a recent ``epoch``.
# Cannot underflow, since GENESIS_EPOCH > LATEST_RANDAO_MIXES_LENGTH
@ -215,7 +215,7 @@ func int_to_bytes4*(x: uint64): array[4, byte] =
result[3] = ((x shr 24) and 0xff).byte
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#generate_seed
func generate_seed*(state: BeaconState, epoch: EpochNumber): Eth2Digest =
func generate_seed*(state: BeaconState, epoch: Epoch): Eth2Digest =
# Generate a seed for the given ``epoch``.
var seed_input : array[32*3, byte]

View File

@ -55,14 +55,14 @@ func get_permuted_index(index: uint64, list_size: uint64, seed: Eth2Digest): uin
if bit != 0:
result = flip
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_shuffling
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_shuffling
func get_shuffling*(seed: Eth2Digest,
validators: openArray[Validator],
epoch: EpochNumber
epoch: Epoch
): seq[seq[ValidatorIndex]] =
## Shuffles ``validators`` into crosslink committees seeded by ``seed`` and
## ``slot``.
## Returns a list of ``EPOCH_LENGTH * committees_per_slot`` committees where
## Returns a list of ``SLOTS_PER_EPOCH * committees_per_slot`` committees where
## each committee is itself a list of validator indices.
##
## TODO: write unit tests for if this produces an "interesting" permutation
@ -102,7 +102,7 @@ func get_new_validator_registry_delta_chain_tip*(
flag: flag
))
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_previous_epoch_committee_count
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_previous_epoch_committee_count
func get_previous_epoch_committee_count(state: BeaconState): uint64 =
# Return the number of committees in the previous epoch of the given ``state``.
let previous_active_validators = get_active_validator_indices(
@ -111,16 +111,17 @@ func get_previous_epoch_committee_count(state: BeaconState): uint64 =
)
get_epoch_committee_count(len(previous_active_validators))
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_next_epoch_committee_count
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_next_epoch_committee_count
func get_next_epoch_committee_count(state: BeaconState): uint64 =
## Return the number of committees in the next epoch of the given ``state``.
let next_active_validators = get_active_validator_indices(
state.validator_registry,
get_current_epoch(state) + 1,
)
get_epoch_committee_count(len(next_active_validators))
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_previous_epoch
func get_previous_epoch(state: BeaconState): EpochNumber =
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.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``.
## If the current epoch is ``GENESIS_EPOCH``, return ``GENESIS_EPOCH``.
let current_epoch = get_current_epoch(state)
@ -129,8 +130,8 @@ func get_previous_epoch(state: BeaconState): EpochNumber =
else:
current_epoch - 1
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot
func get_crosslink_committees_at_slot*(state: BeaconState, slot: uint64,
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot
func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot,
registry_change: bool = false):
seq[CrosslinkCommittee] =
## Returns the list of ``(committee, shard)`` tuples for the ``slot``.
@ -206,8 +207,8 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: uint64,
state.validator_registry,
shuffling_epoch,
)
offset = slot mod EPOCH_LENGTH
committees_per_slot = committees_per_epoch div EPOCH_LENGTH
offset = slot mod SLOTS_PER_EPOCH
committees_per_slot = committees_per_epoch div SLOTS_PER_EPOCH
slot_start_shard = (shuffling_start_shard + committees_per_slot * offset) mod SHARD_COUNT
for i in 0 ..< committees_per_slot.int:

View File

@ -452,7 +452,7 @@ func lowerThan(candidate, current: Eth2Digest): bool =
func processEpoch(state: var BeaconState) =
## https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#per-epoch-processing
if (state.slot + 1) mod EPOCH_LENGTH != 0:
if (state.slot + 1) mod SLOTS_PER_EPOCH != 0:
return
# Precomputation
@ -463,19 +463,19 @@ func processEpoch(state: var BeaconState) =
current_epoch = get_current_epoch(state)
previous_epoch = if current_epoch > GENESIS_EPOCH: current_epoch - 1 else: current_epoch
next_epoch = (current_epoch + 1).EpochNumber
next_epoch = (current_epoch + 1).Epoch
# TODO doing this with iterators failed:
# https://github.com/nim-lang/Nim/issues/9827
let
current_epoch_attestations =
state.latest_attestations.filterIt(
state.slot <= it.data.slot + EPOCH_LENGTH and
state.slot <= it.data.slot + SLOTS_PER_EPOCH and
it.data.slot < state.slot)
current_epoch_boundary_attestations =
boundary_attestations(
state, get_block_root(state, state.slot-EPOCH_LENGTH),
state, get_block_root(state, state.slot-SLOTS_PER_EPOCH),
current_epoch_attestations)
current_epoch_boundary_attester_indices =
@ -507,8 +507,8 @@ func processEpoch(state: var BeaconState) =
let # Previous epoch boundary
# TODO check this with spec...
negative_uint_hack =
if state.slot < 2'u64 * EPOCH_LENGTH: 0'u64
else: state.slot - 2'u64 * EPOCH_LENGTH
if state.slot < 2'u64 * SLOTS_PER_EPOCH: 0'u64
else: state.slot - 2'u64 * SLOTS_PER_EPOCH
previous_epoch_boundary_attestations =
boundary_attestations(
state, get_block_root(state, negative_uint_hack),
@ -677,7 +677,7 @@ func processEpoch(state: var BeaconState) =
# TODO underflows?
statePtr.validator_balances[v] -= base_reward(statePtr[], v)
if epochs_since_finality <= 4'u64 * EPOCH_LENGTH:
if epochs_since_finality <= 4'u64 * SLOTS_PER_EPOCH:
# Expected FFG source
update_balance(
previous_epoch_justified_attester_indices,
@ -748,12 +748,12 @@ func processEpoch(state: var BeaconState) =
if state.finalized_epoch > state.validator_registry_update_epoch and
allIt(
0 ..< get_current_epoch_committee_count(state).int * EPOCH_LENGTH,
0 ..< get_current_epoch_committee_count(state).int * SLOTS_PER_EPOCH,
state.latest_crosslinks[(state.current_shuffling_start_shard + it.uint64) mod SHARD_COUNT].epoch > state.validator_registry_update_epoch):
update_validator_registry(state)
state.current_shuffling_epoch = next_epoch
state.current_shuffling_start_shard = (state.current_shuffling_start_shard + get_current_epoch_committee_count(state) * EPOCH_LENGTH) mod SHARD_COUNT
state.current_shuffling_start_shard = (state.current_shuffling_start_shard + get_current_epoch_committee_count(state) * SLOTS_PER_EPOCH) mod SHARD_COUNT
state.current_shuffling_seed = generate_seed(state, state.current_shuffling_epoch)
else:
# If a validator registry change does NOT happen
@ -766,7 +766,7 @@ func processEpoch(state: var BeaconState) =
block: # Final updates
state.latest_attestations.keepItIf(
not (it.data.slot + EPOCH_LENGTH < state.slot)
not (it.data.slot + SLOTS_PER_EPOCH < state.slot)
)
proc verifyStateRoot(state: BeaconState, blck: BeaconBlock): bool =

View File

@ -85,7 +85,7 @@ proc applyValidatorChangeLog*(log: ChangeLog,
#
outBeaconState.finalized_epoch =
log.signedBlock.slot div EPOCH_LENGTH
log.signedBlock.slot div SLOTS_PER_EPOCH
outBeaconState.validator_registry_delta_chain_tip =
log.beaconState.validator_registry_delta_chain_tip

View File

@ -16,22 +16,22 @@ proc timeSinceGenesis*(s: BeaconState): Timestamp =
Timestamp(int64(fastEpochTime() - s.genesis_time * 1000) -
detectedClockDrift)
proc getSlotFromTime*(s: BeaconState, t = now()): SlotNumber =
proc getSlotFromTime*(s: BeaconState, t = now()): Slot =
GENESIS_SLOT + uint64((int64(t - s.genesis_time * 1000) - detectedClockDrift) div
int64(SECONDS_PER_SLOT * 1000))
func slotStart*(s: BeaconState, slot: SlotNumber): Timestamp =
func slotStart*(s: BeaconState, slot: Slot): Timestamp =
(s.genesis_time + (slot * SECONDS_PER_SLOT)) * 1000
func slotMiddle*(s: BeaconState, slot: SlotNumber): Timestamp =
func slotMiddle*(s: BeaconState, slot: Slot): Timestamp =
s.slotStart(slot) + SECONDS_PER_SLOT * 500
func slotEnd*(s: BeaconState, slot: SlotNumber): Timestamp =
func slotEnd*(s: BeaconState, slot: Slot): Timestamp =
# TODO this is actually past the end, by nim inclusive semantics (sigh)
s.slotStart(slot + 1)
proc randomTimeInSlot*(s: BeaconState,
slot: SlotNumber,
slot: Slot,
interval: HSlice[float, float]): Timestamp =
## Returns a random moment within the slot.
## The interval must be a sub-interval of [0..1].

View File

@ -31,7 +31,7 @@ cli do (validators: int,
startupDelay = 0):
if validators < 64:
echo "The number of validators must be higher than ", EPOCH_LENGTH, " (EPOCH_LENGTH)"
echo "The number of validators must be higher than ", SLOTS_PER_EPOCH, " (SLOTS_PER_EPOCH)"
echo "There must be at least one validator assigned per slot."
quit 1

View File

@ -71,7 +71,7 @@ proc signAttestation*(v: AttachedValidator,
# send RPC
discard
func genRandaoReveal*(k: ValidatorPrivKey, state: BeaconState, slot: SlotNumber):
func genRandaoReveal*(k: ValidatorPrivKey, state: BeaconState, slot: Slot):
ValidatorSig =
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#randao
@ -80,6 +80,6 @@ func genRandaoReveal*(k: ValidatorPrivKey, state: BeaconState, slot: SlotNumber)
bls_sign(k, int_to_bytes32(slot_to_epoch(slot)),
get_domain(state.fork, slot_to_epoch(slot), DOMAIN_RANDAO))
func genRandaoReveal*(v: AttachedValidator, state: BeaconState, slot: SlotNumber):
func genRandaoReveal*(v: AttachedValidator, state: BeaconState, slot: Slot):
ValidatorSig =
genRandaoReveal(v.privKey, state, slot)

View File

@ -178,11 +178,11 @@ method on_receive(self: Node, sig: Sig, reprocess = false) =
var c2 = c
self.log &"Justified: {slot} {($c)[0 ..< 8]}"
# If EPOCH_LENGTH+1 blocks are justified in a row, the oldest is
# If SLOTS_PER_EPOCH+1 blocks are justified in a row, the oldest is
# considered finalized
var finalize = true
for slot2 in countdown(slot-1, max(slot - EPOCH_LENGTH * 1, 0)):
for slot2 in countdown(slot-1, max(slot - SLOTS_PER_EPOCH * 1, 0)):
# Note the max(...)-1 in spec is unneeded, Nim ranges are inclusive
if slot2 < self.blocks[c2].slot:
c2 = self.blocks[c2].parent_hash
@ -195,10 +195,10 @@ method on_receive(self: Node, sig: Sig, reprocess = false) =
if self.scores_at_height.getOrDefault(key2, 0) < NOTARIES * 2 div 3:
finalize = false
self.log &"Not quite finalized: stopped at {slot2} needed {max(slot - EPOCH_LENGTH, 0)}"
self.log &"Not quite finalized: stopped at {slot2} needed {max(slot - SLOTS_PER_EPOCH, 0)}"
break
if slot2 < slot - EPOCH_LENGTH - 1 and finalize and c2 notin self.finalized:
if slot2 < slot - SLOTS_PER_EPOCH - 1 and finalize and c2 notin self.finalized:
self.log &"Finalized: {self.blocks[c2].slot} {($c)[0 ..< 8]}"
self.finalized[c2] = true
@ -217,19 +217,19 @@ method on_receive(self: Node, sig: Sig, reprocess = false) =
self.network.broadcast(self, sig)
func get_sig_targets(self: Node, start_slot: int32): seq[Eth2Digest] =
# Get the portion of the main chain that is within the last EPOCH_LENGTH
# Get the portion of the main chain that is within the last SLOTS_PER_EPOCH
# slots, once again duplicating the parent in cases where the parent and
# child's slots are not consecutive
result = @[]
var i = self.main_chain.high
for slot in countdown(start_slot-1, max(start_slot - EPOCH_LENGTH, 0)):
for slot in countdown(start_slot-1, max(start_slot - SLOTS_PER_EPOCH, 0)):
# Note the max(...)-1 in spec is unneeded, Nim ranges are inclusive
if slot < self.blocks[self.main_chain[i]].slot:
dec i
result.add self.main_chain[i]
for i, x in result:
doAssert self.blocks[x].slot <= start_slot - 1 - i
doAssert result.len == min(EPOCH_LENGTH, start_slot)
doAssert result.len == min(SLOTS_PER_EPOCH, start_slot)
proc tick*(self: Node) =
self.timestamp += initDuration(milliseconds = 100)
@ -244,9 +244,9 @@ proc tick*(self: Node) =
)
self.last_made_block = slot
# Make a sig?
if slot > self.last_made_sig and (slot mod EPOCH_LENGTH) == self.id mod EPOCH_LENGTH:
if slot > self.last_made_sig and (slot mod SLOTS_PER_EPOCH) == self.id mod SLOTS_PER_EPOCH:
var sig_from = self.main_chain.high
while sig_from > 0 and self.blocks[self.main_chain[sig_from]].slot >= slot - EPOCH_LENGTH:
while sig_from > 0 and self.blocks[self.main_chain[sig_from]].slot >= slot - SLOTS_PER_EPOCH:
dec sig_from
let sig = newSig(self.id, self.get_sig_targets(slot), slot, self.timestamp)
self.log &"Sig: {self.id} {sig.slot} {sig.targets.mapIt(($it)[0 ..< 4])}"

View File

@ -21,7 +21,7 @@ import
const
NOTARIES* = 100 # Committee size in Casper v2.1
SLOT_SIZE* = 6 # Slot duration in Casper v2.1
EPOCH_LENGTH* = 25 # Cycle length in Casper v2.
SLOTS_PER_EPOCH* = 25 # Cycle length in Casper v2.
# TODO, clear up if reference semantics are needed
# for the tables. I.e. what's their maximum size.

View File

@ -12,7 +12,7 @@ proc stateSize(deposits: int, maxContent = false) =
# TODO verify this is correct, but generally we collect up to two epochs
# of attestations, and each block has a cap on the number of
# attestations it may hold, so we'll just add so many of them
state.latest_attestations.setLen(MAX_ATTESTATIONS * EPOCH_LENGTH * 2)
state.latest_attestations.setLen(MAX_ATTESTATIONS * SLOTS_PER_EPOCH * 2)
let
crosslink_committees = get_crosslink_committees_at_slot(state, 0)
validatorsPerCommittee =

View File

@ -17,8 +17,8 @@ proc writeJson*(prefix, slot, v: auto) =
write(f, pretty(%*(v)))
cli do(slots = 1945,
validators = EPOCH_LENGTH, # One per shard is minimum
json_interval = EPOCH_LENGTH,
validators = SLOTS_PER_EPOCH, # One per shard is minimum
json_interval = SLOTS_PER_EPOCH,
prefix = 0,
attesterRatio {.desc: "ratio of validators that attest in each round"} = 0.0,
validate = false):

View File

@ -14,5 +14,5 @@ import
suite "Beacon state":
test "Smoke test get_initial_beacon_state":
let state = get_initial_beacon_state(
makeInitialDeposits(EPOCH_LENGTH, {}), 0, Eth1Data(), {})
check: state.validator_registry.len == EPOCH_LENGTH
makeInitialDeposits(SLOTS_PER_EPOCH, {}), 0, Eth1Data(), {})
check: state.validator_registry.len == SLOTS_PER_EPOCH

View File

@ -54,21 +54,21 @@ suite "Block processing":
state = genesisState
previous_block_root = hash_tree_root_final(genesisBlock)
for i in 1..EPOCH_LENGTH.int:
for i in 1..SLOTS_PER_EPOCH.int:
let block_ok = updateState(
state, previous_block_root, none(BeaconBlock), {})
check:
block_ok
check:
state.slot == genesisState.slot + EPOCH_LENGTH
state.slot == genesisState.slot + SLOTS_PER_EPOCH
test "Passes through epoch update, empty block":
var
state = genesisState
previous_block_root = hash_tree_root_final(genesisBlock)
for i in 1..EPOCH_LENGTH.int:
for i in 1..SLOTS_PER_EPOCH.int:
var new_block = makeBlock(state, previous_block_root, BeaconBlockBody())
let block_ok = updateState(
@ -80,7 +80,7 @@ suite "Block processing":
previous_block_root = hash_tree_root_final(new_block)
check:
state.slot == genesisState.slot + EPOCH_LENGTH
state.slot == genesisState.slot + SLOTS_PER_EPOCH
test "Attestation gets processed at epoch":
var

View File

@ -11,7 +11,7 @@ import
func sumCommittees(v: openArray[seq[ValidatorIndex]], reqCommitteeLen: int): int =
for x in v:
## This only holds when num_validators is divisible by
## EPOCH_LENGTH * get_committee_count_per_slot(len(validators))
## SLOTS_PER_EPOCH * get_committee_count_per_slot(len(validators))
## as, in general, not all committees can be equally sized.
assert x.len == reqCommitteeLen
inc result, x.len
@ -31,6 +31,6 @@ suite "Validators":
committees = get_epoch_committee_count(len(validators)).int
check:
s.len == committees
# 32k validators: EPOCH_LENGTH slots * committee_count_per_slot =
# 32k validators: SLOTS_PER_EPOCH slots * committee_count_per_slot =
# get_epoch_committee_count committees.
sumCommittees(s, num_validators div committees) == validators.len() # all validators accounted for

View File

@ -57,7 +57,7 @@ func makeDeposit(i: int, flags: UpdateFlags): Deposit =
)
func makeInitialDeposits*(
n = EPOCH_LENGTH, flags: UpdateFlags = {}): seq[Deposit] =
n = SLOTS_PER_EPOCH, flags: UpdateFlags = {}): seq[Deposit] =
for i in 0..<n.int:
result.add makeDeposit(i + 1, flags)