state loading optimizations (#5881)
* compute post-merge randao mix without loading state * avoid copying state on shuffling computation and compute epochref * speed up state copy for block production
This commit is contained in:
parent
ec710bd90e
commit
afdfe302f3
|
@ -811,7 +811,7 @@ proc getStateByParent(
|
||||||
dag.cfg, summary.parent_root, parentMinSlot..slot, state, rollback)
|
dag.cfg, summary.parent_root, parentMinSlot..slot, state, rollback)
|
||||||
|
|
||||||
proc getNearbyState(
|
proc getNearbyState(
|
||||||
dag: ChainDAGRef, state: ref ForkedHashedBeaconState, bid: BlockId,
|
dag: ChainDAGRef, state: var ForkedHashedBeaconState, bid: BlockId,
|
||||||
lowSlot: Slot): Opt[void] =
|
lowSlot: Slot): Opt[void] =
|
||||||
## Load state from DB that is close to `bid` and has at least slot `lowSlot`.
|
## Load state from DB that is close to `bid` and has at least slot `lowSlot`.
|
||||||
var
|
var
|
||||||
|
@ -823,7 +823,7 @@ proc getNearbyState(
|
||||||
return err()
|
return err()
|
||||||
b = (? dag.atSlot(b, max(stateSlot, 1.Slot) - 1)).bid
|
b = (? dag.atSlot(b, max(stateSlot, 1.Slot) - 1)).bid
|
||||||
let bsi = BlockSlotId.init(b, stateSlot)
|
let bsi = BlockSlotId.init(b, stateSlot)
|
||||||
if not dag.getState(bsi, state[]):
|
if not dag.getState(bsi, state):
|
||||||
if e == GENESIS_EPOCH:
|
if e == GENESIS_EPOCH:
|
||||||
return err()
|
return err()
|
||||||
dec e
|
dec e
|
||||||
|
@ -1426,7 +1426,7 @@ proc ancestorSlot*(
|
||||||
Opt.some stateBid.slot
|
Opt.some stateBid.slot
|
||||||
|
|
||||||
proc computeRandaoMix(
|
proc computeRandaoMix(
|
||||||
dag: ChainDAGRef, bdata: ForkedTrustedSignedBeaconBlock): Opt[Eth2Digest] =
|
bdata: ForkedTrustedSignedBeaconBlock): Opt[Eth2Digest] =
|
||||||
## Compute the requested RANDAO mix for `bdata` without `state`, if possible.
|
## Compute the requested RANDAO mix for `bdata` without `state`, if possible.
|
||||||
withBlck(bdata):
|
withBlck(bdata):
|
||||||
when consensusFork >= ConsensusFork.Bellatrix:
|
when consensusFork >= ConsensusFork.Bellatrix:
|
||||||
|
@ -1449,7 +1449,7 @@ proc computeRandaoMix*(
|
||||||
# If `blck` is post merge, RANDAO information is immediately available
|
# If `blck` is post merge, RANDAO information is immediately available
|
||||||
let
|
let
|
||||||
bdata = ? dag.getForkedBlock(bid)
|
bdata = ? dag.getForkedBlock(bid)
|
||||||
fullMix = dag.computeRandaoMix(bdata)
|
fullMix = computeRandaoMix(bdata)
|
||||||
if fullMix.isSome:
|
if fullMix.isSome:
|
||||||
return fullMix
|
return fullMix
|
||||||
|
|
||||||
|
@ -1502,8 +1502,8 @@ proc computeRandaoMixFromMemory*(
|
||||||
proc computeRandaoMixFromDatabase*(
|
proc computeRandaoMixFromDatabase*(
|
||||||
dag: ChainDAGRef, bid: BlockId, lowSlot: Slot): Opt[Eth2Digest] =
|
dag: ChainDAGRef, bid: BlockId, lowSlot: Slot): Opt[Eth2Digest] =
|
||||||
## Compute requested RANDAO mix for `bid` using closest DB state (~500 ms).
|
## Compute requested RANDAO mix for `bid` using closest DB state (~500 ms).
|
||||||
let state = newClone(dag.headState)
|
let state = assignClone(dag.headState)
|
||||||
? dag.getNearbyState(state, bid, lowSlot)
|
? dag.getNearbyState(state[], bid, lowSlot)
|
||||||
withState(state[]):
|
withState(state[]):
|
||||||
dag.computeRandaoMix(forkyState, bid, lowSlot)
|
dag.computeRandaoMix(forkyState, bid, lowSlot)
|
||||||
|
|
||||||
|
@ -1514,6 +1514,13 @@ proc computeRandaoMix(
|
||||||
if mix.isSome:
|
if mix.isSome:
|
||||||
return mix
|
return mix
|
||||||
|
|
||||||
|
# If `blck` is post merge, RANDAO information is immediately available
|
||||||
|
let
|
||||||
|
bdata = ? dag.getForkedBlock(bid)
|
||||||
|
fullMix = computeRandaoMix(bdata)
|
||||||
|
if fullMix.isSome:
|
||||||
|
return fullMix
|
||||||
|
|
||||||
# Fall back to database
|
# Fall back to database
|
||||||
dag.computeRandaoMixFromDatabase(bid, lowSlot)
|
dag.computeRandaoMixFromDatabase(bid, lowSlot)
|
||||||
|
|
||||||
|
@ -1563,24 +1570,6 @@ proc computeShufflingRefFromMemory*(
|
||||||
tryWithState dag.epochRefState
|
tryWithState dag.epochRefState
|
||||||
tryWithState dag.clearanceState
|
tryWithState dag.clearanceState
|
||||||
|
|
||||||
proc computeShufflingRefFromDatabase*(
|
|
||||||
dag: ChainDAGRef, blck: BlockRef, epoch: Epoch): Opt[ShufflingRef] =
|
|
||||||
## Compute `ShufflingRef` for `blck@epoch` using closest DB state (~500 ms).
|
|
||||||
let state = newClone(dag.headState)
|
|
||||||
? dag.getNearbyState(state, blck.bid, epoch.lowSlotForAttesterShuffling)
|
|
||||||
withState(state[]):
|
|
||||||
dag.computeShufflingRef(forkyState, blck, epoch)
|
|
||||||
|
|
||||||
proc computeShufflingRef(
|
|
||||||
dag: ChainDAGRef, blck: BlockRef, epoch: Epoch): Opt[ShufflingRef] =
|
|
||||||
# Try to compute from states available in memory
|
|
||||||
let shufflingRef = dag.computeShufflingRefFromMemory(blck, epoch)
|
|
||||||
if shufflingRef.isOk:
|
|
||||||
return shufflingRef
|
|
||||||
|
|
||||||
# Fall back to database
|
|
||||||
dag.computeShufflingRefFromDatabase(blck, epoch)
|
|
||||||
|
|
||||||
proc getShufflingRef*(
|
proc getShufflingRef*(
|
||||||
dag: ChainDAGRef, blck: BlockRef, epoch: Epoch,
|
dag: ChainDAGRef, blck: BlockRef, epoch: Epoch,
|
||||||
preFinalized: bool): Opt[ShufflingRef] =
|
preFinalized: bool): Opt[ShufflingRef] =
|
||||||
|
@ -1592,15 +1581,12 @@ proc getShufflingRef*(
|
||||||
return shufflingRef
|
return shufflingRef
|
||||||
|
|
||||||
# Use existing states to quickly compute the shuffling
|
# Use existing states to quickly compute the shuffling
|
||||||
shufflingRef = dag.computeShufflingRef(blck, epoch)
|
shufflingRef = dag.computeShufflingRefFromMemory(blck, epoch)
|
||||||
if shufflingRef.isSome:
|
if shufflingRef.isSome:
|
||||||
dag.putShufflingRef(shufflingRef.get)
|
dag.putShufflingRef(shufflingRef.get)
|
||||||
return shufflingRef
|
return shufflingRef
|
||||||
|
|
||||||
# Last resort, this can take several seconds as this may replay states
|
# Last resort, this can take several seconds as this may replay states
|
||||||
# TODO here, we could check the existing cached states and see if any one
|
|
||||||
# has the right dependent root - unlike EpochRef, we don't need an _exact_
|
|
||||||
# epoch match
|
|
||||||
let epochRef = dag.getEpochRef(blck, epoch, preFinalized).valueOr:
|
let epochRef = dag.getEpochRef(blck, epoch, preFinalized).valueOr:
|
||||||
return Opt.none ShufflingRef
|
return Opt.none ShufflingRef
|
||||||
dag.putShufflingRef(epochRef.shufflingRef)
|
dag.putShufflingRef(epochRef.shufflingRef)
|
||||||
|
@ -2630,7 +2616,7 @@ proc getProposalState*(
|
||||||
|
|
||||||
# Start with the clearance state, since this one typically has been advanced
|
# Start with the clearance state, since this one typically has been advanced
|
||||||
# and thus has a hot hash tree cache
|
# and thus has a hot hash tree cache
|
||||||
let state = newClone(dag.clearanceState)
|
let state = assignClone(dag.clearanceState)
|
||||||
|
|
||||||
var
|
var
|
||||||
info = ForkedEpochInfo()
|
info = ForkedEpochInfo()
|
||||||
|
|
|
@ -1825,9 +1825,6 @@ template runShufflingTests(cfg: RuntimeConfig, numRandomTests: int) =
|
||||||
# If shuffling is computable from DAG, check its correctness
|
# If shuffling is computable from DAG, check its correctness
|
||||||
epochRef.checkShuffling dag.computeShufflingRefFromMemory(blck, epoch)
|
epochRef.checkShuffling dag.computeShufflingRefFromMemory(blck, epoch)
|
||||||
|
|
||||||
# If shuffling is computable from DB, check its correctness
|
|
||||||
epochRef.checkShuffling dag.computeShufflingRefFromDatabase(blck, epoch)
|
|
||||||
|
|
||||||
# Shuffling should be correct when starting from any cached state
|
# Shuffling should be correct when starting from any cached state
|
||||||
for state in states:
|
for state in states:
|
||||||
withState(state[]):
|
withState(state[]):
|
||||||
|
@ -1904,9 +1901,6 @@ template runShufflingTests(cfg: RuntimeConfig, numRandomTests: int) =
|
||||||
# If shuffling is computable from DAG, check its correctness
|
# If shuffling is computable from DAG, check its correctness
|
||||||
epochRef.checkShuffling dag.computeShufflingRefFromMemory(blck, epoch)
|
epochRef.checkShuffling dag.computeShufflingRefFromMemory(blck, epoch)
|
||||||
|
|
||||||
# If shuffling is computable from DB, check its correctness
|
|
||||||
epochRef.checkShuffling dag.computeShufflingRefFromDatabase(blck, epoch)
|
|
||||||
|
|
||||||
suite "Shufflings":
|
suite "Shufflings":
|
||||||
let cfg = defaultRuntimeConfig
|
let cfg = defaultRuntimeConfig
|
||||||
runShufflingTests(cfg, numRandomTests = 150)
|
runShufflingTests(cfg, numRandomTests = 150)
|
||||||
|
|
Loading…
Reference in New Issue