Skip to content

Commit

Permalink
EIP-4844: Implement beaconBlocksMaybeBlobsByRoot (#4869)
Browse files Browse the repository at this point in the history
* Implement beaconBlocksMaybeBlobsByRoot

* Fix empty array typo
  • Loading branch information
dapplion authored Dec 7, 2022
1 parent abd38d9 commit 30246e5
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 3 deletions.
64 changes: 61 additions & 3 deletions packages/beacon-node/src/network/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,67 @@ export class Network implements INetwork {
}

async beaconBlocksMaybeBlobsByRoot(peerId: PeerId, request: phase0.BeaconBlocksByRootRequest): Promise<BlockInput[]> {
// TODO EIP-4844: Will throw an error for blocks post EIP-4844
const blocks = await this.reqResp.beaconBlocksByRoot(peerId, request);
return blocks.map((block) => getBlockInput.preEIP4844(this.config, block));
// Assume all requests are post EIP-4844
if (this.config.getForkSeq(this.chain.forkChoice.getFinalizedBlock().slot) >= ForkSeq.eip4844) {
const blocksAndBlobs = await this.reqResp.beaconBlockAndBlobsSidecarByRoot(peerId, request);
return blocksAndBlobs.map(({beaconBlock, blobsSidecar}) =>
getBlockInput.postEIP4844(this.config, beaconBlock, blobsSidecar)
);
}

// Assume all request are pre EIP-4844
else if (this.config.getForkSeq(this.clock.currentSlot) < ForkSeq.eip4844) {
const blocks = await this.reqResp.beaconBlocksByRoot(peerId, request);
return blocks.map((block) => getBlockInput.preEIP4844(this.config, block));
}

// NOTE: Consider blocks may be post or pre EIP-4844
// TODO EIP-4844: Request either blocks, or blocks+blobs
else {
const results = await Promise.all(
request.map(
async (beaconBlockRoot): Promise<BlockInput | null> => {
const [resultBlockBlobs, resultBlocks] = await Promise.allSettled([
this.reqResp.beaconBlockAndBlobsSidecarByRoot(peerId, [beaconBlockRoot]),
this.reqResp.beaconBlocksByRoot(peerId, [beaconBlockRoot]),
]);

if (resultBlockBlobs.status === "fulfilled" && resultBlockBlobs.value.length === 1) {
const {beaconBlock, blobsSidecar} = resultBlockBlobs.value[0];
return getBlockInput.postEIP4844(this.config, beaconBlock, blobsSidecar);
}

if (resultBlocks.status === "rejected") {
return Promise.reject(resultBlocks.reason);
}

// Promise fullfilled + no result = block not found
if (resultBlocks.value.length < 1) {
return null;
}

const block = resultBlocks.value[0];

if (this.config.getForkSeq(block.message.slot) >= ForkSeq.eip4844) {
// beaconBlockAndBlobsSidecarByRoot should have succeeded
if (resultBlockBlobs.status === "rejected") {
// Recycle existing error for beaconBlockAndBlobsSidecarByRoot if any
return Promise.reject(resultBlockBlobs.reason);
} else {
throw Error(
`Received post EIP-4844 ${beaconBlockRoot} over beaconBlocksByRoot not beaconBlockAndBlobsSidecarByRoot`
);
}
}

// Block is pre EIP-4844
return getBlockInput.preEIP4844(this.config, block);
}
)
);

return results.filter((blockOrNull): blockOrNull is BlockInput => blockOrNull !== null);
}
}

/**
Expand Down
15 changes: 15 additions & 0 deletions packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,21 @@ export class ReqRespBeaconNode extends ReqResp implements IReqRespBeaconNode {
);
}

async beaconBlockAndBlobsSidecarByRoot(
peerId: PeerId,
request: eip4844.BeaconBlockAndBlobsSidecarByRootRequest
): Promise<eip4844.SignedBeaconBlockAndBlobsSidecar[]> {
return collectMaxResponse(
this.sendRequest<eip4844.BeaconBlockAndBlobsSidecarByRootRequest, eip4844.SignedBeaconBlockAndBlobsSidecar>(
peerId,
ReqRespMethod.BeaconBlockAndBlobsSidecarByRoot,
[Version.V1],
request
),
request.length
);
}

/**
* Returns the list of protocols that must be subscribed during a specific fork.
* Any protocol not in this list must be un-subscribed.
Expand Down
4 changes: 4 additions & 0 deletions packages/beacon-node/src/network/reqresp/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export interface IReqRespBeaconNode {
): Promise<allForks.SignedBeaconBlock[]>;
beaconBlocksByRoot(peerId: PeerId, request: phase0.BeaconBlocksByRootRequest): Promise<allForks.SignedBeaconBlock[]>;
blobsSidecarsByRange(peerId: PeerId, request: eip4844.BlobsSidecarsByRangeRequest): Promise<eip4844.BlobsSidecar[]>;
beaconBlockAndBlobsSidecarByRoot(
peerId: PeerId,
request: eip4844.BeaconBlockAndBlobsSidecarByRootRequest
): Promise<eip4844.SignedBeaconBlockAndBlobsSidecar[]>;
pruneOnPeerDisconnect(peerId: PeerId): void;
lightClientBootstrap(peerId: PeerId, request: Uint8Array): Promise<altair.LightClientBootstrap>;
lightClientOptimisticUpdate(peerId: PeerId): Promise<altair.LightClientOptimisticUpdate>;
Expand Down
2 changes: 2 additions & 0 deletions packages/beacon-node/src/network/reqresp/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export enum ReqRespMethod {
BeaconBlocksByRange = "beacon_blocks_by_range",
BeaconBlocksByRoot = "beacon_blocks_by_root",
BlobsSidecarsByRange = "blobs_sidecars_by_range",
BeaconBlockAndBlobsSidecarByRoot = "beacon_block_and_blobs_sidecar_by_root",
LightClientBootstrap = "light_client_bootstrap",
LightClientUpdatesByRange = "light_client_updates_by_range",
LightClientFinalityUpdate = "light_client_finality_update",
Expand All @@ -26,6 +27,7 @@ type RequestBodyByMethod = {
[ReqRespMethod.BeaconBlocksByRange]: unknown;
[ReqRespMethod.BeaconBlocksByRoot]: unknown;
[ReqRespMethod.BlobsSidecarsByRange]: unknown;
[ReqRespMethod.BeaconBlockAndBlobsSidecarByRoot]: unknown;
[ReqRespMethod.LightClientBootstrap]: unknown;
[ReqRespMethod.LightClientUpdatesByRange]: unknown;
[ReqRespMethod.LightClientFinalityUpdate]: unknown;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ describe("network / peers / PeerManager", function () {
beaconBlocksByRange = sinon.stub();
beaconBlocksByRoot = sinon.stub();
blobsSidecarsByRange = sinon.stub();
beaconBlockAndBlobsSidecarByRoot = sinon.stub();
pruneOnPeerDisconnect = sinon.stub();
lightClientBootstrap = sinon.stub();
lightClientOptimisticUpdate = sinon.stub();
Expand Down

0 comments on commit 30246e5

Please sign in to comment.