Require properly configured Engine API connection after the merge (#4006)

This commit is contained in:
zah 2022-08-22 22:44:40 +03:00 committed by GitHub
parent f1ddcfff0f
commit 4e41ed1d5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 75 additions and 32 deletions

View File

@ -172,6 +172,11 @@ type
desc: "Force the use of polling when determining the head block of Eth1"
name: "web3-force-polling" .}: bool
requireEngineAPI* {.
defaultValue: true
desc: "Require Nimbus to be configured with an Engine API end-point after the Bellatrix fork epoch"
name: "require-engine-api-in-bellatrix" .}: bool
nonInteractive* {.
desc: "Do not display interative prompts. Quit on missing configuration"
name: "non-interactive" .}: bool

View File

@ -141,6 +141,8 @@ type
stopFut: Future[void]
getBeaconTime: GetBeaconTimeFn
requireEngineAPI: bool
when hasGenesisDetection:
genesisValidators: seq[ImmutableValidatorData]
genesisValidatorKeyToIndex: Table[ValidatorPubKey, ValidatorIndex]
@ -548,53 +550,67 @@ proc forkchoiceUpdated*(p: Eth1Monitor,
# TODO can't be defined within exchangeTransitionConfiguration
proc `==`(x, y: Quantity): bool {.borrow, noSideEffect.}
proc exchangeTransitionConfiguration*(p: Eth1Monitor): Future[void] {.async.} =
type
EtcStatus {.pure.} = enum
exchangeError
mismatch
localConfigurationUpdated
match
proc exchangeTransitionConfiguration*(p: Eth1Monitor): Future[EtcStatus] {.async.} =
# Eth1 monitor can recycle connections without (external) warning; at least,
# don't crash.
if p.isNil:
debug "exchangeTransitionConfiguration: nil Eth1Monitor"
if p.isNil or p.dataProvider.isNil:
return
return EtcStatus.exchangeError
let ccTransitionConfiguration = TransitionConfigurationV1(
let consensusCfg = TransitionConfigurationV1(
terminalTotalDifficulty: p.depositsChain.cfg.TERMINAL_TOTAL_DIFFICULTY,
terminalBlockHash:
if p.terminalBlockHash.isSome:
p.terminalBlockHash.get
else:
# https://github.com/nim-lang/Nim/issues/19802
(static(default(BlockHash))),
(static default BlockHash),
terminalBlockNumber:
if p.terminalBlockNumber.isSome:
p.terminalBlockNumber.get
else:
# https://github.com/nim-lang/Nim/issues/19802
(static(default(Quantity))))
let ecTransitionConfiguration =
(static default Quantity))
let executionCfg =
try:
awaitWithRetries(
p.dataProvider.web3.provider.engine_exchangeTransitionConfigurationV1(
ccTransitionConfiguration),
consensusCfg),
timeout = 1.seconds)
except CatchableError as err:
debug "Failed to exchange transition configuration", err = err.msg
return
error "Failed to exchange transition configuration", err = err.msg
return EtcStatus.exchangeError
if ccTransitionConfiguration != ecTransitionConfiguration:
warn "exchangeTransitionConfiguration: Configuration mismatch detected",
consensusTerminalTotalDifficulty =
$ccTransitionConfiguration.terminalTotalDifficulty,
consensusTerminalBlockHash =
ccTransitionConfiguration.terminalBlockHash,
consensusTerminalBlockNumber =
ccTransitionConfiguration.terminalBlockNumber.uint64,
executionTerminalTotalDifficulty =
$ecTransitionConfiguration.terminalTotalDifficulty,
executionTerminalBlockHash =
ecTransitionConfiguration.terminalBlockHash,
executionTerminalBlockNumber =
ecTransitionConfiguration.terminalBlockNumber.uint64
if consensusCfg.terminalTotalDifficulty != executionCfg.terminalTotalDifficulty:
warn "Engine API configured with different terminal total difficulty",
engineAPI_value = executionCfg.terminalTotalDifficulty,
localValue = consensusCfg.terminalTotalDifficulty
return EtcStatus.mismatch
if p.terminalBlockNumber.isSome and p.terminalBlockHash.isSome:
var res = EtcStatus.match
if consensusCfg.terminalBlockNumber != executionCfg.terminalBlockNumber:
warn "Engine API reporting different terminal block number",
engineAPI_value = executionCfg.terminalBlockNumber.uint64,
localValue = consensusCfg.terminalBlockNumber.uint64
res = EtcStatus.mismatch
if consensusCfg.terminalBlockHash != executionCfg.terminalBlockHash:
warn "Engine API reporting different terminal block hash",
engineAPI_value = executionCfg.terminalBlockHash,
localValue = consensusCfg.terminalBlockHash
res = EtcStatus.mismatch
return res
else:
p.terminalBlockNumber = some executionCfg.terminalBlockNumber
p.terminalBlockHash = some executionCfg.terminalBlockHash
return EtcStatus.localConfigurationUpdated
template readJsonField(j: JsonNode, fieldName: string, ValueType: type): untyped =
var res: ValueType
@ -1037,7 +1053,8 @@ proc init*(T: type Eth1Monitor,
depositContractSnapshot: Option[DepositContractSnapshot],
eth1Network: Option[Eth1Network],
forcePolling: bool,
jwtSecret: Option[seq[byte]]): T =
jwtSecret: Option[seq[byte]],
requireEngineAPI: bool): T =
doAssert web3Urls.len > 0
var web3Urls = web3Urls
for url in mitems(web3Urls):
@ -1055,7 +1072,8 @@ proc init*(T: type Eth1Monitor,
eth1Progress: newAsyncEvent(),
forcePolling: forcePolling,
jwtSecret: jwtSecret,
blocksPerLogsRequest: targetBlocksPerLogsRequest)
blocksPerLogsRequest: targetBlocksPerLogsRequest,
requireEngineAPI: requireEngineAPI)
proc safeCancel(fut: var Future[void]) =
if not fut.isNil and not fut.finished:
@ -1340,6 +1358,20 @@ proc startEth1Syncing(m: Eth1Monitor, delayBeforeStart: Duration) {.async.} =
await m.ensureDataProvider()
if m.currentEpoch >= m.cfg.BELLATRIX_FORK_EPOCH:
let status = await m.exchangeTransitionConfiguration()
if status == EtcStatus.localConfigurationUpdated:
info "Obtained terminal block from Engine API",
terminalBlockNumber = m.terminalBlockNumber.get.uint64,
terminalBlockHash = m.terminalBlockHash.get
elif status != EtcStatus.match and isFirstRun and m.requireEngineAPI:
fatal "The Bellatrix hard fork requires the beacon node to be connected to a properly configured Engine API end-point. " &
"See https://nimbus.guide/merge.html for more details. " &
"If you want to temporarily continue operating Nimbus without configuring an Engine API end-point, " &
"please specify the command-line option --require-engine-api-in-bellatrix=no when launching it. " &
"Please note that you MUST complete the migration before the network TTD is reached (estimated to happen near 13th of September)"
quit 1
# We might need to reset the chain if the new provider disagrees
# with the previous one regarding the history of the chain or if
# we have detected a conensus violation - our view disagreeing with

View File

@ -538,7 +538,8 @@ proc init*(T: type BeaconNode,
getDepositContractSnapshot(),
eth1Network,
config.web3ForcePolling,
optJwtSecret)
optJwtSecret,
config.requireEngineAPI)
eth1Monitor.loadPersistedDeposits()
@ -639,7 +640,8 @@ proc init*(T: type BeaconNode,
getDepositContractSnapshot(),
eth1Network,
config.web3ForcePolling,
optJwtSecret)
optJwtSecret,
config.requireEngineAPI)
if config.rpcEnabled:
warn "Nimbus's JSON-RPC server has been removed. This includes the --rpc, --rpc-port, and --rpc-address configuration options. https://nimbus.guide/rest-api.html shows how to enable and configure the REST Beacon API server which replaces it."

View File

@ -61,7 +61,8 @@ programMain:
cfg, db = nil, getBeaconTime, config.web3Urls,
none(DepositContractSnapshot), metadata.eth1Network,
forcePolling = false,
rng[].loadJwtSecret(config, allowCreate = false))
rng[].loadJwtSecret(config, allowCreate = false),
true)
waitFor res.ensureDataProvider()
res
else:

View File

@ -22,6 +22,8 @@ As a node operator, you will need to run both an execution client and a consensu
If you were running an execution client before, make sure to update its configuration to include an option for [JWT secrets](./eth1.md#3-pass-the-jwt-secret-to-nimbus) and engine API.
Please note that once the Bellatrix fork epoch is reached on 6th of September 2022, Nimbus will refuse to start unless connected to a properly configured execution client. If you need more time to complete the transition, you can temporarily run the beacon node with the command-line option `--require-engine-api-in-bellatrix=no`, but please note that such a setup will stop working once the network TTD is reached (currently estimated to happen on 13th of September, see https://wenmerge.com/ for more up-to-date information).
### Prepare a suggested fee recipient
After the merge, validators that propose blocks are eligible to recieve transaction fees - read more about fee recipients [here](https://launchpad.ethereum.org/en/merge-readiness#fee-recipient).

View File

@ -59,7 +59,7 @@ proc run() {.async.} =
eth1Monitor = Eth1Monitor.init(
defaultRuntimeConfig, db = nil, nil, @[paramStr(1)],
none(DepositContractSnapshot), none(Eth1Network), false,
some readJwtSecret(paramStr(2)).get)
some readJwtSecret(paramStr(2)).get, true)
await eth1Monitor.ensureDataProvider()
try:

View File

@ -60,7 +60,8 @@ proc run() {.async.} =
jwtSecret = some readJwtSecret("jwt.hex").get
eth1Monitor = Eth1Monitor.init(
defaultRuntimeConfig, db = nil, nil, @[web3Url],
none(DepositContractSnapshot), none(Eth1Network), false, jwtSecret)
none(DepositContractSnapshot), none(Eth1Network),
false, jwtSecret, true)
web3Provider = (await Web3DataProvider.new(
default(Eth1Address), web3Url, jwtSecret)).get