Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/api/test/unit/beacon/testData/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ export const eventTestData: EventData = {
proposal_slot: "10",
validator_index: "42",
fee_recipient: "0x0000000000000000000000000000000000000000",
gas_limit: "30000000",
target_gas_limit: "30000000",
},
signature:
"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
Expand Down
3 changes: 2 additions & 1 deletion packages/beacon-node/src/api/impl/beacon/pool/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ export function getBeaconPoolApi({
chain.forkChoice.notifyPtcMessages(
toRootHex(payloadAttestationMessage.data.beaconBlockRoot),
validatorCommitteeIndices,
payloadAttestationMessage.data.payloadPresent
payloadAttestationMessage.data.payloadPresent,
payloadAttestationMessage.data.blobDataAvailable
);

await network.publishPayloadAttestationMessage(payloadAttestationMessage);
Expand Down
10 changes: 9 additions & 1 deletion packages/beacon-node/src/api/impl/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1067,7 +1067,15 @@ export function getValidatorApi(

const blockIsForSlot = block.slot === slot;
const payloadInput = chain.seenPayloadEnvelopeInputCache.get(block.blockRoot);
const payloadPresent = blockIsForSlot && (payloadInput?.hasPayloadEnvelope() ?? false);
// Spec: set payload_present only if the envelope was seen before get_payload_due_ms()
// into the slot. Use the envelope's own arrival time (getPayloadEnvelopeSource), not
// the input's creation time.
const payloadDueSec = config.getPayloadDueMs() / 1000;
const payloadPresent =
blockIsForSlot &&
payloadInput !== undefined &&
payloadInput.hasPayloadEnvelope() &&
chain.clock.secFromSlot(slot, payloadInput.getPayloadEnvelopeSource().seenTimestampSec) < payloadDueSec;
const blobDataAvailable = blockIsForSlot && (payloadInput?.hasAllData() ?? false);

return {
Expand Down
3 changes: 2 additions & 1 deletion packages/beacon-node/src/chain/blocks/importBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ export async function importBlock(
this.forkChoice.notifyPtcMessages(
toRootHex(payloadAttestation.data.beaconBlockRoot),
ptcIndices,
payloadAttestation.data.payloadPresent
payloadAttestation.data.payloadPresent,
payloadAttestation.data.blobDataAvailable
);
}
} catch (e) {
Expand Down
3 changes: 2 additions & 1 deletion packages/beacon-node/src/chain/prepareNextSlot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ export class PrepareNextSlotScheduler {
// Apply parent payload once here as it's reused by EL prep and SSE emit below
let stateAfterParentPayload: IBeaconStateViewBellatrix = updatedPrepareState;
if (isStatePostGloas(updatedPrepareState)) {
if (this.chain.forkChoice.shouldExtendPayload(updatedHead.blockRoot)) {
// Spec: should_build_on_full(store, head) — see produceBlockBody.ts for context.
if (this.chain.forkChoice.shouldBuildOnFull(updatedHead)) {

@nflaig nflaig May 31, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worth noting that the timing when this is called is not correct, unless I am missing some other changes we did in the meantime but #9164 (comment) and suggestion along the lines here #9164 (comment) are still relevant

we will still reorg the payload when we call shouldBuildOnFull() == false in produceBlockBody.ts but that's at the start of the next slot and the execution payload we prepared here will be on top of the blockHash and not the parentBlockHash

likely delaying this call to PTC deadline + 1 second is fine, but may not be ideal as we also don't wanna delay the FCU for too long as it gives less time to the execution client

likely the ideal approach is

  • call FCU at 8 seconds (as today) if we have verified the parent's payload, or as soon as we receive it afterswards
  • evaluate shouldBuildOnFull() again at ~10 seconds (with PTC votes), or proactively if threshold is reached via event based trigger (something like here) and if parentBlockHash changes, call FCU again, overriding the previous call
  • keep the final decision in produceBlockBody.ts at start of next slot but it should be rare that the parentBlockHash will be different from the prepared block hash if we follow the above

also I noticed we should probably add more logs here to know if we do a payload reorg

parentBlockHash = updatedPrepareState.latestExecutionPayloadBid.blockHash;
// Skip applying parent payload unless we're proposing the next slot or have to emit payload_attributes events
if (feeRecipient !== undefined || this.chain.opts.emitPayloadAttributes === true) {
Expand Down
68 changes: 65 additions & 3 deletions packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
G2_POINT_AT_INFINITY,
IBeaconStateView,
type IBeaconStateViewBellatrix,
type IBeaconStateViewGloas,
computeEpochAtSlot,
computeTimeAtSlot,
isStatePostBellatrix,
isStatePostCapella,
Expand Down Expand Up @@ -58,10 +60,12 @@ import {
PayloadId,
getExpectedGasLimit,
} from "../../execution/index.js";
import {getShufflingDependentRoot} from "../../util/dependentRoot.js";
import {fromGraffitiBytes} from "../../util/graffiti.js";
import {kzg} from "../../util/kzg.js";
import type {BeaconChain} from "../chain.js";
import {CommonBlockBody} from "../interface.js";
import {ProposerPreferencesPool} from "../opPools/index.js";
import {validateBlobsAndKzgCommitments, validateCellsAndKzgCommitments} from "./validateBlobsAndKzgCommitments.js";

// Time to provide the EL to generate a payload from new payload id
Expand Down Expand Up @@ -204,6 +208,9 @@ export async function produceBlockBody<T extends BlockType>(
// this into a completely separate function and have pre/post gloas more separated
const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice);
const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
// TODO GLOAS: post-Gloas, proposer feeRecipient is also carried (signed) in
// ProposerPreferencesPool. Consider using this unified cache instead
// see https://github.com/ChainSafe/lodestar/issues/9379
const feeRecipient = requestedFeeRecipient ?? this.beaconProposerCache.getOrDefault(proposerIndex);

const endExecutionPayload = this.metrics?.executionBlockProductionTimeSteps.startTimer();
Expand All @@ -219,8 +226,11 @@ export async function produceBlockBody<T extends BlockType>(
let parentExecutionRequests: electra.ExecutionRequests;
// Apply parent payload once here as it's reused by EL prep and voluntary exit filtering below
let stateAfterParentPayload: IBeaconStateViewBellatrix = currentState;
const isExtendingPayload = this.forkChoice.shouldExtendPayload(toRootHex(parentBlockRoot));
if (isExtendingPayload) {
// Spec: should_build_on_full(store, head). `parentBlock` is the proposer's head
// (set by chain.getProposerHead(slot)). Returns false when the PTC majority
// signalled the blob data is not available, forcing a build on EMPTY (reorg).
const isBuildingOnFull = this.forkChoice.shouldBuildOnFull(parentBlock);
if (isBuildingOnFull) {
parentBlockHash = currentState.latestExecutionPayloadBid.blockHash;
parentExecutionRequests = await this.getParentExecutionRequests(parentBlock.slot, parentBlock.blockRoot);
stateAfterParentPayload = currentState.withParentPayloadApplied(parentExecutionRequests);
Expand Down Expand Up @@ -299,7 +309,7 @@ export async function produceBlockBody<T extends BlockType>(
// Drop voluntary exits that parent_execution_requests have invalidated (e.g. a withdrawal
// request initiating an exit on the same validator). Op pool selected against the unapplied
// state, so re-validate against the post-apply state to avoid producing an invalid block.
if (isExtendingPayload && commonBlockBody.voluntaryExits.length > 0) {
if (isBuildingOnFull && commonBlockBody.voluntaryExits.length > 0) {
gloasBody.voluntaryExits = commonBlockBody.voluntaryExits.filter((signedVoluntaryExit) =>
stateAfterParentPayload.isValidVoluntaryExit(signedVoluntaryExit, false)
);
Expand Down Expand Up @@ -633,6 +643,8 @@ export async function prepareExecutionPayload(
chain: {
executionEngine: IExecutionEngine;
config: ChainForkConfig;
forkChoice: IForkChoice;
proposerPreferencesPool: ProposerPreferencesPool;
},
logger: Logger,
fork: ForkPostBellatrix,
Expand Down Expand Up @@ -733,6 +745,7 @@ export function getPayloadAttributesForSSE(
chain: {
config: ChainForkConfig;
forkChoice: IForkChoice;
proposerPreferencesPool: ProposerPreferencesPool;
},
{
prepareState,
Expand Down Expand Up @@ -789,6 +802,8 @@ function preparePayloadAttributes(
fork: ForkPostBellatrix,
chain: {
config: ChainForkConfig;
forkChoice: IForkChoice;
proposerPreferencesPool: ProposerPreferencesPool;
},
{
prepareState,
Expand Down Expand Up @@ -851,12 +866,59 @@ function preparePayloadAttributes(
}

if (ForkSeq[fork] >= ForkSeq.gloas) {
if (!isStatePostGloas(prepareState)) {
throw new Error("Expected Gloas state for Gloas payload attributes");
}
(payloadAttributes as gloas.SSEPayloadAttributes["payloadAttributes"]).slotNumber = prepareSlot;
(payloadAttributes as gloas.SSEPayloadAttributes["payloadAttributes"]).targetGasLimit = getProposerTargetGasLimit(
chain,
prepareState,
prepareSlot,
parentBlockRoot
);
}

return payloadAttributes;
}

/**
* Resolve the proposer's preferred (target) gas limit for the Gloas `PayloadAttributesV4`
* `targetGasLimit` field (consensus-specs#5235, execution-apis#796).
*
* Sourced from the `SignedProposerPreferences` the proposer's VC submitted to the pool
* (same `(slot, dependent_root)` lookup as gossip bid validation). When no matching
* preferences are pooled, target the parent payload's gas limit so the gas limit stays
* unchanged (`is_gas_limit_target_compatible` then requires `gas_limit == parent_gas_limit`).
*/
function getProposerTargetGasLimit(
chain: {forkChoice: IForkChoice; proposerPreferencesPool: ProposerPreferencesPool},
state: IBeaconStateViewGloas,
prepareSlot: Slot,
parentBlockRoot: Root
): number {
const parentBlock = chain.forkChoice.getBlockHexDefaultStatus(toRootHex(parentBlockRoot));
const dependentRootHex = (() => {
if (parentBlock === null) {
return null;
}
try {
return getShufflingDependentRoot(
chain.forkChoice,
computeEpochAtSlot(prepareSlot),
computeEpochAtSlot(parentBlock.slot),
parentBlock
);
} catch {
return null;
}
})();

const pref = dependentRootHex !== null ? chain.proposerPreferencesPool.get(prepareSlot, dependentRootHex) : null;
// TODO GLOAS: state.latestExecutionPayloadBid is the latest *bid*, not the latest *executed*
// payload — for EMPTY parents this drifts. Consider having a default value like Prysm's DefaultBuilderGasLimit.
return Number(pref ? pref.message.targetGasLimit : state.latestExecutionPayloadBid.gasLimit);
Comment on lines +917 to +919

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The fallback to state.latestExecutionPayloadBid.gasLimit when no proposer preferences are pooled might be problematic if the parent block was EMPTY. In that case, the bid in the state reflects the proposer's intent for the skipped payload, which may have drifted from the actual gas limit of the last executed block. Consider using a safer default or a value derived from the last successfully executed payload header if available.

}

export async function produceCommonBlockBody<T extends BlockType>(
this: BeaconChain,
blockType: T,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,14 @@ async function validateExecutionPayloadBid(
});
}

// [REJECT] `bid.gas_limit == proposer_preferences.gas_limit`.
// [REJECT] `bid.gas_limit == proposer_preferences.target_gas_limit`.
const bidGasLimit = Number(bid.gasLimit);
if (bidGasLimit !== proposerPreferences.message.gasLimit) {
if (bidGasLimit !== proposerPreferences.message.targetGasLimit) {
throw new ExecutionPayloadBidError(GossipAction.REJECT, {
code: ExecutionPayloadBidErrorCode.PROPOSER_PREFERENCES_GAS_LIMIT_MISMATCH,
builderIndex: bid.builderIndex,
bidGasLimit,
expectedGasLimit: proposerPreferences.message.gasLimit,
expectedGasLimit: proposerPreferences.message.targetGasLimit,
});
}

Expand Down
1 change: 1 addition & 0 deletions packages/beacon-node/src/execution/engine/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export type PayloadAttributes = {
withdrawals?: capella.Withdrawal[];
parentBeaconBlockRoot?: Uint8Array;
slotNumber?: number; // EIP-7843
targetGasLimit?: number; // GLOAS (PayloadAttributesV4, execution-apis#796)
};

export type VersionedHashes = Uint8Array[];
Expand Down
4 changes: 4 additions & 0 deletions packages/beacon-node/src/execution/engine/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ export type PayloadAttributesRpc = {
parentBeaconBlockRoot?: DATA;
/** QUANTITY, 64 Bits - value for the slot number field of the new payload (EIP-7843) */
slotNumber?: QUANTITY;
/** QUANTITY, 64 Bits - target value for the gasLimit field of the new payload (GLOAS, execution-apis#796) */
targetGasLimit?: QUANTITY;
};

export type ClientVersionRpc = {
Expand Down Expand Up @@ -425,6 +427,7 @@ export function serializePayloadAttributes(data: PayloadAttributes): PayloadAttr
withdrawals: data.withdrawals?.map(serializeWithdrawal),
parentBeaconBlockRoot: data.parentBeaconBlockRoot ? bytesToData(data.parentBeaconBlockRoot) : undefined,
slotNumber: data.slotNumber !== undefined ? numToQuantity(data.slotNumber) : undefined,
targetGasLimit: data.targetGasLimit !== undefined ? numToQuantity(data.targetGasLimit) : undefined,
};
}

Expand All @@ -442,6 +445,7 @@ export function deserializePayloadAttributes(data: PayloadAttributesRpc): Payloa
withdrawals: data.withdrawals?.map((withdrawal) => deserializeWithdrawal(withdrawal)),
parentBeaconBlockRoot: data.parentBeaconBlockRoot ? dataToBytes(data.parentBeaconBlockRoot, 32) : undefined,
slotNumber: data.slotNumber !== undefined ? quantityToNum(data.slotNumber) : undefined,
targetGasLimit: data.targetGasLimit !== undefined ? quantityToNum(data.targetGasLimit) : undefined,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
chain.forkChoice.notifyPtcMessages(
toRootHex(payloadAttestationMessage.data.beaconBlockRoot),
validationResult.validatorCommitteeIndices,
payloadAttestationMessage.data.payloadPresent
payloadAttestationMessage.data.payloadPresent,
payloadAttestationMessage.data.blobDataAvailable
);
},
[GossipType.execution_payload_bid]: async ({
Expand Down
7 changes: 4 additions & 3 deletions packages/beacon-node/test/spec/utils/specTestIterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ export const defaultSkipOpts: SkipOpts = {
// TODO-GLOAS: re-enable after Gloas light client is implemented
/^gloas\/light_client\/.*/,
/^gloas\/ssz_static\/LightClient(Bootstrap|FinalityUpdate|Header|OptimisticUpdate|Update)\/.*/,
// TODO-GLOAS: re-enable after on_payload_attestation_message (PTC) fork choice is implemented.
// New test suite added in v1.7.0-alpha.8 (consensus-specs #5206); gloas PTC fork choice
// handling is not yet implemented in Lodestar.
/^gloas\/fork_choice\/on_payload_attestation_message\/.*$/,
],
skippedTests: [
// TODO-GLOAS: re-enable after gloas light client is implemented
/\/gloas_fork$/,
// TODOGLOAS: re-enable after upgrading to v1.7.0-alpha.8
// (which includes #5254). https://github.com/ethereum/consensus-specs/pull/5254
/^gloas\/fork\/fork\/pyspec_tests\/fork_invalid_validator_deposit_followed_by_builder_credentials$/,
],
// TODO GLOAS: Investigate why networking tests are failing since alpha.5
skippedRunners: ["fast_confirmation", "networking"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import {ProtoBlock} from "@lodestar/fork-choice";
import {toRootHex} from "@lodestar/utils";
import {getValidatorApi} from "../../../../../src/api/impl/validator/index.js";
import {defaultApiOptions} from "../../../../../src/api/options.js";
import {PayloadEnvelopeInput} from "../../../../../src/chain/blocks/payloadEnvelopeInput/index.js";
import {
PayloadEnvelopeInput,
PayloadEnvelopeInputSource,
} from "../../../../../src/chain/blocks/payloadEnvelopeInput/index.js";
import {ZERO_HASH_HEX} from "../../../../../src/constants/index.js";
import {SyncState} from "../../../../../src/sync/interface.js";
import {ApiTestModules, getApiTestModules} from "../../../../utils/api.js";
Expand Down Expand Up @@ -66,8 +69,10 @@ describe("api - validator - produceAttestationData", () => {
slot: 0,
blockRoot: ZERO_HASH_HEX,
} as ProtoBlock);
vi.mocked(modules.chain.clock.secFromSlot).mockReturnValue(0);
vi.mocked(modules.chain.seenPayloadEnvelopeInputCache.get).mockReturnValue({
hasPayloadEnvelope: () => true,
getPayloadEnvelopeSource: () => ({source: PayloadEnvelopeInputSource.gossip, seenTimestampSec: 0}),
hasAllData: () => true,
} as PayloadEnvelopeInput);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe("chain / opPools / ProposerPreferencesPool", () => {
proposalSlot,
validatorIndex,
feeRecipient: Buffer.alloc(20, 0xab),
gasLimit: 30_000_000,
targetGasLimit: 30_000_000,
},
signature: Buffer.alloc(96, 0),
});
Expand Down
6 changes: 4 additions & 2 deletions packages/config/src/chainConfig/configs/mainnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ export const chainConfig: ChainConfig = {
SECONDS_PER_ETH1_BLOCK: 14,
// 2**8 (= 256) epochs ~27 hours
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256,
// 2**6 (= 64) epochs
MIN_BUILDER_WITHDRAWABILITY_DELAY: 64,
// 2**13 (= 8,192) epochs ~36 days
MIN_BUILDER_WITHDRAWABILITY_DELAY: 8192,
// 2**8 (= 256) epochs ~27 hours
SHARD_COMMITTEE_PERIOD: 256,
// 2**11 (= 2,048) Eth1 blocks ~8 hours
Expand Down Expand Up @@ -99,6 +99,8 @@ export const chainConfig: ChainConfig = {
CONTRIBUTION_DUE_BPS_GLOAS: 5000,
// 75% of SLOT_DURATION_MS
PAYLOAD_ATTESTATION_DUE_BPS: 7500,
// 75% of SLOT_DURATION_MS
PAYLOAD_DUE_BPS: 7500,

// Validator cycle
// ---------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions packages/config/src/chainConfig/configs/minimal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ export const chainConfig: ChainConfig = {
CONTRIBUTION_DUE_BPS_GLOAS: 5000,
// 75% of SLOT_DURATION_MS
PAYLOAD_ATTESTATION_DUE_BPS: 7500,
// 75% of SLOT_DURATION_MS
PAYLOAD_DUE_BPS: 7500,

// Validator cycle
// ---------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions packages/config/src/chainConfig/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export type ChainConfig = {
SYNC_MESSAGE_DUE_BPS_GLOAS: number;
CONTRIBUTION_DUE_BPS_GLOAS: number;
PAYLOAD_ATTESTATION_DUE_BPS: number;
PAYLOAD_DUE_BPS: number;

// Validator cycle
INACTIVITY_SCORE_BIAS: number;
Expand Down Expand Up @@ -191,6 +192,7 @@ export const chainConfigTypes: SpecTypes<ChainConfig> = {
SYNC_MESSAGE_DUE_BPS_GLOAS: "number",
CONTRIBUTION_DUE_BPS_GLOAS: "number",
PAYLOAD_ATTESTATION_DUE_BPS: "number",
PAYLOAD_DUE_BPS: "number",

// Validator cycle
INACTIVITY_SCORE_BIAS: "number",
Expand Down
3 changes: 3 additions & 0 deletions packages/config/src/forkConfig/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ export function createForkConfig(config: ChainConfig): ForkConfig {
getProposerReorgCutoffMs(_fork: ForkName): number {
return this.getSlotComponentDurationMs(config.PROPOSER_REORG_CUTOFF_BPS);
},
getPayloadDueMs(): number {
return this.getSlotComponentDurationMs(config.PAYLOAD_DUE_BPS);
},

getSlotComponentDurationMs(basisPoints: number): number {
return Math.round((basisPoints * config.SLOT_DURATION_MS) / BASIS_POINTS);
Expand Down
1 change: 1 addition & 0 deletions packages/config/src/forkConfig/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export type ForkConfig = {
getSyncMessageDueMs(fork: ForkName): number;
getSyncContributionDueMs(fork: ForkName): number;
getProposerReorgCutoffMs(fork: ForkName): number;
getPayloadDueMs(): number;

/** Convert basis points to milliseconds into the slot */
getSlotComponentDurationMs(basisPoints: number): number;
Expand Down
14 changes: 12 additions & 2 deletions packages/fork-choice/src/forkChoice/forkChoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,11 @@ export class ForkChoice implements IForkChoice {
return this.protoArray.shouldExtendPayload(blockRoot, this.proposerBoostRoot);
}

/** Spec: should_build_on_full(store, head) */
shouldBuildOnFull(head: ProtoBlock): boolean {
return this.protoArray.shouldBuildOnFull(head);
}

/**
* To predict the proposer head of the next slot. That is, to predict if proposer-boost-reorg could happen.
* Reason why we can't be certain is because information of the head block is not fully available yet
Expand Down Expand Up @@ -934,8 +939,13 @@ export class ForkChoice implements IForkChoice {
* Updates the PTC votes for multiple validators attesting to a block
* Spec: gloas/fork-choice.md#new-on_payload_attestation_message
*/
notifyPtcMessages(blockRoot: RootHex, ptcIndices: number[], payloadPresent: boolean): void {
this.protoArray.notifyPtcMessages(blockRoot, ptcIndices, payloadPresent);
notifyPtcMessages(
blockRoot: RootHex,
ptcIndices: number[],
payloadPresent: boolean,
blobDataAvailable: boolean
): void {
this.protoArray.notifyPtcMessages(blockRoot, ptcIndices, payloadPresent, blobDataAvailable);
}

/**
Expand Down
Loading
Loading