diff --git a/beacon_chain/attestation_pool.nim b/beacon_chain/attestation_pool.nim index 9e6929efa0..01541e2d86 100644 --- a/beacon_chain/attestation_pool.nim +++ b/beacon_chain/attestation_pool.nim @@ -135,16 +135,14 @@ proc slotIndex( # to start counting at the last finalized epoch start slot - anything # earlier than that is thrown out by the above check info "First attestation!", - attestationSlot = $shortLog(attestationSlot), - cat = "init" + attestationSlot = shortLog(attestationSlot) pool.startingSlot = state.finalized_checkpoint.epoch.compute_start_slot_at_epoch() if pool.startingSlot + pool.mapSlotsToAttestations.len.uint64 <= attestationSlot: trace "Growing attestation pool", - attestationSlot = $shortLog(attestationSlot), - startingSlot = $shortLog(pool.startingSlot), - cat = "caching" + attestationSlot = shortLog(attestationSlot), + startingSlot = shortLog(pool.startingSlot) # Make sure there's a pool entry for every slot, even when there's a gap while pool.startingSlot + pool.mapSlotsToAttestations.len.uint64 <= attestationSlot: @@ -153,11 +151,10 @@ proc slotIndex( if pool.startingSlot < state.finalized_checkpoint.epoch.compute_start_slot_at_epoch(): debug "Pruning attestation pool", - startingSlot = $shortLog(pool.startingSlot), - finalizedSlot = $shortLog( + startingSlot = shortLog(pool.startingSlot), + finalizedSlot = shortLog( state.finalized_checkpoint - .epoch.compute_start_slot_at_epoch()), - cat = "pruning" + .epoch.compute_start_slot_at_epoch()) # TODO there should be a better way to remove a whole epoch of stuff.. while pool.startingSlot < @@ -245,8 +242,7 @@ proc addResolved(pool: var AttestationPool, blck: BlockRef, attestation: Attesta if not isValidAttestationTargetEpoch(state, attestation.data): notice "Invalid attestation", attestation = shortLog(attestation), - current_epoch = get_current_epoch(state), - cat = "filtering" + current_epoch = get_current_epoch(state) return # TODO inefficient data structures.. @@ -274,8 +270,7 @@ proc addResolved(pool: var AttestationPool, blck: BlockRef, attestation: Attesta # sets by virtue of not overlapping with some other attestation # and therefore being useful after all? trace "Ignoring subset attestation", - newParticipants = participants, - cat = "filtering" + newParticipants = participants found = true break @@ -284,8 +279,7 @@ proc addResolved(pool: var AttestationPool, blck: BlockRef, attestation: Attesta # can now be removed per same logic as above trace "Removing subset attestations", - newParticipants = participants, - cat = "pruning" + newParticipants = participants a.validations.keepItIf( not it.aggregation_bits.isSubsetOf(validation.aggregation_bits)) @@ -297,8 +291,7 @@ proc addResolved(pool: var AttestationPool, blck: BlockRef, attestation: Attesta attestation = shortLog(attestation), validations = a.validations.len(), current_epoch = get_current_epoch(state), - blockSlot = shortLog(blck.slot), - cat = "filtering" + blockSlot = shortLog(blck.slot) found = true @@ -316,8 +309,7 @@ proc addResolved(pool: var AttestationPool, blck: BlockRef, attestation: Attesta attestation = shortLog(attestation), current_epoch = get_current_epoch(state), validations = 1, - blockSlot = shortLog(blck.slot), - cat = "filtering" + blockSlot = shortLog(blck.slot) proc addAttestation*(pool: var AttestationPool, attestation: Attestation) = ## Add a verified attestation to the fork choice context @@ -400,14 +392,12 @@ proc getAttestationsForSlot*(pool: AttestationPool, newBlockSlot: Slot): Option[AttestationsSeen] = if newBlockSlot < (GENESIS_SLOT + MIN_ATTESTATION_INCLUSION_DELAY): debug "Too early for attestations", - newBlockSlot = shortLog(newBlockSlot), - cat = "query" + newBlockSlot = shortLog(newBlockSlot) return none(AttestationsSeen) if pool.mapSlotsToAttestations.len == 0: # startingSlot not set yet! info "No attestations found (pool empty)", - newBlockSlot = shortLog(newBlockSlot), - cat = "query" + newBlockSlot = shortLog(newBlockSlot) return none(AttestationsSeen) let @@ -423,8 +413,7 @@ proc getAttestationsForSlot*(pool: AttestationPool, newBlockSlot: Slot): info "No attestations matching the slot range", attestationSlot = shortLog(attestationSlot), startingSlot = shortLog(pool.startingSlot), - endingSlot = shortLog(pool.startingSlot + pool.mapSlotsToAttestations.len.uint64), - cat = "query" + endingSlot = shortLog(pool.startingSlot + pool.mapSlotsToAttestations.len.uint64) return none(AttestationsSeen) let slotDequeIdx = int(attestationSlot - pool.startingSlot) @@ -484,7 +473,7 @@ proc getAttestationsForBlock*(pool: AttestationPool, # to include a broken attestation if not check_attestation(state, attestation, {}, cache): warn "Attestation no longer validates...", - cat = "query" + attestation = shortLog(attestation) continue for v in a.validations[1..^1]: @@ -637,7 +626,7 @@ proc pruneBefore*(pool: var AttestationPool, finalizedhead: BlockSlot) = proc selectHead*(pool: var AttestationPool): BlockRef = let head_v1 = pool.selectHead_v1() # let head_v2 = pool.selectHead_v2() - # + # # if head_v1 != head_v2: # error "Fork choice engines in disagreement, using block from v1.", # v1_block = shortlog(head_v1), diff --git a/beacon_chain/beacon_chain_db.nim b/beacon_chain/beacon_chain_db.nim index 56d97a0300..66d73915a9 100644 --- a/beacon_chain/beacon_chain_db.nim +++ b/beacon_chain/beacon_chain_db.nim @@ -115,10 +115,10 @@ proc get(db: BeaconChainDB, key: openArray[byte], res: var auto): bool = found -proc putBlock*(db: BeaconChainDB, key: Eth2Digest, value: SignedBeaconBlock) = - db.put(subkey(type value, key), value) -proc putBlock*(db: BeaconChainDB, key: Eth2Digest, value: TrustedSignedBeaconBlock) = - db.put(subkey(SignedBeaconBlock, key), value) +proc putBlock*(db: BeaconChainDB, value: SignedBeaconBlock) = + db.put(subkey(type value, value.root), value) +proc putBlock*(db: BeaconChainDB, value: TrustedSignedBeaconBlock) = + db.put(subkey(SignedBeaconBlock, value.root), value) proc putState*(db: BeaconChainDB, key: Eth2Digest, value: BeaconState) = # TODO prune old states - this is less easy than it seems as we never know @@ -133,11 +133,6 @@ proc putStateRoot*(db: BeaconChainDB, root: Eth2Digest, slot: Slot, value: Eth2Digest) = db.put(subkey(root, slot), value) -proc putBlock*(db: BeaconChainDB, value: SomeSignedBeaconBlock) = - # TODO this should perhaps be a TrustedSignedBeaconBlock, but there's no - # trivial way to coerce one type into the other, as it stands.. - db.putBlock(hash_tree_root(value.message), value) - proc delBlock*(db: BeaconChainDB, key: Eth2Digest) = db.backend.del(subkey(SignedBeaconBlock, key)).expect( "working database") @@ -156,7 +151,7 @@ proc putTailBlock*(db: BeaconChainDB, key: Eth2Digest) = proc getBlock*(db: BeaconChainDB, key: Eth2Digest): Opt[TrustedSignedBeaconBlock] = # We only store blocks that we trust in the database - result.ok(TrustedSignedBeaconBlock()) + result.ok(TrustedSignedBeaconBlock(root: key)) if not db.get(subkey(SignedBeaconBlock, key), result.get): result.err() @@ -195,14 +190,14 @@ proc containsState*(db: BeaconChainDB, key: Eth2Digest): bool = db.backend.contains(subkey(BeaconState, key)).expect("working database") iterator getAncestors*(db: BeaconChainDB, root: Eth2Digest): - tuple[root: Eth2Digest, blck: TrustedSignedBeaconBlock] = + TrustedSignedBeaconBlock = ## Load a chain of ancestors for blck - returns a list of blocks with the ## oldest block last (blck will be at result[0]). ## ## The search will go on until the ancestor cannot be found. - var res: tuple[root: Eth2Digest, blck: TrustedSignedBeaconBlock] + var res: TrustedSignedBeaconBlock res.root = root - while db.get(subkey(SignedBeaconBlock, res.root), res.blck): + while db.get(subkey(SignedBeaconBlock, res.root), res): yield res - res.root = res.blck.message.parent_root + res.root = res.message.parent_root diff --git a/beacon_chain/beacon_node.nim b/beacon_chain/beacon_node.nim index 82c2633f65..745ddd4d8a 100644 --- a/beacon_chain/beacon_node.nim +++ b/beacon_chain/beacon_node.nim @@ -290,31 +290,29 @@ proc onAttestation(node: BeaconNode, attestation: Attestation) = # We received an attestation from the network but don't know much about it # yet - in particular, we haven't verified that it belongs to particular chain # we're on, or that it follows the rules of the protocol - logScope: pcs = "on_attestation" + logScope: + attestation = shortLog(attestation) + pcs = "on_attestation" let wallSlot = node.beaconClock.now().toSlot() head = node.blockPool.head debug "Attestation received", - attestation = shortLog(attestation), - headRoot = shortLog(head.blck.root), - headSlot = shortLog(head.blck.slot), - wallSlot = shortLog(wallSlot.slot), - cat = "consensus" # Tag "consensus|attestation"? + head = shortLog(head.blck), + wallSlot = shortLog(wallSlot.slot) if not wallSlot.afterGenesis or wallSlot.slot < head.blck.slot: warn "Received attestation before genesis or head - clock is wrong?", afterGenesis = wallSlot.afterGenesis, wallSlot = shortLog(wallSlot.slot), - headSlot = shortLog(head.blck.slot), - cat = "clock_drift" # Tag "attestation|clock_drift"? + head = shortLog(head.blck) return if attestation.data.slot > head.blck.slot and (attestation.data.slot - head.blck.slot) > MaxEmptySlotCount: warn "Ignoring attestation, head block too old (out of sync?)", - attestationSlot = attestation.data.slot, headSlot = head.blck.slot + head = head.blck return node.attestationPool.addAttestation(attestation) @@ -326,28 +324,24 @@ proc dumpBlock[T]( case res.error of Invalid: dump( - node.config.dumpDirInvalid, signedBlock, - hash_tree_root(signedBlock.message)) + node.config.dumpDirInvalid, signedBlock) of MissingParent: dump( - node.config.dumpDirIncoming, signedBlock, - hash_tree_root(signedBlock.message)) + node.config.dumpDirIncoming, signedBlock) else: discard proc storeBlock( node: BeaconNode, signedBlock: SignedBeaconBlock): Result[void, BlockError] = - let blockRoot = hash_tree_root(signedBlock.message) debug "Block received", signedBlock = shortLog(signedBlock.message), - blockRoot = shortLog(blockRoot), - cat = "block_listener", + blockRoot = shortLog(signedBlock.root), pcs = "receive_block" beacon_blocks_received.inc() {.gcsafe.}: # TODO: fork choice and blockpool should sync via messages instead of callbacks - let blck = node.blockPool.addRawBlock(blockRoot, signedBlock) do (validBlock: BlockRef): + let blck = node.blockPool.addRawBlock(signedBlock) do (validBlock: BlockRef): # Callback add to fork choice if valid # node.attestationPool.addForkChoice_v2(validBlock) discard "TODO: Deactivated" @@ -364,8 +358,7 @@ proc storeBlock( # all of them. Let's add them to the attestation pool. for attestation in signedBlock.message.body.attestations: debug "Attestation from block", - attestation = shortLog(attestation), - cat = "consensus" # Tag "consensus|attestation"? + attestation = shortLog(attestation) node.attestationPool.addAttestation(attestation) ok() @@ -418,8 +411,7 @@ proc onSlotStart(node: BeaconNode, lastSlot, scheduledSlot: Slot) {.gcsafe, asyn headRoot = shortLog(node.blockPool.head.blck.root), finalizedSlot = shortLog(node.blockPool.finalizedHead.blck.slot), finalizedRoot = shortLog(node.blockPool.finalizedHead.blck.root), - finalizedEpoch = shortLog(node.blockPool.finalizedHead.blck.slot.compute_epoch_at_slot()), - cat = "scheduling" + finalizedEpoch = shortLog(node.blockPool.finalizedHead.blck.slot.compute_epoch_at_slot()) # Check before any re-scheduling of onSlotStart() # Offset backwards slightly to allow this epoch's finalization check to occur @@ -447,8 +439,7 @@ proc onSlotStart(node: BeaconNode, lastSlot, scheduledSlot: Slot) {.gcsafe, asyn beaconTime = shortLog(beaconTime), lastSlot = shortLog(lastSlot), scheduledSlot = shortLog(scheduledSlot), - nextSlot = shortLog(nextSlot), - cat = "clock_drift" # tag "scheduling|clock_drift"? + nextSlot = shortLog(nextSlot) addTimer(saturate(node.beaconClock.fromNow(nextSlot))) do (p: pointer): asyncCheck node.onSlotStart(slot, nextSlot) @@ -474,8 +465,7 @@ proc onSlotStart(node: BeaconNode, lastSlot, scheduledSlot: Slot) {.gcsafe, asyn lastSlot = shortLog(lastSlot), slot = shortLog(slot), nextSlot = shortLog(nextSlot), - scheduledSlot = shortLog(scheduledSlot), - cat = "overload" + scheduledSlot = shortLog(scheduledSlot) addTimer(saturate(node.beaconClock.fromNow(nextSlot))) do (p: pointer): # We pass the current slot here to indicate that work should be skipped! @@ -522,8 +512,7 @@ proc onSlotStart(node: BeaconNode, lastSlot, scheduledSlot: Slot) {.gcsafe, asyn headRoot = shortLog(node.blockPool.head.blck.root), finalizedSlot = shortLog(node.blockPool.finalizedHead.blck.slot), finalizedEpoch = shortLog(node.blockPool.finalizedHead.blck.slot.compute_epoch_at_slot()), - finalizedRoot = shortLog(node.blockPool.finalizedHead.blck.root), - cat = "scheduling" + finalizedRoot = shortLog(node.blockPool.finalizedHead.blck.root) when declared(GC_fullCollect): # The slots in the beacon node work as frames in a game: we want to make @@ -844,8 +833,7 @@ proc run*(node: BeaconNode) = info "Scheduling first slot action", beaconTime = shortLog(node.beaconClock.now()), nextSlot = shortLog(nextSlot), - fromNow = shortLog(fromNow), - cat = "scheduling" + fromNow = shortLog(fromNow) addTimer(fromNow) do (p: pointer): asyncCheck node.onSlotStart(curSlot, nextSlot) @@ -896,15 +884,12 @@ proc start(node: BeaconNode) = timeSinceFinalization = int64(finalizedHead.slot.toBeaconTime()) - int64(node.beaconClock.now()), - headSlot = shortLog(head.blck.slot), - headRoot = shortLog(head.blck.root), - finalizedSlot = shortLog(finalizedHead.blck.slot), - finalizedRoot = shortLog(finalizedHead.blck.root), + head = shortLog(head.blck), + finalizedHead = shortLog(finalizedHead), SLOTS_PER_EPOCH, SECONDS_PER_SLOT, SPEC_VERSION, dataDir = node.config.dataDir.string, - cat = "init", pcs = "start_beacon_node" if genesisTime.inFuture: diff --git a/beacon_chain/block_pool.nim b/beacon_chain/block_pool.nim index 11b39ab110..31607bef62 100644 --- a/beacon_chain/block_pool.nim +++ b/beacon_chain/block_pool.nim @@ -53,8 +53,7 @@ template head*(pool: BlockPool): Head = template finalizedHead*(pool: BlockPool): BlockSlot = pool.dag.finalizedHead -proc addRawBlock*(pool: var BlockPool, blockRoot: Eth2Digest, - signedBlock: SignedBeaconBlock, +proc addRawBlock*(pool: var BlockPool, signedBlock: SignedBeaconBlock, callback: proc(blck: BlockRef) ): Result[BlockRef, BlockError] = ## Add a raw block to the blockpool @@ -65,7 +64,7 @@ proc addRawBlock*(pool: var BlockPool, blockRoot: Eth2Digest, # - the ugly `inAdd` field # - the callback # - callback may be problematic as it's called in async validator duties - result = addRawBlock(pool.dag, pool.quarantine, blockRoot, signedBlock, callback) + result = addRawBlock(pool.dag, pool.quarantine, signedBlock, callback) export parent # func parent*(bs: BlockSlot): BlockSlot export isAncestorOf # func isAncestorOf*(a, b: BlockRef): bool diff --git a/beacon_chain/block_pools/candidate_chains.nim b/beacon_chain/block_pools/candidate_chains.nim index 864cf5d795..ebf1f53296 100644 --- a/beacon_chain/block_pools/candidate_chains.nim +++ b/beacon_chain/block_pools/candidate_chains.nim @@ -26,8 +26,8 @@ declareCounter beacon_state_data_cache_misses, "dag.cachedStates misses" logScope: topics = "hotdb" proc putBlock*( - dag: var CandidateChains, blockRoot: Eth2Digest, signedBlock: SignedBeaconBlock) = - dag.db.putBlock(blockRoot, signedBlock) + dag: var CandidateChains, signedBlock: SignedBeaconBlock) = + dag.db.putBlock(signedBlock) proc updateStateData*( dag: CandidateChains, state: var StateData, bs: BlockSlot) {.gcsafe.} @@ -226,14 +226,14 @@ proc init*(T: type CandidateChains, if headRoot != tailRoot: var curRef: BlockRef - for root, blck in db.getAncestors(headRoot): - if root == tailRef.root: + for blck in db.getAncestors(headRoot): + if blck.root == tailRef.root: doAssert(not curRef.isNil) link(tailRef, curRef) curRef = curRef.parent break - let newRef = BlockRef.init(root, blck.message) + let newRef = BlockRef.init(blck.root, blck.message) if curRef == nil: curRef = newRef headRef = newRef @@ -428,8 +428,8 @@ proc putState*(dag: CandidateChains, state: HashedBeaconState, blck: BlockRef) = info "Storing state", blck = shortLog(blck), stateSlot = shortLog(state.data.slot), - stateRoot = shortLog(state.root), - cat = "caching" + stateRoot = shortLog(state.root) + dag.db.putState(state.root, state.data) if not rootWritten: dag.db.putStateRoot(blck.root, state.data.slot, state.root) @@ -542,7 +542,9 @@ proc skipAndUpdateState( proc rewindState(dag: CandidateChains, state: var StateData, bs: BlockSlot): seq[BlockRef] = - logScope: pcs = "replay_state" + logScope: + blockSlot = shortLog(bs) + pcs = "replay_state" var ancestors = @[bs.blck] # Common case: the last block applied is the parent of the block to apply: @@ -586,11 +588,7 @@ proc rewindState(dag: CandidateChains, state: var StateData, bs: BlockSlot): trace "Replaying state transitions via in-memory cache", stateSlot = shortLog(state.data.data.slot), ancestorStateRoot = shortLog(state.data.root), - ancestorStateSlot = shortLog(state.data.data.slot), - slot = shortLog(bs.slot), - blockRoot = shortLog(bs.blck.root), - ancestors = ancestors.len, - cat = "replay_state" + ancestors = ancestors.len return ancestors @@ -607,11 +605,7 @@ proc rewindState(dag: CandidateChains, state: var StateData, bs: BlockSlot): # list of parent blocks and couldn't find a corresponding state in the # database, which should never happen (at least we should have the # tail state in there!) - error "Couldn't find ancestor state root!", - blockRoot = shortLog(bs.blck.root), - blockSlot = shortLog(bs.blck.slot), - slot = shortLog(bs.slot), - cat = "crash" + fatal "Couldn't find ancestor state root!" doAssert false, "Oh noes, we passed big bang!" let @@ -624,20 +618,12 @@ proc rewindState(dag: CandidateChains, state: var StateData, bs: BlockSlot): # list of parent blocks and couldn't find a corresponding state in the # database, which should never happen (at least we should have the # tail state in there!) - error "Couldn't find ancestor state or block parent missing!", - blockRoot = shortLog(bs.blck.root), - blockSlot = shortLog(bs.blck.slot), - slot = shortLog(bs.slot), - cat = "crash" + fatal "Couldn't find ancestor state or block parent missing!" doAssert false, "Oh noes, we passed big bang!" trace "Replaying state transitions", stateSlot = shortLog(state.data.data.slot), - ancestorStateSlot = shortLog(state.data.data.slot), - slot = shortLog(bs.slot), - blockRoot = shortLog(bs.blck.root), - ancestors = ancestors.len, - cat = "replay_state" + ancestors = ancestors.len ancestors @@ -743,12 +729,12 @@ proc updateHead*(dag: CandidateChains, newHead: BlockRef) = ## blocks that were once considered potential candidates for a tree will ## now fall from grace, or no longer be considered resolved. doAssert newHead.parent != nil or newHead.slot == 0 - logScope: pcs = "fork_choice" + logScope: + newHead = shortLog(newHead) + pcs = "fork_choice" if dag.head.blck == newHead: - info "No head block update", - head = shortLog(newHead), - cat = "fork_choice" + info "No head block update" return @@ -779,8 +765,7 @@ proc updateHead*(dag: CandidateChains, newHead: BlockRef) = headBlock = shortLog(dag.headState.blck), stateSlot = shortLog(dag.headState.data.data.slot), justifiedEpoch = shortLog(dag.headState.data.data.current_justified_checkpoint.epoch), - finalizedEpoch = shortLog(dag.headState.data.data.finalized_checkpoint.epoch), - cat = "fork_choice" + finalizedEpoch = shortLog(dag.headState.data.data.finalized_checkpoint.epoch) # A reasonable criterion for "reorganizations of the chain" beacon_reorgs_total.inc() @@ -790,9 +775,7 @@ proc updateHead*(dag: CandidateChains, newHead: BlockRef) = headBlock = shortLog(dag.headState.blck), stateSlot = shortLog(dag.headState.data.data.slot), justifiedEpoch = shortLog(dag.headState.data.data.current_justified_checkpoint.epoch), - finalizedEpoch = shortLog(dag.headState.data.data.finalized_checkpoint.epoch), - cat = "fork_choice" - + finalizedEpoch = shortLog(dag.headState.data.data.finalized_checkpoint.epoch) let finalizedEpochStartSlot = dag.headState.data.data.finalized_checkpoint.epoch. @@ -855,9 +838,7 @@ proc updateHead*(dag: CandidateChains, newHead: BlockRef) = info "Finalized block", finalizedHead = shortLog(finalizedHead), - head = shortLog(newHead), - heads = dag.heads.len, - cat = "fork_choice" + heads = dag.heads.len # TODO prune everything before weak subjectivity period @@ -904,22 +885,18 @@ proc preInit*( # TODO probably should just init a blockpool with the freshly written # state - but there's more refactoring needed to make it nice - doing # a minimal patch for now.. - let - blockRoot = hash_tree_root(signedBlock.message) - doAssert signedBlock.message.state_root == hash_tree_root(state) notice "New database from snapshot", - blockRoot = shortLog(blockRoot), + blockRoot = shortLog(signedBlock.root), stateRoot = shortLog(signedBlock.message.state_root), fork = state.fork, - validators = state.validators.len(), - cat = "initialization" + validators = state.validators.len() db.putState(state) db.putBlock(signedBlock) - db.putTailBlock(blockRoot) - db.putHeadBlock(blockRoot) - db.putStateRoot(blockRoot, state.slot, signedBlock.message.state_root) + db.putTailBlock(signedBlock.root) + db.putHeadBlock(signedBlock.root) + db.putStateRoot(signedBlock.root, state.slot, signedBlock.message.state_root) proc getProposer*( dag: CandidateChains, head: BlockRef, slot: Slot): diff --git a/beacon_chain/block_pools/clearance.nim b/beacon_chain/block_pools/clearance.nim index deeb84cbac..f3436fa6a3 100644 --- a/beacon_chain/block_pools/clearance.nim +++ b/beacon_chain/block_pools/clearance.nim @@ -36,15 +36,12 @@ func getOrResolve*(dag: CandidateChains, quarantine: var Quarantine, root: Eth2D proc addRawBlock*( dag: var CandidateChains, quarantine: var Quarantine, - blockRoot: Eth2Digest, - signedBlock: SignedBeaconBlock, - callback: proc(blck: BlockRef) + signedBlock: SignedBeaconBlock, callback: proc(blck: BlockRef) ): Result[BlockRef, BlockError] proc addResolvedBlock( dag: var CandidateChains, quarantine: var Quarantine, - state: BeaconState, blockRoot: Eth2Digest, - signedBlock: SignedBeaconBlock, parent: BlockRef, + state: BeaconState, signedBlock: SignedBeaconBlock, parent: BlockRef, callback: proc(blck: BlockRef) ): BlockRef = # TODO: `addResolvedBlock` is accumulating significant cruft @@ -55,7 +52,9 @@ proc addResolvedBlock( logScope: pcs = "block_resolution" doAssert state.slot == signedBlock.message.slot, "state must match block" - let blockRef = BlockRef.init(blockRoot, signedBlock.message) + let + blockRoot = signedBlock.root + blockRef = BlockRef.init(blockRoot, signedBlock.message) blockRef.epochsInfo = filterIt(parent.epochsInfo, it.epoch + 1 >= state.slot.compute_epoch_at_slot) link(parent, blockRef) @@ -64,7 +63,7 @@ proc addResolvedBlock( trace "Populating block dag", key = blockRoot, val = blockRef # Resolved blocks should be stored in database - dag.putBlock(blockRoot, signedBlock) + dag.putBlock(signedBlock) # This block *might* have caused a justification - make sure we stow away # that information: @@ -92,8 +91,7 @@ proc addResolvedBlock( blck = shortLog(signedBlock.message), blockRoot = shortLog(blockRoot), justifiedHead = foundHead.get().justified, - heads = dag.heads.len(), - cat = "filtering" + heads = dag.heads.len() # This MUST be added before the quarantine callback(blockRef) @@ -113,8 +111,8 @@ proc addResolvedBlock( var keepGoing = true while keepGoing: let retries = quarantine.orphans - for k, v in retries: - discard addRawBlock(dag, quarantine, k, v, callback) + for _, v in retries: + discard addRawBlock(dag, quarantine, v, callback) # Keep going for as long as the pending dag is shrinking # TODO inefficient! so what? keepGoing = quarantine.orphans.len < retries.len @@ -123,7 +121,6 @@ proc addResolvedBlock( proc addRawBlock*( dag: var CandidateChains, quarantine: var Quarantine, - blockRoot: Eth2Digest, signedBlock: SignedBeaconBlock, callback: proc(blck: BlockRef) ): Result[BlockRef, BlockError] = @@ -141,18 +138,16 @@ proc addRawBlock*( # This would be easy apart from the "Block already exists" # early return. + logScope: + blck = shortLog(signedBlock.message) + blockRoot = shortLog(signedBlock.root) - let blck = signedBlock.message - doAssert blockRoot == hash_tree_root(blck), "blockRoot: 0x" & shortLog(blockRoot) & ", signedBlock: 0x" & shortLog(hash_tree_root(blck)) - - logScope: pcs = "block_addition" + template blck(): untyped = signedBlock.message # shortcuts without copy + template blockRoot(): untyped = signedBlock.root # Already seen this block?? if blockRoot in dag.blocks: - debug "Block already exists", - blck = shortLog(blck), - blockRoot = shortLog(blockRoot), - cat = "filtering" + debug "Block already exists" # There can be a scenario where we receive a block we already received. # However this block was before the last finalized epoch and so its parent @@ -168,11 +163,8 @@ proc addRawBlock*( # by the time it gets here. if blck.slot <= dag.finalizedHead.slot: debug "Old block, dropping", - blck = shortLog(blck), finalizedHead = shortLog(dag.finalizedHead), - tail = shortLog(dag.tail), - blockRoot = shortLog(blockRoot), - cat = "filtering" + tail = shortLog(dag.tail) return err Unviable @@ -183,8 +175,6 @@ proc addRawBlock*( # A block whose parent is newer than the block itself is clearly invalid - # discard it immediately notice "Invalid block slot", - blck = shortLog(blck), - blockRoot = shortLog(blockRoot), parentBlock = shortLog(parent) return err Invalid @@ -199,11 +189,8 @@ proc addRawBlock*( # latest thing that happened on the chain and they're performing their # duty correctly. debug "Unviable block, dropping", - blck = shortLog(blck), finalizedHead = shortLog(dag.finalizedHead), - tail = shortLog(dag.tail), - blockRoot = shortLog(blockRoot), - cat = "filtering" + tail = shortLog(dag.tail) return err Unviable @@ -233,17 +220,14 @@ proc addRawBlock*( if not state_transition(dag.runtimePreset, dag.tmpState.data, signedBlock, stateCache, dag.updateFlags, restore): # TODO find a better way to log all this block data - notice "Invalid block", - blck = shortLog(blck), - blockRoot = shortLog(blockRoot), - cat = "filtering" + notice "Invalid block" return err Invalid # Careful, tmpState.data has been updated but not blck - we need to create # the BlockRef first! dag.tmpState.blck = addResolvedBlock( dag, quarantine, - dag.tmpState.data.data, blockRoot, signedBlock, parent, + dag.tmpState.data.data, signedBlock, parent, callback ) dag.putState(dag.tmpState.data, dag.tmpState.blck) @@ -255,7 +239,7 @@ proc addRawBlock*( # the pending dag calls this function back later in a loop, so as long # as dag.add(...) requires a SignedBeaconBlock, easier to keep them in # pending too. - quarantine.add(dag, signedBlock, some(blockRoot)) + quarantine.add(dag, signedBlock) # TODO possibly, it makes sense to check the database - that would allow sync # to simply fill up the database with random blocks the other clients @@ -280,11 +264,8 @@ proc addRawBlock*( # from that branch, so right now, we'll just do a blind guess debug "Unresolved block (parent missing)", - blck = shortLog(blck), - blockRoot = shortLog(blockRoot), orphans = quarantine.orphans.len, - missing = quarantine.missing.len, - cat = "filtering" + missing = quarantine.missing.len return err MissingParent @@ -296,6 +277,7 @@ proc isValidBeaconBlock*( logScope: topics = "clearance valid_blck" received_block = shortLog(signed_beacon_block.message) + blockRoot = shortLog(signed_beacon_block.root) # In general, checks are ordered from cheap to expensive. Especially, crypto # verification could be quite a bit more expensive than the rest. This is an diff --git a/beacon_chain/block_pools/quarantine.nim b/beacon_chain/block_pools/quarantine.nim index 3c4265883d..626cad64b3 100644 --- a/beacon_chain/block_pools/quarantine.nim +++ b/beacon_chain/block_pools/quarantine.nim @@ -10,12 +10,13 @@ import stew/bitops2, metrics, ../spec/[datatypes, digest], - ../ssz/merkleization, block_pools_types export options -logScope: topics = "quarant" +logScope: + topics = "quarant" + {.push raises: [Defect].} func checkMissing*(quarantine: var Quarantine): seq[FetchRecord] = @@ -43,15 +44,9 @@ func addMissing*(quarantine: var Quarantine, broot: Eth2Digest) {.inline.} = discard quarantine.missing.hasKeyOrPut(broot, MissingBlock()) func add*(quarantine: var Quarantine, dag: CandidateChains, - sblck: SignedBeaconBlock, - broot: Option[Eth2Digest] = none[Eth2Digest]()) = + sblck: SignedBeaconBlock) = ## Adds block to quarantine's `orphans` and `missing` lists. - let blockRoot = if broot.isSome(): - broot.get() - else: - hash_tree_root(sblck.message) - - quarantine.orphans[blockRoot] = sblck + quarantine.orphans[sblck.root] = sblck let parentRoot = sblck.message.parent_root quarantine.addMissing(parentRoot) diff --git a/beacon_chain/fork_choice/fork_choice.nim b/beacon_chain/fork_choice/fork_choice.nim index 7b4f828bbc..9e8680c40f 100644 --- a/beacon_chain/fork_choice/fork_choice.nim +++ b/beacon_chain/fork_choice/fork_choice.nim @@ -45,7 +45,6 @@ func compute_deltas( logScope: topics = "fork_choice" - cat = "fork_choice" # API: # - The private procs uses the ForkChoiceError error code diff --git a/beacon_chain/fork_choice/proto_array.nim b/beacon_chain/fork_choice/proto_array.nim index 8e8693405b..df874bc250 100644 --- a/beacon_chain/fork_choice/proto_array.nim +++ b/beacon_chain/fork_choice/proto_array.nim @@ -19,7 +19,6 @@ import logScope: topics = "fork_choice" - cat = "fork_choice" # https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/fork-choice.md # This is a port of https://github.com/sigp/lighthouse/pull/804 diff --git a/beacon_chain/nimbus_binary_common.nim b/beacon_chain/nimbus_binary_common.nim index 8ec706287f..9b58985532 100644 --- a/beacon_chain/nimbus_binary_common.nim +++ b/beacon_chain/nimbus_binary_common.nim @@ -80,8 +80,7 @@ proc sleepToSlotOffset*(clock: BeaconClock, extra: chronos.Duration, if fromNow.inFuture: trace msg, slot = shortLog(slot), - fromNow = shortLog(fromNow.offset), - cat = "scheduling" + fromNow = shortLog(fromNow.offset) await sleepAsync(fromNow.offset) return true diff --git a/beacon_chain/request_manager.nim b/beacon_chain/request_manager.nim index 24e70d3527..4573409eaf 100644 --- a/beacon_chain/request_manager.nim +++ b/beacon_chain/request_manager.nim @@ -41,8 +41,7 @@ proc checkResponse(roots: openArray[Eth2Digest], if len(blocks) > len(roots): return false for blk in blocks: - let blockRoot = hash_tree_root(blk.message) - let res = checks.find(blockRoot) + let res = checks.find(blk.root) if res == -1: return false else: diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index 906720fa30..9cf0bb54b7 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -295,15 +295,15 @@ func is_valid_genesis_state*(preset: RuntimePreset, # TODO this is now a non-spec helper function, and it's not really accurate # so only usable/used in research/ and tests/ func get_initial_beacon_block*(state: BeaconState): SignedBeaconBlock = - SignedBeaconBlock( - message: BeaconBlock( + let message = BeaconBlock( slot: GENESIS_SLOT, state_root: hash_tree_root(state), body: BeaconBlockBody( # TODO: This shouldn't be necessary if OpaqueBlob is the default - randao_reveal: ValidatorSig(kind: OpaqueBlob)))) + randao_reveal: ValidatorSig(kind: OpaqueBlob))) # parent_root, randao_reveal, eth1_data, signature, and body automatically # initialized to default values. + SignedBeaconBlock(message: message, root: hash_tree_root(message)) # https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#get_block_root_at_slot func get_block_root_at_slot*(state: BeaconState, @@ -589,16 +589,16 @@ proc check_attestation*( stateSlot = state.slot data = attestation.data - trace "process_attestation: beginning", - attestation=attestation + logScope: + attestation = shortLog(attestation) + trace "process_attestation: beginning" let committee_count_at_slot = get_committee_count_at_slot(get_shuffled_active_validator_indices( state, stateSlot.compute_epoch_at_slot, stateCache).len.uint64).uint64 if not (data.index < committee_count_at_slot): - warn("Data index exceeds committee count", - data_index = data.index, - committee_count = committee_count_at_slot) + warn "Data index exceeds committee count", + committee_count = committee_count_at_slot return if not isValidAttestationTargetEpoch(state, data): @@ -612,10 +612,10 @@ proc check_attestation*( let committee = get_beacon_committee( state, data.slot, data.index.CommitteeIndex, stateCache) if attestation.aggregation_bits.len != committee.len: - warn("Inconsistent aggregation and committee length", + warn "Inconsistent aggregation and committee length", aggregation_bits_len = attestation.aggregation_bits.len, committee_len = committee.len - ) + return let ffg_check_data = (data.source.epoch, data.source.root, data.target.epoch) @@ -623,17 +623,17 @@ proc check_attestation*( if data.target.epoch == get_current_epoch(state): if not (ffg_check_data == (state.current_justified_checkpoint.epoch, state.current_justified_checkpoint.root, get_current_epoch(state))): - warn("FFG data not matching current justified epoch") + warn "FFG data not matching current justified epoch" return else: if not (ffg_check_data == (state.previous_justified_checkpoint.epoch, state.previous_justified_checkpoint.root, get_previous_epoch(state))): - warn("FFG data not matching previous justified epoch") + warn "FFG data not matching previous justified epoch" return if not is_valid_indexed_attestation( state, get_indexed_attestation(state, attestation, stateCache), flags): - warn("process_attestation: signature or bitfields incorrect") + warn "process_attestation: signature or bitfields incorrect" return true diff --git a/beacon_chain/spec/datatypes.nim b/beacon_chain/spec/datatypes.nim index dd83398e99..6937ff214f 100644 --- a/beacon_chain/spec/datatypes.nim +++ b/beacon_chain/spec/datatypes.nim @@ -416,10 +416,14 @@ type message*: BeaconBlock signature*: ValidatorSig + root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block + TrustedSignedBeaconBlock* = object message*: TrustedBeaconBlock signature*: TrustedSig + root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block + # https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#signedbeaconblockheader SignedBeaconBlockHeader* = object message*: BeaconBlockHeader diff --git a/beacon_chain/spec/state_transition.nim b/beacon_chain/spec/state_transition.nim index 55366b3168..7e4f62cf79 100644 --- a/beacon_chain/spec/state_transition.nim +++ b/beacon_chain/spec/state_transition.nim @@ -235,9 +235,9 @@ proc state_transition*( verify_block_signature(state.data, signedBlock): # TODO after checking scaffolding, remove this - trace "in state_transition: processing block, signature passed", - signature = signedBlock.signature, - blockRoot = hash_tree_root(signedBlock.message) + trace "state_transition: processing block, signature passed", + signature = shortLog(signedBlock.signature), + blockRoot = shortLog(signedBlock.root) if process_block(preset, state.data, signedBlock.message, flags, stateCache): if skipStateRootValidation in flags or verifyStateRoot(state.data, signedBlock.message): # State root is what it should be - we're done! diff --git a/beacon_chain/spec/state_transition_epoch.nim b/beacon_chain/spec/state_transition_epoch.nim index 551037d8c2..2e146b96fe 100644 --- a/beacon_chain/spec/state_transition_epoch.nim +++ b/beacon_chain/spec/state_transition_epoch.nim @@ -173,8 +173,7 @@ proc process_justification_and_finalization*(state: var BeaconState, debug "Justified with previous epoch", current_epoch = current_epoch, - checkpoint = shortLog(state.current_justified_checkpoint), - cat = "justification" + checkpoint = shortLog(state.current_justified_checkpoint) let matching_target_attestations_current = get_matching_target_attestations(state, current_epoch) # Current epoch @@ -187,8 +186,7 @@ proc process_justification_and_finalization*(state: var BeaconState, debug "Justified with current epoch", current_epoch = current_epoch, - checkpoint = shortLog(state.current_justified_checkpoint), - cat = "justification" + checkpoint = shortLog(state.current_justified_checkpoint) # Process finalizations let bitfield = state.justification_bits @@ -201,8 +199,7 @@ proc process_justification_and_finalization*(state: var BeaconState, debug "Finalized with rule 234", current_epoch = current_epoch, - checkpoint = shortLog(state.finalized_checkpoint), - cat = "finalization" + checkpoint = shortLog(state.finalized_checkpoint) ## The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as ## source @@ -212,8 +209,7 @@ proc process_justification_and_finalization*(state: var BeaconState, debug "Finalized with rule 23", current_epoch = current_epoch, - checkpoint = shortLog(state.finalized_checkpoint), - cat = "finalization" + checkpoint = shortLog(state.finalized_checkpoint) ## The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as ## source @@ -223,8 +219,7 @@ proc process_justification_and_finalization*(state: var BeaconState, debug "Finalized with rule 123", current_epoch = current_epoch, - checkpoint = shortLog(state.finalized_checkpoint), - cat = "finalization" + checkpoint = shortLog(state.finalized_checkpoint) ## The 1st/2nd most recent epochs are justified, the 1st using the 2nd as ## source @@ -234,8 +229,7 @@ proc process_justification_and_finalization*(state: var BeaconState, debug "Finalized with rule 12", current_epoch = current_epoch, - checkpoint = shortLog(state.finalized_checkpoint), - cat = "finalization" + checkpoint = shortLog(state.finalized_checkpoint) # https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#helpers func get_base_reward(state: BeaconState, index: ValidatorIndex, diff --git a/beacon_chain/ssz/bytes_reader.nim b/beacon_chain/ssz/bytes_reader.nim index 27bde42cfc..d9d9b8c4db 100644 --- a/beacon_chain/ssz/bytes_reader.nim +++ b/beacon_chain/ssz/bytes_reader.nim @@ -4,7 +4,7 @@ import typetraits, options, stew/[bitops2, endians2, objects], serialization/testing/tracing, - ../spec/[digest, datatypes], ./types, ./spec_types + ../spec/[digest, datatypes], ./types, ./spec_types, ./merkleization template raiseIncorrectSize(T: type) = const typeName = name(T) @@ -267,5 +267,7 @@ func readSszValue*[T](input: openarray[byte], val: var T) {.raisesssz.} = type(field), input.toOpenArray(int(startOffset), int(endOffset - 1))) + when val is SignedBeaconBlock | TrustedSignedBeaconBlock: + val.root = hash_tree_root(val.message) else: unsupported T diff --git a/beacon_chain/sszdump.nim b/beacon_chain/sszdump.nim index 76913e0420..b418d8dc3a 100644 --- a/beacon_chain/sszdump.nim +++ b/beacon_chain/sszdump.nim @@ -18,16 +18,13 @@ proc dump*(dir: string, v: AttestationData, validator: ValidatorPubKey) = logErrors: SSZ.saveFile(dir / &"att-{v.slot}-{v.index}-{shortLog(validator)}.ssz", v) -proc dump*(dir: string, v: SignedBeaconBlock, root: Eth2Digest) = +proc dump*(dir: string, v: SignedBeaconBlock) = logErrors: - SSZ.saveFile(dir / &"block-{v.message.slot}-{shortLog(root)}.ssz", v) + SSZ.saveFile(dir / &"block-{v.message.slot}-{shortLog(v.root)}.ssz", v) -proc dump*(dir: string, v: TrustedSignedBeaconBlock, root: Eth2Digest) = +proc dump*(dir: string, v: TrustedSignedBeaconBlock) = logErrors: - SSZ.saveFile(dir / &"block-{v.message.slot}-{shortLog(root)}.ssz", v) - -proc dump*(dir: string, v: SomeSignedBeaconBlock, blck: BlockRef) = - dump(dir, v, blck.root) + SSZ.saveFile(dir / &"block-{v.message.slot}-{shortLog(v.root)}.ssz", v) proc dump*(dir: string, v: HashedBeaconState, blck: BlockRef) = logErrors: diff --git a/beacon_chain/validator_api.nim b/beacon_chain/validator_api.nim index e581956518..24c8de387b 100644 --- a/beacon_chain/validator_api.nim +++ b/beacon_chain/validator_api.nim @@ -195,7 +195,7 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) = rpcServer.rpc("get_v1_beacon_states_fork") do (stateId: string) -> Fork: withStateForStateId(stateId): return state.fork - + rpcServer.rpc("get_v1_beacon_states_finality_checkpoints") do ( stateId: string) -> BeaconStatesFinalityCheckpointsTuple: withStateForStateId(stateId): @@ -229,11 +229,11 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) = seq[BeaconStatesCommitteesTuple]: withStateForStateId(stateId): var cache = StateCache() # TODO is this OK? - + proc getCommittee(slot: Slot, index: CommitteeIndex): BeaconStatesCommitteesTuple = let vals = get_beacon_committee(state, slot, index, cache).mapIt(it.uint64) return (index: index.uint64, slot: slot.uint64, validators: vals) - + proc forSlot(slot: Slot, res: var seq[BeaconStatesCommitteesTuple]) = if index == 0: # TODO this means if the parameter is missing (its optional) let committees_per_slot = get_committee_count_at_slot(state, slot) @@ -323,8 +323,7 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) = if head.slot >= body.message.slot: raise newException(CatchableError, "Proposal is for a past slot: " & $body.message.slot) - if head == await proposeSignedBlock(node, head, AttachedValidator(), - body, hash_tree_root(body.message)): + if head == await proposeSignedBlock(node, head, AttachedValidator(), body): raise newException(CatchableError, "Could not propose block") return true diff --git a/beacon_chain/validator_client.nim b/beacon_chain/validator_client.nim index 7ea1151652..c087b5ada4 100644 --- a/beacon_chain/validator_client.nim +++ b/beacon_chain/validator_client.nim @@ -115,8 +115,7 @@ proc onSlotStart(vc: ValidatorClient, lastSlot, scheduledSlot: Slot) {.gcsafe, a lastSlot = shortLog(lastSlot), scheduledSlot = shortLog(scheduledSlot), beaconTime = shortLog(beaconTime), - portBN = vc.config.rpcPort, - cat = "scheduling" + portBN = vc.config.rpcPort try: # at the start of each epoch - request all validator duties @@ -141,9 +140,9 @@ proc onSlotStart(vc: ValidatorClient, lastSlot, scheduledSlot: Slot) {.gcsafe, a message: await vc.client.get_v1_validator_block(slot, vc.graffitiBytes, randao_reveal) ) - let blockRoot = hash_tree_root(newBlock.message) + newBlock.root = hash_tree_root(newBlock.message) newBlock.signature = await validator.signBlockProposal( - vc.fork, vc.beaconGenesis.genesis_validators_root, slot, blockRoot) + vc.fork, vc.beaconGenesis.genesis_validators_root, slot, newBlock.root) discard await vc.client.post_v1_validator_block(newBlock) @@ -181,8 +180,7 @@ proc onSlotStart(vc: ValidatorClient, lastSlot, scheduledSlot: Slot) {.gcsafe, a info "Slot end", slot = shortLog(slot), nextSlot = shortLog(nextSlot), - portBN = vc.config.rpcPort, - cat = "scheduling" + portBN = vc.config.rpcPort when declared(GC_fullCollect): # The slots in the validator client work as frames in a game: we want to make @@ -240,8 +238,7 @@ programMain: info "Scheduling first slot action", beaconTime = shortLog(vc.beaconClock.now()), nextSlot = shortLog(nextSlot), - fromNow = shortLog(fromNow), - cat = "scheduling" + fromNow = shortLog(fromNow) addTimer(fromNow) do (p: pointer) {.gcsafe.}: asyncCheck vc.onSlotStart(curSlot, nextSlot) diff --git a/beacon_chain/validator_duties.nim b/beacon_chain/validator_duties.nim index 6006324dee..7d5e4979f1 100644 --- a/beacon_chain/validator_duties.nim +++ b/beacon_chain/validator_duties.nim @@ -145,8 +145,7 @@ proc createAndSendAttestation(node: BeaconNode, info "Attestation sent", attestation = shortLog(attestation), validator = shortLog(validator), - indexInCommittee = indexInCommittee, - cat = "consensus" + indexInCommittee = indexInCommittee type ValidatorInfoForMakeBeaconBlockKind* = enum @@ -222,11 +221,10 @@ proc makeBeaconBlockForHeadAndSlot*(node: BeaconNode, proc proposeSignedBlock*(node: BeaconNode, head: BlockRef, validator: AttachedValidator, - newBlock: SignedBeaconBlock, - blockRoot: Eth2Digest): Future[BlockRef] {.async.} = + newBlock: SignedBeaconBlock): Future[BlockRef] {.async.} = {.gcsafe.}: # TODO: fork choice and blockpool should sync via messages instead of callbacks - let newBlockRef = node.blockPool.addRawBlock(blockRoot, newBlock) do (validBlock: BlockRef): + let newBlockRef = node.blockPool.addRawBlock(newBlock) do (validBlock: BlockRef): # Callback Add to fork choice # node.attestationPool.addForkChoice_v2(validBlock) discard "TODO: Deactivated" @@ -234,19 +232,17 @@ proc proposeSignedBlock*(node: BeaconNode, if newBlockRef.isErr: warn "Unable to add proposed block to block pool", newBlock = shortLog(newBlock.message), - blockRoot = shortLog(blockRoot), - cat = "bug" + blockRoot = shortLog(newBlock.root) return head info "Block proposed", blck = shortLog(newBlock.message), blockRoot = shortLog(newBlockRef[].root), - validator = shortLog(validator), - cat = "consensus" + validator = shortLog(validator) if node.config.dumpEnabled: - dump(node.config.dumpDirOutgoing, newBlock, newBlockRef[]) + dump(node.config.dumpDirOutgoing, newBlock) node.network.broadcast(node.topicBeaconBlocks, newBlock) @@ -267,8 +263,7 @@ proc proposeBlock(node: BeaconNode, warn "Skipping proposal, have newer head already", headSlot = shortLog(head.slot), headBlockRoot = shortLog(head.root), - slot = shortLog(slot), - cat = "fastforward" + slot = shortLog(slot) return head let valInfo = ValidatorInfoForMakeBeaconBlock(kind: viValidator, validator: validator) @@ -280,17 +275,16 @@ proc proposeBlock(node: BeaconNode, message: beaconBlockTuple.message.get() ) - let blockRoot = hash_tree_root(newBlock.message) - + newBlock.root = hash_tree_root(newBlock.message) newBlock.signature = await validator.signBlockProposal( - beaconBlockTuple.fork, beaconBlockTuple.genesis_validators_root, slot, blockRoot) + beaconBlockTuple.fork, beaconBlockTuple.genesis_validators_root, slot, newBlock.root) - return await node.proposeSignedBlock(head, validator, newBlock, blockRoot) + return await node.proposeSignedBlock(head, validator, newBlock) proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) = ## Perform all attestations that the validators attached to this node should ## perform during the given slot - logScope: pcs = "on_attestation" + logScope: pcs = "handleAttestations" if slot + SLOTS_PER_EPOCH < head.slot: # The latest block we know about is a lot newer than the slot we're being @@ -316,8 +310,7 @@ proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) = trace "Checking attestations", attestationHeadRoot = shortLog(attestationHead.blck.root), - attestationSlot = shortLog(slot), - cat = "attestation" + attestationSlot = shortLog(slot) # Collect data to send before node.stateCache grows stale var attestations: seq[tuple[ @@ -381,7 +374,6 @@ proc handleProposal(node: BeaconNode, head: BlockRef, slot: Slot): slot = shortLog(slot), proposer_index = proposer.get()[0], proposer = shortLog(proposer.get()[1]), - cat = "consensus", pcs = "wait_for_proposal" return head @@ -455,8 +447,7 @@ proc handleValidatorDuties*( notice "Catching up", curSlot = shortLog(curSlot), lastSlot = shortLog(lastSlot), - slot = shortLog(slot), - cat = "overload" + slot = shortLog(slot) # For every slot we're catching up, we'll propose then send # attestations - head should normally be advancing along the same branch diff --git a/ncli/ncli_db.nim b/ncli/ncli_db.nim index ffa9b60e3f..9f41cb78cb 100644 --- a/ncli/ncli_db.nim +++ b/ncli/ncli_db.nim @@ -106,7 +106,7 @@ proc cmdBench(conf: DbConf) = b.message.slot.compute_epoch_at_slot withTimer(timers[if isEpoch: tApplyEpochBlock else: tApplyBlock]): if not state_transition(defaultRuntimePreset, state[], b, {}, noRollback): - dump("./", b, hash_tree_root(b.message)) + dump("./", b) echo "State transition failed (!)" quit 1 @@ -137,7 +137,7 @@ proc cmdDumpBlock(conf: DbConf) = try: let root = Eth2Digest(data: hexToByteArray[32](blockRoot)) if (let blck = db.getBlock(root); blck.isSome): - dump("./", blck.get(), root) + dump("./", blck.get()) else: echo "Couldn't load ", root except CatchableError as e: diff --git a/research/block_sim.nim b/research/block_sim.nim index 359b29ae64..cbe335e2aa 100644 --- a/research/block_sim.nim +++ b/research/block_sim.nim @@ -127,14 +127,14 @@ cli do(slots = SLOTS_PER_EPOCH * 6, let blockRoot = withTimerRet(timers[tHashBlock]): hash_tree_root(newBlock.message) - + newBlock.root = blockRoot # Careful, state no longer valid after here because of the await.. newBlock.signature = withTimerRet(timers[tSignBlock]): get_block_signature( state.fork, state.genesis_validators_root, newBlock.message.slot, blockRoot, privKey) - let added = blockPool.addRawBlock(blockRoot, newBlock) do (validBlock: BlockRef): + let added = blockPool.addRawBlock(newBlock) do (validBlock: BlockRef): # Callback Add to fork choice attPool.addForkChoice_v2(validBlock) blck() = added[] diff --git a/research/state_sim.nim b/research/state_sim.nim index 2d1132e359..2375217646 100644 --- a/research/state_sim.nim +++ b/research/state_sim.nim @@ -99,6 +99,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6, flags = flags) latest_block_root = withTimerRet(timers[tHashBlock]): hash_tree_root(signedBlock.message) + signedBlock.root = latest_block_root if attesterRatio > 0.0: # attesterRatio is the fraction of attesters that actually do their diff --git a/tests/mocking/mock_blocks.nim b/tests/mocking/mock_blocks.nim index ee987b9842..c730c57810 100644 --- a/tests/mocking/mock_blocks.nim +++ b/tests/mocking/mock_blocks.nim @@ -29,9 +29,10 @@ proc signMockBlockImpl( signedBlock.message.body.randao_reveal = get_epoch_signature( state.fork, state.genesis_validators_root, block_slot.compute_epoch_at_slot, privkey) + signedBlock.root = hash_tree_root(signedBlock.message) signedBlock.signature = get_block_signature( state.fork, state.genesis_validators_root, block_slot, - hash_tree_root(signedBlock.message), privkey) + signedBlock.root, privkey) proc signMockBlock*(state: BeaconState, signedBlock: var SignedBeaconBlock) = signMockBlockImpl(state, signedBlock) diff --git a/tests/official/test_fixture_ssz_consensus_objects.nim b/tests/official/test_fixture_ssz_consensus_objects.nim index b926c27475..c7e0725a8e 100644 --- a/tests/official/test_fixture_ssz_consensus_objects.nim +++ b/tests/official/test_fixture_ssz_consensus_objects.nim @@ -50,6 +50,7 @@ proc checkSSZ(T: type SignedBeaconBlock, dir: string, expectedHash: SSZHashTreeR [hash_tree_root(deserialized.message), hash_tree_root(deserialized.signature)])) + check deserialized.root == hash_tree_root(deserialized.message) check SSZ.encode(deserialized[]) == encoded check sszSize(deserialized[]) == encoded.len diff --git a/tests/test_attestation_pool.nim b/tests/test_attestation_pool.nim index ec594924c7..57d9c964bf 100644 --- a/tests/test_attestation_pool.nim +++ b/tests/test_attestation_pool.nim @@ -166,8 +166,7 @@ suiteReport "Attestation pool processing" & preset(): var cache = StateCache() let b1 = addTestBlock(state.data, blockPool[].tail.root, cache) - b1Root = hash_tree_root(b1.message) - b1Add = blockpool[].addRawBlock(b1Root, b1) do (validBlock: BlockRef): + b1Add = blockpool[].addRawBlock(b1) do (validBlock: BlockRef): # Callback Add to fork choice pool[].addForkChoice_v2(validBlock) @@ -177,9 +176,8 @@ suiteReport "Attestation pool processing" & preset(): head == b1Add[] let - b2 = addTestBlock(state.data, b1Root, cache) - b2Root = hash_tree_root(b2.message) - b2Add = blockpool[].addRawBlock(b2Root, b2) do (validBlock: BlockRef): + b2 = addTestBlock(state.data, b1.root, cache) + b2Add = blockpool[].addRawBlock(b2) do (validBlock: BlockRef): # Callback Add to fork choice pool[].addForkChoice_v2(validBlock) @@ -192,8 +190,7 @@ suiteReport "Attestation pool processing" & preset(): var cache = StateCache() let b10 = makeTestBlock(state.data, blockPool[].tail.root, cache) - b10Root = hash_tree_root(b10.message) - b10Add = blockpool[].addRawBlock(b10Root, b10) do (validBlock: BlockRef): + b10Add = blockpool[].addRawBlock(b10) do (validBlock: BlockRef): # Callback Add to fork choice pool[].addForkChoice_v2(validBlock) @@ -206,14 +203,13 @@ suiteReport "Attestation pool processing" & preset(): b11 = makeTestBlock(state.data, blockPool[].tail.root, cache, graffiti = GraffitiBytes [1'u8, 0, 0, 0 ,0 ,0 ,0 ,0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ) - b11Root = hash_tree_root(b11.message) - b11Add = blockpool[].addRawBlock(b11Root, b11) do (validBlock: BlockRef): + b11Add = blockpool[].addRawBlock(b11) do (validBlock: BlockRef): # Callback Add to fork choice pool[].addForkChoice_v2(validBlock) bc1 = get_beacon_committee( state.data.data, state.data.data.slot, 1.CommitteeIndex, cache) - attestation0 = makeAttestation(state.data.data, b10Root, bc1[0], cache) + attestation0 = makeAttestation(state.data.data, b10.root, bc1[0], cache) pool[].addAttestation(attestation0) @@ -224,13 +220,13 @@ suiteReport "Attestation pool processing" & preset(): head2 == b10Add[] let - attestation1 = makeAttestation(state.data.data, b11Root, bc1[1], cache) - attestation2 = makeAttestation(state.data.data, b11Root, bc1[2], cache) + attestation1 = makeAttestation(state.data.data, b11.root, bc1[1], cache) + attestation2 = makeAttestation(state.data.data, b11.root, bc1[2], cache) pool[].addAttestation(attestation1) let head3 = pool[].selectHead() # Warning - the tiebreak are incorrect and guaranteed consensus fork, it should be bigger - let smaller = if b10Root.data < b11Root.data: b10Add else: b11Add + let smaller = if b10.root.data < b11.root.data: b10Add else: b11Add check: # Ties broken lexicographically in spec -> ? @@ -251,8 +247,7 @@ suiteReport "Attestation pool processing" & preset(): var cache = StateCache() let b10 = makeTestBlock(state.data, blockPool[].tail.root, cache) - b10Root = hash_tree_root(b10.message) - b10Add = blockpool[].addRawBlock(b10Root, b10) do (validBlock: BlockRef): + b10Add = blockpool[].addRawBlock(b10) do (validBlock: BlockRef): # Callback Add to fork choice pool[].addForkChoice_v2(validBlock) @@ -264,7 +259,7 @@ suiteReport "Attestation pool processing" & preset(): # ------------------------------------------------------------- # Add back the old block to ensure we have a duplicate error let b10_clone = b10 # Assumes deep copy - let b10Add_clone = blockpool[].addRawBlock(b10Root, b10_clone) do (validBlock: BlockRef): + let b10Add_clone = blockpool[].addRawBlock(b10_clone) do (validBlock: BlockRef): # Callback Add to fork choice pool[].addForkChoice_v2(validBlock) doAssert: b10Add_clone.error == Duplicate @@ -277,8 +272,7 @@ suiteReport "Attestation pool processing" & preset(): let b10 = makeTestBlock(state.data, blockPool[].tail.root, cache) - b10Root = hash_tree_root(b10.message) - b10Add = blockpool[].addRawBlock(b10Root, b10) do (validBlock: BlockRef): + b10Add = blockpool[].addRawBlock(b10) do (validBlock: BlockRef): # Callback Add to fork choice pool[].addForkChoice_v2(validBlock) @@ -294,7 +288,7 @@ suiteReport "Attestation pool processing" & preset(): # ------------------------------------------------------------- # Pass an epoch - var block_root = b10Root + var block_root = b10.root var attestations: seq[Attestation] @@ -306,8 +300,8 @@ suiteReport "Attestation pool processing" & preset(): let block_ok = state_transition(defaultRuntimePreset, state.data, new_block, {skipBLSValidation}, noRollback) doAssert: block_ok - block_root = hash_tree_root(new_block.message) - let blockRef = blockpool[].addRawBlock(block_root, new_block) do (validBlock: BlockRef): + block_root = new_block.root + let blockRef = blockpool[].addRawBlock(new_block) do (validBlock: BlockRef): # Callback Add to fork choice pool[].addForkChoice_v2(validBlock) @@ -344,10 +338,10 @@ suiteReport "Attestation pool processing" & preset(): doAssert: blockPool[].finalizedHead.slot != 0 pool[].pruneBefore(blockPool[].finalizedHead) - doAssert: b10Root notin pool.forkChoice_v2 + doAssert: b10.root notin pool.forkChoice_v2 # Add back the old block to ensure we have a duplicate error - let b10Add_clone = blockpool[].addRawBlock(b10Root, b10_clone) do (validBlock: BlockRef): + let b10Add_clone = blockpool[].addRawBlock(b10_clone) do (validBlock: BlockRef): # Callback Add to fork choice pool[].addForkChoice_v2(validBlock) doAssert: b10Add_clone.error == Duplicate diff --git a/tests/test_beacon_chain_db.nim b/tests/test_beacon_chain_db.nim index bb41e5d893..d6d00ac12a 100644 --- a/tests/test_beacon_chain_db.nim +++ b/tests/test_beacon_chain_db.nim @@ -29,6 +29,12 @@ template wrappedTimedTest(name: string, body: untyped) = body wrappedTest() +func withDigest(blck: TrustedBeaconBlock): TrustedSignedBeaconBlock = + TrustedSignedBeaconBlock( + message: blck, + root: hash_tree_root(blck) + ) + suiteReport "Beacon chain DB" & preset(): wrappedTimedTest "empty database" & preset(): var @@ -42,7 +48,7 @@ suiteReport "Beacon chain DB" & preset(): db = init(BeaconChainDB, kvStore MemStoreRef.init()) let - signedBlock = TrustedSignedBeaconBlock() + signedBlock = withDigest(TrustedBeaconBlock()) root = hash_tree_root(signedBlock.message) db.putBlock(signedBlock) @@ -74,33 +80,31 @@ suiteReport "Beacon chain DB" & preset(): db = init(BeaconChainDB, kvStore MemStoreRef.init()) let - a0 = TrustedSignedBeaconBlock(message: + a0 = withDigest( TrustedBeaconBlock(slot: GENESIS_SLOT + 0)) - a0r = hash_tree_root(a0.message) - a1 = TrustedSignedBeaconBlock(message: - TrustedBeaconBlock(slot: GENESIS_SLOT + 1, parent_root: a0r)) - a1r = hash_tree_root(a1.message) - a2 = TrustedSignedBeaconBlock(message: - TrustedBeaconBlock(slot: GENESIS_SLOT + 2, parent_root: a1r)) + a1 = withDigest( + TrustedBeaconBlock(slot: GENESIS_SLOT + 1, parent_root: a0.root)) + a2 = withDigest( + TrustedBeaconBlock(slot: GENESIS_SLOT + 2, parent_root: a1.root)) a2r = hash_tree_root(a2.message) - doAssert toSeq(db.getAncestors(a0r)) == [] - doAssert toSeq(db.getAncestors(a2r)) == [] + doAssert toSeq(db.getAncestors(a0.root)) == [] + doAssert toSeq(db.getAncestors(a2.root)) == [] db.putBlock(a2) - doAssert toSeq(db.getAncestors(a0r)) == [] - doAssert toSeq(db.getAncestors(a2r)) == [(a2r, a2)] + doAssert toSeq(db.getAncestors(a0.root)) == [] + doAssert toSeq(db.getAncestors(a2.root)) == [a2] db.putBlock(a1) - doAssert toSeq(db.getAncestors(a0r)) == [] - doAssert toSeq(db.getAncestors(a2r)) == [(a2r, a2), (a1r, a1)] + doAssert toSeq(db.getAncestors(a0.root)) == [] + doAssert toSeq(db.getAncestors(a2.root)) == [a2, a1] db.putBlock(a0) - doAssert toSeq(db.getAncestors(a0r)) == [(a0r, a0)] - doAssert toSeq(db.getAncestors(a2r)) == [(a2r, a2), (a1r, a1), (a0r, a0)] + doAssert toSeq(db.getAncestors(a0.root)) == [a0] + doAssert toSeq(db.getAncestors(a2.root)) == [a2, a1, a0] wrappedTimedTest "sanity check genesis roundtrip" & preset(): # This is a really dumb way of checking that we can roundtrip a genesis diff --git a/tests/test_block_pool.nim b/tests/test_block_pool.nim index cc8a9fb6a9..50b20032cf 100644 --- a/tests/test_block_pool.nim +++ b/tests/test_block_pool.nim @@ -110,9 +110,9 @@ suiteReport "Block pool processing" & preset(): timedTest "Simple block add&get" & preset(): let - b1Add = pool.addRawBlock(b1Root, b1) do (validBlock: BlockRef): + b1Add = pool.addRawBlock(b1) do (validBlock: BlockRef): discard - b1Get = pool.get(b1Root) + b1Get = pool.get(b1.root) check: b1Get.isSome() @@ -122,13 +122,13 @@ suiteReport "Block pool processing" & preset(): pool.heads[0].blck == b1Add[] let - b2Add = pool.addRawBlock(b2Root, b2) do (validBlock: BlockRef): + b2Add = pool.addRawBlock(b2) do (validBlock: BlockRef): discard - b2Get = pool.get(b2Root) + b2Get = pool.get(b2.root) check: b2Get.isSome() - b2Get.get().refs.root == b2Root + b2Get.get().refs.root == b2.root b2Add[].root == b2Get.get().refs.root pool.heads.len == 1 pool.heads[0].blck == b2Add[] @@ -138,9 +138,8 @@ suiteReport "Block pool processing" & preset(): process_slots(stateData.data, stateData.data.data.slot + 1) let - b4 = addTestBlock(stateData.data, b2Root, cache) - b4Root = hash_tree_root(b4.message) - b4Add = pool.addRawBlock(b4Root, b4) do (validBlock: BlockRef): + b4 = addTestBlock(stateData.data, b2.root, cache) + b4Add = pool.addRawBlock(b4) do (validBlock: BlockRef): discard check: @@ -177,22 +176,22 @@ suiteReport "Block pool processing" & preset(): blocks[0..<2] == [BlockRef nil, nil] # block 3 is missing! timedTest "Reverse order block add & get" & preset(): - let missing = pool.addRawBlock(b2Root, b2) do (validBlock: BLockRef): + let missing = pool.addRawBlock(b2) do (validBlock: BLockRef): discard check: missing.error == MissingParent check: - pool.get(b2Root).isNone() # Unresolved, shouldn't show up - FetchRecord(root: b1Root) in pool.checkMissing() + pool.get(b2.root).isNone() # Unresolved, shouldn't show up + FetchRecord(root: b1.root) in pool.checkMissing() - let status = pool.addRawBlock(b1Root, b1) do (validBlock: BlockRef): + let status = pool.addRawBlock(b1) do (validBlock: BlockRef): discard check: status.isOk let - b1Get = pool.get(b1Root) - b2Get = pool.get(b2Root) + b1Get = pool.get(b1.root) + b2Get = pool.get(b2.root) check: b1Get.isSome() @@ -223,9 +222,9 @@ suiteReport "Block pool processing" & preset(): timedTest "Adding the same block twice returns a Duplicate error" & preset(): let - b10 = pool.addRawBlock(b1Root, b1) do (validBlock: BlockRef): + b10 = pool.addRawBlock(b1) do (validBlock: BlockRef): discard - b11 = pool.addRawBlock(b1Root, b1) do (validBlock: BlockRef): + b11 = pool.addRawBlock(b1) do (validBlock: BlockRef): discard check: @@ -234,7 +233,7 @@ suiteReport "Block pool processing" & preset(): timedTest "updateHead updates head and headState" & preset(): let - b1Add = pool.addRawBlock(b1Root, b1) do (validBlock: BlockRef): + b1Add = pool.addRawBlock(b1) do (validBlock: BlockRef): discard pool.updateHead(b1Add[]) @@ -245,9 +244,9 @@ suiteReport "Block pool processing" & preset(): timedTest "updateStateData sanity" & preset(): let - b1Add = pool.addRawBlock(b1Root, b1) do (validBlock: BlockRef): + b1Add = pool.addRawBlock(b1) do (validBlock: BlockRef): discard - b2Add = pool.addRawBlock(b2Root, b2) do (validBlock: BlockRef): + b2Add = pool.addRawBlock(b2) do (validBlock: BlockRef): discard bs1 = BlockSlot(blck: b1Add[], slot: b1.message.slot) bs1_3 = b1Add[].atSlot(3.Slot) @@ -311,7 +310,7 @@ suiteReport "BlockPool finalization tests" & preset(): let lateBlock = makeTestBlock(tmpState[], pool.head.blck.root, cache) block: - let status = pool.addRawBlock(hash_tree_root(blck.message), blck) do (validBlock: BlockRef): + let status = pool.addRawBlock(blck) do (validBlock: BlockRef): discard check: status.isOk() @@ -328,7 +327,7 @@ suiteReport "BlockPool finalization tests" & preset(): attestations = makeFullAttestations( pool.headState.data.data, pool.head.blck.root, pool.headState.data.data.slot, cache, {})) - let added = pool.addRawBlock(hash_tree_root(blck.message), blck) do (validBlock: BlockRef): + let added = pool.addRawBlock(blck) do (validBlock: BlockRef): discard check: added.isOk() pool.updateHead(added[]) @@ -341,7 +340,7 @@ suiteReport "BlockPool finalization tests" & preset(): block: # The late block is a block whose parent was finalized long ago and thus # is no longer a viable head candidate - let status = pool.addRawBlock(hash_tree_root(lateBlock.message), lateBlock) do (validBlock: BlockRef): + let status = pool.addRawBlock(lateBlock) do (validBlock: BlockRef): discard check: status.error == Unviable diff --git a/tests/test_state_transition.nim b/tests/test_state_transition.nim index 5a43a68e71..7fc792c0d0 100644 --- a/tests/test_state_transition.nim +++ b/tests/test_state_transition.nim @@ -36,7 +36,7 @@ suiteReport "Block processing" & preset(): timedTest "Passes from genesis state, empty block" & preset(): var - previous_block_root = hash_tree_root(genesisBlock.message) + previous_block_root = genesisBlock.root cache = StateCache() new_block = makeTestBlock(state[], previous_block_root, cache) @@ -65,7 +65,7 @@ suiteReport "Block processing" & preset(): check: block_ok - previous_block_root = hash_tree_root(new_block.message) + previous_block_root = new_block.root check: state.data.slot == genesisState.data.slot + SLOTS_PER_EPOCH diff --git a/tests/testblockutil.nim b/tests/testblockutil.nim index 89e05e1142..cc37146fee 100644 --- a/tests/testblockutil.nim +++ b/tests/testblockutil.nim @@ -73,13 +73,14 @@ proc makeInitialDeposits*( func signBlock*( fork: Fork, genesis_validators_root: Eth2Digest, blck: BeaconBlock, privKey: ValidatorPrivKey, flags: UpdateFlags = {}): SignedBeaconBlock = + var root = hash_tree_root(blck) SignedBeaconBlock( message: blck, + root: root, signature: if skipBlsValidation notin flags: get_block_signature( - fork, genesis_validators_root, blck.slot, - hash_tree_root(blck), privKey) + fork, genesis_validators_root, blck.slot, root, privKey) else: ValidatorSig() )