mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-01-11 06:46:10 +00:00
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:
parent
309f8690de
commit
5a03e7400e
@ -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 =
|
||||
|
@ -219,3 +219,5 @@ const
|
||||
"Block has incorrect fork"
|
||||
ValidatorNotActive* =
|
||||
"Validator inactive"
|
||||
BlobsOutOfRange* =
|
||||
"Requested slot is outside of blobs window"
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user