cache block hash (#1329)
hash_tree_root was turning up when running beacon_node, turns out to be repeated hash_tree_root invocations - this pr brings them back down to normal. this PR caches the root of a block in the SignedBeaconBlock object - this has the potential downside that even invalid blocks will be hashed (as part of deserialization) - later, one could imagine delaying this until checks have passed there's also some cleanup of the `cat=` logs which were applied randomly and haphazardly, and to a large degree are duplicated by other information in the log statements - in particular, topics fulfill the same role
This commit is contained in:
parent
6052f36fcd
commit
8b01284b0e
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -270,31 +270,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)
|
||||
|
@ -306,28 +304,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"
|
||||
|
@ -344,8 +338,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()
|
||||
|
@ -398,8 +391,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
|
||||
|
@ -427,8 +419,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)
|
||||
|
@ -454,8 +445,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!
|
||||
|
@ -502,8 +492,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
|
||||
|
@ -824,8 +813,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)
|
||||
|
@ -876,15 +864,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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -45,7 +45,6 @@ func compute_deltas(
|
|||
|
||||
logScope:
|
||||
topics = "fork_choice"
|
||||
cat = "fork_choice"
|
||||
|
||||
# API:
|
||||
# - The private procs uses the ForkChoiceError error code
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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[]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue