Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cache block hash #1329

Merged
merged 1 commit into from
Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 16 additions & 27 deletions beacon_chain/attestation_pool.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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 <
Expand Down Expand Up @@ -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..
Expand Down Expand Up @@ -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

Expand All @@ -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))
Expand All @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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]:
Expand Down Expand Up @@ -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),
Expand Down
23 changes: 9 additions & 14 deletions beacon_chain/beacon_chain_db.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")
Expand All @@ -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()

Expand Down Expand Up @@ -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
53 changes: 19 additions & 34 deletions beacon_chain/beacon_node.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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"
Expand All @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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!
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
5 changes: 2 additions & 3 deletions beacon_chain/block_pool.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading