reuse validator key cache better (#1562)

new key cache can be used for old epochs in the same tree
This commit is contained in:
Jacek Sieka 2020-08-26 17:06:40 +02:00 committed by GitHub
parent ab22bad188
commit f26d6a4fd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 4 deletions

View File

@ -136,6 +136,16 @@ proc init*(
epochRef
func updateKeyStores*(epochRef: EpochRef, blck: BlockRef, finalized: BlockRef) =
# Because key stores are additive lists, we can use a newer list whereever an
# older list is expected - all indices in the new list will be valid for the
# old list also
var blck = blck
while blck != nil and blck.slot >= finalized.slot:
for e in blck.epochRefs:
e.validator_key_store = epochRef.validator_key_store
blck = blck.parent
func link*(parent, child: BlockRef) =
doAssert (not (parent.root == Eth2Digest() or child.root == Eth2Digest())),
"blocks missing root!"
@ -400,6 +410,7 @@ proc getEpochRef*(dag: ChainDAGRef, blck: BlockRef, epoch: Epoch): EpochRef =
# TODO consider constraining the number of epochrefs per state
ancestor.blck.epochRefs.add newEpochRef
newEpochRef.updateKeyStores(blck.parent, dag.finalizedHead.blck)
newEpochRef
proc getState(

View File

@ -65,7 +65,10 @@ proc addResolvedBlock(
let prevEpochRef = blockRef.findEpochRef(blockEpoch - 1)
epochRef = EpochRef.init(state.data.data, cache, prevEpochRef)
blockRef.epochAncestor(blockEpoch).blck.epochRefs.add epochRef
let ancestor = blockRef.epochAncestor(blockEpoch)
epochRef.updateKeyStores(ancestor.blck.parent, dag.finalizedHead.blck)
ancestor.blck.epochRefs.add epochRef
dag.blocks[blockRoot] = blockRef
trace "Populating block dag", key = blockRoot, val = blockRef

View File

@ -343,15 +343,31 @@ suiteReport "chain DAG finalization tests" & preset():
check:
dag.heads.len() == 1
let headER = dag.heads[0].findEpochRef(dag.heads[0].slot.epoch)
check:
# Epochrefs should share validator key set when the validator set is
# stable
not dag.heads[0].findEpochRef(dag.heads[0].slot.epoch).isNil
not headER.isNil
not dag.heads[0].findEpochRef(dag.heads[0].slot.epoch - 1).isNil
dag.heads[0].findEpochRef(dag.heads[0].slot.epoch) !=
headER !=
dag.heads[0].findEpochRef(dag.heads[0].slot.epoch - 1)
dag.heads[0].findEpochRef(dag.heads[0].slot.epoch).validator_key_store[1] ==
headER.validator_key_store[1] ==
dag.heads[0].findEpochRef(dag.heads[0].slot.epoch - 1).validator_key_store[1]
block:
var cur = dag.heads[0]
while cur != nil:
if cur.slot < dag.finalizedHead.blck.slot:
# Cache should be cleaned on finalization
check: cur.epochRefs.len == 0
else:
# EpochRef validator keystores should back-propagate to all previous
# epochs
for e in cur.epochRefs:
check (addr headER.validator_keys) == (addr e.validator_keys)
cur = cur.parent
block:
# The late block is a block whose parent was finalized long ago and thus
# is no longer a viable head candidate