allow Eth1 monitor to run without genesis_deposit_contract_snapshot.ssz (#3279)

This commit is contained in:
tersec 2022-01-21 10:59:09 +00:00 committed by GitHub
parent 0ea6dfa517
commit 1a37cae329
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 21 deletions

View File

@ -868,11 +868,35 @@ proc init*(T: type Eth1Chain, cfg: RuntimeConfig, db: BeaconChainDB): T =
finalizedBlockHash: finalizedDeposits.eth1Block, finalizedBlockHash: finalizedDeposits.eth1Block,
finalizedDepositsMerkleizer: finalizedDeposits.createMerkleizer) finalizedDepositsMerkleizer: finalizedDeposits.createMerkleizer)
proc createInitialDepositSnapshot*(
depositContractAddress: Eth1Address,
depositContractDeployedAt: BlockHashOrNumber,
web3Url: string): Future[Result[DepositContractSnapshot, string]] {.async.} =
let dataProviderRes =
await Web3DataProvider.new(depositContractAddress, web3Url)
if dataProviderRes.isErr:
return err(dataProviderRes.error)
var dataProvider = dataProviderRes.get
let knownStartBlockHash =
if depositContractDeployedAt.isHash:
depositContractDeployedAt.hash
else:
try:
var blk = awaitWithRetries(
dataProvider.getBlockByNumber(depositContractDeployedAt.number))
blk.hash.asEth2Digest
except CatchableError as err:
return err(err.msg)
return ok DepositContractSnapshot(eth1Block: knownStartBlockHash)
proc init*(T: type Eth1Monitor, proc init*(T: type Eth1Monitor,
cfg: RuntimeConfig, cfg: RuntimeConfig,
db: BeaconChainDB, db: BeaconChainDB,
web3Urls: seq[string], web3Urls: seq[string],
depositContractSnapshot: DepositContractSnapshot, depositContractSnapshot: Option[DepositContractSnapshot],
eth1Network: Option[Eth1Network], eth1Network: Option[Eth1Network],
forcePolling: bool): T = forcePolling: bool): T =
doAssert web3Urls.len > 0 doAssert web3Urls.len > 0
@ -881,7 +905,8 @@ proc init*(T: type Eth1Monitor,
for url in mitems(web3Urls): for url in mitems(web3Urls):
fixupWeb3Urls url fixupWeb3Urls url
putInitialDepositContractSnapshot(db, depositContractSnapshot) if depositContractSnapshot.isSome:
putInitialDepositContractSnapshot(db, depositContractSnapshot.get)
T(state: Initialized, T(state: Initialized,
depositsChain: Eth1Chain.init(cfg, db), depositsChain: Eth1Chain.init(cfg, db),
@ -911,6 +936,19 @@ proc resetState(m: Eth1Monitor) {.async.} =
await m.dataProvider.close() await m.dataProvider.close()
m.dataProvider = nil m.dataProvider = nil
proc ensureDataProvider*(m: Eth1Monitor) {.async.} =
if not m.dataProvider.isNil:
return
let web3Url = m.web3Urls[m.startIdx mod m.web3Urls.len]
inc m.startIdx
m.dataProvider = block:
let v = await Web3DataProvider.new(m.depositContractAddress, web3Url)
if v.isErr():
raise (ref CatchableError)(msg: v.error())
v.get()
proc stop(m: Eth1Monitor) {.async.} = proc stop(m: Eth1Monitor) {.async.} =
if m.state == Started: if m.state == Started:
m.state = Stopping m.state = Stopping
@ -1112,20 +1150,14 @@ proc startEth1Syncing(m: Eth1Monitor, delayBeforeStart: Duration) {.async.} =
if delayBeforeStart != ZeroDuration: if delayBeforeStart != ZeroDuration:
await sleepAsync(delayBeforeStart) await sleepAsync(delayBeforeStart)
let web3Url = m.web3Urls[m.startIdx mod m.web3Urls.len] await m.ensureDataProvider()
inc m.startIdx let
web3Url = m.web3Urls[(m.startIdx + m.web3Urls.len - 1) mod m.web3Urls.len]
web3 = m.dataProvider.web3
info "Starting Eth1 deposit contract monitoring", info "Starting Eth1 deposit contract monitoring",
contract = $m.depositContractAddress, url = web3Url contract = $m.depositContractAddress, url = web3Url
m.dataProvider = block:
let v = await Web3DataProvider.new(m.depositContractAddress, web3Url)
if v.isErr():
raise (ref CatchableError)(msg: v.error())
v.get()
let web3 = m.dataProvider.web3
if m.state == Initialized and m.eth1Network.isSome: if m.state == Initialized and m.eth1Network.isSome:
let let
providerNetwork = awaitWithRetries web3.provider.net_version() providerNetwork = awaitWithRetries web3.provider.net_version()
@ -1239,6 +1271,7 @@ proc start(m: Eth1Monitor, delayBeforeStart: Duration) =
if runFut.error[] of CatchableError: if runFut.error[] of CatchableError:
if runFut == m.runFut: if runFut == m.runFut:
warn "Eth1 chain monitoring failure, restarting", err = runFut.error.msg warn "Eth1 chain monitoring failure, restarting", err = runFut.error.msg
m.dataProvider = nil
m.state = Failed m.state = Failed
else: else:
fatal "Fatal exception reached", err = runFut.error.msg fatal "Fatal exception reached", err = runFut.error.msg

View File

@ -119,11 +119,20 @@ proc init*(T: type BeaconNode,
depositContractDeployedAt: BlockHashOrNumber, depositContractDeployedAt: BlockHashOrNumber,
eth1Network: Option[Eth1Network], eth1Network: Option[Eth1Network],
genesisStateContents: string, genesisStateContents: string,
genesisDepositsSnapshotContents: string): BeaconNode {. depositContractSnapshotContents: string): BeaconNode {.
raises: [Defect, CatchableError].} = raises: [Defect, CatchableError].} =
var taskpool: TaskpoolPtr var taskpool: TaskpoolPtr
let depositContractSnapshot = if depositContractSnapshotContents.len > 0:
try:
some SSZ.decode(depositContractSnapshotContents, DepositContractSnapshot)
except CatchableError as err:
fatal "Invalid deposit contract snapshot", err = err.msg
quit 1
else:
none DepositContractSnapshot
try: try:
if config.numThreads < 0: if config.numThreads < 0:
fatal "The number of threads --numThreads cannot be negative." fatal "The number of threads --numThreads cannot be negative."
@ -199,6 +208,24 @@ proc init*(T: type BeaconNode,
fatal "--finalized-checkpoint-block cannot be specified without --finalized-checkpoint-state" fatal "--finalized-checkpoint-block cannot be specified without --finalized-checkpoint-state"
quit 1 quit 1
template getDepositContractSnapshot: auto =
if depositContractSnapshot.isSome:
depositContractSnapshot
elif not cfg.DEPOSIT_CONTRACT_ADDRESS.isZeroMemory:
let snapshotRes = waitFor createInitialDepositSnapshot(
cfg.DEPOSIT_CONTRACT_ADDRESS,
depositContractDeployedAt,
config.web3Urls[0])
if snapshotRes.isErr:
fatal "Failed to locate the deposit contract deployment block",
depositContract = cfg.DEPOSIT_CONTRACT_ADDRESS,
deploymentBlock = $depositContractDeployedAt
quit 1
else:
some snapshotRes.get
else:
none(DepositContractSnapshot)
var eth1Monitor: Eth1Monitor var eth1Monitor: Eth1Monitor
if not ChainDAGRef.isInitialized(db).isOk(): if not ChainDAGRef.isInitialized(db).isOk():
var var
@ -207,7 +234,7 @@ proc init*(T: type BeaconNode,
if genesisStateContents.len == 0 and checkpointState == nil: if genesisStateContents.len == 0 and checkpointState == nil:
when hasGenesisDetection: when hasGenesisDetection:
if genesisDepositsSnapshotContents.len > 0: if depositContractSnapshotContents.len > 0:
fatal "A deposits snapshot cannot be provided without also providing a matching beacon state snapshot" fatal "A deposits snapshot cannot be provided without also providing a matching beacon state snapshot"
quit 1 quit 1
@ -224,7 +251,7 @@ proc init*(T: type BeaconNode,
cfg, cfg,
db, db,
config.web3Urls, config.web3Urls,
depositContractDeployedAt, getDepositContractSnapshot(),
eth1Network, eth1Network,
config.web3ForcePolling) config.web3ForcePolling)
@ -346,16 +373,12 @@ proc init*(T: type BeaconNode,
headStateSlot = getStateField(dag.headState.data, slot) headStateSlot = getStateField(dag.headState.data, slot)
quit 1 quit 1
if eth1Monitor.isNil and if eth1Monitor.isNil and config.web3Urls.len > 0:
config.web3Urls.len > 0 and
genesisDepositsSnapshotContents.len > 0:
let genesisDepositsSnapshot = SSZ.decode(genesisDepositsSnapshotContents,
DepositContractSnapshot)
eth1Monitor = Eth1Monitor.init( eth1Monitor = Eth1Monitor.init(
cfg, cfg,
db, db,
config.web3Urls, config.web3Urls,
genesisDepositsSnapshot, getDepositContractSnapshot(),
eth1Network, eth1Network,
config.web3ForcePolling) config.web3ForcePolling)