diff --git a/beacon_chain/attestation_pool.nim b/beacon_chain/attestation_pool.nim index 5f3710cf2..4d5d0a855 100644 --- a/beacon_chain/attestation_pool.nim +++ b/beacon_chain/attestation_pool.nim @@ -161,13 +161,13 @@ proc slotIndex( attestationSlot = $humaneSlotNum(attestationSlot) 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", 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.Slot <= attestationSlot: + while pool.startingSlot + pool.slots.len.uint64 <= attestationSlot: pool.slots.addLast(SlotData()) if pool.startingSlot < state.finalized_epoch.get_epoch_start_slot(): @@ -193,7 +193,7 @@ proc add*(pool: var AttestationPool, let attestationSlot = attestation.data.slot - idx = pool.slotIndex(state, attestationSlot) + idx = pool.slotIndex(state, attestationSlot.Slot) slotData = addr pool.slots[idx] validation = Validation( aggregation_bitfield: attestation.aggregation_bitfield, @@ -279,11 +279,11 @@ proc getAttestationsForBlock*(pool: AttestationPool, attestationSlot = newBlockSlot - MIN_ATTESTATION_INCLUSION_DELAY if attestationSlot < pool.startingSlot or - attestationSlot >= pool.startingSlot + pool.slots.len.Slot: + attestationSlot >= pool.startingSlot + pool.slots.len.uint64: info "No attestations", attestationSlot = humaneSlotNum(attestationSlot), startingSlot = humaneSlotNum(pool.startingSlot), - endingSlot = humaneSlotNum(pool.startingSlot + pool.slots.len.Slot) + endingSlot = humaneSlotNum(pool.startingSlot + pool.slots.len.uint64) return diff --git a/beacon_chain/beacon_node.nim b/beacon_chain/beacon_node.nim index 67f37ff5d..b4e7af6e6 100644 --- a/beacon_chain/beacon_node.nim +++ b/beacon_chain/beacon_node.nim @@ -308,7 +308,7 @@ proc proposeBlock(node: BeaconNode, newBlock.state_root = Eth2Digest(data: hash_tree_root(state)) let proposal = Proposal( - slot: slot, + slot: slot.uint64, shard: BEACON_CHAIN_SHARD_NUMBER, block_root: Eth2Digest(data: signed_root(newBlock, "signature")), signature: ValidatorSig(), @@ -441,7 +441,7 @@ proc scheduleEpochActions(node: BeaconNode, epoch: Epoch) = let start = if epoch == GENESIS_EPOCH: 1.uint64 else: 0.uint64 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 block: # Schedule block proposals diff --git a/beacon_chain/block_pool.nim b/beacon_chain/block_pool.nim index fffc83dc3..c42a3c11d 100644 --- a/beacon_chain/block_pool.nim +++ b/beacon_chain/block_pool.nim @@ -54,7 +54,7 @@ proc init*(T: type BlockPool, db: BeaconChainDB): BlockPool = var blocksBySlot = initTable[uint64, seq[BlockRef]]() for _, b in tables.pairs(blocks): let slot = db.getBlock(b.root).get().slot - blocksBySlot.mgetOrPut(slot, @[]).add(b) + blocksBySlot.mgetOrPut(slot.uint64, @[]).add(b) BlockPool( pending: initTable[Eth2Digest, BeaconBlock](), @@ -146,7 +146,7 @@ proc add*( pool.blocks[blockRoot] = blockRef - pool.addSlotMapping(blck.slot, blockRef) + pool.addSlotMapping(blck.slot.uint64, blockRef) # Resolved blocks should be stored in database pool.db.putBlock(blockRoot, blck) @@ -229,8 +229,8 @@ proc getOrResolve*(pool: var BlockPool, root: Eth2Digest): BlockRef = if result.isNil: pool.unresolved[root] = UnresolvedBlock() -iterator blockRootsForSlot*(pool: BlockPool, slot: uint64): Eth2Digest = - for br in pool.blocksBySlot.getOrDefault(slot, @[]): +iterator blockRootsForSlot*(pool: BlockPool, slot: uint64|Slot): Eth2Digest = + for br in pool.blocksBySlot.getOrDefault(slot.uint64, @[]): yield br.root proc checkUnresolved*(pool: var BlockPool): seq[Eth2Digest] = diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index accf57279..74bebaf68 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -280,7 +280,7 @@ func get_attestation_participants*(state: BeaconState, ## Return the participant indices at for the ``attestation_data`` and ## ``bitfield``. let crosslink_committees = get_crosslink_committees_at_slot( - state, attestation_data.slot) + state, attestation_data.slot.Slot) doAssert anyIt( crosslink_committees, 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 ## be followed! + let attestation_data_slot = attestation.data.slot.Slot + if not (attestation.data.slot >= GENESIS_SLOT): warn("Attestation predates genesis slot", attestation_slot = attestation.data.slot, @@ -386,7 +388,7 @@ proc checkAttestation*( return 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 else: state.previous_justified_epoch @@ -410,12 +412,12 @@ proc checkAttestation*( attestation.data.latest_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_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) return @@ -423,7 +425,7 @@ proc checkAttestation*( assert anyIt(attestation.aggregation_bitfield, 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] @@ -475,7 +477,7 @@ proc checkAttestation*( data: attestation.data, custody_bit: true)), ], 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), ) @@ -513,7 +515,7 @@ proc makeAttestationData*( justified_block_root = get_block_root(state, justified_slot) AttestationData( - slot: state.slot, + slot: state.slot.uint64, shard: shard, beacon_block_root: beacon_block_root, epoch_boundary_root: epoch_boundary_root, diff --git a/beacon_chain/spec/datatypes.nim b/beacon_chain/spec/datatypes.nim index 68617c326..82999d176 100644 --- a/beacon_chain/spec/datatypes.nim +++ b/beacon_chain/spec/datatypes.nim @@ -18,7 +18,7 @@ # types / composition import - eth/common, math, + eth/common, hashes, math, ./crypto, ./digest # TODO Data types: @@ -39,6 +39,11 @@ import # TODO Many of these constants should go into a config object that can be used # to run.. well.. a chain with different constants! + +type + Slot* = distinct uint64 + Epoch* = uint64 + const SPEC_VERSION* = "0.4.0" ## \ ## Spec version we're aiming to be compatible with, right now @@ -103,8 +108,9 @@ const # 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_SLOT* = 2'u64^32 - GENESIS_EPOCH* = GENESIS_SLOT div SLOTS_PER_EPOCH # slot_to_epoch(GENESIS_SLOT) + GENESIS_SLOT* = (2'u64^32).Slot + GENESIS_EPOCH* = (GENESIS_SLOT.uint64 div SLOTS_PER_EPOCH).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() @@ -172,12 +178,6 @@ const type 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 # 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 ##\ ## Last crosslink - justified_epoch*: uint64 ##\ + justified_epoch*: Epoch ##\ ## Last justified epoch in the beacon state 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 VoluntaryExit* = object # Minimum epoch for processing exit - epoch*: uint64 + epoch*: Epoch # Index of the exiting validator validator_index*: uint64 # Validator signature @@ -321,12 +321,12 @@ type ## Each block collects attestations, or votes, on past blocks, thus a chain ## is formed. - slot*: uint64 + slot*: Slot parent_root*: Eth2Digest ##\ ##\ Root hash of the previous block state_root*: Eth2Digest ##\ - ##\ The state root, _after_ this block has been processed + ## The state root, _after_ this block has been processed randao_reveal*: ValidatorSig ##\ ## 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 BeaconState* = object - slot*: uint64 + slot*: Slot genesis_time*: uint64 fork*: Fork ##\ ## For versioning hard forks @@ -385,7 +385,7 @@ type validator_balances*: seq[uint64] ##\ ## Validator balances in Gwei! - validator_registry_update_epoch*: uint64 + validator_registry_update_epoch*: Epoch # TODO remove or conditionally compile; not in spec anymore validator_registry_delta_chain_tip*: Eth2Digest ##\ @@ -395,16 +395,16 @@ type latest_randao_mixes*: array[LATEST_BLOCK_ROOTS_LENGTH.int, Eth2Digest] previous_shuffling_start_shard*: uint64 current_shuffling_start_shard*: uint64 - previous_shuffling_epoch*: uint64 - current_shuffling_epoch*: uint64 + previous_shuffling_epoch*: Epoch + current_shuffling_epoch*: Epoch previous_shuffling_seed*: Eth2Digest current_shuffling_seed*: Eth2Digest # Finality - previous_justified_epoch*: uint64 - justified_epoch*: uint64 + previous_justified_epoch*: Epoch + justified_epoch*: Epoch justification_bitfield*: uint64 - finalized_epoch*: uint64 + finalized_epoch*: Epoch # Recent state latest_crosslinks*: array[SHARD_COUNT, Crosslink] @@ -434,13 +434,13 @@ type withdrawal_credentials*: Eth2Digest ##\ ## Withdrawal credentials - activation_epoch*: uint64 ##\ + activation_epoch*: Epoch ##\ ## Epoch when validator activated - exit_epoch*: uint64 ##\ + exit_epoch*: Epoch ##\ ## Epoch when validator exited - withdrawable_epoch*: uint64 ##\ + withdrawable_epoch*: Epoch ##\ ## Epoch when validator is eligible to withdraw 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 Crosslink* = object - epoch*: uint64 ##\ + epoch*: Epoch ##\ ## Epoch number crosslink_data_root*: Eth2Digest ##\ @@ -462,13 +462,13 @@ type aggregation_bitfield*: seq[byte] # Attester participation bitfield data*: AttestationData # Attestation data 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 Fork* = object previous_version*: uint64 # Previous 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 Eth1Data* = object @@ -522,8 +522,39 @@ type func shortValidatorKey*(state: BeaconState, validatorIdx: int): string = ($state.validator_registry[validatorIdx].pubkey)[0..7] -func humaneSlotNum*(s: Slot): Slot = - s - GENESIS_SLOT +template ethTimeUnit(typ: type) = + 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 = e - GENESIS_EPOCH diff --git a/beacon_chain/spec/helpers.nim b/beacon_chain/spec/helpers.nim index 6b4ee174f..3760fae48 100644 --- a/beacon_chain/spec/helpers.nim +++ b/beacon_chain/spec/helpers.nim @@ -120,13 +120,13 @@ func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest = o[1] # 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 = - slot div SLOTS_PER_EPOCH +func slot_to_epoch*(slot: Slot|uint64): 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 func get_epoch_start_slot*(epoch: Epoch): Slot = # 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 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 ## target. let - target_epoch_1 = slot_to_epoch(attestation_data_1.slot) - target_epoch_2 = slot_to_epoch(attestation_data_2.slot) + # RLP artifact + 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 # 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 source_epoch_1 = attestation_data_1.justified_epoch source_epoch_2 = attestation_data_2.justified_epoch - target_epoch_1 = slot_to_epoch(attestation_data_1.slot) - target_epoch_2 = slot_to_epoch(attestation_data_2.slot) + # RLP artifact + 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 diff --git a/beacon_chain/spec/validator.nim b/beacon_chain/spec/validator.nim index 0ade06e41..e235a6e50 100644 --- a/beacon_chain/spec/validator.nim +++ b/beacon_chain/spec/validator.nim @@ -126,7 +126,7 @@ func get_previous_epoch*(state: BeaconState): 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 -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): seq[CrosslinkCommittee] = ## Returns the list of ``(committee, shard)`` tuples for the ``slot``. diff --git a/beacon_chain/ssz.nim b/beacon_chain/ssz.nim index f1afeba4e..03c05974e 100644 --- a/beacon_chain/ssz.nim +++ b/beacon_chain/ssz.nim @@ -153,6 +153,12 @@ proc endRecord*(w: var SszWriter, memo: RecordWritingMemo) = let finalSize = uint32(w.stream.pos - memo.initialStreamPos - 4) 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) = # We are not using overloads here, because this leads to # 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 when defined(debugFieldSizes) and obj is (BeaconState|BeaconBlock): let start = w.stream.pos - w.writeValue field + w.writeValue field.toSSZType debugEcho fieldName, ": ", w.stream.pos - start else: - w.writeValue field + w.writeValue field.toSSZType w.endRecord(memo) proc readValue*(r: var SszReader, result: var auto) = @@ -235,7 +241,10 @@ proc readValue*(r: var SszReader, result: var auto) = else: result.deserializeFields(fieldName, field): - field = r.readValue(field.type) + when field is Slot: + field = r.readValue(uint64).Slot + else: + field = r.readValue(field.type) if r.stream[].pos != endPos: raise newException(CorruptedDataError, "SSZ includes unexpected bytes past the end of the deserialized object") @@ -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 withHash: 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 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: found_field_name = true break - h.update hash_tree_root(field) + h.update hash_tree_root(field.toSSZType) doAssert found_field_name diff --git a/beacon_chain/state_transition.nim b/beacon_chain/state_transition.nim index 343797858..cb535cb60 100644 --- a/beacon_chain/state_transition.nim +++ b/beacon_chain/state_transition.nim @@ -49,7 +49,7 @@ func verifyBlockSignature(state: BeaconState, blck: BeaconBlock): bool = proposer = state.validator_registry[get_beacon_proposer_index(state, state.slot)] proposal = Proposal( - slot: blck.slot, + slot: blck.slot.uint64, shard: BEACON_CHAIN_SHARD_NUMBER, block_root: Eth2Digest(data: signed_root(blck, "signature")), signature: blck.signature) @@ -361,7 +361,8 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock, let transfer_message = signed_root(transfer, "signature") if not bls_verify( 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" return false @@ -611,7 +612,7 @@ func processEpoch(state: var BeaconState) = let previous_epoch_head_attestations = 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 = 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 block: - for slot in get_epoch_start_slot(previous_epoch) ..< get_epoch_start_slot(next_epoch): - let crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot) + for slot in get_epoch_start_slot(previous_epoch).uint64 ..< + 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: 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 func inclusion_distances(state: BeaconState): auto = - result = initTable[ValidatorIndex, uint64]() + result = initTable[ValidatorIndex, Slot]() for a in previous_epoch_attestations: for v in get_attestation_participants( @@ -801,7 +804,7 @@ func processEpoch(state: var BeaconState) = else: ## Last case will not occur. If this assumption becomes false, ## indexing into distances will fail. - initTable[ValidatorIndex, uint64]() + initTable[ValidatorIndex, Slot]() for index in active_validator_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, ## then perform O(n) O(1) lookups. Keep same iteration order and rules in ## 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(...) 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 block: - for slot in get_epoch_start_slot(previous_epoch) ..< get_epoch_start_slot(current_epoch): - let crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot) + for slot in get_epoch_start_slot(previous_epoch).uint64 ..< + 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: let committee_attesting_validators = diff --git a/beacon_chain/sync_protocol.nim b/beacon_chain/sync_protocol.nim index 026e41106..1a93d858c 100644 --- a/beacon_chain/sync_protocol.nim +++ b/beacon_chain/sync_protocol.nim @@ -24,7 +24,7 @@ type func toHeader(b: BeaconBlock): BeaconBlockHeader = BeaconBlockHeader( - slot: b.slot, + slot: b.slot.uint64, parent_root: b.parent_root, state_root: b.state_root, randao_reveal: b.randao_reveal, @@ -35,7 +35,7 @@ func toHeader(b: BeaconBlock): BeaconBlockHeader = proc fromHeaderAndBody(b: var BeaconBlock, h: BeaconBlockHeader, body: BeaconBlockBody) = assert(hash_tree_root_final(body) == h.body) - b.slot = h.slot + b.slot = h.slot.Slot b.parent_root = h.parent_root b.state_root = h.state_root b.randao_reveal = h.randao_reveal @@ -76,7 +76,7 @@ p2pProtocol BeaconSync(version = 1, latestFinalizedRoot: Eth2Digest # TODO latestFinalizedEpoch: uint64 = node.state.data.finalized_epoch bestRoot: Eth2Digest # TODO - bestSlot: uint64 = node.state.data.slot + bestSlot: uint64 = node.state.data.slot.uint64 let m = await handshake(peer, timeout = 500, status(networkId, latestFinalizedRoot, diff --git a/research/serialized_sizes.nim b/research/serialized_sizes.nim index 7aa85e2ba..468419cfc 100644 --- a/research/serialized_sizes.nim +++ b/research/serialized_sizes.nim @@ -15,7 +15,7 @@ proc stateSize(deposits: int, maxContent = false) = # attestations it may hold, so we'll just add so many of them state.latest_attestations.setLen(MAX_ATTESTATIONS * SLOTS_PER_EPOCH * 2) let - crosslink_committees = get_crosslink_committees_at_slot(state, 0) + crosslink_committees = get_crosslink_committees_at_slot(state, 0.Slot) validatorsPerCommittee = len(crosslink_committees[0].committee) # close enough.. for a in state.latest_attestations.mitems(): diff --git a/research/state_sim.nim b/research/state_sim.nim index a63bc4756..e0264d94f 100644 --- a/research/state_sim.nim +++ b/research/state_sim.nim @@ -36,6 +36,8 @@ template withTimerRet(stats: var RunningStat, body: untyped): untyped = tmp +proc `%`*(x: Slot): JsonNode {.borrow.} + proc writeJson*(prefix, slot, v: auto) = var f: File defer: close(f) @@ -80,7 +82,7 @@ cli do(slots = 1945, attestations[attestations_idx] = @[] 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 withTimer(timers[t]): diff --git a/tests/test_beacon_chain_db.nim b/tests/test_beacon_chain_db.nim index 30baf404c..609de1105 100644 --- a/tests/test_beacon_chain_db.nim +++ b/tests/test_beacon_chain_db.nim @@ -57,11 +57,12 @@ suite "Beacon chain DB": check: x == y let - a0 = BeaconBlock(slot: 0) + # TODO Not GENESIS_SLOT? + a0 = BeaconBlock(slot: 0.Slot) 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) - a2 = BeaconBlock(slot: 2, parent_root: a1r) + a2 = BeaconBlock(slot: 2.Slot, parent_root: a1r) a2r = hash_tree_root_final(a2) doAssert toSeq(db.getAncestors(a0r)) == [] diff --git a/tests/test_ssz.nim b/tests/test_ssz.nim index 3d093f64f..95fe90abb 100644 --- a/tests/test_ssz.nim +++ b/tests/test_ssz.nim @@ -74,8 +74,9 @@ suite "Simple serialization": SSZ.roundripTest [1, 2, 3] SSZ.roundripTest @[1, 2, 3] SSZ.roundripTest SigKey.random().getKey() - SSZ.roundripTest BeaconBlock(slot: 42, signature: sign(SigKey.random(), 0'u64, "")) - SSZ.roundripTest BeaconState(slot: 42) + SSZ.roundripTest BeaconBlock( + slot: 42.Slot, signature: sign(SigKey.random(), 0'u64, "")) + SSZ.roundripTest BeaconState(slot: 42.Slot) suite "Tree hashing": # TODO Nothing but smoke tests for now.. diff --git a/tests/testutil.nim b/tests/testutil.nim index 6f4b0da05..719bd54c5 100644 --- a/tests/testutil.nim +++ b/tests/testutil.nim @@ -120,7 +120,7 @@ proc addBlock*( # Once we've collected all the state data, we sign the block data along with # some book-keeping values signed_data = Proposal( - slot: new_block.slot, + slot: new_block.slot.uint64, shard: BEACON_CHAIN_SHARD_NUMBER, block_root: Eth2Digest(data: signed_root(new_block, "signature")), signature: ValidatorSig(),