Skip to content

Commit 07d4160

Browse files
authored
Migrating the deposit contract snapshot can no longer fail on start-up (#4438)
The missing piece of data that had to be obtained previously from the configured EL client is now part of the network metadata baked into the binary.
1 parent bf50e5a commit 07d4160

File tree

10 files changed

+83
-63
lines changed

10 files changed

+83
-63
lines changed

beacon_chain/eth1/eth1_monitor.nim

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,18 +1064,33 @@ template getOrDefault[T, E](r: Result[T, E]): T =
10641064
type TT = T
10651065
get(r, default(TT))
10661066

1067-
proc init*(T: type Eth1Chain, cfg: RuntimeConfig, db: BeaconChainDB): T =
1067+
proc init*(T: type Eth1Chain,
1068+
cfg: RuntimeConfig,
1069+
db: BeaconChainDB,
1070+
depositContractBlockNumber: uint64,
1071+
depositContractBlockHash: Eth2Digest): T =
10681072
let
1069-
finalizedDeposits =
1073+
(finalizedBlockHash, depositContractState) =
10701074
if db != nil:
1071-
db.getDepositTreeSnapshot().getOrDefault()
1075+
let treeSnapshot = db.getDepositTreeSnapshot()
1076+
if treeSnapshot.isSome:
1077+
(treeSnapshot.get.eth1Block, treeSnapshot.get.depositContractState)
1078+
else:
1079+
let oldSnapshot = db.getUpgradableDepositSnapshot()
1080+
if oldSnapshot.isSome:
1081+
(oldSnapshot.get.eth1Block, oldSnapshot.get.depositContractState)
1082+
else:
1083+
db.putDepositTreeSnapshot DepositTreeSnapshot(
1084+
eth1Block: depositContractBlockHash,
1085+
blockHeight: depositContractBlockNumber)
1086+
(depositContractBlockHash, default(DepositContractState))
10721087
else:
1073-
default(DepositTreeSnapshot)
1074-
m = DepositsMerkleizer.init(finalizedDeposits.depositContractState)
1088+
(depositContractBlockHash, default(DepositContractState))
1089+
m = DepositsMerkleizer.init(depositContractState)
10751090

10761091
T(db: db,
10771092
cfg: cfg,
1078-
finalizedBlockHash: finalizedDeposits.eth1Block,
1093+
finalizedBlockHash: finalizedBlockHash,
10791094
finalizedDepositsMerkleizer: m,
10801095
headMerkleizer: copy m)
10811096

@@ -1095,7 +1110,8 @@ proc currentEpoch(m: Eth1Monitor): Epoch =
10951110

10961111
proc init*(T: type Eth1Monitor,
10971112
cfg: RuntimeConfig,
1098-
depositContractDeployedAt: BlockHashOrNumber,
1113+
depositContractBlockNumber: uint64,
1114+
depositContractBlockHash: Eth2Digest,
10991115
db: BeaconChainDB,
11001116
getBeaconTime: GetBeaconTimeFn,
11011117
web3Urls: seq[string],
@@ -1108,10 +1124,15 @@ proc init*(T: type Eth1Monitor,
11081124
for url in mitems(web3Urls):
11091125
fixupWeb3Urls url
11101126

1127+
let eth1Chain = Eth1Chain.init(
1128+
cfg, db, depositContractBlockNumber, depositContractBlockHash)
1129+
11111130
T(state: Initialized,
1112-
depositsChain: Eth1Chain.init(cfg, db),
1131+
depositsChain: eth1Chain,
11131132
depositContractAddress: cfg.DEPOSIT_CONTRACT_ADDRESS,
1114-
depositContractDeployedAt: depositContractDeployedAt,
1133+
depositContractDeployedAt: BlockHashOrNumber(
1134+
isHash: true,
1135+
hash: depositContractBlockHash),
11151136
getBeaconTime: getBeaconTime,
11161137
web3Urls: web3Urls,
11171138
eth1Network: eth1Network,
@@ -1121,37 +1142,6 @@ proc init*(T: type Eth1Monitor,
11211142
blocksPerLogsRequest: targetBlocksPerLogsRequest,
11221143
ttdReachedField: ttdReached)
11231144

1124-
proc runDbMigrations*(m: Eth1Monitor) {.async.} =
1125-
template db: auto = m.depositsChain.db
1126-
1127-
if db.hasDepositTreeSnapshot():
1128-
return
1129-
1130-
# There might be an old deposit snapshot in the database that needs upgrade.
1131-
let oldSnapshot = db.getUpgradableDepositSnapshot()
1132-
if oldSnapshot.isSome:
1133-
let
1134-
hash = oldSnapshot.get.eth1Block.asBlockHash()
1135-
blk = awaitWithRetries m.dataProvider.getBlockByHash(hash)
1136-
blockNumber = uint64(blk.number)
1137-
1138-
db.putDepositTreeSnapshot oldSnapshot.get.toDepositTreeSnapshot(blockNumber)
1139-
elif not m.depositContractAddress.isZeroMemory:
1140-
# If there is no DCS record at all, create one pointing to the deployment block
1141-
# of the deposit contract and insert it as a starting point.
1142-
let blk = try:
1143-
awaitWithRetries m.dataProvider.getBlock(m.depositContractDeployedAt)
1144-
except CatchableError as e:
1145-
fatal "Failed to fetch deployment block",
1146-
depositContract = m.depositContractAddress,
1147-
deploymentBlock = $m.depositContractDeployedAt,
1148-
err = e.msg
1149-
quit 1
1150-
doAssert blk != nil, "getBlock should not return nil"
1151-
db.putDepositTreeSnapshot DepositTreeSnapshot(
1152-
eth1Block: blk.hash.asEth2Digest,
1153-
blockHeight: uint64 blk.number)
1154-
11551145
proc safeCancel(fut: var Future[void]) =
11561146
if not fut.isNil and not fut.finished:
11571147
fut.cancel()
@@ -1483,8 +1473,6 @@ proc startEth1Syncing(m: Eth1Monitor, delayBeforeStart: Duration) {.async.} =
14831473
await m.ensureDataProvider()
14841474
doAssert m.dataProvider != nil, "close not called concurrently"
14851475

1486-
await m.runDbMigrations()
1487-
14881476
# We might need to reset the chain if the new provider disagrees
14891477
# with the previous one regarding the history of the chain or if
14901478
# we have detected a conensus violation - our view disagreeing with

beacon_chain/networking/network_metadata.nim

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ else:
1212

1313
import
1414
std/[sequtils, strutils, os],
15-
stew/byteutils, stew/shims/macros, nimcrypto/hash,
16-
eth/common/eth_types as commonEthTypes,
15+
stew/[byteutils, objects], stew/shims/macros, nimcrypto/hash,
1716
web3/[ethtypes, conversions],
1817
chronicles,
1918
eth/common/eth_types_json_serialization,
@@ -59,7 +58,8 @@ type
5958
# Parsing `enr.Records` is still not possible at compile-time
6059
bootstrapNodes*: seq[string]
6160

62-
depositContractDeployedAt*: BlockHashOrNumber
61+
depositContractBlock*: uint64
62+
depositContractBlockHash*: Eth2Digest
6363

6464
# Please note that we are using `string` here because SSZ.decode
6565
# is not currently usable at compile time and we want to load the
@@ -112,6 +112,7 @@ proc loadEth2NetworkMetadata*(path: string, eth1Network = none(Eth1Network)): Et
112112
configPath = path & "/config.yaml"
113113
deployBlockPath = path & "/deploy_block.txt"
114114
depositContractBlockPath = path & "/deposit_contract_block.txt"
115+
depositContractBlockHashPath = path & "/deposit_contract_block_hash.txt"
115116
bootstrapNodesPath = path & "/bootstrap_nodes.txt"
116117
bootEnrPath = path & "/boot_enr.yaml"
117118
runtimeConfig = if fileExists(configPath):
@@ -126,22 +127,43 @@ proc loadEth2NetworkMetadata*(path: string, eth1Network = none(Eth1Network)): Et
126127
else:
127128
defaultRuntimeConfig
128129

129-
depositContractBlock = if fileExists(depositContractBlockPath):
130+
depositContractBlockStr = if fileExists(depositContractBlockPath):
130131
readFile(depositContractBlockPath).strip
131132
else:
132133
""
133134

134-
deployBlock = if fileExists(deployBlockPath):
135+
depositContractBlockHashStr = if fileExists(depositContractBlockHashPath):
136+
readFile(depositContractBlockHashPath).strip
137+
else:
138+
""
139+
140+
deployBlockStr = if fileExists(deployBlockPath):
135141
readFile(deployBlockPath).strip
136142
else:
137143
""
138144

139-
depositContractDeployedAt = if depositContractBlock.len > 0:
140-
BlockHashOrNumber.init(depositContractBlock)
141-
elif deployBlock.len > 0:
142-
BlockHashOrNumber.init(deployBlock)
145+
depositContractBlock = if depositContractBlockStr.len > 0:
146+
parseBiggestUInt depositContractBlockStr
147+
elif deployBlockStr.len > 0:
148+
parseBiggestUInt deployBlockStr
149+
elif not runtimeConfig.DEPOSIT_CONTRACT_ADDRESS.isDefaultValue:
150+
raise newException(ValueError,
151+
"A network with deposit contract should specify the " &
152+
"deposit contract deployment block in a file named " &
153+
"deposit_contract_block.txt or deploy_block.txt")
143154
else:
144-
BlockHashOrNumber(isHash: false, number: 1)
155+
1'u64
156+
157+
depositContractBlockHash = if depositContractBlockHashStr.len > 0:
158+
Eth2Digest.strictParse(depositContractBlockHashStr)
159+
elif (not runtimeConfig.DEPOSIT_CONTRACT_ADDRESS.isDefaultValue) and
160+
depositContractBlock != 0:
161+
raise newException(ValueError,
162+
"A network with deposit contract should specify the " &
163+
"deposit contract deployment block hash in a file " &
164+
"name deposit_contract_block_hash.txt")
165+
else:
166+
default(Eth2Digest)
145167

146168
bootstrapNodes = deduplicate(
147169
readBootstrapNodes(bootstrapNodesPath) &
@@ -162,7 +184,8 @@ proc loadEth2NetworkMetadata*(path: string, eth1Network = none(Eth1Network)): Et
162184
eth1Network: eth1Network,
163185
cfg: runtimeConfig,
164186
bootstrapNodes: bootstrapNodes,
165-
depositContractDeployedAt: depositContractDeployedAt,
187+
depositContractBlock: depositContractBlock,
188+
depositContractBlockHash: depositContractBlockHash,
166189
genesisData: genesisData,
167190
genesisDepositsSnapshot: genesisDepositsSnapshot)
168191

@@ -262,7 +285,6 @@ proc getMetadataForNetwork*(
262285

263286
metadata
264287

265-
266288
proc getRuntimeConfig*(
267289
eth2Network: Option[string]): RuntimeConfig {.raises: [Defect, IOError].} =
268290
## Returns the run-time config for a network specified on the command line

beacon_chain/nimbus_beacon_node.nim

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,8 @@ proc init*(T: type BeaconNode,
477477
# that would do only this - see Paul's proposal for this.
478478
let eth1Monitor = Eth1Monitor.init(
479479
cfg,
480-
metadata.depositContractDeployedAt,
480+
metadata.depositContractBlock,
481+
metadata.depositContractBlockHash,
481482
db,
482483
nil,
483484
config.web3Urls,
@@ -573,7 +574,8 @@ proc init*(T: type BeaconNode,
573574
if eth1Monitor.isNil and config.web3Urls.len > 0:
574575
eth1Monitor = Eth1Monitor.init(
575576
cfg,
576-
metadata.depositContractDeployedAt,
577+
metadata.depositContractBlock,
578+
metadata.depositContractBlockHash,
577579
db,
578580
getBeaconTime,
579581
config.web3Urls,

beacon_chain/nimbus_light_client.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ programMain:
9191
if config.web3Urls.len > 0:
9292
let res = Eth1Monitor.init(
9393
cfg,
94-
metadata.depositContractDeployedAt,
94+
metadata.depositContractBlock,
95+
metadata.depositContractBlockHash,
9596
db = nil,
9697
getBeaconTime,
9798
config.web3Urls,

beacon_chain/spec/digest.nim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,13 @@ proc readValue*(r: var JsonReader, a: var Eth2Digest) {.raises: [Defect, IOError
154154
except ValueError:
155155
raiseUnexpectedValue(r, "Hex string expected")
156156

157+
func strictParse*(T: type Eth2Digest, hexStr: openArray[char]): T
158+
{.raises: [Defect, ValueError].} =
159+
## TODO We use this local definition because the string parsing functions
160+
## provided by nimcrypto are currently too lax in their requirements
161+
## for the input string. Invalid strings are silently ignored.
162+
hexToByteArrayStrict(hexStr, result.data)
163+
157164
func toGaugeValue*(hash: Eth2Digest): int64 =
158165
# Only the last 8 bytes are taken into consideration in accordance
159166
# to the ETH2 metrics spec:

beacon_chain/spec/presets.nim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ when const_preset == "mainnet":
202202
# Ethereum PoW Mainnet
203203
DEPOSIT_CHAIN_ID: 1,
204204
DEPOSIT_NETWORK_ID: 1,
205-
DEPOSIT_CONTRACT_ADDRESS: Eth1Address.fromHex("0x00000000219ab540356cBB839Cbe05303d7705Fa")
205+
DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address)
206206
)
207207

208208
elif const_preset == "minimal":
@@ -307,7 +307,7 @@ elif const_preset == "minimal":
307307
DEPOSIT_CHAIN_ID: 5,
308308
DEPOSIT_NETWORK_ID: 5,
309309
# Configured on a per testnet basis
310-
DEPOSIT_CONTRACT_ADDRESS: Eth1Address.fromHex("0x1234567890123456789012345678901234567890")
310+
DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address)
311311
)
312312

313313
else:

research/block_sim.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
326326
var
327327
validatorMonitor = newClone(ValidatorMonitor.init())
328328
dag = ChainDAGRef.init(cfg, db, validatorMonitor, {})
329-
eth1Chain = Eth1Chain.init(cfg, db)
329+
eth1Chain = Eth1Chain.init(cfg, db, 0, default Eth2Digest)
330330
merkleizer = DepositsMerkleizer.init(depositTreeSnapshot.depositContractState)
331331
taskpool = Taskpool.new()
332332
verifier = BatchVerifier(rng: keys.newRng(), taskpool: taskpool)

vendor/merge-testnets

Submodule merge-testnets updated 147 files

vendor/nim-stew

0 commit comments

Comments
 (0)