Skip to content

Commit c3599d8

Browse files
committed
better error handling
1 parent 7d71cfe commit c3599d8

19 files changed

+575
-519
lines changed

nimbus_verified_proxy/engine/accounts.nim

Lines changed: 59 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ proc getAccountFromProof*(
2828
accountCodeHash: Hash32,
2929
accountStorageRoot: Hash32,
3030
mptNodes: seq[RlpEncodedBytes],
31-
): Result[Account, string] =
31+
): Account {.raises: [VerificationError].} =
3232
let
3333
mptNodesBytes = mptNodes.mapIt(distinctBase(it))
3434
acc = Account(
@@ -44,15 +44,15 @@ proc getAccountFromProof*(
4444

4545
case proofResult.kind
4646
of MissingKey:
47-
return ok(EMPTY_ACCOUNT)
47+
return EMPTY_ACCOUNT
4848
of ValidProof:
49-
return ok(acc)
49+
return acc
5050
of InvalidProof:
51-
return err(proofResult.errorMsg)
51+
raise newException(VerificationError, proofResult.errorMsg)
5252

5353
proc getStorageFromProof(
5454
account: Account, storageProof: StorageProof
55-
): Result[UInt256, string] =
55+
): UInt256 {.raises: [VerificationError].} =
5656
let
5757
storageMptNodes = storageProof.proof.mapIt(distinctBase(it))
5858
key = toSeq(keccak256(toBytesBE(storageProof.key)).data)
@@ -62,39 +62,41 @@ proc getStorageFromProof(
6262

6363
case proofResult.kind
6464
of MissingKey:
65-
return ok(UInt256.zero)
65+
return UInt256.zero
6666
of ValidProof:
67-
return ok(storageProof.value)
67+
return storageProof.value
6868
of InvalidProof:
69-
return err(proofResult.errorMsg)
69+
raise newException(VerificationError, proofResult.errorMsg)
7070

7171
proc getStorageFromProof*(
7272
stateRoot: Hash32,
7373
requestedSlot: UInt256,
7474
proof: ProofResponse,
7575
storageProofIndex = 0,
76-
): Result[UInt256, string] =
77-
let account =
78-
?getAccountFromProof(
79-
stateRoot, proof.address, proof.balance, proof.nonce, proof.codeHash,
80-
proof.storageHash, proof.accountProof,
81-
)
76+
): UInt256 {.raises: [VerificationError].} =
77+
let account = getAccountFromProof(
78+
stateRoot, proof.address, proof.balance, proof.nonce, proof.codeHash,
79+
proof.storageHash, proof.accountProof,
80+
)
8281

8382
if account.storageRoot == EMPTY_ROOT_HASH:
8483
# valid account with empty storage, in that case getStorageAt
8584
# return 0 value
86-
return ok(u256(0))
85+
return u256(0)
8786

8887
if proof.storageProof.len() <= storageProofIndex:
89-
return err("no storage proof for requested slot")
88+
# this is not an UnavailableDataError because the unavailable data is in the proof
89+
raise newException(VerificationError, "no storage proof for requested slot")
9090

9191
let storageProof = proof.storageProof[storageProofIndex]
9292

9393
if len(storageProof.proof) == 0:
94-
return err("empty mpt proof for account with not empty storage")
94+
raise newException(
95+
VerificationError, "empty mpt proof for account with not empty storage"
96+
)
9597

9698
if storageProof.key != requestedSlot:
97-
return err("received proof for invalid slot")
99+
raise newException(VerificationError, "received proof for invalid slot")
98100

99101
getStorageFromProof(account, storageProof)
100102

@@ -103,29 +105,29 @@ proc getAccount*(
103105
address: Address,
104106
blockNumber: base.BlockNumber,
105107
stateRoot: Root,
106-
): Future[Result[Account, string]] {.async: (raises: []).} =
108+
): Future[Account] {.async: (raises: [CancelledError, EngineError]).} =
107109
let
108110
cacheKey = (stateRoot, address)
109111
cachedAcc = engine.accountsCache.get(cacheKey)
110112
if cachedAcc.isSome():
111-
return ok(cachedAcc.get())
113+
return cachedAcc.get()
112114

113115
info "Forwarding eth_getAccount", blockNumber
114116

115117
let
116118
proof =
117119
try:
118120
await engine.backend.eth_getProof(address, @[], blockId(blockNumber))
119-
except CatchableError as e:
120-
return err(e.msg)
121+
except EthBackendError as e:
122+
e.msg = "getProof failed for account: " & e.msg
123+
raise e
121124

122125
account = getAccountFromProof(
123126
stateRoot, proof.address, proof.balance, proof.nonce, proof.codeHash,
124127
proof.storageHash, proof.accountProof,
125128
)
126129

127-
if account.isOk():
128-
engine.accountsCache.put(cacheKey, account.get())
130+
engine.accountsCache.put(cacheKey, account)
129131

130132
return account
131133

@@ -134,63 +136,65 @@ proc getCode*(
134136
address: Address,
135137
blockNumber: base.BlockNumber,
136138
stateRoot: Root,
137-
): Future[Result[seq[byte], string]] {.async: (raises: []).} =
139+
): Future[seq[byte]] {.async: (raises: [CancelledError, EngineError]).} =
138140
# get verified account details for the address at blockNumber
139-
let account = (await engine.getAccount(address, blockNumber, stateRoot)).valueOr:
140-
return err(error)
141+
let account = await engine.getAccount(address, blockNumber, stateRoot)
141142

142143
# if the account does not have any code, return empty hex data
143144
if account.codeHash == EMPTY_CODE_HASH:
144-
return ok(newSeq[byte]())
145+
return newSeq[byte]()
145146

146147
let
147148
cacheKey = (stateRoot, address)
148149
cachedCode = engine.codeCache.get(cacheKey)
149150
if cachedCode.isSome():
150-
return ok(cachedCode.get())
151+
return cachedCode.get()
151152

152153
info "Forwarding eth_getCode", blockNumber
153154

154155
let code =
155156
try:
156157
await engine.backend.eth_getCode(address, blockId(blockNumber))
157-
except CatchableError as e:
158-
return err(e.msg)
158+
except EthBackendError as e:
159+
e.msg = "Code fetch failed: " & e.msg
160+
raise e
159161

160162
# verify the byte code. since we verified the account against
161163
# the state root we just need to verify the code hash
162164
if account.codeHash == keccak256(code):
163165
engine.codeCache.put(cacheKey, code)
164-
return ok(code)
166+
return code
165167
else:
166-
return err("received code doesn't match the account code hash")
168+
raise newException(
169+
VerificationError, "received code doesn't match the account code hash"
170+
)
167171

168172
proc getStorageAt*(
169173
engine: RpcVerificationEngine,
170174
address: Address,
171175
slot: UInt256,
172176
blockNumber: base.BlockNumber,
173177
stateRoot: Root,
174-
): Future[Result[UInt256, string]] {.async: (raises: []).} =
178+
): Future[UInt256] {.async: (raises: [CancelledError, EngineError]).} =
175179
let
176180
cacheKey = (stateRoot, address, slot)
177181
cachedSlotValue = engine.storageCache.get(cacheKey)
178182
if cachedSlotValue.isSome():
179-
return ok(cachedSlotValue.get())
183+
return cachedSlotValue.get()
180184

181185
info "Forwarding eth_getStorageAt", blockNumber
182186

183187
let
184188
proof =
185189
try:
186190
await engine.backend.eth_getProof(address, @[slot], blockId(blockNumber))
187-
except CatchableError as e:
188-
return err(e.msg)
191+
except EthBackendError as e:
192+
e.msg = "getProof failed for account: " & e.msg
193+
raise e
189194

190195
slotValue = getStorageFromProof(stateRoot, slot, proof)
191196

192-
if slotValue.isOk():
193-
engine.storageCache.put(cacheKey, slotValue.get())
197+
engine.storageCache.put(cacheKey, slotValue)
194198

195199
return slotValue
196200

@@ -200,7 +204,7 @@ proc populateCachesForAccountAndSlots(
200204
slots: seq[UInt256],
201205
blockNumber: base.BlockNumber,
202206
stateRoot: Root,
203-
): Future[Result[void, string]] {.async: (raises: []).} =
207+
) {.async: (raises: [CancelledError, EngineError]).} =
204208
var slotsToFetch: seq[UInt256]
205209
for s in slots:
206210
let storageCacheKey = (stateRoot, address, s)
@@ -214,47 +218,42 @@ proc populateCachesForAccountAndSlots(
214218
proof =
215219
try:
216220
await engine.backend.eth_getProof(address, slotsToFetch, blockId(blockNumber))
217-
except CatchableError as e:
218-
return err(e.msg)
221+
except EthBackendError as e:
222+
e.msg = "getProof failed for populating accounts and slots cache: " & e.msg
223+
raise e
224+
219225
account = getAccountFromProof(
220226
stateRoot, proof.address, proof.balance, proof.nonce, proof.codeHash,
221227
proof.storageHash, proof.accountProof,
222228
)
223229

224-
if account.isOk():
225-
engine.accountsCache.put(accountCacheKey, account.get())
230+
engine.accountsCache.put(accountCacheKey, account)
226231

227232
for i, s in slotsToFetch:
228-
let slotValue = getStorageFromProof(stateRoot, s, proof, i)
233+
let
234+
slotValue = getStorageFromProof(stateRoot, s, proof, i)
235+
storageCacheKey = (stateRoot, address, s)
229236

230-
if slotValue.isOk():
231-
let storageCacheKey = (stateRoot, address, s)
232-
engine.storageCache.put(storageCacheKey, slotValue.get())
233-
234-
ok()
237+
engine.storageCache.put(storageCacheKey, slotValue)
235238

236239
proc populateCachesUsingAccessList*(
237240
engine: RpcVerificationEngine,
238241
blockNumber: base.BlockNumber,
239242
stateRoot: Root,
240243
tx: TransactionArgs,
241-
): Future[Result[void, string]] {.async: (raises: []).} =
244+
) {.async: (raises: [CancelledError, EngineError]).} =
242245
let accessListRes: AccessListResult =
243246
try:
244247
await engine.backend.eth_createAccessList(tx, blockId(blockNumber))
245-
except CatchableError as e:
246-
return err(e.msg)
248+
except EthBackendError as e:
249+
e.msg = "AccessList fetch failed for populating cache: " & e.msg
250+
raise e
247251

248-
var futs = newSeqOfCap[Future[Result[void, string]]](accessListRes.accessList.len())
252+
var futs = newSeqOfCap[Future[void]](accessListRes.accessList.len())
249253
for accessPair in accessListRes.accessList:
250254
let slots = accessPair.storageKeys.mapIt(UInt256.fromBytesBE(it.data))
251255
futs.add engine.populateCachesForAccountAndSlots(
252256
accessPair.address, slots, blockNumber, stateRoot
253257
)
254258

255-
try:
256-
await allFutures(futs)
257-
except CatchableError as e:
258-
return err(e.msg)
259-
260-
ok()
259+
await allFutures(futs)

0 commit comments

Comments
 (0)