Feature: Prevent loading an existing data directory for the wrong network (#2825)
* Prevent loading an existing data directory for the wrong network * Fix and add more info
This commit is contained in:
parent
f0f607b23b
commit
6c3bbbf22c
|
@ -0,0 +1,84 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2021-2024 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
# at your option.
|
||||
# This file may not be copied, modified, or distributed except according to
|
||||
# those terms.
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
import
|
||||
std/[typetraits, tables],
|
||||
eth/common/base,
|
||||
eth/common/times,
|
||||
eth/common/hashes,
|
||||
eth/common/addresses,
|
||||
stew/endians2,
|
||||
stint,
|
||||
nimcrypto/sha2,
|
||||
./chain_config
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# When the client doing initialization step, it will go through
|
||||
# complicated steps before the genesis hash is ready. See `CommonRef.init`.
|
||||
# If the genesis happen to exists in database belonging to other network,
|
||||
# it will replace the one in CommonRef cache.
|
||||
# That is the reason why using genesis header or genesis hash + ChainId is
|
||||
# not a good solution to prevent loading existing data directory for
|
||||
# the wrong network.
|
||||
# But the ChainConfig + raw Genesis hash will make the job done before
|
||||
# CommonRef creation.
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private helper functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
func update(ctx: var sha256, val: uint64 | UInt256) =
|
||||
ctx.update(val.toBytesLE)
|
||||
|
||||
func update(ctx: var sha256, val: ChainId | EthTime | NetworkId) =
|
||||
ctx.update(distinctBase val)
|
||||
|
||||
func update(ctx: var sha256, val: bool) =
|
||||
ctx.update([val.byte])
|
||||
|
||||
func update(ctx: var sha256, val: Hash32 | Bytes8 | Bytes32 | Address) =
|
||||
ctx.update(val.data)
|
||||
|
||||
func update[T](ctx: var sha256, val: Opt[T]) =
|
||||
if val.isSome:
|
||||
ctx.update(val.get)
|
||||
|
||||
func update[K, V](ctx: var sha256, val: Table[K, V]) =
|
||||
mixin update
|
||||
for k, v in val:
|
||||
ctx.update(k)
|
||||
ctx.update(v)
|
||||
|
||||
func update[T: object](ctx: var sha256, val: T) =
|
||||
for f in fields(val):
|
||||
ctx.update(f)
|
||||
|
||||
func update[T: ref](ctx: var sha256, val: T) =
|
||||
for f in fields(val[]):
|
||||
ctx.update(f)
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
func calcHash*(networkId: NetworkId, conf: ChainConfig, genesis: Genesis): Hash32 =
|
||||
var ctx: sha256
|
||||
ctx.init()
|
||||
ctx.update(networkId)
|
||||
ctx.update(conf)
|
||||
if genesis.isNil.not:
|
||||
ctx.update(genesis)
|
||||
ctx.finish(result.data)
|
||||
ctx.clear()
|
||||
|
||||
func calcHash*(networkId: NetworkId, params: NetworkParams): Hash32 =
|
||||
calcHash(networkId, params.config, params.genesis)
|
|
@ -21,7 +21,7 @@ type
|
|||
canonicalHeadHash = 4
|
||||
slotHashToSlot = 5
|
||||
contractHash = 6
|
||||
transitionStatus = 7
|
||||
dataDirId = 7
|
||||
safeHash = 8
|
||||
finalizedHash = 9
|
||||
beaconState = 10
|
||||
|
@ -59,6 +59,10 @@ func canonicalHeadHashKey*(): DbKey {.inline.} =
|
|||
result.data[0] = byte ord(canonicalHeadHash)
|
||||
result.dataEndPos = 1
|
||||
|
||||
func dataDirIdKey*(): DbKey {.inline.} =
|
||||
result.data[0] = byte ord(dataDirId)
|
||||
result.dataEndPos = 1
|
||||
|
||||
func slotHashToSlotKey*(h: openArray[byte]): DbKey {.inline.} =
|
||||
doAssert(h.len == 32)
|
||||
result.data[0] = byte ord(slotHashToSlot)
|
||||
|
|
|
@ -17,6 +17,7 @@ import
|
|||
metrics,
|
||||
metrics/chronicles_support,
|
||||
kzg4844/kzg,
|
||||
stew/byteutils,
|
||||
./rpc,
|
||||
./version,
|
||||
./constants,
|
||||
|
@ -24,7 +25,9 @@ import
|
|||
./nimbus_import,
|
||||
./core/eip4844,
|
||||
./db/core_db/persistent,
|
||||
./sync/handlers
|
||||
./db/storage_types,
|
||||
./sync/handlers,
|
||||
./common/chain_config_hash
|
||||
|
||||
from beacon_chain/nimbus_binary_common import setupFileLimits
|
||||
|
||||
|
@ -153,6 +156,24 @@ proc setupMetrics(nimbus: NimbusNode, conf: NimbusConf) =
|
|||
nimbus.metricsServer = res.get
|
||||
waitFor nimbus.metricsServer.start()
|
||||
|
||||
proc preventLoadingDataDirForTheWrongNetwork(db: CoreDbRef; conf: NimbusConf) =
|
||||
let
|
||||
kvt = db.ctx.getKvt()
|
||||
calculatedId = calcHash(conf.networkId, conf.networkParams)
|
||||
dataDirIdBytes = kvt.get(dataDirIdKey().toOpenArray).valueOr:
|
||||
# an empty database
|
||||
info "Writing data dir ID", ID=calculatedId
|
||||
kvt.put(dataDirIdKey().toOpenArray, calculatedId.data).isOkOr:
|
||||
fatal "Cannot write data dir ID", ID=calculatedId
|
||||
quit(QuitFailure)
|
||||
return
|
||||
|
||||
if calculatedId.data != dataDirIdBytes:
|
||||
fatal "Data dir already initialized with other network configuration",
|
||||
get=dataDirIdBytes.toHex,
|
||||
expected=calculatedId
|
||||
quit(QuitFailure)
|
||||
|
||||
proc run(nimbus: NimbusNode, conf: NimbusConf) =
|
||||
## logging
|
||||
setLogLevel(conf.logLevel)
|
||||
|
@ -192,6 +213,7 @@ proc run(nimbus: NimbusNode, conf: NimbusConf) =
|
|||
string conf.dataDir,
|
||||
conf.dbOptions(noKeyCache = conf.cmd == NimbusCmd.`import`))
|
||||
|
||||
preventLoadingDataDirForTheWrongNetwork(coreDB, conf)
|
||||
setupMetrics(nimbus, conf)
|
||||
|
||||
let com = CommonRef.new(
|
||||
|
|
Loading…
Reference in New Issue