Blobs sidecars by range (#4464)

* Add blobs_sidecars_by_range RPC

* Update beacon_chain/spec/datatypes/eip4844.nim

Co-authored-by: tersec <tersec@users.noreply.github.com>

Co-authored-by: tersec <tersec@users.noreply.github.com>
This commit is contained in:
henridf 2023-01-12 13:33:24 +01:00 committed by GitHub
parent 309f8690de
commit 5a03e7400e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 1 deletions

View File

@ -1050,6 +1050,13 @@ proc getBlockSSZ*(
getBlockSSZ(db, key, data, eip4844.TrustedSignedBeaconBlock)
proc getBlobsSidecarSZ*(db: BeaconChainDB, key: Eth2Digest, data: var seq[byte]):
bool =
let dataPtr = addr data # Short-lived
func decode(data: openArray[byte]) =
assign(dataPtr[], data)
db.blobs.get(key.data, decode).expectDb()
proc getBlockSZ*(
db: BeaconChainDB, key: Eth2Digest, data: var seq[byte],
T: type phase0.TrustedSignedBeaconBlock): bool =

View File

@ -219,3 +219,5 @@ const
"Block has incorrect fork"
ValidatorNotActive* =
"Validator inactive"
BlobsOutOfRange* =
"Requested slot is outside of blobs window"

View File

@ -35,6 +35,8 @@ const
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.2/specs/eip4844/polynomial-commitments.md#constants
BLS_MODULUS* = "52435875175126190479447740508185965837690552500527637822603658699938581184513".u256
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-rc.0/specs/eip4844/p2p-interface.md#configuration
MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS* = 4096'u64
type
# this block belongs elsewhere - will figure out after implementing c-kzg bindings

View File

@ -14,7 +14,7 @@ import
std/[options, tables, sets, macros],
chronicles, chronos, snappy/codec,
libp2p/switch,
../spec/datatypes/[phase0, altair, bellatrix, capella],
../spec/datatypes/[phase0, altair, bellatrix, capella, eip4844],
../spec/[helpers, forks, network],
".."/[beacon_clock],
../networking/eth2_network,
@ -26,6 +26,7 @@ logScope:
const
MAX_REQUEST_BLOCKS* = 1024
MAX_REQUEST_BLOBS_SIDECARS = 128
blockResponseCost = allowedOpsPerSecondCost(64) # Allow syncing ~64 blocks/sec (minus request costs)
@ -400,6 +401,77 @@ p2pProtocol BeaconSync(version = 1,
debug "Block root request done",
peer, roots = blockRoots.len, count, found
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-rc.0/specs/eip4844/p2p-interface.md#blobssidecarsbyrange-v1
proc blobsSidecarsByRange(
peer: Peer,
startSlot: Slot,
reqCount: uint64,
response: MultipleChunksResponse[
BlobsSidecar, MAX_REQUEST_BLOBS_SIDECARS])
{.async, libp2pProtocol("blobs_sidecars_by_range", 1).} =
# TODO This code is more complicated than it needs to be, since the type
# of the multiple chunks response is not actually used in this server
# implementation (it's used to derive the signature of the client
# function, not in the code below!)
# TODO although you can't tell from this function definition, a magic
# client call that returns `seq[ref BlobsSidecar]` will
# will be generated by the libp2p macro - we guarantee that seq items
# are `not-nil` in the implementation
trace "got blobs range request", peer, startSlot, count = reqCount
if reqCount == 0:
raise newException(InvalidInputsError, "Empty range requested")
let
dag = peer.networkState.dag
epochBoundary =
if MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS >= dag.head.slot.epoch:
GENESIS_EPOCH
else:
dag.head.slot.epoch - MIN_EPOCHS_FOR_BLOBS_SIDECARS_REQUESTS
if startSlot.epoch < epochBoundary:
raise newException(ResourceUnavailableError, BlobsOutOfRange)
var blockIds: array[MAX_REQUEST_BLOBS_SIDECARS, BlockId]
let
# Limit number of blocks in response
count = int min(reqCount, blockIds.lenu64)
endIndex = count - 1
startIndex =
dag.getBlockRange(startSlot, 1, blockIds.toOpenArray(0, endIndex))
var
found = 0
bytes: seq[byte]
for i in startIndex..endIndex:
if dag.db.getBlobsSidecarSZ(blockIds[i].root, bytes):
# In general, there is not much intermediate time between post-merge
# blocks all being optimistic and none of them being optimistic. The
# EL catches up, tells the CL the head is verified, and that's it.
if blockIds[i].slot.epoch >= dag.cfg.BELLATRIX_FORK_EPOCH and
dag.is_optimistic(dag.head.root):
continue
let uncompressedLen = uncompressedLenFramed(bytes).valueOr:
warn "Cannot read blobs sidecar size, database corrupt?",
bytes = bytes.len(), blck = shortLog(blockIds[i])
continue
# TODO extract from libp2pProtocol
peer.awaitQuota(blockResponseCost, "blobs_sidecars_by_range/1")
peer.network.awaitQuota(blockResponseCost, "blobs_sidecars_by_range/1")
await response.writeBytesSZ(
uncompressedLen, bytes,
peer.networkState.forkDigestAtEpoch(blockIds[i].slot.epoch).data)
inc found
debug "BlobsSidecar range request done",
peer, startSlot, count
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-rc.0/specs/altair/light-client/p2p-interface.md#getlightclientbootstrap
proc lightClientBootstrap(
peer: Peer,