implement blob_sidecar Beacon API streaming (#5728)
This commit is contained in:
parent
a45609c4a3
commit
69af8f943e
|
@ -47,6 +47,7 @@ type
|
||||||
blsToExecQueue*: AsyncEventQueue[SignedBLSToExecutionChange]
|
blsToExecQueue*: AsyncEventQueue[SignedBLSToExecutionChange]
|
||||||
propSlashQueue*: AsyncEventQueue[ProposerSlashing]
|
propSlashQueue*: AsyncEventQueue[ProposerSlashing]
|
||||||
attSlashQueue*: AsyncEventQueue[AttesterSlashing]
|
attSlashQueue*: AsyncEventQueue[AttesterSlashing]
|
||||||
|
blobSidecarQueue*: AsyncEventQueue[BlobSidecarInfoObject]
|
||||||
finalQueue*: AsyncEventQueue[FinalizationInfoObject]
|
finalQueue*: AsyncEventQueue[FinalizationInfoObject]
|
||||||
reorgQueue*: AsyncEventQueue[ReorgInfoObject]
|
reorgQueue*: AsyncEventQueue[ReorgInfoObject]
|
||||||
contribQueue*: AsyncEventQueue[SignedContributionAndProof]
|
contribQueue*: AsyncEventQueue[SignedContributionAndProof]
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import ../spec/helpers
|
import
|
||||||
|
std/tables,
|
||||||
|
../spec/helpers
|
||||||
|
|
||||||
from std/sequtils import mapIt
|
from std/sequtils import mapIt
|
||||||
from std/strutils import join
|
from std/strutils import join
|
||||||
|
|
||||||
|
@ -18,10 +21,14 @@ type
|
||||||
BlobQuarantine* = object
|
BlobQuarantine* = object
|
||||||
blobs*:
|
blobs*:
|
||||||
OrderedTable[(Eth2Digest, BlobIndex, KzgCommitment), ref BlobSidecar]
|
OrderedTable[(Eth2Digest, BlobIndex, KzgCommitment), ref BlobSidecar]
|
||||||
|
onBlobSidecarCallback*: OnBlobSidecarCallback
|
||||||
|
|
||||||
BlobFetchRecord* = object
|
BlobFetchRecord* = object
|
||||||
block_root*: Eth2Digest
|
block_root*: Eth2Digest
|
||||||
indices*: seq[BlobIndex]
|
indices*: seq[BlobIndex]
|
||||||
|
|
||||||
|
OnBlobSidecarCallback = proc(data: BlobSidecar) {.gcsafe, raises: [].}
|
||||||
|
|
||||||
func shortLog*(x: seq[BlobIndex]): string =
|
func shortLog*(x: seq[BlobIndex]): string =
|
||||||
"<" & x.mapIt($it).join(", ") & ">"
|
"<" & x.mapIt($it).join(", ") & ">"
|
||||||
|
|
||||||
|
@ -86,3 +93,7 @@ func blobFetchRecord*(quarantine: BlobQuarantine, blck: deneb.SignedBeaconBlock)
|
||||||
(blck.root, idx, blck.message.body.blob_kzg_commitments[i])):
|
(blck.root, idx, blck.message.body.blob_kzg_commitments[i])):
|
||||||
indices.add(idx)
|
indices.add(idx)
|
||||||
BlobFetchRecord(block_root: blck.root, indices: indices)
|
BlobFetchRecord(block_root: blck.root, indices: indices)
|
||||||
|
|
||||||
|
func init*(
|
||||||
|
T: type BlobQuarantine, onBlobSidecarCallback: OnBlobSidecarCallback): T =
|
||||||
|
T(onBlobSidecarCallback: onBlobSidecarCallback)
|
||||||
|
|
|
@ -440,8 +440,11 @@ proc validateBlobSidecar*(
|
||||||
if not ok:
|
if not ok:
|
||||||
return dag.checkedReject("BlobSidecar: blob invalid")
|
return dag.checkedReject("BlobSidecar: blob invalid")
|
||||||
|
|
||||||
ok()
|
# Send notification about new blob sidecar via callback
|
||||||
|
if not(isNil(blobQuarantine.onBlobSidecarCallback)):
|
||||||
|
blobQuarantine.onBlobSidecarCallback(blob_sidecar)
|
||||||
|
|
||||||
|
ok()
|
||||||
|
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/p2p-interface.md#beacon_block
|
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/p2p-interface.md#beacon_block
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/bellatrix/p2p-interface.md#beacon_block
|
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/bellatrix/p2p-interface.md#beacon_block
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[os, random, sequtils, terminal, times],
|
std/[os, random, terminal, times],
|
||||||
chronos, chronicles,
|
chronos, chronicles,
|
||||||
metrics, metrics/chronos_httpserver,
|
metrics, metrics/chronos_httpserver,
|
||||||
stew/[byteutils, io2],
|
stew/[byteutils, io2],
|
||||||
|
@ -273,6 +273,8 @@ proc checkWeakSubjectivityCheckpoint(
|
||||||
headStateSlot = getStateField(dag.headState, slot)
|
headStateSlot = getStateField(dag.headState, slot)
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
|
from ./spec/state_transition_block import kzg_commitment_to_versioned_hash
|
||||||
|
|
||||||
proc initFullNode(
|
proc initFullNode(
|
||||||
node: BeaconNode,
|
node: BeaconNode,
|
||||||
rng: ref HmacDrbgContext,
|
rng: ref HmacDrbgContext,
|
||||||
|
@ -293,6 +295,14 @@ proc initFullNode(
|
||||||
node.eventBus.propSlashQueue.emit(data)
|
node.eventBus.propSlashQueue.emit(data)
|
||||||
proc onAttesterSlashingAdded(data: AttesterSlashing) =
|
proc onAttesterSlashingAdded(data: AttesterSlashing) =
|
||||||
node.eventBus.attSlashQueue.emit(data)
|
node.eventBus.attSlashQueue.emit(data)
|
||||||
|
proc onBlobSidecarAdded(data: BlobSidecar) =
|
||||||
|
node.eventBus.blobSidecarQueue.emit(
|
||||||
|
BlobSidecarInfoObject(
|
||||||
|
block_root: hash_tree_root(data.signed_block_header.message),
|
||||||
|
index: data.index,
|
||||||
|
slot: data.signed_block_header.message.slot,
|
||||||
|
kzg_commitment: data.kzg_commitment,
|
||||||
|
versioned_hash: data.kzg_commitment.kzg_commitment_to_versioned_hash))
|
||||||
proc onBlockAdded(data: ForkedTrustedSignedBeaconBlock) =
|
proc onBlockAdded(data: ForkedTrustedSignedBeaconBlock) =
|
||||||
let optimistic =
|
let optimistic =
|
||||||
if node.currentSlot().epoch() >= dag.cfg.BELLATRIX_FORK_EPOCH:
|
if node.currentSlot().epoch() >= dag.cfg.BELLATRIX_FORK_EPOCH:
|
||||||
|
@ -373,7 +383,7 @@ proc initFullNode(
|
||||||
validatorChangePool = newClone(ValidatorChangePool.init(
|
validatorChangePool = newClone(ValidatorChangePool.init(
|
||||||
dag, attestationPool, onVoluntaryExitAdded, onBLSToExecutionChangeAdded,
|
dag, attestationPool, onVoluntaryExitAdded, onBLSToExecutionChangeAdded,
|
||||||
onProposerSlashingAdded, onAttesterSlashingAdded))
|
onProposerSlashingAdded, onAttesterSlashingAdded))
|
||||||
blobQuarantine = newClone(BlobQuarantine())
|
blobQuarantine = newClone(BlobQuarantine.init(onBlobSidecarAdded))
|
||||||
consensusManager = ConsensusManager.new(
|
consensusManager = ConsensusManager.new(
|
||||||
dag, attestationPool, quarantine, node.elManager,
|
dag, attestationPool, quarantine, node.elManager,
|
||||||
ActionTracker.init(node.network.nodeId, config.subscribeAllSubnets),
|
ActionTracker.init(node.network.nodeId, config.subscribeAllSubnets),
|
||||||
|
@ -553,6 +563,7 @@ proc init*(T: type BeaconNode,
|
||||||
blsToExecQueue: newAsyncEventQueue[SignedBLSToExecutionChange](),
|
blsToExecQueue: newAsyncEventQueue[SignedBLSToExecutionChange](),
|
||||||
propSlashQueue: newAsyncEventQueue[ProposerSlashing](),
|
propSlashQueue: newAsyncEventQueue[ProposerSlashing](),
|
||||||
attSlashQueue: newAsyncEventQueue[AttesterSlashing](),
|
attSlashQueue: newAsyncEventQueue[AttesterSlashing](),
|
||||||
|
blobSidecarQueue: newAsyncEventQueue[BlobSidecarInfoObject](),
|
||||||
finalQueue: newAsyncEventQueue[FinalizationInfoObject](),
|
finalQueue: newAsyncEventQueue[FinalizationInfoObject](),
|
||||||
reorgQueue: newAsyncEventQueue[ReorgInfoObject](),
|
reorgQueue: newAsyncEventQueue[ReorgInfoObject](),
|
||||||
contribQueue: newAsyncEventQueue[SignedContributionAndProof](),
|
contribQueue: newAsyncEventQueue[SignedContributionAndProof](),
|
||||||
|
@ -869,6 +880,8 @@ func verifyFinalization(node: BeaconNode, slot: Slot) =
|
||||||
# finalization occurs every slot, to 4 slots vs scheduledSlot.
|
# finalization occurs every slot, to 4 slots vs scheduledSlot.
|
||||||
doAssert finalizedEpoch + 4 >= epoch
|
doAssert finalizedEpoch + 4 >= epoch
|
||||||
|
|
||||||
|
from std/sequtils import toSeq
|
||||||
|
|
||||||
func subnetLog(v: BitArray): string =
|
func subnetLog(v: BitArray): string =
|
||||||
$toSeq(v.oneIndices())
|
$toSeq(v.oneIndices())
|
||||||
|
|
||||||
|
|
|
@ -145,6 +145,10 @@ proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
||||||
let handler = response.eventHandler(node.eventBus.attSlashQueue,
|
let handler = response.eventHandler(node.eventBus.attSlashQueue,
|
||||||
"attester_slashing")
|
"attester_slashing")
|
||||||
res.add(handler)
|
res.add(handler)
|
||||||
|
if EventTopic.BlobSidecar in eventTopics:
|
||||||
|
let handler = response.eventHandler(node.eventBus.blobSidecarQueue,
|
||||||
|
"blob_sidecar")
|
||||||
|
res.add(handler)
|
||||||
if EventTopic.FinalizedCheckpoint in eventTopics:
|
if EventTopic.FinalizedCheckpoint in eventTopics:
|
||||||
let handler = response.eventHandler(node.eventBus.finalQueue,
|
let handler = response.eventHandler(node.eventBus.finalQueue,
|
||||||
"finalized_checkpoint")
|
"finalized_checkpoint")
|
||||||
|
|
|
@ -60,6 +60,16 @@ type
|
||||||
kzg_commitment_inclusion_proof*:
|
kzg_commitment_inclusion_proof*:
|
||||||
array[KZG_COMMITMENT_INCLUSION_PROOF_DEPTH, Eth2Digest]
|
array[KZG_COMMITMENT_INCLUSION_PROOF_DEPTH, Eth2Digest]
|
||||||
|
|
||||||
|
# https://github.com/ethereum/beacon-APIs/blob/4882aa0803b622b75bab286b285599d70b7a2429/apis/eventstream/index.yaml#L138-L142
|
||||||
|
# Spec object, not only internal, because it gets serialized out for the
|
||||||
|
# event stream Beacon API
|
||||||
|
BlobSidecarInfoObject* = object
|
||||||
|
block_root*: Eth2Digest
|
||||||
|
index*: BlobIndex
|
||||||
|
slot*: Slot
|
||||||
|
kzg_commitment*: KzgCommitment
|
||||||
|
versioned_hash*: VersionedHash
|
||||||
|
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/deneb/p2p-interface.md#blobidentifier
|
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/deneb/p2p-interface.md#blobidentifier
|
||||||
BlobIdentifier* = object
|
BlobIdentifier* = object
|
||||||
block_root*: Eth2Digest
|
block_root*: Eth2Digest
|
||||||
|
|
|
@ -51,6 +51,7 @@ RestJson.useDefaultSerializationFor(
|
||||||
BLSToExecutionChange,
|
BLSToExecutionChange,
|
||||||
BeaconBlockHeader,
|
BeaconBlockHeader,
|
||||||
BlobSidecar,
|
BlobSidecar,
|
||||||
|
BlobSidecarInfoObject,
|
||||||
BlobsBundle,
|
BlobsBundle,
|
||||||
Checkpoint,
|
Checkpoint,
|
||||||
ContributionAndProof,
|
ContributionAndProof,
|
||||||
|
@ -299,6 +300,7 @@ const
|
||||||
type
|
type
|
||||||
EncodeTypes* =
|
EncodeTypes* =
|
||||||
AttesterSlashing |
|
AttesterSlashing |
|
||||||
|
BlobSidecarInfoObject |
|
||||||
DeleteKeystoresBody |
|
DeleteKeystoresBody |
|
||||||
EmptyBody |
|
EmptyBody |
|
||||||
ImportDistributedKeystoresBody |
|
ImportDistributedKeystoresBody |
|
||||||
|
@ -4145,6 +4147,8 @@ proc decodeString*(t: typedesc[EventTopic],
|
||||||
ok(EventTopic.ProposerSlashing)
|
ok(EventTopic.ProposerSlashing)
|
||||||
of "attester_slashing":
|
of "attester_slashing":
|
||||||
ok(EventTopic.AttesterSlashing)
|
ok(EventTopic.AttesterSlashing)
|
||||||
|
of "blob_sidecar":
|
||||||
|
ok(EventTopic.BlobSidecar)
|
||||||
of "finalized_checkpoint":
|
of "finalized_checkpoint":
|
||||||
ok(EventTopic.FinalizedCheckpoint)
|
ok(EventTopic.FinalizedCheckpoint)
|
||||||
of "chain_reorg":
|
of "chain_reorg":
|
||||||
|
@ -4174,6 +4178,8 @@ proc encodeString*(value: set[EventTopic]): Result[string, cstring] =
|
||||||
res.add("proposer_slashing,")
|
res.add("proposer_slashing,")
|
||||||
if EventTopic.AttesterSlashing in value:
|
if EventTopic.AttesterSlashing in value:
|
||||||
res.add("attester_slashing,")
|
res.add("attester_slashing,")
|
||||||
|
if EventTopic.BlobSidecar in value:
|
||||||
|
res.add("blob_sidecar,")
|
||||||
if EventTopic.FinalizedCheckpoint in value:
|
if EventTopic.FinalizedCheckpoint in value:
|
||||||
res.add("finalized_checkpoint,")
|
res.add("finalized_checkpoint,")
|
||||||
if EventTopic.ChainReorg in value:
|
if EventTopic.ChainReorg in value:
|
||||||
|
|
|
@ -55,8 +55,9 @@ type
|
||||||
# https://github.com/ethereum/beacon-APIs/blob/v2.4.2/apis/eventstream/index.yaml
|
# https://github.com/ethereum/beacon-APIs/blob/v2.4.2/apis/eventstream/index.yaml
|
||||||
EventTopic* {.pure.} = enum
|
EventTopic* {.pure.} = enum
|
||||||
Head, Block, Attestation, VoluntaryExit, BLSToExecutionChange,
|
Head, Block, Attestation, VoluntaryExit, BLSToExecutionChange,
|
||||||
ProposerSlashing, AttesterSlashing, FinalizedCheckpoint, ChainReorg,
|
ProposerSlashing, AttesterSlashing, BlobSidecar, FinalizedCheckpoint,
|
||||||
ContributionAndProof, LightClientFinalityUpdate, LightClientOptimisticUpdate
|
ChainReorg, ContributionAndProof, LightClientFinalityUpdate,
|
||||||
|
LightClientOptimisticUpdate
|
||||||
|
|
||||||
EventTopics* = set[EventTopic]
|
EventTopics* = set[EventTopic]
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[parsecsv, streams],
|
std/parsecsv,
|
||||||
stew/[io2, byteutils], chronicles, confutils, snappy,
|
stew/[io2, byteutils], chronicles, confutils, snappy,
|
||||||
../beacon_chain/spec/datatypes/base,
|
../beacon_chain/spec/datatypes/base,
|
||||||
./ncli_common
|
./ncli_common
|
||||||
|
@ -200,6 +200,8 @@ proc advanceEpochs*(aggregator: var ValidatorDbAggregator, epoch: Epoch,
|
||||||
aggregator.epochsAggregated = 0
|
aggregator.epochsAggregated = 0
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
|
import std/streams
|
||||||
|
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
import system/ansi_c
|
import system/ansi_c
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue