Skip to content

Commit 4580bc2

Browse files
committed
txs, receipts and logs
1 parent 379b4ff commit 4580bc2

File tree

2 files changed

+171
-3
lines changed

2 files changed

+171
-3
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import
2+
stint,
3+
results,
4+
eth/common/eth_types_rlp,
5+
eth/trie/[ordered_trie, trie_defs],
6+
json_rpc/[rpcproxy, rpcserver, rpcclient],
7+
web3/[eth_api_types, eth_api],
8+
../../execution_chain/beacon/web3_eth_conv,
9+
../types,
10+
./blocks
11+
12+
template toLog(lg: LogObject): Log =
13+
Log(address: lg.address, topics: lg.topics, data: lg.data)
14+
15+
func toLogs(logs: openArray[LogObject]): seq[Log] =
16+
result = newSeqOfCap[Log](logs.len)
17+
for lg in logs:
18+
result.add(toLog(lg))
19+
20+
func toReceipt(rec: ReceiptObject): Receipt =
21+
let isHash = if rec.status.isSome: false else: true
22+
23+
var status = false
24+
if rec.status.isSome:
25+
if rec.status.get() == 1.Quantity:
26+
status = true
27+
28+
return Receipt(
29+
hash: rec.transactionHash,
30+
isHash: isHash,
31+
status: status,
32+
cumulativeGasUsed: rec.cumulativeGasUsed.GasInt,
33+
logs: toLogs(rec.logs),
34+
logsBloom: rec.logsBloom,
35+
receiptType: rec.`type`.get(0.Web3Quantity).ReceiptType,
36+
)
37+
38+
func toReceipts(recs: openArray[ReceiptObject]): seq[Receipt] =
39+
for r in recs:
40+
result.add(toReceipt(r))
41+
42+
proc getReceipts*(
43+
vp: VerifiedRpcProxy, blockTag: BlockTag
44+
): Future[Result[seq[ReceiptObject], string]] {.async.} =
45+
let
46+
header = (await vp.getHeader(blockTag)).valueOr:
47+
return err(error)
48+
rxs =
49+
try:
50+
await vp.rpcClient.eth_getBlockReceipts(blockTag)
51+
except CatchableError as e:
52+
return err(e.msg)
53+
54+
if rxs.isSome():
55+
if orderedTrieRoot(toReceipts(rxs.get())) != header.receiptsRoot:
56+
return
57+
err("downloaded receipts do not evaluate to the receipts root of the block")
58+
else:
59+
return err("error downloading the receipts")
60+
61+
return ok(rxs.get())
62+
63+
proc getReceipts*(
64+
vp: VerifiedRpcProxy, blockHash: Hash32
65+
): Future[Result[seq[ReceiptObject], string]] {.async.} =
66+
let
67+
header = (await vp.getHeader(blockHash)).valueOr:
68+
return err(error)
69+
blockTag =
70+
BlockTag(RtBlockIdentifier(kind: bidNumber, number: Quantity(header.number)))
71+
rxs =
72+
try:
73+
await vp.rpcClient.eth_getBlockReceipts(blockTag)
74+
except CatchableError as e:
75+
return err(e.msg)
76+
77+
if rxs.isSome():
78+
if orderedTrieRoot(toReceipts(rxs.get())) != header.receiptsRoot:
79+
return
80+
err("downloaded receipts do not evaluate to the receipts root of the block")
81+
else:
82+
return err("error downloading the receipts")
83+
84+
return ok(rxs.get())
85+
86+
proc getLogs*(
87+
vp: VerifiedRpcProxy, filterOptions: FilterOptions
88+
): Future[Result[seq[LogObject], string]] {.async.} =
89+
let logObjs =
90+
try:
91+
await vp.rpcClient.eth_getLogs(filterOptions)
92+
except CatchableError as e:
93+
return err(e.msg)
94+
95+
var res = newSeq[LogObject]()
96+
97+
# store block hashes contains the logs so that we can batch receipt requests
98+
for lg in logObjs:
99+
if lg.blockHash.isSome():
100+
let lgBlkHash = lg.blockHash.get()
101+
# TODO: a cache will solve downloading the same block receipts for multiple logs
102+
var rxs = (await vp.getReceipts(lgBlkHash)).valueOr:
103+
return err(error)
104+
105+
if lg.transactionIndex.isNone():
106+
for rx in rxs:
107+
for rxLog in rx.logs:
108+
# only add verified logs
109+
if rxLog.address == lg.address and rxLog.data == lg.data and
110+
rxLog.topics == lg.topics:
111+
res.add(lg)
112+
else:
113+
let
114+
txIdx = lg.transactionIndex.get()
115+
rx = rxs[distinctBase(txIdx)]
116+
117+
# only add verified logs
118+
for rxLog in rx.logs:
119+
if rxLog.address == lg.address and rxLog.data == lg.data and rxLog.topics == lg.topics:
120+
res.add(lg)
121+
122+
if res.len == 0:
123+
return err("no logs could be verified")
124+
125+
return ok(res)

nimbus_verified_proxy/rpc/rpc_eth_api.nim

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import
1616
../types,
1717
../header_store,
1818
./accounts,
19-
./blocks
19+
./blocks,
20+
./transactions,
21+
./receipts
2022

2123
logScope:
2224
topics = "verified_proxy"
@@ -138,13 +140,54 @@ proc installEthApiHandlers*(vp: VerifiedRpcProxy) =
138140

139141
x.tx
140142

143+
vp.proxy.rpc("eth_getTransactionByHash") do(txHash: Hash32) -> TransactionObject:
144+
let tx =
145+
try:
146+
await vp.rpcClient.eth_getTransactionByHash(txHash)
147+
except CatchableError as e:
148+
raise newException(ValueError, e.msg)
149+
if tx.hash != txHash:
150+
raise newException(
151+
ValueError,
152+
"the downloaded transaction hash doesn't match the requested transaction hash",
153+
)
154+
155+
if not checkTxHash(tx, txHash):
156+
raise
157+
newException(ValueError, "the transaction doesn't hash to the provided hash")
158+
159+
return tx
160+
161+
vp.proxy.rpc("eth_getBlockReceipts") do(blockTag: BlockTag) -> Opt[seq[ReceiptObject]]:
162+
let rxs = (await vp.getReceipts(blockTag)).valueOr:
163+
raise newException(ValueError, error)
164+
return Opt.some(rxs)
165+
166+
vp.proxy.rpc("eth_getTransactionReceipt") do(txHash: Hash32) -> ReceiptObject:
167+
let
168+
rx =
169+
try:
170+
await vp.rpcClient.eth_getTransactionReceipt(txHash)
171+
except CatchableError as e:
172+
raise newException(ValueError, e.msg)
173+
rxs = (await vp.getReceipts(rx.blockHash)).valueOr:
174+
raise newException(ValueError, error)
175+
176+
for r in rxs:
177+
if r.transactionHash == txHash:
178+
return r
179+
180+
raise newException(ValueError, "receipt couldn't be verified")
181+
182+
vp.proxy.rpc("eth_getLogs") do(filterOptions: FilterOptions) -> seq[LogObject]:
183+
(await vp.getLogs(filterOptions)).valueOr:
184+
raise newException(ValueError, error)
185+
141186
# TODO:
142187
# Following methods are forwarded directly to the web3 provider and therefore
143188
# are not validated in any way.
144189
vp.proxy.registerProxyMethod("net_version")
145-
vp.proxy.registerProxyMethod("eth_call")
146190
vp.proxy.registerProxyMethod("eth_sendRawTransaction")
147-
vp.proxy.registerProxyMethod("eth_getTransactionReceipt")
148191

149192
# Used to be in eth1_monitor.nim; not sure why it was deleted,
150193
# so I copied it here. --Adam

0 commit comments

Comments
 (0)