Skip to content

Commit

Permalink
add the IL publishing
Browse files Browse the repository at this point in the history
  • Loading branch information
g11tech committed Mar 17, 2024
1 parent 40bd276 commit 13f6ccc
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 18 deletions.
44 changes: 28 additions & 16 deletions packages/beacon-node/src/api/impl/beacon/blocks/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {fromHexString, toHexString} from "@chainsafe/ssz";
import {routes, ServerApi, ResponseFormat} from "@lodestar/api";
import {computeTimeAtSlot, reconstructFullBlockOrContents} from "@lodestar/state-transition";
import {SLOTS_PER_HISTORICAL_ROOT, ForkName} from "@lodestar/params";
import {SLOTS_PER_HISTORICAL_ROOT, isForkBlobs, isForkILs} from "@lodestar/params";
import {sleep, toHex} from "@lodestar/utils";
import {allForks, deneb, isSignedBlockContents, ProducedBlockSource} from "@lodestar/types";
import {allForks, deneb, electra, isSignedBlockContents, ProducedBlockSource, ssz} from "@lodestar/types";
import {BlockSource, getBlockInput, ImportBlockOpts, BlockInput} from "../../../../chain/blocks/types.js";
import {promiseAllMaybeAsync} from "../../../../util/promises.js";
import {isOptimisticBlock} from "../../../../util/forkChoice.js";
Expand Down Expand Up @@ -42,32 +42,42 @@ export function getBeaconBlockApi({
opts: PublishBlockOpts = {}
) => {
const seenTimestampSec = Date.now() / 1000;
let blockForImport: BlockInput, signedBlock: allForks.SignedBeaconBlock, blobSidecars: deneb.BlobSidecars;
const signedBlock = isSignedBlockContents(signedBlockOrContents)
? signedBlockOrContents.signedBlock
: signedBlockOrContents;
// if block is locally produced, full or blinded, it already is 'consensus' validated as it went through
// state transition to produce the stateRoot
const slot = signedBlock.message.slot;
const fork = config.getForkName(slot);

let blockForImport: BlockInput, blobSidecars: deneb.BlobSidecars, inclusionLists: electra.NewInclusionListRequest[];
if (isSignedBlockContents(signedBlockOrContents)) {
({signedBlock} = signedBlockOrContents);
blobSidecars = computeBlobSidecars(config, signedBlock, signedBlockOrContents);
blockForImport = getBlockInput.postDeneb(
config,
signedBlock,
null,
{fork: ForkName.deneb, blobs: blobSidecars, blobsBytes: [null]},
BlockSource.api
);
let blockData;
if (!isForkBlobs(fork)) {
throw Error(`Invalid fork=${fork} for publishing signedBlockOrContents`);
} else if (!isForkILs(fork)) {
inclusionLists = [];
blockData = {fork, blobs: blobSidecars, blobsBytes: [null]};
} else {
// stub the values
const ilSummary = ssz.electra.ILSummary.defaultValue();
const ilTransactions = [ssz.electra.ILTransactions.defaultValue()];
inclusionLists = [ssz.electra.NewInclusionListRequest.defaultValue()];
blockData = {fork, blobs: blobSidecars, blobsBytes: [null], ilSummary, inclusionLists: ilTransactions};
}

blockForImport = getBlockInput.postDeneb(config, signedBlock, null, blockData, BlockSource.api);
} else {
signedBlock = signedBlockOrContents;
blobSidecars = [];
inclusionLists = [];
// TODO: Once API supports submitting data as SSZ, replace null with blockBytes
blockForImport = getBlockInput.preDeneb(config, signedBlock, BlockSource.api, null);
}

// check what validations have been requested before broadcasting and publishing the block
// TODO: add validation time to metrics
const broadcastValidation = opts.broadcastValidation ?? routes.beacon.BroadcastValidation.gossip;
// if block is locally produced, full or blinded, it already is 'consensus' validated as it went through
// state transition to produce the stateRoot
const slot = signedBlock.message.slot;
const fork = config.getForkName(slot);
const blockRoot = toHex(chain.config.getForkTypes(slot).BeaconBlock.hashTreeRoot(signedBlock.message));
// bodyRoot should be the same to produced block
const bodyRoot = toHex(chain.config.getForkTypes(slot).BeaconBlockBody.hashTreeRoot(signedBlock.message.body));
Expand Down Expand Up @@ -191,6 +201,8 @@ export function getBeaconBlockApi({
// b) they might require more hops to reach recipients in peerDAS kind of setup where
// blobs might need to hop between nodes because of partial subnet subscription
...blobSidecars.map((blobSidecar) => () => network.publishBlobSidecar(blobSidecar)),
// republish the inclusion list even though it might have been already published
...inclusionLists.map((inclusionList) => () => network.publishInclusionList(inclusionList)),
() => network.publishBeaconBlock(signedBlock) as Promise<unknown>,
() =>
// there is no rush to persist block since we published it to gossip anyway
Expand Down
3 changes: 2 additions & 1 deletion packages/beacon-node/src/network/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import type {AddressManager, ConnectionManager, Registrar, TransportManager} from "@libp2p/interface-internal";
import type {Datastore} from "interface-datastore";
import {Identify} from "@chainsafe/libp2p-identify";
import {Slot, SlotRootHex, allForks, altair, capella, deneb, phase0} from "@lodestar/types";
import {Slot, SlotRootHex, allForks, altair, capella, deneb, electra, phase0} from "@lodestar/types";
import {PeerIdStr} from "../util/peerId.js";
import {INetworkEventBus} from "./events.js";
import {INetworkCorePublic} from "./core/types.js";
Expand Down Expand Up @@ -61,6 +61,7 @@ export interface INetwork extends INetworkCorePublic {
// Gossip
publishBeaconBlock(signedBlock: allForks.SignedBeaconBlock): Promise<number>;
publishBlobSidecar(blobSidecar: deneb.BlobSidecar): Promise<number>;
publishInclusionList(inclusionList: electra.NewInclusionListRequest): Promise<number>;
publishBeaconAggregateAndProof(aggregateAndProof: phase0.SignedAggregateAndProof): Promise<number>;
publishBeaconAttestation(attestation: phase0.Attestation, subnet: number): Promise<number>;
publishVoluntaryExit(voluntaryExit: phase0.SignedVoluntaryExit): Promise<number>;
Expand Down
9 changes: 8 additions & 1 deletion packages/beacon-node/src/network/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {BeaconConfig} from "@lodestar/config";
import {sleep} from "@lodestar/utils";
import {LoggerNode} from "@lodestar/logger/node";
import {computeStartSlotAtEpoch, computeTimeAtSlot} from "@lodestar/state-transition";
import {phase0, allForks, deneb, altair, Root, capella, SlotRootHex} from "@lodestar/types";
import {phase0, allForks, deneb, electra, altair, Root, capella, SlotRootHex} from "@lodestar/types";
import {routes} from "@lodestar/api";
import {ResponseIncoming} from "@lodestar/reqresp";
import {ForkSeq, MAX_BLOBS_PER_BLOCK} from "@lodestar/params";
Expand Down Expand Up @@ -302,6 +302,13 @@ export class Network implements INetwork {
});
}

async publishInclusionList(inclusionList: electra.NewInclusionListRequest): Promise<number> {
const fork = this.config.getForkName(inclusionList.slot);
return this.publishGossip<GossipType.inclusion_list>({type: GossipType.inclusion_list, fork}, inclusionList, {
ignoreDuplicatePublishError: true,
});
}

async publishBeaconAggregateAndProof(aggregateAndProof: phase0.SignedAggregateAndProof): Promise<number> {
const fork = this.config.getForkName(aggregateAndProof.message.aggregate.data.slot);
return this.publishGossip<GossipType.beacon_aggregate_and_proof>(
Expand Down

0 comments on commit 13f6ccc

Please sign in to comment.