fix state rewind
* rewind fast path comparison was not taking skipped slots into account properly * less messy blockref creation
This commit is contained in:
parent
f20127f4c6
commit
fb9c4fabf4
|
@ -249,9 +249,10 @@ proc init*(T: type BlockPool, db: BeaconChainDB): BlockPool =
|
||||||
res
|
res
|
||||||
|
|
||||||
proc addResolvedBlock(
|
proc addResolvedBlock(
|
||||||
pool: var BlockPool, state: var StateData, blockRoot: Eth2Digest,
|
pool: var BlockPool, state: BeaconState, blockRoot: Eth2Digest,
|
||||||
signedBlock: SignedBeaconBlock, parent: BlockRef): BlockRef =
|
signedBlock: SignedBeaconBlock, parent: BlockRef): BlockRef =
|
||||||
logScope: pcs = "block_resolution"
|
logScope: pcs = "block_resolution"
|
||||||
|
doAssert state.slot == signedBlock.message.slot, "state must match block"
|
||||||
|
|
||||||
let blockRef = BlockRef.init(blockRoot, signedBlock.message)
|
let blockRef = BlockRef.init(blockRoot, signedBlock.message)
|
||||||
link(parent, blockRef)
|
link(parent, blockRef)
|
||||||
|
@ -262,17 +263,10 @@ proc addResolvedBlock(
|
||||||
# Resolved blocks should be stored in database
|
# Resolved blocks should be stored in database
|
||||||
pool.db.putBlock(blockRoot, signedBlock)
|
pool.db.putBlock(blockRoot, signedBlock)
|
||||||
|
|
||||||
# TODO this is a bit ugly - we update state.data outside of this function then
|
|
||||||
# set the rest here - need a blockRef to update it. Clean this up -
|
|
||||||
# hopefully it won't be necessary by the time hash caching and the rest
|
|
||||||
# is done..
|
|
||||||
doAssert state.data.data.slot == blockRef.slot
|
|
||||||
state.blck = blockRef
|
|
||||||
|
|
||||||
# This block *might* have caused a justification - make sure we stow away
|
# This block *might* have caused a justification - make sure we stow away
|
||||||
# that information:
|
# that information:
|
||||||
let justifiedSlot =
|
let justifiedSlot =
|
||||||
state.data.data.current_justified_checkpoint.epoch.compute_start_slot_at_epoch()
|
state.current_justified_checkpoint.epoch.compute_start_slot_at_epoch()
|
||||||
|
|
||||||
var foundHead: Option[Head]
|
var foundHead: Option[Head]
|
||||||
for head in pool.heads.mitems():
|
for head in pool.heads.mitems():
|
||||||
|
@ -389,9 +383,12 @@ proc add*(
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Careful, pool.tmpState is now partially inconsistent and will be updated
|
# Careful, tmpState.data has been updated but not blck - we need to create
|
||||||
# inside addResolvedBlock
|
# the BlockRef first!
|
||||||
return pool.addResolvedBlock(pool.tmpState, blockRoot, signedBlock, parent)
|
pool.tmpState.blck = pool.addResolvedBlock(
|
||||||
|
pool.tmpState.data.data, blockRoot, signedBlock, parent)
|
||||||
|
|
||||||
|
return pool.tmpState.blck
|
||||||
|
|
||||||
# TODO already checked hash though? main reason to keep this is because
|
# TODO already checked hash though? main reason to keep this is because
|
||||||
# the pending pool calls this function back later in a loop, so as long
|
# the pending pool calls this function back later in a loop, so as long
|
||||||
|
@ -603,7 +600,7 @@ proc rewindState(pool: BlockPool, state: var StateData, bs: BlockSlot):
|
||||||
var ancestors = @[pool.get(bs.blck)]
|
var ancestors = @[pool.get(bs.blck)]
|
||||||
# Common case: the last block applied is the parent of the block to apply:
|
# Common case: the last block applied is the parent of the block to apply:
|
||||||
if not bs.blck.parent.isNil and state.blck.root == bs.blck.parent.root and
|
if not bs.blck.parent.isNil and state.blck.root == bs.blck.parent.root and
|
||||||
state.data.data.slot < bs.slot:
|
state.data.data.slot < bs.blck.slot:
|
||||||
return ancestors
|
return ancestors
|
||||||
|
|
||||||
# It appears that the parent root of the proposed new block is different from
|
# It appears that the parent root of the proposed new block is different from
|
||||||
|
@ -693,6 +690,7 @@ proc updateStateData*(pool: BlockPool, state: var StateData, bs: BlockSlot) =
|
||||||
if state.data.data.slot != bs.slot:
|
if state.data.data.slot != bs.slot:
|
||||||
# Might be that we're moving to the same block but later slot
|
# Might be that we're moving to the same block but later slot
|
||||||
process_slots(state.data, bs.slot)
|
process_slots(state.data, bs.slot)
|
||||||
|
# TODO we will not save if multiple slots are skipped here
|
||||||
pool.maybePutState(state.data, bs.blck)
|
pool.maybePutState(state.data, bs.blck)
|
||||||
|
|
||||||
return # State already at the right spot
|
return # State already at the right spot
|
||||||
|
@ -715,6 +713,7 @@ proc updateStateData*(pool: BlockPool, state: var StateData, bs: BlockSlot) =
|
||||||
doAssert ok, "Blocks in database should never fail to apply.."
|
doAssert ok, "Blocks in database should never fail to apply.."
|
||||||
|
|
||||||
# TODO check if this triggers rest of state transition, or should
|
# TODO check if this triggers rest of state transition, or should
|
||||||
|
# TODO we will not save if multiple slots are skipped here
|
||||||
process_slots(state.data, bs.slot)
|
process_slots(state.data, bs.slot)
|
||||||
pool.maybePutState(state.data, bs.blck)
|
pool.maybePutState(state.data, bs.blck)
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,55 @@ when const_preset == "minimal": # Too much stack space used on mainnet
|
||||||
pool.head.blck == b1Add
|
pool.head.blck == b1Add
|
||||||
pool.headState.data.data.slot == b1Add.slot
|
pool.headState.data.data.slot == b1Add.slot
|
||||||
|
|
||||||
|
timedTest "updateStateData sanity" & preset():
|
||||||
|
let
|
||||||
|
b1Add = pool.add(b1Root, b1)
|
||||||
|
b2Add = pool.add(b2Root, b2)
|
||||||
|
bs1 = BlockSlot(blck: b1Add, slot: b1.message.slot)
|
||||||
|
bs1_3 = b1Add.atSlot(3.Slot)
|
||||||
|
bs2 = BlockSlot(blck: b2Add, slot: b2.message.slot)
|
||||||
|
bs2_3 = b2Add.atSlot(3.Slot)
|
||||||
|
|
||||||
|
var tmpState = pool.headState
|
||||||
|
|
||||||
|
# move to specific block
|
||||||
|
pool.updateStateData(tmpState, bs1)
|
||||||
|
|
||||||
|
check:
|
||||||
|
tmpState.blck == b1Add
|
||||||
|
tmpState.data.data.slot == bs1.slot
|
||||||
|
|
||||||
|
# Skip slots
|
||||||
|
pool.updateStateData(tmpState, bs1_3) # skip slots
|
||||||
|
|
||||||
|
check:
|
||||||
|
tmpState.blck == b1Add
|
||||||
|
tmpState.data.data.slot == bs1_3.slot
|
||||||
|
|
||||||
|
# Move back slots, but not blocks
|
||||||
|
pool.updateStateData(tmpState, bs1_3.parent())
|
||||||
|
check:
|
||||||
|
tmpState.blck == b1Add
|
||||||
|
tmpState.data.data.slot == bs1_3.parent().slot
|
||||||
|
|
||||||
|
# Move to different block and slot
|
||||||
|
pool.updateStateData(tmpState, bs2_3)
|
||||||
|
check:
|
||||||
|
tmpState.blck == b2Add
|
||||||
|
tmpState.data.data.slot == bs2_3.slot
|
||||||
|
|
||||||
|
# Move back slot and block
|
||||||
|
pool.updateStateData(tmpState, bs1)
|
||||||
|
check:
|
||||||
|
tmpState.blck == b1Add
|
||||||
|
tmpState.data.data.slot == bs1.slot
|
||||||
|
|
||||||
|
# Move back to genesis
|
||||||
|
pool.updateStateData(tmpState, bs1.parent())
|
||||||
|
check:
|
||||||
|
tmpState.blck == b1Add.parent
|
||||||
|
tmpState.data.data.slot == bs1.parent.slot
|
||||||
|
|
||||||
suite "BlockPool finalization tests" & preset():
|
suite "BlockPool finalization tests" & preset():
|
||||||
setup:
|
setup:
|
||||||
var
|
var
|
||||||
|
|
Loading…
Reference in New Issue