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
|
canonicalHeadHash = 4
|
||||||
slotHashToSlot = 5
|
slotHashToSlot = 5
|
||||||
contractHash = 6
|
contractHash = 6
|
||||||
transitionStatus = 7
|
dataDirId = 7
|
||||||
safeHash = 8
|
safeHash = 8
|
||||||
finalizedHash = 9
|
finalizedHash = 9
|
||||||
beaconState = 10
|
beaconState = 10
|
||||||
|
@ -59,6 +59,10 @@ func canonicalHeadHashKey*(): DbKey {.inline.} =
|
||||||
result.data[0] = byte ord(canonicalHeadHash)
|
result.data[0] = byte ord(canonicalHeadHash)
|
||||||
result.dataEndPos = 1
|
result.dataEndPos = 1
|
||||||
|
|
||||||
|
func dataDirIdKey*(): DbKey {.inline.} =
|
||||||
|
result.data[0] = byte ord(dataDirId)
|
||||||
|
result.dataEndPos = 1
|
||||||
|
|
||||||
func slotHashToSlotKey*(h: openArray[byte]): DbKey {.inline.} =
|
func slotHashToSlotKey*(h: openArray[byte]): DbKey {.inline.} =
|
||||||
doAssert(h.len == 32)
|
doAssert(h.len == 32)
|
||||||
result.data[0] = byte ord(slotHashToSlot)
|
result.data[0] = byte ord(slotHashToSlot)
|
||||||
|
|
|
@ -17,6 +17,7 @@ import
|
||||||
metrics,
|
metrics,
|
||||||
metrics/chronicles_support,
|
metrics/chronicles_support,
|
||||||
kzg4844/kzg,
|
kzg4844/kzg,
|
||||||
|
stew/byteutils,
|
||||||
./rpc,
|
./rpc,
|
||||||
./version,
|
./version,
|
||||||
./constants,
|
./constants,
|
||||||
|
@ -24,7 +25,9 @@ import
|
||||||
./nimbus_import,
|
./nimbus_import,
|
||||||
./core/eip4844,
|
./core/eip4844,
|
||||||
./db/core_db/persistent,
|
./db/core_db/persistent,
|
||||||
./sync/handlers
|
./db/storage_types,
|
||||||
|
./sync/handlers,
|
||||||
|
./common/chain_config_hash
|
||||||
|
|
||||||
from beacon_chain/nimbus_binary_common import setupFileLimits
|
from beacon_chain/nimbus_binary_common import setupFileLimits
|
||||||
|
|
||||||
|
@ -153,6 +156,24 @@ proc setupMetrics(nimbus: NimbusNode, conf: NimbusConf) =
|
||||||
nimbus.metricsServer = res.get
|
nimbus.metricsServer = res.get
|
||||||
waitFor nimbus.metricsServer.start()
|
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) =
|
proc run(nimbus: NimbusNode, conf: NimbusConf) =
|
||||||
## logging
|
## logging
|
||||||
setLogLevel(conf.logLevel)
|
setLogLevel(conf.logLevel)
|
||||||
|
@ -192,6 +213,7 @@ proc run(nimbus: NimbusNode, conf: NimbusConf) =
|
||||||
string conf.dataDir,
|
string conf.dataDir,
|
||||||
conf.dbOptions(noKeyCache = conf.cmd == NimbusCmd.`import`))
|
conf.dbOptions(noKeyCache = conf.cmd == NimbusCmd.`import`))
|
||||||
|
|
||||||
|
preventLoadingDataDirForTheWrongNetwork(coreDB, conf)
|
||||||
setupMetrics(nimbus, conf)
|
setupMetrics(nimbus, conf)
|
||||||
|
|
||||||
let com = CommonRef.new(
|
let com = CommonRef.new(
|
||||||
|
|
Loading…
Reference in New Issue