Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(reqresp)!: support byte based handlers #5417

Merged
merged 36 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2384cf0
Update reqresp to support only binary handler
nazarhussain Apr 25, 2023
d49fc69
Convert beacon-node reqresp to support only binary handlers
nazarhussain Apr 25, 2023
03b5195
Update the beacon-reqresp and tests
nazarhussain Apr 25, 2023
3161fc9
Update the readme
nazarhussain Apr 25, 2023
0d6a345
Fix lint errors
nazarhussain Apr 25, 2023
4928697
Increase the genesis delay to fix slow startup of nodes
nazarhussain Apr 25, 2023
8132e6d
Fix the table reporter
nazarhussain Apr 25, 2023
1661277
Fix a type issue
nazarhussain Apr 25, 2023
ed9930e
Update the table reporter
nazarhussain Apr 26, 2023
ac16179
Fix el log file name
nazarhussain Apr 26, 2023
bccea02
Update the metadata response to support fork digest
nazarhussain Apr 26, 2023
c74d70c
Update context bytes for v1,v2 protocols
nazarhussain Apr 26, 2023
98f3a28
Update beacon metadata response
nazarhussain Apr 26, 2023
90e14c2
Add more test fixtures
nazarhussain Apr 26, 2023
35a4d98
Add protocol version to log for debugging
nazarhussain Apr 26, 2023
f39e505
Update the metadata response format
nazarhussain Apr 26, 2023
058838e
Remove unncessary comments
nazarhussain Apr 26, 2023
cefac0b
Debug logger
nazarhussain Apr 26, 2023
a084ba4
Fix the sim log reporter
nazarhussain Apr 26, 2023
0cf18f2
Revert the genesis slot delay
nazarhussain Apr 26, 2023
86f7d8a
Fix e2e test types
nazarhussain Apr 26, 2023
3b86180
Fix e2e tests
nazarhussain Apr 28, 2023
533b57f
Update structure of handler
nazarhussain Apr 28, 2023
12915af
Update the beacon-node handlers
nazarhussain Apr 28, 2023
0d04498
Fix linter errors
nazarhussain Apr 28, 2023
edf9f08
Fix readme file
nazarhussain Apr 28, 2023
18782f2
Fix prettier warnings
nazarhussain Apr 28, 2023
205315a
Review PR
dapplion Apr 30, 2023
e580c48
Fix lib import
dapplion Apr 30, 2023
2a26701
Update readme example
dapplion May 1, 2023
56a6e80
Use Version enum
dapplion May 1, 2023
83094d8
Simplify MetadataController
dapplion May 1, 2023
434abad
Add ReqResp interop test
dapplion May 1, 2023
e6d47ef
Add INVALID_RESPONSE_SSZ
dapplion May 1, 2023
b313730
Review PR
dapplion May 2, 2023
0f3ddce
Merge remote-tracking branch 'origin/unstable' into nh/5378-reqresp-b…
dapplion May 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 0 additions & 4 deletions packages/beacon-node/src/network/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,6 @@ export class MetadataController {
return this._metadata.seqNumber;
}

get currentSlot(): number {
return this.chain.clock.currentSlot;
}

get syncnets(): BitArray {
return this._metadata.syncnets;
}
Expand Down
276 changes: 115 additions & 161 deletions packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import {ContextBytesType, EncodedPayloadBytes, EncodedPayloadType, ProtocolDescriptor} from "@lodestar/reqresp";
import {ResponseOutgoing} from "@lodestar/reqresp";
import {deneb} from "@lodestar/types";
import {toHex} from "@lodestar/utils";
import {IBeaconChain} from "../../../chain/index.js";
import {IBeaconDb} from "../../../db/index.js";
import {getSlotFromSignedBeaconBlockSerialized} from "../../../util/sszBytes.js";

export async function* onBeaconBlockAndBlobsSidecarByRoot(
_protocol: ProtocolDescriptor<deneb.BeaconBlockAndBlobsSidecarByRootRequest, deneb.SignedBeaconBlockAndBlobsSidecar>,
requestBody: deneb.BeaconBlockAndBlobsSidecarByRootRequest,
chain: IBeaconChain,
db: IBeaconDb
): AsyncIterable<EncodedPayloadBytes> {
): AsyncIterable<ResponseOutgoing> {
const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;

for (const blockRoot of requestBody) {
Expand Down Expand Up @@ -40,15 +39,10 @@ export async function* onBeaconBlockAndBlobsSidecarByRoot(
if (forkSlot === null) {
throw Error(`Invalid block bytes for block ${blockRootHex}`);
}
const fork = chain.config.getForkName(forkSlot);

yield {
type: EncodedPayloadType.bytes,
bytes: signedBeaconBlockAndBlobsSidecarFromBytes(blockBytes, blobsSidecarBytes),
contextBytes: {
type: ContextBytesType.ForkDigest,
fork,
},
data: signedBeaconBlockAndBlobsSidecarFromBytes(blockBytes, blobsSidecarBytes),
fork: chain.config.getForkName(forkSlot),
};
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,31 @@
import {GENESIS_SLOT, MAX_REQUEST_BLOCKS} from "@lodestar/params";
import {
ContextBytesType,
EncodedPayloadBytes,
EncodedPayloadType,
ProtocolDescriptor,
ResponseError,
RespStatus,
} from "@lodestar/reqresp";
import {allForks, deneb, phase0} from "@lodestar/types";
import {ResponseError, ResponseOutgoing, RespStatus} from "@lodestar/reqresp";
import {deneb, phase0} from "@lodestar/types";
import {fromHex} from "@lodestar/utils";
import {IBeaconChain} from "../../../chain/index.js";
import {IBeaconDb} from "../../../db/index.js";

// TODO: Unit test

export function onBeaconBlocksByRange(
protocol:
| ProtocolDescriptor<phase0.BeaconBlocksByRangeRequest, allForks.SignedBeaconBlock>
| ProtocolDescriptor<deneb.BlobsSidecarsByRangeRequest, allForks.SignedBeaconBlock>,
request: phase0.BeaconBlocksByRangeRequest,
chain: IBeaconChain,
db: IBeaconDb
): AsyncIterable<EncodedPayloadBytes> {
return onBlocksOrBlobsSidecarsByRange(protocol, request, chain, {
): AsyncIterable<ResponseOutgoing> {
return onBlocksOrBlobsSidecarsByRange(request, chain, {
finalized: db.blockArchive,
unfinalized: db.block,
});
}

export async function* onBlocksOrBlobsSidecarsByRange(
protocol:
| ProtocolDescriptor<deneb.BlobsSidecarsByRangeRequest, allForks.SignedBeaconBlock>
| ProtocolDescriptor<deneb.BlobsSidecarsByRangeRequest, deneb.SignedBeaconBlockAndBlobsSidecar>
| ProtocolDescriptor<deneb.BlobsSidecarsByRangeRequest, deneb.BlobsSidecar>,
request: deneb.BlobsSidecarsByRangeRequest,
chain: IBeaconChain,
db: {
finalized: Pick<IBeaconDb["blockArchive"], "binaryEntriesStream" | "decodeKey">;
unfinalized: Pick<IBeaconDb["block"], "getBinary">;
}
): AsyncIterable<EncodedPayloadBytes> {
): AsyncIterable<ResponseOutgoing> {
const {startSlot, count} = validateBeaconBlocksByRangeRequest(request);
const endSlot = startSlot + count;

Expand All @@ -57,15 +43,8 @@ export async function* onBlocksOrBlobsSidecarsByRange(
// Chain of blobs won't change
for await (const {key, value} of db.finalized.binaryEntriesStream({gte: startSlot, lt: endSlot})) {
yield {
type: EncodedPayloadType.bytes,
bytes: value,
contextBytes:
protocol.contextBytes.type === ContextBytesType.Empty
? {type: ContextBytesType.Empty}
: {
type: ContextBytesType.ForkDigest,
fork: chain.config.getForkName(db.finalized.decodeKey(key)),
},
data: value,
fork: chain.config.getForkName(db.finalized.decodeKey(key)),
};
}
}
Expand Down Expand Up @@ -95,15 +74,8 @@ export async function* onBlocksOrBlobsSidecarsByRange(
}

yield {
type: EncodedPayloadType.bytes,
bytes: blockBytes,
contextBytes:
protocol.contextBytes.type === ContextBytesType.Empty
? {type: ContextBytesType.Empty}
: {
type: ContextBytesType.ForkDigest,
fork: chain.config.getForkName(block.slot),
},
data: blockBytes,
fork: chain.config.getForkName(block.slot),
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import {toHexString} from "@chainsafe/ssz";
import {ContextBytesType, EncodedPayloadBytes, EncodedPayloadType, ProtocolDescriptor} from "@lodestar/reqresp";
import {Slot, allForks, phase0} from "@lodestar/types";
import {ResponseOutgoing} from "@lodestar/reqresp";
import {Slot, phase0} from "@lodestar/types";
import {IBeaconChain} from "../../../chain/index.js";
import {IBeaconDb} from "../../../db/index.js";
import {getSlotFromSignedBeaconBlockSerialized} from "../../../util/sszBytes.js";

export async function* onBeaconBlocksByRoot(
protocol: ProtocolDescriptor<phase0.BeaconBlocksByRootRequest, allForks.SignedBeaconBlock>,
requestBody: phase0.BeaconBlocksByRootRequest,
chain: IBeaconChain,
db: IBeaconDb
): AsyncIterable<EncodedPayloadBytes> {
): AsyncIterable<ResponseOutgoing> {
for (const blockRoot of requestBody) {
const root = blockRoot;
const summary = chain.forkChoice.getBlock(root);
Expand Down Expand Up @@ -40,15 +39,8 @@ export async function* onBeaconBlocksByRoot(
}

yield {
type: EncodedPayloadType.bytes,
bytes: blockBytes,
contextBytes:
protocol.contextBytes.type === ContextBytesType.ForkDigest
? {
type: ContextBytesType.ForkDigest,
fork: chain.config.getForkName(slot),
}
: {type: ContextBytesType.Empty},
data: blockBytes,
fork: chain.config.getForkName(slot),
};
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import {deneb} from "@lodestar/types";
import {EncodedPayloadBytes, ProtocolDescriptor} from "@lodestar/reqresp";
import {ResponseOutgoing} from "@lodestar/reqresp";
import {IBeaconChain} from "../../../chain/index.js";
import {IBeaconDb} from "../../../db/index.js";
import {onBlocksOrBlobsSidecarsByRange} from "./beaconBlocksByRange.js";

// TODO DENEB: Unit test

export function onBlobsSidecarsByRange(
protocol: ProtocolDescriptor<deneb.BlobsSidecarsByRangeRequest, deneb.BlobsSidecar>,
request: deneb.BlobsSidecarsByRangeRequest,
chain: IBeaconChain,
db: IBeaconDb
): AsyncIterable<EncodedPayloadBytes> {
return onBlocksOrBlobsSidecarsByRange(protocol, request, chain, {
): AsyncIterable<ResponseOutgoing> {
return onBlocksOrBlobsSidecarsByRange(request, chain, {
finalized: db.blobsSidecarArchive,
unfinalized: db.blobsSidecar,
});
Expand Down
65 changes: 36 additions & 29 deletions packages/beacon-node/src/network/reqresp/handlers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {HandlerTypeFromMessage} from "@lodestar/reqresp";
import * as protocols from "@lodestar/reqresp/protocols";
import {PeerId} from "@libp2p/interface-peer-id";
import {phase0, ssz} from "@lodestar/types";
import {ProtocolHandler, ResponseOutgoing} from "@lodestar/reqresp";
import {IBeaconChain} from "../../../chain/index.js";
import {IBeaconDb} from "../../../db/index.js";
import {onBeaconBlocksByRange} from "./beaconBlocksByRange.js";
Expand All @@ -13,48 +14,54 @@ import {onLightClientUpdatesByRange} from "./lightClientUpdatesByRange.js";
import {onStatus} from "./status.js";

export interface ReqRespHandlers {
onStatus: HandlerTypeFromMessage<typeof protocols.Status>;
onBeaconBlocksByRange: HandlerTypeFromMessage<typeof protocols.BeaconBlocksByRange>;
onBeaconBlocksByRoot: HandlerTypeFromMessage<typeof protocols.BeaconBlocksByRoot>;
onBeaconBlockAndBlobsSidecarByRoot: HandlerTypeFromMessage<typeof protocols.BeaconBlockAndBlobsSidecarByRoot>;
onBlobsSidecarsByRange: HandlerTypeFromMessage<typeof protocols.BlobsSidecarsByRange>;
onLightClientBootstrap: HandlerTypeFromMessage<typeof protocols.LightClientBootstrap>;
onLightClientUpdatesByRange: HandlerTypeFromMessage<typeof protocols.LightClientUpdatesByRange>;
onLightClientFinalityUpdate: HandlerTypeFromMessage<typeof protocols.LightClientFinalityUpdate>;
onLightClientOptimisticUpdate: HandlerTypeFromMessage<typeof protocols.LightClientOptimisticUpdate>;
onStatus: (req: phase0.Status, peerId: PeerId) => AsyncIterable<ResponseOutgoing>;
onBeaconBlocksByRange: ProtocolHandler;
onBeaconBlocksByRoot: ProtocolHandler;
onBeaconBlockAndBlobsSidecarByRoot: ProtocolHandler;
onBlobsSidecarsByRange: ProtocolHandler;
onLightClientBootstrap: ProtocolHandler;
onLightClientUpdatesByRange: ProtocolHandler;
onLightClientFinalityUpdate: ProtocolHandler;
onLightClientOptimisticUpdate: ProtocolHandler;
}
/**
* The ReqRespHandler module handles app-level requests / responses from other peers,
* fetching state from the chain and database as needed.
*/
export function getReqRespHandlers({db, chain}: {db: IBeaconDb; chain: IBeaconChain}): ReqRespHandlers {
return {
async *onStatus(protocol) {
yield* onStatus(protocol, chain);
async *onStatus() {
yield* onStatus(chain);
},
async *onBeaconBlocksByRange(protocol, req) {
yield* onBeaconBlocksByRange(protocol, req, chain, db);
async *onBeaconBlocksByRange(req) {
const body = ssz.phase0.BeaconBlocksByRangeRequest.deserialize(req.data);
twoeths marked this conversation as resolved.
Show resolved Hide resolved
yield* onBeaconBlocksByRange(body, chain, db);
},
async *onBeaconBlocksByRoot(protocol, req) {
yield* onBeaconBlocksByRoot(protocol, req, chain, db);
async *onBeaconBlocksByRoot(req) {
const body = ssz.phase0.BeaconBlocksByRootRequest.deserialize(req.data);
yield* onBeaconBlocksByRoot(body, chain, db);
},
async *onBeaconBlockAndBlobsSidecarByRoot(protocol, req) {
yield* onBeaconBlockAndBlobsSidecarByRoot(protocol, req, chain, db);
async *onBeaconBlockAndBlobsSidecarByRoot(req) {
const body = ssz.deneb.BeaconBlockAndBlobsSidecarByRootRequest.deserialize(req.data);
yield* onBeaconBlockAndBlobsSidecarByRoot(body, chain, db);
},
async *onBlobsSidecarsByRange(protocol, req) {
yield* onBlobsSidecarsByRange(protocol, req, chain, db);
async *onBlobsSidecarsByRange(req) {
const body = ssz.deneb.BlobsSidecarsByRangeRequest.deserialize(req.data);
yield* onBlobsSidecarsByRange(body, chain, db);
},
async *onLightClientBootstrap(protocol, req) {
yield* onLightClientBootstrap(protocol, req, chain);
async *onLightClientBootstrap(req) {
const body = ssz.Root.deserialize(req.data);
yield* onLightClientBootstrap(body, chain);
},
async *onLightClientUpdatesByRange(protocol, req) {
yield* onLightClientUpdatesByRange(protocol, req, chain);
async *onLightClientUpdatesByRange(req) {
const body = ssz.altair.LightClientUpdatesByRange.deserialize(req.data);
yield* onLightClientUpdatesByRange(body, chain);
},
async *onLightClientFinalityUpdate(protocol) {
yield* onLightClientFinalityUpdate(protocol, chain);
async *onLightClientFinalityUpdate() {
yield* onLightClientFinalityUpdate(chain);
},
async *onLightClientOptimisticUpdate(protocol) {
yield* onLightClientOptimisticUpdate(protocol, chain);
async *onLightClientOptimisticUpdate() {
yield* onLightClientOptimisticUpdate(chain);
},
};
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
import {
EncodedPayloadType,
RespStatus,
ResponseError,
LightClientServerError,
LightClientServerErrorCode,
EncodedPayloadBytes,
ContextBytesType,
ProtocolDescriptor,
ResponseOutgoing,
} from "@lodestar/reqresp";
import {Root, allForks} from "@lodestar/types";
import {Root} from "@lodestar/types";
import {IBeaconChain} from "../../../chain/index.js";
import {ReqRespMethod, responseSszTypeByMethod} from "../types.js";

export async function* onLightClientBootstrap(
protocol: ProtocolDescriptor<Root, allForks.LightClientBootstrap>,
requestBody: Root,
chain: IBeaconChain
): AsyncIterable<EncodedPayloadBytes> {
export async function* onLightClientBootstrap(requestBody: Root, chain: IBeaconChain): AsyncIterable<ResponseOutgoing> {
try {
const bootstrap = await chain.lightClientServer.getBootstrap(requestBody);
const fork = chain.config.getForkName(bootstrap.header.beacon.slot);
const type = responseSszTypeByMethod[ReqRespMethod.LightClientBootstrap](fork, 0);
yield {
type: EncodedPayloadType.bytes,
bytes: protocol
.responseType(chain.config.getForkName(chain.clock.currentSlot))
.serialize(await chain.lightClientServer.getBootstrap(requestBody)),
contextBytes: {
type: ContextBytesType.ForkDigest,
fork: chain.config.getForkName(chain.clock.currentSlot),
},
data: type.serialize(bootstrap),
fork,
};
} catch (e) {
if ((e as LightClientServerError).type?.code === LightClientServerErrorCode.RESOURCE_UNAVAILABLE) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
import {
ContextBytesType,
EncodedPayloadBytes,
EncodedPayloadType,
ProtocolDescriptor,
RespStatus,
ResponseError,
} from "@lodestar/reqresp";
import {allForks} from "@lodestar/types";
import {ResponseOutgoing, RespStatus, ResponseError} from "@lodestar/reqresp";
import {IBeaconChain} from "../../../chain/index.js";
import {ReqRespMethod, responseSszTypeByMethod} from "../types.js";

export async function* onLightClientFinalityUpdate(
protocol: ProtocolDescriptor<null, allForks.LightClientFinalityUpdate>,
chain: IBeaconChain
): AsyncIterable<EncodedPayloadBytes> {
const finalityUpdate = chain.lightClientServer.getFinalityUpdate();
if (finalityUpdate === null) {
export async function* onLightClientFinalityUpdate(chain: IBeaconChain): AsyncIterable<ResponseOutgoing> {
const update = chain.lightClientServer.getFinalityUpdate();
if (update === null) {
throw new ResponseError(RespStatus.RESOURCE_UNAVAILABLE, "No latest finality update available");
} else {
const fork = chain.config.getForkName(update.signatureSlot);
const type = responseSszTypeByMethod[ReqRespMethod.LightClientFinalityUpdate](fork, 0);
yield {
type: EncodedPayloadType.bytes,
bytes: protocol.responseType(chain.config.getForkName(chain.clock.currentSlot)).serialize(finalityUpdate),
contextBytes: {
type: ContextBytesType.ForkDigest,
fork: chain.config.getForkName(chain.clock.currentSlot),
},
data: type.serialize(update),
fork,
};
}
}