Revert writing backfill root to database (#3215)

Introduced in #3171, it turns out we can just follow the block headers
to achieve the same effect

* leaves the constant in the code so as to avoid confusion when reading
database that had the constant written (such as the fleet nodes and
other unstable users)
This commit is contained in:
Jacek Sieka 2021-12-21 11:40:14 +01:00 committed by GitHub
parent c270ec21e4
commit 1021e3324e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 51 additions and 70 deletions

View File

@ -137,9 +137,7 @@ type
## only recent contract state data (i.e. only recent `deposit_roots`). ## only recent contract state data (i.e. only recent `deposit_roots`).
kHashToStateDiff # Obsolete kHashToStateDiff # Obsolete
kHashToStateOnlyMutableValidators kHashToStateOnlyMutableValidators
kBackfillBlock kBackfillBlock # Obsolete, was in `unstable` for a while, but never released
## Pointer to the earliest block that we have backfilled - if this is not
## set, backfill == tail
BeaconBlockSummary* = object BeaconBlockSummary* = object
## Cache of beacon block summaries - during startup when we construct the ## Cache of beacon block summaries - during startup when we construct the
@ -477,7 +475,7 @@ proc close*(db: BeaconchainDB) =
db.db = nil db.db = nil
func toBeaconBlockSummary(v: SomeSomeBeaconBlock): BeaconBlockSummary = func toBeaconBlockSummary*(v: SomeSomeBeaconBlock): BeaconBlockSummary =
BeaconBlockSummary( BeaconBlockSummary(
slot: v.slot, slot: v.slot,
parent_root: v.parent_root, parent_root: v.parent_root,
@ -591,9 +589,6 @@ proc putTailBlock*(db: BeaconChainDB, key: Eth2Digest) =
proc putGenesisBlock*(db: BeaconChainDB, key: Eth2Digest) = proc putGenesisBlock*(db: BeaconChainDB, key: Eth2Digest) =
db.keyValues.putRaw(subkey(kGenesisBlock), key) db.keyValues.putRaw(subkey(kGenesisBlock), key)
proc putBackfillBlock*(db: BeaconChainDB, key: Eth2Digest) =
db.keyValues.putRaw(subkey(kBackfillBlock), key)
proc putEth2FinalizedTo*(db: BeaconChainDB, proc putEth2FinalizedTo*(db: BeaconChainDB,
eth1Checkpoint: DepositContractSnapshot) = eth1Checkpoint: DepositContractSnapshot) =
db.keyValues.putSnappySSZ(subkey(kDepositsFinalizedByEth2), eth1Checkpoint) db.keyValues.putSnappySSZ(subkey(kDepositsFinalizedByEth2), eth1Checkpoint)
@ -797,9 +792,6 @@ proc getGenesisBlock*(db: BeaconChainDB): Opt[Eth2Digest] =
db.keyValues.getRaw(subkey(kGenesisBlock), Eth2Digest) or db.keyValues.getRaw(subkey(kGenesisBlock), Eth2Digest) or
db.v0.getGenesisBlock() db.v0.getGenesisBlock()
proc getBackfillBlock*(db: BeaconChainDB): Opt[Eth2Digest] =
db.keyValues.getRaw(subkey(kBackfillBlock), Eth2Digest)
proc getEth2FinalizedTo(db: BeaconChainDBV0): Opt[DepositContractSnapshot] = proc getEth2FinalizedTo(db: BeaconChainDBV0): Opt[DepositContractSnapshot] =
result.ok(DepositContractSnapshot()) result.ok(DepositContractSnapshot())
let r = db.backend.getSnappySSZ(subkey(kDepositsFinalizedByEth2), result.get) let r = db.backend.getSnappySSZ(subkey(kDepositsFinalizedByEth2), result.get)
@ -856,7 +848,7 @@ iterator getAncestors*(db: BeaconChainDB, root: Eth2Digest):
yield res yield res
root = res.message.parent_root root = res.message.parent_root
proc loadSummaries(db: BeaconChainDB): Table[Eth2Digest, BeaconBlockSummary] = proc loadSummaries*(db: BeaconChainDB): Table[Eth2Digest, BeaconBlockSummary] =
# Load summaries into table - there's no telling what order they're in so we # Load summaries into table - there's no telling what order they're in so we
# load them all - bugs in nim prevent this code from living in the iterator. # load them all - bugs in nim prevent this code from living in the iterator.
var summaries = initTable[Eth2Digest, BeaconBlockSummary](1024*1024) var summaries = initTable[Eth2Digest, BeaconBlockSummary](1024*1024)

View File

@ -273,7 +273,7 @@ proc addBackfillBlock*(
logScope: logScope:
blockRoot = shortLog(signedBlock.root) blockRoot = shortLog(signedBlock.root)
blck = shortLog(signedBlock.message) blck = shortLog(signedBlock.message)
backfill = (dag.backfill.slot, shortLog(dag.backfill.root)) backfill = (dag.backfill.slot, shortLog(dag.backfill.parent_root))
template blck(): untyped = signedBlock.message # shortcuts without copy template blck(): untyped = signedBlock.message # shortcuts without copy
template blockRoot(): untyped = signedBlock.root template blockRoot(): untyped = signedBlock.root
@ -292,7 +292,7 @@ proc addBackfillBlock*(
debug "Block unviable or duplicate" debug "Block unviable or duplicate"
return err(BlockError.UnviableFork) return err(BlockError.UnviableFork)
if dag.backfill.root != signedBlock.root: if dag.backfill.parent_root != signedBlock.root:
debug "Block does not match expected backfill root" debug "Block does not match expected backfill root"
return err(BlockError.MissingParent) # MissingChild really, but .. return err(BlockError.MissingParent) # MissingChild really, but ..
@ -319,8 +319,7 @@ proc addBackfillBlock*(
return err(BlockError.Invalid) return err(BlockError.Invalid)
dag.putBlock(signedBlock.asTrusted()) dag.putBlock(signedBlock.asTrusted())
dag.db.putBackfillBlock(signedBlock.root) dag.backfill = blck.toBeaconBlockSummary()
dag.backfill = (blck.slot, blck.parent_root)
# Invariants maintained on startup # Invariants maintained on startup
doAssert dag.backfillBlocks.lenu64 == dag.tail.slot.uint64 doAssert dag.backfillBlocks.lenu64 == dag.tail.slot.uint64

View File

@ -113,14 +113,9 @@ type
## go - the tail block is unique in that its parent is set to `nil`, even ## go - the tail block is unique in that its parent is set to `nil`, even
## in the case where a later genesis block exists. ## in the case where a later genesis block exists.
backfill*: tuple[slot: Slot, root: Eth2Digest] ##\ backfill*: BeaconBlockSummary ##\
## The backfill is root of the parent of the the earliest block that we ## The backfill points to the oldest block that we have, in the database -
## have synced, when performing a checkpoint sync start. Because the ## when backfilling, we'll be fetching its parent first
## `tail` BlockRef does not have a parent, we store here the root of the
## block we're expecting during backfill.
## When starting a checkpoint sync, `backfill` == `tail.parent_root` - we
## then sync backards, moving the backfill (but not tail!) until we hit
## genesis at which point we set backfill to the zero hash.
heads*: seq[BlockRef] ##\ heads*: seq[BlockRef] ##\
## Candidate heads of candidate chains ## Candidate heads of candidate chains

View File

@ -354,7 +354,6 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
let let
tailBlockRoot = db.getTailBlock() tailBlockRoot = db.getTailBlock()
headBlockRoot = db.getHeadBlock() headBlockRoot = db.getHeadBlock()
backfillBlockRoot = db.getBackfillBlock()
doAssert tailBlockRoot.isSome(), "Missing tail block, database corrupt?" doAssert tailBlockRoot.isSome(), "Missing tail block, database corrupt?"
doAssert headBlockRoot.isSome(), "Missing head block, database corrupt?" doAssert headBlockRoot.isSome(), "Missing head block, database corrupt?"
@ -375,18 +374,6 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
"preInit should have initialized the database with a genesis block") "preInit should have initialized the database with a genesis block")
withBlck(genesisBlock): BlockRef.init(genesisBlockRoot, blck.message) withBlck(genesisBlock): BlockRef.init(genesisBlockRoot, blck.message)
let backfill =
if backfillBlockRoot.isSome():
let backfillBlock = db.getForkedBlock(backfillBlockRoot.get()).expect(
"backfill block must be present in database, database corrupt?")
(getForkedBlockField(backfillBlock, slot),
getForkedBlockField(backfillBlock, parentRoot))
elif tailRef.slot > GENESIS_SLOT:
(getForkedBlockField(tailBlock, slot),
getForkedBlockField(tailBlock, parentRoot))
else:
(GENESIS_SLOT, Eth2Digest())
var var
blocks: HashSet[KeyedBlockRef] blocks: HashSet[KeyedBlockRef]
headRef: BlockRef headRef: BlockRef
@ -399,11 +386,15 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
var var
backfillBlocks = newSeq[Eth2Digest](tailRef.slot.int) backfillBlocks = newSeq[Eth2Digest](tailRef.slot.int)
curRef: BlockRef curRef: BlockRef
backfill = BeaconBlockSummary(slot: GENESIS_SLOT)
for blck in db.getAncestorSummaries(headRoot): for blck in db.getAncestorSummaries(headRoot):
if blck.summary.slot < tailRef.slot: if blck.summary.slot < tailRef.slot:
backfillBlocks[blck.summary.slot.int] = blck.root backfillBlocks[blck.summary.slot.int] = blck.root
backfill = blck.summary
elif blck.summary.slot == tailRef.slot: elif blck.summary.slot == tailRef.slot:
backfill = blck.summary
if curRef == nil: if curRef == nil:
curRef = tailRef curRef = tailRef
headRef = tailRef headRef = tailRef
@ -564,7 +555,7 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
finalizedHead = shortLog(dag.finalizedHead), finalizedHead = shortLog(dag.finalizedHead),
tail = shortLog(dag.tail), tail = shortLog(dag.tail),
totalBlocks = dag.blocks.len(), totalBlocks = dag.blocks.len(),
backfill = (dag.backfill.slot, shortLog(dag.backfill.root)) backfill = (dag.backfill.slot, shortLog(dag.backfill.parent_root))
dag dag
@ -1386,33 +1377,45 @@ proc updateHead*(
dag.finalizedHead.slot.epoch) dag.finalizedHead.slot.epoch)
dag.onFinHappened(data) dag.onFinHappened(data)
proc isInitialized*(T: type ChainDAGRef, db: BeaconChainDB): bool = proc isInitialized*(T: type ChainDAGRef, db: BeaconChainDB): Result[void, cstring] =
# Lightweight check to see if we have the minimal information needed to # Lightweight check to see if we have the minimal information needed to
# load up a database - we don't check head here - if something is wrong with # load up a database - we don't check head here - if something is wrong with
# head, it's likely an initialized, but corrupt database - init will detect # head, it's likely an initialized, but corrupt database - init will detect
# that # that
let let
genesisBlockRoot = db.getGenesisBlock() genesisBlockRoot = db.getGenesisBlock()
tailBlockRoot = db.getTailBlock()
if not (genesisBlockRoot.isSome() and tailBlockRoot.isSome()): if not genesisBlockRoot.isSome():
return false return err("Genesis block root missing")
let let
genesisBlock = db.getForkedBlock(genesisBlockRoot.get()) genesisBlock = db.getForkedBlock(genesisBlockRoot.get())
tailBlock = db.getForkedBlock(tailBlockRoot.get()) if not genesisBlock.isSome():
return err("Genesis block missing")
if not (genesisBlock.isSome() and tailBlock.isSome()):
return false
let let
genesisStateRoot = withBlck(genesisBlock.get()): blck.message.state_root genesisStateRoot = withBlck(genesisBlock.get()): blck.message.state_root
if not db.containsState(genesisStateRoot):
return err("Genesis state missing")
let
tailBlockRoot = db.getTailBlock()
if not tailBlockRoot.isSome():
return err("Tail block root missing")
let
tailBlock = db.getForkedBlock(tailBlockRoot.get())
if not tailBlock.isSome():
return err("Tail block missing")
let
tailStateRoot = withBlck(tailBlock.get()): blck.message.state_root tailStateRoot = withBlck(tailBlock.get()): blck.message.state_root
if not ( if not db.containsState(tailStateRoot):
db.containsState(genesisStateRoot) and db.containsState(tailStateRoot)): return err("Tail state missing")
return false
true ok()
proc preInit*( proc preInit*(
T: type ChainDAGRef, db: BeaconChainDB, T: type ChainDAGRef, db: BeaconChainDB,

View File

@ -199,7 +199,7 @@ proc init(T: type BeaconNode,
quit 1 quit 1
var eth1Monitor: Eth1Monitor var eth1Monitor: Eth1Monitor
if not ChainDAGRef.isInitialized(db): if not ChainDAGRef.isInitialized(db).isOk():
var var
tailState: ref ForkedHashedBeaconState tailState: ref ForkedHashedBeaconState
tailBlock: ForkedTrustedSignedBeaconBlock tailBlock: ForkedTrustedSignedBeaconBlock
@ -279,7 +279,7 @@ proc init(T: type BeaconNode,
try: try:
ChainDAGRef.preInit(db, genesisState[], tailState[], tailBlock) ChainDAGRef.preInit(db, genesisState[], tailState[], tailBlock)
doAssert ChainDAGRef.isInitialized(db), "preInit should have initialized db" doAssert ChainDAGRef.isInitialized(db).isOk(), "preInit should have initialized db"
except CatchableError as exc: except CatchableError as exc:
error "Failed to initialize database", err = exc.msg error "Failed to initialize database", err = exc.msg
quit 1 quit 1

View File

@ -5,6 +5,3 @@
@if release: @if release:
-d:"chronicles_line_numbers:0" -d:"chronicles_line_numbers:0"
@end @end
# Use only `secp256k1` public key cryptography as an identity in LibP2P.
-d:"libp2p_pki_schemes=secp256k1"

View File

@ -5,6 +5,3 @@
@if release: @if release:
-d:"chronicles_line_numbers:0" -d:"chronicles_line_numbers:0"
@end @end
# Use only `secp256k1` public key cryptography as an identity in LibP2P.
-d:"libp2p_pki_schemes=secp256k1"

View File

@ -5,6 +5,3 @@
@if release: @if release:
-d:"chronicles_line_numbers:0" -d:"chronicles_line_numbers:0"
@end @end
# Use only `secp256k1` public key cryptography as an identity in LibP2P.
-d:"libp2p_pki_schemes=secp256k1"

View File

@ -195,8 +195,8 @@ proc cmdBench(conf: DbConf, cfg: RuntimeConfig) =
db.close() db.close()
dbBenchmark.close() dbBenchmark.close()
if not ChainDAGRef.isInitialized(db): if (let v = ChainDAGRef.isInitialized(db); v.isErr()):
echo "Database not initialized" echo "Database not initialized: ", v.error()
quit 1 quit 1
echo "Initializing block pool..." echo "Initializing block pool..."
@ -470,8 +470,8 @@ proc cmdRewindState(conf: DbConf, cfg: RuntimeConfig) =
let db = BeaconChainDB.new(conf.databaseDir.string) let db = BeaconChainDB.new(conf.databaseDir.string)
defer: db.close() defer: db.close()
if not ChainDAGRef.isInitialized(db): if (let v = ChainDAGRef.isInitialized(db); v.isErr()):
echo "Database not initialized" echo "Database not initialized: ", v.error()
quit 1 quit 1
echo "Initializing block pool..." echo "Initializing block pool..."
@ -501,8 +501,8 @@ proc cmdExportEra(conf: DbConf, cfg: RuntimeConfig) =
let db = BeaconChainDB.new(conf.databaseDir.string) let db = BeaconChainDB.new(conf.databaseDir.string)
defer: db.close() defer: db.close()
if not ChainDAGRef.isInitialized(db): if (let v = ChainDAGRef.isInitialized(db); v.isErr()):
echo "Database not initialized" echo "Database not initialized: ", v.error()
quit 1 quit 1
echo "Initializing block pool..." echo "Initializing block pool..."
@ -565,8 +565,8 @@ proc cmdValidatorPerf(conf: DbConf, cfg: RuntimeConfig) =
defer: defer:
db.close() db.close()
if not ChainDAGRef.isInitialized(db): if (let v = ChainDAGRef.isInitialized(db); v.isErr()):
echo "Database not initialized" echo "Database not initialized: ", v.error()
quit 1 quit 1
echo "# Initializing block pool..." echo "# Initializing block pool..."
@ -705,8 +705,8 @@ proc cmdValidatorDb(conf: DbConf, cfg: RuntimeConfig) =
defer: defer:
db.close() db.close()
if not ChainDAGRef.isInitialized(db): if (let v = ChainDAGRef.isInitialized(db); v.isErr()):
echo "Database not initialized" echo "Database not initialized: ", v.error()
quit 1 quit 1
echo "Initializing block pool..." echo "Initializing block pool..."

2
tests/nim.cfg Normal file
View File

@ -0,0 +1,2 @@
# Use only `secp256k1` public key cryptography as an identity in LibP2P.
-d:"libp2p_pki_schemes=secp256k1"

View File

@ -1 +0,0 @@
-d:"libp2p_pki_schemes=secp256k1"