Skip to content

Commit d28454f

Browse files
committed
Add getHeader callback for finalized history network
1 parent 5057fc1 commit d28454f

File tree

3 files changed

+49
-24
lines changed

3 files changed

+49
-24
lines changed

portal/network/finalized_history/content/content_keys.nim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ func receiptsContentKey*(blockNumber: uint64): ContentKey =
4646
contentType: receipts, receiptsKey: BlockNumberKey(blockNumber: blockNumber)
4747
)
4848

49+
template blockNumber*(contentKey: ContentKey): uint64 =
50+
## Returns the block number for the given content key
51+
case contentKey.contentType
52+
of unused:
53+
raiseAssert "ContentKey may not have unused value as content type"
54+
of blockBody:
55+
contentKey.blockBodyKey.blockNumber
56+
of receipts:
57+
contentKey.receiptsKey.blockNumber
58+
4959
proc readSszBytes*(data: openArray[byte], val: var ContentKey) {.raises: [SszError].} =
5060
mixin readSszValue
5161
if data.len() > 0 and data[0] == ord(unused):

portal/network/finalized_history/finalized_history_network.nim

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,29 @@ logScope:
2929

3030
const pingExtensionCapabilities = {CapabilitiesType, HistoryRadiusType}
3131

32-
type FinalizedHistoryNetwork* = ref object
33-
portalProtocol*: PortalProtocol
34-
contentDB*: ContentDB
35-
contentQueue*: AsyncQueue[(Opt[NodeId], ContentKeysList, seq[seq[byte]])]
36-
# cfg*: RuntimeConfig
37-
processContentLoops: seq[Future[void]]
38-
statusLogLoop: Future[void]
39-
contentRequestRetries: int
40-
contentQueueWorkers: int
32+
type
33+
GetHeaderCallback* = proc(blockNumber: uint64): Future[Result[Header, string]] {.
34+
async: (raises: [CancelledError]), gcsafe
35+
.}
36+
37+
FinalizedHistoryNetwork* = ref object
38+
portalProtocol*: PortalProtocol
39+
contentDB*: ContentDB
40+
contentQueue*: AsyncQueue[(Opt[NodeId], ContentKeysList, seq[seq[byte]])]
41+
getHeader*: GetHeaderCallback
42+
# cfg*: RuntimeConfig
43+
processContentLoops: seq[Future[void]]
44+
statusLogLoop: Future[void]
45+
contentRequestRetries: int
46+
contentQueueWorkers: int
47+
48+
proc defaultNoGetHeader(
49+
blockNumber: uint64
50+
): Future[Result[Header, string]] {.async: (raises: [CancelledError]), gcsafe.} =
51+
err(
52+
"No getHeader callback set for PortalNode, cannot verify offered content for block: " &
53+
$blockNumber
54+
)
4155

4256
func toContentIdHandler(contentKey: ContentKeyByteList): results.Opt[ContentId] =
4357
toContentId(contentKey)
@@ -48,6 +62,7 @@ proc new*(
4862
baseProtocol: protocol.Protocol,
4963
contentDB: ContentDB,
5064
streamManager: StreamManager,
65+
getHeaderCallback: GetHeaderCallback = defaultNoGetHeader,
5166
# cfg: RuntimeConfig,
5267
bootstrapRecords: openArray[Record] = [],
5368
portalConfig: PortalProtocolConfig = defaultPortalProtocolConfig,
@@ -79,6 +94,7 @@ proc new*(
7994
portalProtocol: portalProtocol,
8095
contentDB: contentDB,
8196
contentQueue: contentQueue,
97+
getHeader: getHeaderCallback,
8298
# cfg: cfg,
8399
contentRequestRetries: contentRequestRetries,
84100
contentQueueWorkers: contentQueueWorkers,
@@ -90,6 +106,12 @@ proc getContent*(
90106
V: type ContentValueType,
91107
header: Header,
92108
): Future[Opt[V]] {.async: (raises: [CancelledError]).} =
109+
## Get the decoded content for the given content key.
110+
##
111+
## When the content is found locally, no validation is performed.
112+
## Else, the content is fetched from the network and validated with the provided header.
113+
## If content validation fails, the node is banned for a certain period of time and
114+
## content request is retried `contentRequestRetries` times.
93115
let contentKeyBytes = encode(contentKey)
94116

95117
logScope:
@@ -146,29 +168,21 @@ proc validateContent(
146168
let contentKey = finalized_history_content.decode(contentKeyBytes).valueOr:
147169
return err("Error decoding content key")
148170

171+
let header = ?(await n.getHeader(contentKey.blockNumber()))
172+
149173
case contentKey.contentType
150174
of unused:
151175
raiseAssert("ContentKey contentType: unused")
152176
of blockBody:
153-
let
154-
# TODO: Need to get the header (or just tx root/uncle root/withdrawals root) from the EL client via
155-
# JSON-RPC.
156-
# OR if directly integrated the EL client, we can just pass the header here.
157-
header = Header()
158-
blockBody = decodeRlp(content, BlockBody).valueOr:
159-
return err("Error decoding block body: " & error)
177+
let blockBody = decodeRlp(content, BlockBody).valueOr:
178+
return err("Error decoding block body: " & error)
160179
validateBlockBody(blockBody, header).isOkOr:
161180
return err("Failed validating block body: " & error)
162181

163182
ok()
164183
of receipts:
165-
let
166-
# TODO: Need to get the header (or just tx root/uncle root/withdrawals root) from the EL client via
167-
# JSON-RPC.
168-
# OR if directly integrated the EL client, we can just pass the header here.
169-
header = Header()
170-
receipts = decodeRlp(content, seq[Receipt]).valueOr:
171-
return err("Error decoding receipts: " & error)
184+
let receipts = decodeRlp(content, seq[Receipt]).valueOr:
185+
return err("Error decoding receipts: " & error)
172186
validateReceipts(receipts, header).isOkOr:
173187
return err("Failed validating receipts: " & error)
174188

portal/network/finalized_history/finalized_history_validation.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
{.push raises: [].}
99

1010
import
11-
std/typetraits,
1211
eth/trie/ordered_trie,
1312
eth/common/[headers_rlp, blocks_rlp, receipts, hashes],
1413
./finalized_history_content
@@ -49,6 +48,7 @@ func validateBlockBody*(body: BlockBody, header: Header): Result[void, string] =
4948
ok()
5049

5150
func validateReceipts*(receipts: Receipts, header: Header): Result[void, string] =
51+
## Validate the receipts against the receiptsRoot from the header.
5252
let calculatedReceiptsRoot = orderedTrieRoot(receipts)
5353
if calculatedReceiptsRoot != header.receiptsRoot:
5454
err(
@@ -70,6 +70,7 @@ func validateContent*(
7070
func validateContent*(
7171
key: ContentKey, contentBytes: seq[byte], header: Header
7272
): Result[void, string] =
73+
## Validate the encoded content against the header.
7374
case key.contentType
7475
of unused:
7576
raiseAssert("ContentKey contentType: unused")

0 commit comments

Comments
 (0)