fix sync issue when upgrading from 1.1.0-inited db
This patch writes a full genesis state to `kvstore` if one was missing, which fixes 1.2.0 restarting sync when upgrading from 1.1.0, or when downgrading to a pre-1.1.0 release.
This commit is contained in:
parent
e1a8049ed5
commit
54d6884c89
|
@ -567,7 +567,7 @@ proc getBlockSummary*(db: BeaconChainDB, key: Eth2Digest): Opt[BeaconBlockSummar
|
|||
result.err()
|
||||
|
||||
proc getStateOnlyMutableValidators(
|
||||
db: BeaconChainDB, key: Eth2Digest, output: var BeaconState,
|
||||
db: BeaconChainDB, store: KvStoreRef, key: Eth2Digest, output: var BeaconState,
|
||||
rollback: RollbackProc): bool =
|
||||
## Load state into `output` - BeaconState is large so we want to avoid
|
||||
## re-allocating it if possible
|
||||
|
@ -580,7 +580,7 @@ proc getStateOnlyMutableValidators(
|
|||
# TODO RVO is inefficient for large objects:
|
||||
# https://github.com/nim-lang/Nim/issues/13879
|
||||
|
||||
case db.stateStore.getEncoded(
|
||||
case store.getEncoded(
|
||||
subkey(
|
||||
BeaconStateNoImmutableValidators, key),
|
||||
isomorphicCast[BeaconStateNoImmutableValidators](output))
|
||||
|
@ -620,7 +620,7 @@ proc getState*(
|
|||
# https://github.com/nim-lang/Nim/issues/14126
|
||||
# TODO RVO is inefficient for large objects:
|
||||
# https://github.com/nim-lang/Nim/issues/13879
|
||||
if getStateOnlyMutableValidators(db, key, output, rollback):
|
||||
if getStateOnlyMutableValidators(db, db.stateStore, key, output, rollback):
|
||||
return true
|
||||
|
||||
case db.backend.getEncoded(subkey(BeaconState, key), output)
|
||||
|
@ -682,6 +682,38 @@ proc containsState*(db: BeaconChainDB, key: Eth2Digest): bool =
|
|||
proc containsStateDiff*(db: BeaconChainDB, key: Eth2Digest): bool =
|
||||
db.backend.contains(subkey(BeaconStateDiff, key)).expect("working database (disk broken/full?)")
|
||||
|
||||
proc repairGenesisState*(db: BeaconChainDB, key: Eth2Digest): KvResult[void] =
|
||||
# Nimbus 1.0 reads and writes writes genesis BeaconState to `backend`
|
||||
# Nimbus 1.1 writes a genesis BeaconStateNoImmutableValidators to `backend` and
|
||||
# reads both BeaconState and BeaconStateNoImmutableValidators from `backend`
|
||||
# Nimbus 1.2 writes a genesis BeaconStateNoImmutableValidators to `stateStore`
|
||||
# and reads BeaconState from `backend` and BeaconStateNoImmutableValidators
|
||||
# from `stateStore`. This means that 1.2 cannot read a database created with
|
||||
# 1.1 and earlier versions can't read databases created with either of 1.1
|
||||
# and 1.2.
|
||||
# Here, we will try to repair the database so that no matter what, there will
|
||||
# be a `BeaconState` in `backend`:
|
||||
|
||||
if ? db.backend.contains(subkey(BeaconState, key)):
|
||||
# No compatibility issues, life goes on
|
||||
discard
|
||||
elif ? db.backend.contains(subkey(BeaconStateNoImmutableValidators, key)):
|
||||
# 1.1 writes this but not a full state - rewrite a full state
|
||||
var output = new BeaconState
|
||||
if not getStateOnlyMutableValidators(db, db.backend, key, output[], noRollback):
|
||||
return err("Cannot load partial state")
|
||||
|
||||
putStateFull(db, output[])
|
||||
elif ? db.stateStore.contains(subkey(BeaconStateNoImmutableValidators, key)):
|
||||
# 1.2 writes this but not a full state - rewrite a full state
|
||||
var output = new BeaconState
|
||||
if not getStateOnlyMutableValidators(db, db.stateStore, key, output[], noRollback):
|
||||
return err("Cannot load partial state")
|
||||
|
||||
putStateFull(db, output[])
|
||||
|
||||
ok()
|
||||
|
||||
iterator getAncestors*(db: BeaconChainDB, root: Eth2Digest):
|
||||
TrustedSignedBeaconBlock =
|
||||
## Load a chain of ancestors for blck - returns a list of blocks with the
|
||||
|
|
|
@ -1099,6 +1099,11 @@ proc isInitialized*(T: type ChainDAGRef, db: BeaconChainDB): bool =
|
|||
if not (headBlock.isSome() and tailBlock.isSome()):
|
||||
return false
|
||||
|
||||
# 1.1 and 1.2 need a compatibility hack
|
||||
if db.repairGenesisState(tailBlock.get().message.state_root).isErr():
|
||||
notice "Could not repair genesis state"
|
||||
return false
|
||||
|
||||
if not db.containsState(tailBlock.get().message.state_root):
|
||||
return false
|
||||
|
||||
|
@ -1120,6 +1125,7 @@ proc preInit*(
|
|||
validators = tailState.validators.len()
|
||||
|
||||
db.putState(tailState)
|
||||
db.putStateFull(tailState)
|
||||
db.putBlock(tailBlock)
|
||||
db.putTailBlock(tailBlock.root)
|
||||
db.putHeadBlock(tailBlock.root)
|
||||
|
@ -1130,6 +1136,7 @@ proc preInit*(
|
|||
else:
|
||||
doAssert genesisState.slot == GENESIS_SLOT
|
||||
db.putState(genesisState)
|
||||
db.putStateFull(genesisState)
|
||||
let genesisBlock = get_initial_beacon_block(genesisState)
|
||||
db.putBlock(genesisBlock)
|
||||
db.putStateRoot(genesisBlock.root, GENESIS_SLOT, genesisBlock.message.state_root)
|
||||
|
|
Loading…
Reference in New Issue