@lodestar/beacon-node 1.41.0-dev.afd446235e → 1.41.0-dev.bb33751bfd
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +1 -0
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +20 -2
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +47 -0
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/blockInput/types.d.ts +2 -1
- package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/types.js +1 -0
- package/lib/chain/blocks/blockInput/types.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js +3 -0
- package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +4 -0
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +15 -7
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/constants/network.d.ts +1 -2
- package/lib/constants/network.d.ts.map +1 -1
- package/lib/constants/network.js +0 -1
- package/lib/constants/network.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts +0 -8
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +3 -48
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +3 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/util/clock.d.ts +6 -0
- package/lib/util/clock.d.ts.map +1 -1
- package/lib/util/clock.js +9 -3
- package/lib/util/clock.js.map +1 -1
- package/package.json +25 -25
- package/src/api/impl/debug/index.ts +1 -0
- package/src/chain/blocks/blockInput/blockInput.ts +68 -3
- package/src/chain/blocks/blockInput/types.ts +1 -0
- package/src/chain/blocks/verifyBlocksDataAvailability.ts +3 -0
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +9 -2
- package/src/chain/seenCache/seenGossipBlockInput.ts +16 -7
- package/src/constants/network.ts +0 -1
- package/src/network/peers/peerManager.ts +4 -61
- package/src/network/processor/gossipHandlers.ts +7 -3
- package/src/util/clock.ts +9 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {ForkName, ForkPostFulu, ForkPreDeneb, ForkPreGloas, NUMBER_OF_COLUMNS} from "@lodestar/params";
|
|
2
|
-
import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
|
|
1
|
+
import {ForkName, ForkPostFulu, ForkPostGloas, ForkPreDeneb, ForkPreGloas, NUMBER_OF_COLUMNS} from "@lodestar/params";
|
|
2
|
+
import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu, gloas} from "@lodestar/types";
|
|
3
3
|
import {byteArrayEquals, fromHex, prettyBytes, toRootHex, withTimeout} from "@lodestar/utils";
|
|
4
4
|
import {VersionedHashes} from "../../../execution/index.js";
|
|
5
5
|
import {kzgCommitmentToVersionedHash} from "../../../util/blobs.js";
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
SourceMeta,
|
|
25
25
|
} from "./types.js";
|
|
26
26
|
|
|
27
|
-
export type BlockInput = BlockInputPreData | BlockInputBlobs | BlockInputColumns;
|
|
27
|
+
export type BlockInput = BlockInputPreData | BlockInputBlobs | BlockInputColumns | BlockInputNoData;
|
|
28
28
|
|
|
29
29
|
export function isBlockInputPreDeneb(blockInput: IBlockInput): blockInput is BlockInputPreData {
|
|
30
30
|
return blockInput.type === DAType.PreData;
|
|
@@ -37,6 +37,10 @@ export function isBlockInputColumns(blockInput: IBlockInput): blockInput is Bloc
|
|
|
37
37
|
return blockInput.type === DAType.Columns;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
export function isBlockInputNoData(blockInput: IBlockInput): blockInput is BlockInputNoData {
|
|
41
|
+
return blockInput.type === DAType.NoData;
|
|
42
|
+
}
|
|
43
|
+
|
|
40
44
|
function createPromise<T>(): PromiseParts<T> {
|
|
41
45
|
let resolve!: (value: T) => void;
|
|
42
46
|
let reject!: (e: Error) => void;
|
|
@@ -903,3 +907,64 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
|
|
|
903
907
|
return Promise.resolve(this.getSampledColumns());
|
|
904
908
|
}
|
|
905
909
|
}
|
|
910
|
+
|
|
911
|
+
type BlockInputNoDataState = {
|
|
912
|
+
hasBlock: true;
|
|
913
|
+
hasAllData: true;
|
|
914
|
+
block: SignedBeaconBlock<ForkPostGloas>;
|
|
915
|
+
source: SourceMeta;
|
|
916
|
+
timeCompleteSec: number;
|
|
917
|
+
};
|
|
918
|
+
|
|
919
|
+
export class BlockInputNoData extends AbstractBlockInput<ForkPostGloas, null> {
|
|
920
|
+
type = DAType.NoData as const;
|
|
921
|
+
|
|
922
|
+
state: BlockInputNoDataState;
|
|
923
|
+
|
|
924
|
+
private constructor(init: BlockInputInit, state: BlockInputNoDataState) {
|
|
925
|
+
super(init);
|
|
926
|
+
this.state = state;
|
|
927
|
+
this.dataPromise.resolve(null);
|
|
928
|
+
this.blockPromise.resolve(state.block);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
static createFromBlock(props: AddBlock<ForkPostGloas> & CreateBlockInputMeta): BlockInputNoData {
|
|
932
|
+
const init: BlockInputInit = {
|
|
933
|
+
daOutOfRange: props.daOutOfRange,
|
|
934
|
+
timeCreated: props.seenTimestampSec,
|
|
935
|
+
forkName: props.forkName,
|
|
936
|
+
slot: props.block.message.slot,
|
|
937
|
+
blockRootHex: props.blockRootHex,
|
|
938
|
+
parentRootHex: toRootHex(props.block.message.parentRoot),
|
|
939
|
+
};
|
|
940
|
+
const state: BlockInputNoDataState = {
|
|
941
|
+
hasBlock: true,
|
|
942
|
+
hasAllData: true,
|
|
943
|
+
block: props.block,
|
|
944
|
+
source: {
|
|
945
|
+
source: props.source,
|
|
946
|
+
seenTimestampSec: props.seenTimestampSec,
|
|
947
|
+
peerIdStr: props.peerIdStr,
|
|
948
|
+
},
|
|
949
|
+
timeCompleteSec: props.seenTimestampSec,
|
|
950
|
+
};
|
|
951
|
+
return new BlockInputNoData(init, state);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
addBlock(_: AddBlock<ForkPostGloas>, opts = {throwOnDuplicateAdd: true}): void {
|
|
955
|
+
if (opts.throwOnDuplicateAdd) {
|
|
956
|
+
throw new BlockInputError(
|
|
957
|
+
{
|
|
958
|
+
code: BlockInputErrorCode.INVALID_CONSTRUCTION,
|
|
959
|
+
blockRoot: this.blockRootHex,
|
|
960
|
+
},
|
|
961
|
+
"Cannot addBlock to BlockInputNoData - block already exists"
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
getBlobKzgCommitments(): deneb.BlobKzgCommitments {
|
|
967
|
+
return (this.state.block.message.body as gloas.BeaconBlockBody).signedExecutionPayloadBid.message
|
|
968
|
+
.blobKzgCommitments;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
@@ -29,6 +29,9 @@ export async function verifyBlocksDataAvailability(
|
|
|
29
29
|
|
|
30
30
|
const availableTime = Math.max(0, Math.max(...blocks.map((blockInput) => blockInput.getTimeComplete())));
|
|
31
31
|
const dataAvailabilityStatuses: DataAvailabilityStatus[] = blocks.map((blockInput) => {
|
|
32
|
+
if (blockInput.type === DAType.NoData) {
|
|
33
|
+
return DataAvailabilityStatus.NotRequired;
|
|
34
|
+
}
|
|
32
35
|
if (blockInput.type === DAType.PreData) {
|
|
33
36
|
return DataAvailabilityStatus.PreData;
|
|
34
37
|
}
|
|
@@ -21,7 +21,7 @@ import {Metrics} from "../../metrics/metrics.js";
|
|
|
21
21
|
import {IClock} from "../../util/clock.js";
|
|
22
22
|
import {BlockError, BlockErrorCode} from "../errors/index.js";
|
|
23
23
|
import {BlockProcessOpts} from "../options.js";
|
|
24
|
-
import {isBlockInputBlobs, isBlockInputColumns} from "./blockInput/blockInput.js";
|
|
24
|
+
import {isBlockInputBlobs, isBlockInputColumns, isBlockInputNoData} from "./blockInput/blockInput.js";
|
|
25
25
|
import {IBlockInput} from "./blockInput/types.js";
|
|
26
26
|
import {ImportBlockOpts} from "./types.js";
|
|
27
27
|
|
|
@@ -51,7 +51,8 @@ type VerifyBlockExecutionResponse =
|
|
|
51
51
|
| VerifyExecutionErrorResponse
|
|
52
52
|
| {executionStatus: ExecutionStatus.Valid; lvhResponse: LVHValidResponse; execError: null}
|
|
53
53
|
| {executionStatus: ExecutionStatus.Syncing; lvhResponse?: LVHValidResponse; execError: null}
|
|
54
|
-
| {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null}
|
|
54
|
+
| {executionStatus: ExecutionStatus.PreMerge; lvhResponse: undefined; execError: null}
|
|
55
|
+
| {executionStatus: ExecutionStatus.PayloadSeparated; lvhResponse: undefined; execError: null};
|
|
55
56
|
|
|
56
57
|
/**
|
|
57
58
|
* Verifies 1 or more execution payloads from a linear sequence of blocks.
|
|
@@ -148,6 +149,12 @@ export async function verifyBlockExecutionPayload(
|
|
|
148
149
|
preState0: CachedBeaconStateAllForks
|
|
149
150
|
): Promise<VerifyBlockExecutionResponse> {
|
|
150
151
|
const block = blockInput.getBlock();
|
|
152
|
+
|
|
153
|
+
// Gloas block doesn't have execution payload. Return right away
|
|
154
|
+
if (isBlockInputNoData(blockInput)) {
|
|
155
|
+
return {executionStatus: ExecutionStatus.PayloadSeparated, lvhResponse: undefined, execError: null};
|
|
156
|
+
}
|
|
157
|
+
|
|
151
158
|
/** Not null if execution is enabled */
|
|
152
159
|
const executionPayloadEnabled =
|
|
153
160
|
isExecutionStateType(preState0) &&
|
|
@@ -3,6 +3,7 @@ import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
|
3
3
|
import {
|
|
4
4
|
ForkName,
|
|
5
5
|
ForkPostFulu,
|
|
6
|
+
ForkPostGloas,
|
|
6
7
|
ForkPreGloas,
|
|
7
8
|
SLOTS_PER_EPOCH,
|
|
8
9
|
isForkPostDeneb,
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
BlockInput,
|
|
21
22
|
BlockInputBlobs,
|
|
22
23
|
BlockInputColumns,
|
|
24
|
+
BlockInputNoData,
|
|
23
25
|
BlockInputPreData,
|
|
24
26
|
BlockWithSource,
|
|
25
27
|
DAType,
|
|
@@ -179,12 +181,19 @@ export class SeenBlockInput {
|
|
|
179
181
|
if (!blockInput) {
|
|
180
182
|
const {forkName, daOutOfRange} = this.buildCommonProps(block.message.slot);
|
|
181
183
|
|
|
182
|
-
// TODO GLOAS: Implement
|
|
183
184
|
if (isForkPostGloas(forkName)) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
// Post-gloas
|
|
186
|
+
blockInput = BlockInputNoData.createFromBlock({
|
|
187
|
+
block: block as SignedBeaconBlock<ForkPostGloas>,
|
|
188
|
+
blockRootHex,
|
|
189
|
+
daOutOfRange,
|
|
190
|
+
forkName,
|
|
191
|
+
source,
|
|
192
|
+
seenTimestampSec,
|
|
193
|
+
peerIdStr,
|
|
194
|
+
});
|
|
195
|
+
} else if (!isForkPostDeneb(forkName)) {
|
|
196
|
+
// Pre-deneb
|
|
188
197
|
blockInput = BlockInputPreData.createFromBlock({
|
|
189
198
|
block,
|
|
190
199
|
blockRootHex,
|
|
@@ -194,8 +203,8 @@ export class SeenBlockInput {
|
|
|
194
203
|
seenTimestampSec,
|
|
195
204
|
peerIdStr,
|
|
196
205
|
});
|
|
197
|
-
// Fulu Only
|
|
198
206
|
} else if (isForkPostFulu(forkName)) {
|
|
207
|
+
// Fulu Only
|
|
199
208
|
blockInput = BlockInputColumns.createFromBlock({
|
|
200
209
|
block: block as SignedBeaconBlock<ForkPostFulu & ForkPreGloas>,
|
|
201
210
|
blockRootHex,
|
|
@@ -207,8 +216,8 @@ export class SeenBlockInput {
|
|
|
207
216
|
seenTimestampSec,
|
|
208
217
|
peerIdStr,
|
|
209
218
|
});
|
|
210
|
-
// Deneb and Electra
|
|
211
219
|
} else {
|
|
220
|
+
// Deneb and Electra
|
|
212
221
|
blockInput = BlockInputBlobs.createFromBlock({
|
|
213
222
|
block: block as SignedBeaconBlock<ForkBlobsDA>,
|
|
214
223
|
blockRootHex,
|
package/src/constants/network.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Connection,
|
|
1
|
+
import {Connection, PeerId, PrivateKey} from "@libp2p/interface";
|
|
2
2
|
import {BitArray} from "@chainsafe/ssz";
|
|
3
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
4
4
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
@@ -162,9 +162,6 @@ export class PeerManager {
|
|
|
162
162
|
|
|
163
163
|
// A single map of connected peers with all necessary data to handle PINGs, STATUS, and metrics
|
|
164
164
|
private connectedPeers: Map<PeerIdStr, PeerData>;
|
|
165
|
-
/** Track one in-flight identify call per peer/connection id */
|
|
166
|
-
private readonly identifyInProgress = new Map<PeerIdStr, string>();
|
|
167
|
-
|
|
168
165
|
private opts: PeerManagerOpts;
|
|
169
166
|
private intervals: NodeJS.Timeout[] = [];
|
|
170
167
|
|
|
@@ -195,7 +192,6 @@ export class PeerManager {
|
|
|
195
192
|
|
|
196
193
|
this.libp2p.services.components.events.addEventListener(Libp2pEvent.connectionOpen, this.onLibp2pPeerConnect);
|
|
197
194
|
this.libp2p.services.components.events.addEventListener(Libp2pEvent.connectionClose, this.onLibp2pPeerDisconnect);
|
|
198
|
-
this.libp2p.services.components.events.addEventListener(Libp2pEvent.peerIdentify, this.onPeerIdentify);
|
|
199
195
|
this.networkEventBus.on(NetworkEvent.reqRespRequest, this.onRequest);
|
|
200
196
|
|
|
201
197
|
this.lastStatus = this.statusCache.get();
|
|
@@ -239,7 +235,6 @@ export class PeerManager {
|
|
|
239
235
|
Libp2pEvent.connectionClose,
|
|
240
236
|
this.onLibp2pPeerDisconnect
|
|
241
237
|
);
|
|
242
|
-
this.libp2p.services.components.events.removeEventListener(Libp2pEvent.peerIdentify, this.onPeerIdentify);
|
|
243
238
|
this.networkEventBus.off(NetworkEvent.reqRespRequest, this.onRequest);
|
|
244
239
|
for (const interval of this.intervals) clearInterval(interval);
|
|
245
240
|
}
|
|
@@ -490,25 +485,7 @@ export class PeerManager {
|
|
|
490
485
|
// peers that close identify right after connection open or turn out to be
|
|
491
486
|
// irrelevant.
|
|
492
487
|
if (peerData?.agentVersion === null) {
|
|
493
|
-
|
|
494
|
-
const connection = getConnection(this.libp2p, peerIdStr);
|
|
495
|
-
if (!connection || connection.status !== "open") {
|
|
496
|
-
this.logger.debug("Peer has no open connection for identify", {peerId: prettyPrintPeerId(peer)});
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
const identifyKey = connection.id;
|
|
501
|
-
if (this.identifyInProgress.get(peerIdStr) === identifyKey) {
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
this.identifyInProgress.set(peerIdStr, identifyKey);
|
|
506
|
-
void this.identifyPeer(peerIdStr, prettyPrintPeerId(peer), connection, identifyKey).finally(() => {
|
|
507
|
-
// Clear only if this identify attempt is still the active one for this peer
|
|
508
|
-
if (this.identifyInProgress.get(peerIdStr) === identifyKey) {
|
|
509
|
-
this.identifyInProgress.delete(peerIdStr);
|
|
510
|
-
}
|
|
511
|
-
});
|
|
488
|
+
void this.identifyPeer(peer.toString(), prettyPrintPeerId(peer), getConnection(this.libp2p, peer.toString()));
|
|
512
489
|
}
|
|
513
490
|
}
|
|
514
491
|
}
|
|
@@ -867,7 +844,6 @@ export class PeerManager {
|
|
|
867
844
|
|
|
868
845
|
// remove the ping and status timer for the peer
|
|
869
846
|
this.connectedPeers.delete(peerIdStr);
|
|
870
|
-
this.identifyInProgress.delete(peerIdStr);
|
|
871
847
|
|
|
872
848
|
this.logger.verbose(logMessage, logContext);
|
|
873
849
|
this.networkEventBus.emit(NetworkEvent.peerDisconnected, {peer: peerIdStr});
|
|
@@ -885,47 +861,14 @@ export class PeerManager {
|
|
|
885
861
|
}
|
|
886
862
|
}
|
|
887
863
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
* This captures agentVersion from identify-push or successful inbound/outbound identify,
|
|
891
|
-
* even if our explicit identify request failed earlier.
|
|
892
|
-
*/
|
|
893
|
-
private onPeerIdentify = (evt: CustomEvent<IdentifyResult>): void => {
|
|
894
|
-
const {peerId, agentVersion} = evt.detail;
|
|
895
|
-
if (!agentVersion) return;
|
|
896
|
-
|
|
897
|
-
const peerIdStr = peerId.toString();
|
|
898
|
-
const peerData = this.connectedPeers.get(peerIdStr);
|
|
899
|
-
if (!peerData) return;
|
|
900
|
-
|
|
901
|
-
peerData.agentVersion = agentVersion;
|
|
902
|
-
peerData.agentClient = getKnownClientFromAgentVersion(agentVersion);
|
|
903
|
-
this.identifyInProgress.delete(peerIdStr);
|
|
904
|
-
};
|
|
905
|
-
|
|
906
|
-
private async identifyPeer(
|
|
907
|
-
peerIdStr: string,
|
|
908
|
-
peerIdPretty: string,
|
|
909
|
-
connection: Connection,
|
|
910
|
-
identifyKey: string
|
|
911
|
-
): Promise<void> {
|
|
912
|
-
if (this.identifyInProgress.get(peerIdStr) !== identifyKey) {
|
|
913
|
-
return;
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
if (connection.status !== "open") {
|
|
864
|
+
private async identifyPeer(peerIdStr: string, peerIdPretty: string, connection?: Connection): Promise<void> {
|
|
865
|
+
if (!connection || connection.status !== "open") {
|
|
917
866
|
this.logger.debug("Peer has no open connection for identify", {peerId: peerIdPretty});
|
|
918
867
|
return;
|
|
919
868
|
}
|
|
920
869
|
|
|
921
870
|
try {
|
|
922
871
|
const result = await this.libp2p.services.identify.identify(connection);
|
|
923
|
-
|
|
924
|
-
// A newer identify attempt may have superseded this one (e.g. reconnect).
|
|
925
|
-
if (this.identifyInProgress.get(peerIdStr) !== identifyKey) {
|
|
926
|
-
return;
|
|
927
|
-
}
|
|
928
|
-
|
|
929
872
|
const agentVersion = result.agentVersion;
|
|
930
873
|
if (agentVersion) {
|
|
931
874
|
const connectedPeerData = this.connectedPeers.get(peerIdStr);
|
|
@@ -2,6 +2,7 @@ import {routes} from "@lodestar/api";
|
|
|
2
2
|
import {BeaconConfig, ChainForkConfig} from "@lodestar/config";
|
|
3
3
|
import {
|
|
4
4
|
ForkName,
|
|
5
|
+
ForkPostDeneb,
|
|
5
6
|
ForkPostElectra,
|
|
6
7
|
ForkPreElectra,
|
|
7
8
|
ForkSeq,
|
|
@@ -70,6 +71,7 @@ import {validateGossipPayloadAttestationMessage} from "../../chain/validation/pa
|
|
|
70
71
|
import {OpSource} from "../../chain/validatorMonitor.js";
|
|
71
72
|
import {Metrics} from "../../metrics/index.js";
|
|
72
73
|
import {kzgCommitmentToVersionedHash} from "../../util/blobs.js";
|
|
74
|
+
import {getBlobKzgCommitments} from "../../util/dataColumns.ts";
|
|
73
75
|
import {INetworkCore} from "../core/index.js";
|
|
74
76
|
import {NetworkEventBus} from "../events.js";
|
|
75
77
|
import {
|
|
@@ -417,9 +419,11 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
417
419
|
chain.getBlobsTracker.triggerGetBlobs(blockInput);
|
|
418
420
|
} else {
|
|
419
421
|
metrics?.blockInputFetchStats.totalDataAvailableBlockInputs.inc();
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
422
|
+
const blobCount = getBlobKzgCommitments(
|
|
423
|
+
blockInput.forkName,
|
|
424
|
+
signedBlock as SignedBeaconBlock<ForkPostDeneb>
|
|
425
|
+
).length;
|
|
426
|
+
metrics?.blockInputFetchStats.totalDataAvailableBlockInputBlobs.inc(blobCount);
|
|
423
427
|
}
|
|
424
428
|
|
|
425
429
|
chain
|
package/src/util/clock.ts
CHANGED
|
@@ -92,15 +92,17 @@ export class Clock extends EventEmitter implements IClock {
|
|
|
92
92
|
}
|
|
93
93
|
return slot;
|
|
94
94
|
}
|
|
95
|
-
|
|
96
95
|
/**
|
|
97
96
|
* If it's too close to next slot given MAXIMUM_GOSSIP_CLOCK_DISPARITY, return currentSlot + 1.
|
|
98
97
|
* Otherwise return currentSlot
|
|
98
|
+
*
|
|
99
|
+
* Spec: phase0/p2p-interface.md - gossip validation uses `current_time + MAXIMUM_GOSSIP_CLOCK_DISPARITY < message_time`
|
|
100
|
+
* to reject future messages (strict `<`), so the boundary (exactly equal) is accepted, hence `<=` here.
|
|
99
101
|
*/
|
|
100
102
|
get currentSlotWithGossipDisparity(): Slot {
|
|
101
103
|
const currentSlot = this.currentSlot;
|
|
102
104
|
const nextSlotTime = computeTimeAtSlot(this.config, currentSlot + 1, this.genesisTime) * 1000;
|
|
103
|
-
return nextSlotTime - Date.now()
|
|
105
|
+
return nextSlotTime - Date.now() <= this.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY ? currentSlot + 1 : currentSlot;
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
get currentEpoch(): Epoch {
|
|
@@ -121,6 +123,9 @@ export class Clock extends EventEmitter implements IClock {
|
|
|
121
123
|
|
|
122
124
|
/**
|
|
123
125
|
* Check if a slot is current slot given MAXIMUM_GOSSIP_CLOCK_DISPARITY.
|
|
126
|
+
*
|
|
127
|
+
* Uses `<=` for disparity checks because the spec rejects with strict `<`
|
|
128
|
+
* (phase0/p2p-interface.md), meaning the boundary (exactly equal) is accepted.
|
|
124
129
|
*/
|
|
125
130
|
isCurrentSlotGivenGossipDisparity(slot: Slot): boolean {
|
|
126
131
|
const currentSlot = this.currentSlot;
|
|
@@ -129,12 +134,12 @@ export class Clock extends EventEmitter implements IClock {
|
|
|
129
134
|
}
|
|
130
135
|
const nextSlotTime = computeTimeAtSlot(this.config, currentSlot + 1, this.genesisTime) * 1000;
|
|
131
136
|
// we're too close to next slot, accept next slot
|
|
132
|
-
if (nextSlotTime - Date.now()
|
|
137
|
+
if (nextSlotTime - Date.now() <= this.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY) {
|
|
133
138
|
return slot === currentSlot + 1;
|
|
134
139
|
}
|
|
135
140
|
const currentSlotTime = computeTimeAtSlot(this.config, currentSlot, this.genesisTime) * 1000;
|
|
136
141
|
// we've just passed the current slot, accept previous slot
|
|
137
|
-
if (Date.now() - currentSlotTime
|
|
142
|
+
if (Date.now() - currentSlotTime <= this.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY) {
|
|
138
143
|
return slot === currentSlot - 1;
|
|
139
144
|
}
|
|
140
145
|
return false;
|