Skip to content

Commit

Permalink
fix: response checking from RequestManager for blobs (#6755)
Browse files Browse the repository at this point in the history
* rewrite: response checking from RequestManager for blobs

* clean whitespace

* use a comparator and std instead

* sort incoming blobs by index

* fix list traversal

---------

Co-authored-by: tersec <[email protected]>
  • Loading branch information
agnxsh and tersec authored Dec 12, 2024
1 parent 031d24f commit 98a7f44
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 13 deletions.
2 changes: 1 addition & 1 deletion beacon_chain/spec/helpers.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# Uncategorized helper functions from the spec

import
std/sequtils,
# Status libraries
stew/[byteutils, endians2, objects],
nimcrypto/sha2,
Expand Down Expand Up @@ -542,7 +543,6 @@ proc compute_execution_block_hash*(blck: ForkyBeaconBlock): Eth2Digest =
rlpHash(blockToBlockHeader(blck)).to(Eth2Digest)

from std/math import exp, ln
from std/sequtils import foldl

func ln_binomial(n, k: int): float64 =
if k > n:
Expand Down
40 changes: 28 additions & 12 deletions beacon_chain/sync/request_manager.nim
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import
"."/sync_protocol, "."/sync_manager,
../gossip_processing/block_processor

from std/algorithm import binarySearch, sort
from ../beacon_clock import GetBeaconTimeFn
export block_quarantine, sync_manager

Expand Down Expand Up @@ -102,21 +103,32 @@ proc checkResponse(roots: openArray[Eth2Digest],
checks.del(res)
true

func cmpSidecarIdentifier(x: BlobIdentifier | DataColumnIdentifier,
y: ref BlobSidecar | ref DataColumnSidecar): int =
cmp(x.index, y.index)

proc checkResponse(idList: seq[BlobIdentifier],
blobs: openArray[ref BlobSidecar]): bool =
if len(blobs) > len(idList):
if blobs.len > idList.len:
return false
for blob in blobs:
let block_root = hash_tree_root(blob.signed_block_header.message)
var found = false
for id in idList:
if id.block_root == block_root and id.index == blob.index:
found = true
break
if not found:
var i = 0
while i < blobs.len:
let
block_root = hash_tree_root(blobs[i].signed_block_header.message)
id = idList[i]

# Check if the blob response is a subset
if binarySearch(idList, blobs[i], cmpSidecarIdentifier) == -1:
return false
blob[].verify_blob_sidecar_inclusion_proof().isOkOr:

# Verify block_root and index match
if id.block_root != block_root or id.index != blobs[i].index:
return false

# Verify inclusion proof
blobs[i][].verify_blob_sidecar_inclusion_proof().isOkOr:
return false
inc i
true

proc requestBlocksByRoot(rman: RequestManager, items: seq[Eth2Digest]) {.async: (raises: [CancelledError]).} =
Expand Down Expand Up @@ -190,6 +202,9 @@ proc requestBlocksByRoot(rman: RequestManager, items: seq[Eth2Digest]) {.async:
if not(isNil(peer)):
rman.network.peerPool.release(peer)

func cmpBlobIndexes(x, y: ref BlobSidecar): int =
cmp(x.index, y.index)

proc fetchBlobsFromNetwork(self: RequestManager,
idList: seq[BlobIdentifier])
{.async: (raises: [CancelledError]).} =
Expand All @@ -203,8 +218,9 @@ proc fetchBlobsFromNetwork(self: RequestManager,
let blobs = await blobSidecarsByRoot(peer, BlobIdentifierList idList)

if blobs.isOk:
let ublobs = blobs.get()
if not checkResponse(idList, ublobs.asSeq()):
var ublobs = blobs.get().asSeq()
ublobs.sort(cmpBlobIndexes)
if not checkResponse(idList, ublobs):
debug "Mismatched response to blobs by root",
peer = peer, blobs = shortLog(idList), ublobs = len(ublobs)
peer.updateScore(PeerScoreBadResponse)
Expand Down

0 comments on commit 98a7f44

Please sign in to comment.