@lodestar/beacon-node 1.35.0-dev.8689cc3545 → 1.35.0-dev.894daf8b44
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/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +8 -2
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/config/constants.d.ts +9 -9
- package/lib/api/impl/config/constants.js +16 -9
- package/lib/api/impl/config/constants.js.map +1 -1
- package/lib/api/impl/lodestar/index.js +1 -1
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +24 -33
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +3 -2
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +7 -6
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +1 -7
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +4 -6
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +2 -2
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/lightClient/index.d.ts +2 -2
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +2 -0
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/opPools/attestationPool.d.ts +2 -3
- package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/attestationPool.js +3 -5
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.d.ts +3 -2
- package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +6 -5
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/types.d.ts +1 -1
- package/lib/chain/opPools/types.d.ts.map +1 -1
- package/lib/chain/opPools/types.js +1 -1
- package/lib/chain/opPools/types.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts +3 -3
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +8 -8
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +1 -4
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +13 -4
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +1 -0
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +1 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +8 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +9 -8
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +1 -1
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/lightClientFinalityUpdate.d.ts.map +1 -1
- package/lib/chain/validation/lightClientFinalityUpdate.js +4 -3
- package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.d.ts +6 -4
- package/lib/chain/validation/lightClientOptimisticUpdate.d.ts.map +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.js +11 -11
- package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +21 -15
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +1 -1
- package/lib/metrics/metrics/lodestar.js +3 -3
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/gossipsub.js +1 -1
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/gossip/scoringParameters.js +4 -4
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/network.d.ts +1 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +9 -9
- package/lib/network/network.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +2 -1
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/processor/gossipHandlers.js +1 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +1 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +2 -3
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/subnets/attnetsService.d.ts.map +1 -1
- package/lib/network/subnets/attnetsService.js +1 -1
- package/lib/network/subnets/attnetsService.js.map +1 -1
- package/lib/node/notifier.js +1 -1
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/types.d.ts +0 -1
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +0 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +18 -20
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +2 -1
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +8 -3
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +2 -1
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/util/clock.d.ts +8 -3
- package/lib/util/clock.d.ts.map +1 -1
- package/lib/util/clock.js +8 -5
- package/lib/util/clock.js.map +1 -1
- package/lib/util/dataColumns.d.ts.map +1 -1
- package/lib/util/dataColumns.js +4 -2
- package/lib/util/dataColumns.js.map +1 -1
- package/package.json +14 -14
- package/src/api/impl/beacon/blocks/index.ts +11 -2
- package/src/api/impl/config/constants.ts +17 -9
- package/src/api/impl/lodestar/index.ts +1 -1
- package/src/api/impl/validator/index.ts +25 -37
- package/src/chain/archiveStore/historicalState/worker.ts +1 -1
- package/src/chain/blocks/blockInput/blockInput.ts +7 -4
- package/src/chain/blocks/importBlock.ts +8 -12
- package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -2
- package/src/chain/blocks/writeBlockInputToDb.ts +1 -9
- package/src/chain/chain.ts +3 -16
- package/src/chain/emitter.ts +2 -2
- package/src/chain/lightClient/index.ts +11 -3
- package/src/chain/opPools/attestationPool.ts +2 -3
- package/src/chain/opPools/syncCommitteeMessagePool.ts +5 -3
- package/src/chain/opPools/types.ts +1 -1
- package/src/chain/prepareNextSlot.ts +8 -8
- package/src/chain/produceBlock/produceBlockBody.ts +16 -14
- package/src/chain/regen/interface.ts +1 -0
- package/src/chain/seenCache/seenGossipBlockInput.ts +10 -2
- package/src/chain/stateCache/persistentCheckpointsCache.ts +10 -8
- package/src/chain/validation/dataColumnSidecar.ts +1 -1
- package/src/chain/validation/lightClientFinalityUpdate.ts +4 -3
- package/src/chain/validation/lightClientOptimisticUpdate.ts +12 -11
- package/src/chain/validatorMonitor.ts +28 -17
- package/src/metrics/metrics/lodestar.ts +3 -3
- package/src/network/gossip/gossipsub.ts +1 -1
- package/src/network/gossip/scoringParameters.ts +4 -4
- package/src/network/network.ts +9 -9
- package/src/network/peers/peerManager.ts +2 -1
- package/src/network/processor/gossipHandlers.ts +1 -1
- package/src/network/processor/index.ts +2 -3
- package/src/network/subnets/attnetsService.ts +3 -6
- package/src/node/notifier.ts +1 -1
- package/src/sync/types.ts +0 -2
- package/src/sync/unknownBlock.ts +19 -21
- package/src/sync/utils/downloadByRange.ts +12 -6
- package/src/sync/utils/downloadByRoot.ts +12 -4
- package/src/util/clock.ts +14 -6
- package/src/util/dataColumns.ts +11 -2
package/src/network/network.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {BeaconConfig} from "@lodestar/config";
|
|
|
7
7
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
8
8
|
import {ForkSeq} from "@lodestar/params";
|
|
9
9
|
import {ResponseIncoming} from "@lodestar/reqresp";
|
|
10
|
-
import {computeEpochAtSlot
|
|
10
|
+
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
11
11
|
import {
|
|
12
12
|
AttesterSlashing,
|
|
13
13
|
LightClientBootstrap,
|
|
@@ -689,9 +689,9 @@ export class Network implements INetwork {
|
|
|
689
689
|
// TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
|
|
690
690
|
|
|
691
691
|
try {
|
|
692
|
-
// messages SHOULD be broadcast after
|
|
692
|
+
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
693
693
|
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
694
|
-
await this.
|
|
694
|
+
await this.waitForSyncMessageCutoff(finalityUpdate.signatureSlot);
|
|
695
695
|
await this.publishLightClientFinalityUpdate(finalityUpdate);
|
|
696
696
|
} catch (e) {
|
|
697
697
|
// Non-mandatory route on most of network as of Oct 2022. May not have found any peers on topic yet
|
|
@@ -706,9 +706,9 @@ export class Network implements INetwork {
|
|
|
706
706
|
// TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
|
|
707
707
|
|
|
708
708
|
try {
|
|
709
|
-
// messages SHOULD be broadcast after
|
|
709
|
+
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
710
710
|
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
711
|
-
await this.
|
|
711
|
+
await this.waitForSyncMessageCutoff(optimisticUpdate.signatureSlot);
|
|
712
712
|
await this.publishLightClientOptimisticUpdate(optimisticUpdate);
|
|
713
713
|
} catch (e) {
|
|
714
714
|
// Non-mandatory route on most of network as of Oct 2022. May not have found any peers on topic yet
|
|
@@ -719,10 +719,10 @@ export class Network implements INetwork {
|
|
|
719
719
|
}
|
|
720
720
|
};
|
|
721
721
|
|
|
722
|
-
private
|
|
723
|
-
const
|
|
724
|
-
const
|
|
725
|
-
await sleep(
|
|
722
|
+
private waitForSyncMessageCutoff = async (slot: number): Promise<void> => {
|
|
723
|
+
const fork = this.config.getForkName(slot);
|
|
724
|
+
const msToCutoffTime = this.config.getSyncMessageDueMs(fork) - this.chain.clock.msFromSlot(slot);
|
|
725
|
+
await sleep(msToCutoffTime, this.controller.signal);
|
|
726
726
|
};
|
|
727
727
|
|
|
728
728
|
private onHead = async (): Promise<void> => {
|
|
@@ -3,6 +3,7 @@ import {BitArray} from "@chainsafe/ssz";
|
|
|
3
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
4
4
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
5
5
|
import {ForkSeq, SLOTS_PER_EPOCH, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
|
|
6
|
+
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
6
7
|
import {Metadata, Status, altair, fulu, phase0} from "@lodestar/types";
|
|
7
8
|
import {prettyPrintIndices, toHex, withTimeout} from "@lodestar/utils";
|
|
8
9
|
import {GOODBYE_KNOWN_CODES, GoodByeReasonCode, Libp2pEvent} from "../../constants/index.js";
|
|
@@ -599,7 +600,7 @@ export class PeerManager {
|
|
|
599
600
|
subnet: query.subnet,
|
|
600
601
|
type,
|
|
601
602
|
maxPeersToDiscover: query.maxPeersToDiscover,
|
|
602
|
-
toUnixMs:
|
|
603
|
+
toUnixMs: computeTimeAtSlot(this.config, query.toSlot, this.clock.genesisTime) * 1000,
|
|
603
604
|
});
|
|
604
605
|
}
|
|
605
606
|
|
|
@@ -379,7 +379,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
379
379
|
|
|
380
380
|
// Handler - MUST NOT `await`, to allow validation result to be propagated
|
|
381
381
|
|
|
382
|
-
const delaySec = seenTimestampSec - (
|
|
382
|
+
const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
|
|
383
383
|
metrics?.gossipBlock.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
|
|
384
384
|
chain.validatorMonitor?.registerBeaconBlock(OpSource.gossip, delaySec, signedBlock.message);
|
|
385
385
|
if (!blockInput.hasBlockAndAllData()) {
|
|
@@ -230,14 +230,13 @@ export class NetworkProcessor {
|
|
|
230
230
|
return queue.getAll();
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
searchUnknownSlotRoot(
|
|
234
|
-
const {slot, root} = slotRoot;
|
|
233
|
+
searchUnknownSlotRoot({slot, root}: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
|
|
235
234
|
if (this.chain.seenBlock(root) || this.unknownRootsBySlot.getOrDefault(slot).has(root)) {
|
|
236
235
|
return;
|
|
237
236
|
}
|
|
238
237
|
// Search for the unknown block
|
|
239
238
|
this.unknownRootsBySlot.getOrDefault(slot).add(root);
|
|
240
|
-
this.chain.emitter.emit(ChainEvent.unknownBlockRoot, {
|
|
239
|
+
this.chain.emitter.emit(ChainEvent.unknownBlockRoot, {rootHex: root, peer, source});
|
|
241
240
|
}
|
|
242
241
|
|
|
243
242
|
private onPendingGossipsubMessage(message: PendingGossipsubMessage): void {
|
|
@@ -163,12 +163,9 @@ export class AttnetsService implements IAttnetsService {
|
|
|
163
163
|
*/
|
|
164
164
|
private onSlot = (clockSlot: Slot): void => {
|
|
165
165
|
try {
|
|
166
|
-
setTimeout(
|
|
167
|
-
()
|
|
168
|
-
|
|
169
|
-
},
|
|
170
|
-
this.config.SECONDS_PER_SLOT * 0.5 * 1000
|
|
171
|
-
);
|
|
166
|
+
setTimeout(() => {
|
|
167
|
+
this.onHalfSlot(clockSlot);
|
|
168
|
+
}, this.config.SLOT_DURATION_MS * 0.5);
|
|
172
169
|
|
|
173
170
|
for (const [dutiedSlot, dutiedInfo] of this.aggregatorSlotSubnet.entries()) {
|
|
174
171
|
if (dutiedSlot === clockSlot + this.opts.slotsToSubscribeBeforeAggregatorDuty) {
|
package/src/node/notifier.ts
CHANGED
|
@@ -157,7 +157,7 @@ export async function runNodeNotifier(modules: NodeNotifierModules): Promise<voi
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
function timeToNextHalfSlot(config: BeaconConfig, chain: IBeaconChain, isFirstTime: boolean): number {
|
|
160
|
-
const msPerSlot = config.
|
|
160
|
+
const msPerSlot = config.SLOT_DURATION_MS;
|
|
161
161
|
const msPerHalfSlot = msPerSlot / 2;
|
|
162
162
|
const msFromGenesis = Date.now() - chain.genesisTime * 1000;
|
|
163
163
|
const msToNextSlot =
|
package/src/sync/types.ts
CHANGED
|
@@ -37,8 +37,6 @@ export type PendingBlockInput = {
|
|
|
37
37
|
export type PendingRootHex = {
|
|
38
38
|
status: PendingBlockInputStatus.pending | PendingBlockInputStatus.fetching;
|
|
39
39
|
rootHex: RootHex;
|
|
40
|
-
// optional because we may not know the slot of parent_unknown event
|
|
41
|
-
slot?: Slot;
|
|
42
40
|
timeAddedSec: number;
|
|
43
41
|
timeSyncedSec?: number;
|
|
44
42
|
peerIdStrings: Set<string>;
|
package/src/sync/unknownBlock.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ForkSeq
|
|
2
|
+
import {ForkSeq} from "@lodestar/params";
|
|
3
3
|
import {RequestError, RequestErrorCode} from "@lodestar/reqresp";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
5
|
+
import {RootHex} from "@lodestar/types";
|
|
6
|
+
import {Logger, prettyPrintIndices, pruneSetToMax, sleep} from "@lodestar/utils";
|
|
6
7
|
import {isBlockInputBlobs, isBlockInputColumns} from "../chain/blocks/blockInput/blockInput.js";
|
|
7
8
|
import {BlockInputSource, IBlockInput} from "../chain/blocks/blockInput/types.js";
|
|
8
9
|
import {BlockError, BlockErrorCode} from "../chain/errors/index.js";
|
|
@@ -78,7 +79,6 @@ export class BlockInputSync {
|
|
|
78
79
|
*/
|
|
79
80
|
private readonly pendingBlocks = new Map<RootHex, BlockInputSyncCacheItem>();
|
|
80
81
|
private readonly knownBadBlocks = new Set<RootHex>();
|
|
81
|
-
private readonly proposerBoostSecWindow: number;
|
|
82
82
|
private readonly maxPendingBlocks;
|
|
83
83
|
private subscribedToNetworkEvents = false;
|
|
84
84
|
private peerBalancer: UnknownBlockPeerBalancer;
|
|
@@ -92,7 +92,6 @@ export class BlockInputSync {
|
|
|
92
92
|
private readonly opts?: SyncOptions
|
|
93
93
|
) {
|
|
94
94
|
this.maxPendingBlocks = opts?.maxPendingBlocks ?? MAX_PENDING_BLOCKS;
|
|
95
|
-
this.proposerBoostSecWindow = this.config.SECONDS_PER_SLOT / INTERVALS_PER_SLOT;
|
|
96
95
|
this.peerBalancer = new UnknownBlockPeerBalancer();
|
|
97
96
|
|
|
98
97
|
if (metrics) {
|
|
@@ -146,8 +145,7 @@ export class BlockInputSync {
|
|
|
146
145
|
*/
|
|
147
146
|
private onUnknownBlockRoot = (data: ChainEventData[ChainEvent.unknownBlockRoot]): void => {
|
|
148
147
|
try {
|
|
149
|
-
|
|
150
|
-
this.addByRootHex(root, slot, data.peer);
|
|
148
|
+
this.addByRootHex(data.rootHex, data.peer);
|
|
151
149
|
this.triggerUnknownBlockSearch();
|
|
152
150
|
this.metrics?.blockInputSync.requests.inc({type: PendingBlockType.UNKNOWN_BLOCK_ROOT});
|
|
153
151
|
this.metrics?.blockInputSync.source.inc({source: data.source});
|
|
@@ -175,8 +173,7 @@ export class BlockInputSync {
|
|
|
175
173
|
*/
|
|
176
174
|
private onUnknownParent = (data: ChainEventData[ChainEvent.unknownParent]): void => {
|
|
177
175
|
try {
|
|
178
|
-
|
|
179
|
-
this.addByRootHex(data.blockInput.parentRootHex, undefined, data.peer);
|
|
176
|
+
this.addByRootHex(data.blockInput.parentRootHex, data.peer);
|
|
180
177
|
this.addByBlockInput(data.blockInput, data.peer);
|
|
181
178
|
this.triggerUnknownBlockSearch();
|
|
182
179
|
this.metrics?.blockInputSync.requests.inc({type: PendingBlockType.UNKNOWN_PARENT});
|
|
@@ -186,12 +183,11 @@ export class BlockInputSync {
|
|
|
186
183
|
}
|
|
187
184
|
};
|
|
188
185
|
|
|
189
|
-
private addByRootHex = (rootHex: RootHex,
|
|
186
|
+
private addByRootHex = (rootHex: RootHex, peerIdStr?: PeerIdStr): void => {
|
|
190
187
|
let pendingBlock = this.pendingBlocks.get(rootHex);
|
|
191
188
|
if (!pendingBlock) {
|
|
192
189
|
pendingBlock = {
|
|
193
190
|
status: PendingBlockInputStatus.pending,
|
|
194
|
-
slot,
|
|
195
191
|
rootHex: rootHex,
|
|
196
192
|
peerIdStrings: new Set(),
|
|
197
193
|
timeAddedSec: Date.now() / 1000,
|
|
@@ -199,7 +195,7 @@ export class BlockInputSync {
|
|
|
199
195
|
this.pendingBlocks.set(rootHex, pendingBlock);
|
|
200
196
|
|
|
201
197
|
this.logger.verbose("Added new rootHex to BlockInputSync.pendingBlocks", {
|
|
202
|
-
|
|
198
|
+
root: pendingBlock.rootHex,
|
|
203
199
|
peerIdStr: peerIdStr ?? "unknown peer",
|
|
204
200
|
});
|
|
205
201
|
}
|
|
@@ -318,7 +314,7 @@ export class BlockInputSync {
|
|
|
318
314
|
const rootHex = getBlockInputSyncCacheItemRootHex(block);
|
|
319
315
|
const logCtx = {
|
|
320
316
|
slot: getBlockInputSyncCacheItemSlot(block),
|
|
321
|
-
|
|
317
|
+
root: rootHex,
|
|
322
318
|
pendingBlocks: this.pendingBlocks.size,
|
|
323
319
|
};
|
|
324
320
|
|
|
@@ -334,7 +330,7 @@ export class BlockInputSync {
|
|
|
334
330
|
this.pendingBlocks.set(pending.blockInput.blockRootHex, pending);
|
|
335
331
|
const blockSlot = pending.blockInput.slot;
|
|
336
332
|
const finalizedSlot = this.chain.forkChoice.getFinalizedBlock().slot;
|
|
337
|
-
const delaySec = Date.now() / 1000 - (this.
|
|
333
|
+
const delaySec = Date.now() / 1000 - computeTimeAtSlot(this.config, blockSlot, this.chain.genesisTime);
|
|
338
334
|
this.metrics?.blockInputSync.elapsedTimeTillReceived.observe(delaySec);
|
|
339
335
|
|
|
340
336
|
const parentInForkChoice = this.chain.forkChoice.hasBlockHex(pending.blockInput.parentRootHex);
|
|
@@ -362,7 +358,7 @@ export class BlockInputSync {
|
|
|
362
358
|
});
|
|
363
359
|
this.removeAndDownScoreAllDescendants(block);
|
|
364
360
|
} else {
|
|
365
|
-
this.onUnknownBlockRoot({
|
|
361
|
+
this.onUnknownBlockRoot({rootHex: pending.blockInput.parentRootHex, source: BlockInputSource.byRoot});
|
|
366
362
|
}
|
|
367
363
|
} else {
|
|
368
364
|
this.metrics?.blockInputSync.downloadedBlocksError.inc();
|
|
@@ -399,18 +395,20 @@ export class BlockInputSync {
|
|
|
399
395
|
// this prevents unbundling attack
|
|
400
396
|
// see https://lighthouse-blog.sigmaprime.io/mev-unbundling-rpc.html
|
|
401
397
|
const {slot: blockSlot, proposerIndex} = pendingBlock.blockInput.getBlock().message;
|
|
398
|
+
const fork = this.config.getForkName(blockSlot);
|
|
399
|
+
const proposerBoostWindowMs = this.config.getAttestationDueMs(fork);
|
|
402
400
|
if (
|
|
403
|
-
this.chain.clock.
|
|
401
|
+
this.chain.clock.msFromSlot(blockSlot) < proposerBoostWindowMs &&
|
|
404
402
|
this.chain.seenBlockProposers.isKnown(blockSlot, proposerIndex)
|
|
405
403
|
) {
|
|
406
404
|
// proposer is known by a gossip block already, wait a bit to make sure this block is not
|
|
407
405
|
// eligible for proposer boost to prevent unbundling attack
|
|
408
406
|
this.logger.verbose("Avoid proposer boost for this block of known proposer", {
|
|
409
407
|
slot: blockSlot,
|
|
410
|
-
|
|
408
|
+
root: pendingBlock.blockInput.blockRootHex,
|
|
411
409
|
proposerIndex,
|
|
412
410
|
});
|
|
413
|
-
await sleep(
|
|
411
|
+
await sleep(proposerBoostWindowMs);
|
|
414
412
|
}
|
|
415
413
|
// At gossip time, it's critical to keep a good number of mesh peers.
|
|
416
414
|
// To do that, the Gossip Job Wait Time should be consistently <3s to avoid the behavior penalties in gossip
|
|
@@ -500,7 +498,7 @@ export class BlockInputSync {
|
|
|
500
498
|
: null;
|
|
501
499
|
|
|
502
500
|
const fetchStartSec = Date.now() / 1000;
|
|
503
|
-
let slot = isPendingBlockInput(cacheItem) ? cacheItem.blockInput.slot :
|
|
501
|
+
let slot = isPendingBlockInput(cacheItem) ? cacheItem.blockInput.slot : undefined;
|
|
504
502
|
if (slot !== undefined) {
|
|
505
503
|
this.metrics?.blockInputSync.fetchBegin.observe(this.chain.clock.secFromSlot(slot, fetchStartSec));
|
|
506
504
|
}
|
|
@@ -515,7 +513,7 @@ export class BlockInputSync {
|
|
|
515
513
|
const peerMeta = this.peerBalancer.bestPeerForPendingColumns(pendingColumns, excludedPeers);
|
|
516
514
|
if (peerMeta === null) {
|
|
517
515
|
// no more peer with needed columns to try, throw error
|
|
518
|
-
let message = `Error fetching UnknownBlockRoot slot=${slot}
|
|
516
|
+
let message = `Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: cannot find peer`;
|
|
519
517
|
if (pendingColumns) {
|
|
520
518
|
message += ` with needed columns=${prettyPrintIndices(Array.from(pendingColumns))}`;
|
|
521
519
|
}
|
|
@@ -605,7 +603,7 @@ export class BlockInputSync {
|
|
|
605
603
|
}
|
|
606
604
|
} // end while loop over peers
|
|
607
605
|
|
|
608
|
-
const message = `Error fetching BlockInput with slot=${slot}
|
|
606
|
+
const message = `Error fetching BlockInput with slot=${slot} root=${rootHex} after ${i - 1} attempts.`;
|
|
609
607
|
|
|
610
608
|
if (!isPendingBlockInput(cacheItem)) {
|
|
611
609
|
throw Error(`${message} No block and no data was found.`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ForkPostDeneb, ForkPostFulu} from "@lodestar/params";
|
|
2
|
+
import {ForkPostDeneb, ForkPostFulu, ForkPreFulu, ForkPreGloas} from "@lodestar/params";
|
|
3
3
|
import {SignedBeaconBlock, Slot, deneb, fulu, phase0} from "@lodestar/types";
|
|
4
4
|
import {LodestarError, Logger, fromHex, prettyBytes, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
5
5
|
import {
|
|
@@ -458,14 +458,16 @@ export function validateBlockByRangeResponse(
|
|
|
458
458
|
}
|
|
459
459
|
|
|
460
460
|
/**
|
|
461
|
-
* Should not be called directly. Only exported for unit testing purposes
|
|
461
|
+
* Should not be called directly. Only exported for unit testing purposes.
|
|
462
|
+
* This is used only in Deneb and Electra
|
|
462
463
|
*/
|
|
463
464
|
export async function validateBlobsByRangeResponse(
|
|
464
465
|
dataRequestBlocks: ValidatedBlock[],
|
|
465
466
|
blobSidecars: deneb.BlobSidecars
|
|
466
467
|
): Promise<ValidatedBlobSidecars[]> {
|
|
467
468
|
const expectedBlobCount = dataRequestBlocks.reduce(
|
|
468
|
-
(acc, {block}) =>
|
|
469
|
+
(acc, {block}) =>
|
|
470
|
+
(block as SignedBeaconBlock<ForkPostDeneb & ForkPreFulu>).message.body.blobKzgCommitments.length + acc,
|
|
469
471
|
0
|
|
470
472
|
);
|
|
471
473
|
if (blobSidecars.length > expectedBlobCount) {
|
|
@@ -492,7 +494,8 @@ export async function validateBlobsByRangeResponse(
|
|
|
492
494
|
const validateSidecarsPromises: Promise<ValidatedBlobSidecars>[] = [];
|
|
493
495
|
for (let blockIndex = 0, blobSidecarIndex = 0; blockIndex < dataRequestBlocks.length; blockIndex++) {
|
|
494
496
|
const {block, blockRoot} = dataRequestBlocks[blockIndex];
|
|
495
|
-
const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostDeneb>).message.body
|
|
497
|
+
const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostDeneb & ForkPreFulu>).message.body
|
|
498
|
+
.blobKzgCommitments;
|
|
496
499
|
if (blockKzgCommitments.length === 0) {
|
|
497
500
|
continue;
|
|
498
501
|
}
|
|
@@ -532,8 +535,9 @@ export async function validateColumnsByRangeResponse(
|
|
|
532
535
|
columnSidecars: fulu.DataColumnSidecars
|
|
533
536
|
): Promise<WarnResult<ValidatedColumnSidecars[], DownloadByRangeError>> {
|
|
534
537
|
// Expected column count considering currently-validated batch blocks
|
|
538
|
+
// TODO GLOAS: Post-gloas's blobKzgCommitments is not in beacon block body. Need to source it from somewhere else.
|
|
535
539
|
const expectedColumnCount = dataRequestBlocks.reduce((acc, {block}) => {
|
|
536
|
-
return (block as SignedBeaconBlock<ForkPostDeneb>).message.body.blobKzgCommitments.length > 0
|
|
540
|
+
return (block as SignedBeaconBlock<ForkPostDeneb & ForkPreGloas>).message.body.blobKzgCommitments.length > 0
|
|
537
541
|
? request.columns.length + acc
|
|
538
542
|
: acc;
|
|
539
543
|
}, 0);
|
|
@@ -566,7 +570,9 @@ export async function validateColumnsByRangeResponse(
|
|
|
566
570
|
const {block, blockRoot} = dataRequestBlocks[blockIndex];
|
|
567
571
|
const slot = block.message.slot;
|
|
568
572
|
const blockRootHex = toRootHex(blockRoot);
|
|
569
|
-
|
|
573
|
+
// TODO GLOAS: Post-gloas's blobKzgCommitments is not in beacon block body. Need to source it from somewhere else.
|
|
574
|
+
const blockKzgCommitments = (block as SignedBeaconBlock<ForkPostFulu & ForkPreGloas>).message.body
|
|
575
|
+
.blobKzgCommitments;
|
|
570
576
|
const expectedColumns = blockKzgCommitments.length ? request.columns.length : 0;
|
|
571
577
|
|
|
572
578
|
if (expectedColumns === 0) {
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
ForkPostDeneb,
|
|
5
|
+
ForkPostFulu,
|
|
6
|
+
ForkPreFulu,
|
|
7
|
+
ForkPreGloas,
|
|
8
|
+
isForkPostDeneb,
|
|
9
|
+
isForkPostFulu,
|
|
10
|
+
} from "@lodestar/params";
|
|
11
|
+
import {BeaconBlockBody, BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
|
|
5
12
|
import {LodestarError, fromHex, prettyBytes, prettyPrintIndices, toHex, toRootHex} from "@lodestar/utils";
|
|
6
13
|
import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
|
|
7
14
|
import {BlockInputSource, IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
@@ -269,7 +276,7 @@ export async function fetchByRoot({
|
|
|
269
276
|
missing: network.custodyConfig.sampledColumns,
|
|
270
277
|
});
|
|
271
278
|
} else if (isForkPostDeneb(forkName)) {
|
|
272
|
-
const commitments = (block as SignedBeaconBlock<ForkPostDeneb>).message.body.blobKzgCommitments;
|
|
279
|
+
const commitments = (block as SignedBeaconBlock<ForkPostDeneb & ForkPreFulu>).message.body.blobKzgCommitments;
|
|
273
280
|
const blobCount = commitments.length;
|
|
274
281
|
blobSidecars = await fetchAndValidateBlobs({
|
|
275
282
|
config,
|
|
@@ -369,7 +376,8 @@ export async function fetchAndValidateColumns({
|
|
|
369
376
|
}: FetchByRootAndValidateColumnsProps): Promise<WarnResult<fulu.DataColumnSidecars, DownloadByRootError>> {
|
|
370
377
|
const {peerId: peerIdStr} = peerMeta;
|
|
371
378
|
const slot = block.message.slot;
|
|
372
|
-
|
|
379
|
+
// TODO GLOAS: Get blob count from somewhere else since blobKzgCommitments is absent from block body
|
|
380
|
+
const blobCount = (block.message.body as BeaconBlockBody<ForkPostFulu & ForkPreGloas>).blobKzgCommitments.length;
|
|
373
381
|
if (blobCount === 0) {
|
|
374
382
|
return {result: [], warnings: null};
|
|
375
383
|
}
|
package/src/util/clock.ts
CHANGED
|
@@ -9,12 +9,12 @@ import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../constants/constants.js";
|
|
|
9
9
|
export enum ClockEvent {
|
|
10
10
|
/**
|
|
11
11
|
* This event signals the start of a new slot, and that subsequent calls to `clock.currentSlot` will equal `slot`.
|
|
12
|
-
* This event is guaranteed to be emitted every `
|
|
12
|
+
* This event is guaranteed to be emitted every `SLOT_DURATION_MS` milliseconds.
|
|
13
13
|
*/
|
|
14
14
|
slot = "clock:slot",
|
|
15
15
|
/**
|
|
16
16
|
* This event signals the start of a new epoch, and that subsequent calls to `clock.currentEpoch` will return `epoch`.
|
|
17
|
-
* This event is guaranteed to be emitted every `
|
|
17
|
+
* This event is guaranteed to be emitted every `SLOT_DURATION_MS * SLOTS_PER_EPOCH` milliseconds.
|
|
18
18
|
*/
|
|
19
19
|
epoch = "clock:epoch",
|
|
20
20
|
}
|
|
@@ -29,7 +29,7 @@ export type ClockEvents = {
|
|
|
29
29
|
*
|
|
30
30
|
* The time is dependent on:
|
|
31
31
|
* - `state.genesisTime` - the genesis time
|
|
32
|
-
* - `
|
|
32
|
+
* - `SLOT_DURATION_MS` - # of milliseconds per slot
|
|
33
33
|
* - `SLOTS_PER_EPOCH` - # of slots per epoch
|
|
34
34
|
*/
|
|
35
35
|
export type IClock = StrictEventEmitter<EventEmitter, ClockEvents> & {
|
|
@@ -58,6 +58,10 @@ export type IClock = StrictEventEmitter<EventEmitter, ClockEvents> & {
|
|
|
58
58
|
* Return second from a slot to either toSec or now.
|
|
59
59
|
*/
|
|
60
60
|
secFromSlot(slot: Slot, toSec?: number): number;
|
|
61
|
+
/**
|
|
62
|
+
* Return milliseconds from a slot to either toMs or now.
|
|
63
|
+
*/
|
|
64
|
+
msFromSlot(slot: Slot, toMs?: number): number;
|
|
61
65
|
};
|
|
62
66
|
|
|
63
67
|
/**
|
|
@@ -170,12 +174,16 @@ export class Clock extends EventEmitter implements IClock {
|
|
|
170
174
|
}
|
|
171
175
|
|
|
172
176
|
secFromSlot(slot: Slot, toSec = Date.now() / 1000): number {
|
|
173
|
-
return toSec - (this.
|
|
177
|
+
return toSec - computeTimeAtSlot(this.config, slot, this.genesisTime);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
msFromSlot(slot: Slot, toMs = Date.now()): number {
|
|
181
|
+
return toMs - computeTimeAtSlot(this.config, slot, this.genesisTime) * 1000;
|
|
174
182
|
}
|
|
175
183
|
|
|
176
184
|
private onNextSlot = (slot?: Slot): void => {
|
|
177
185
|
const clockSlot = slot ?? getCurrentSlot(this.config, this.genesisTime);
|
|
178
|
-
// process multiple clock slots in the case the main thread has been saturated for >
|
|
186
|
+
// process multiple clock slots in the case the main thread has been saturated for > SLOT_DURATION_MS
|
|
179
187
|
while (this._currentSlot < clockSlot && !this.signal.aborted) {
|
|
180
188
|
const previousSlot = this._currentSlot;
|
|
181
189
|
this._currentSlot++;
|
|
@@ -197,7 +205,7 @@ export class Clock extends EventEmitter implements IClock {
|
|
|
197
205
|
};
|
|
198
206
|
|
|
199
207
|
private msUntilNextSlot(): number {
|
|
200
|
-
const milliSecondsPerSlot = this.config.
|
|
208
|
+
const milliSecondsPerSlot = this.config.SLOT_DURATION_MS;
|
|
201
209
|
const diffInMilliSeconds = Date.now() - this.genesisTime * 1000;
|
|
202
210
|
return milliSecondsPerSlot - (diffInMilliSeconds % milliSecondsPerSlot);
|
|
203
211
|
}
|
package/src/util/dataColumns.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import {digest} from "@chainsafe/as-sha256";
|
|
2
2
|
import {Tree} from "@chainsafe/persistent-merkle-tree";
|
|
3
3
|
import {ChainForkConfig} from "@lodestar/config";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ForkAll,
|
|
6
|
+
ForkName,
|
|
7
|
+
ForkPostFulu,
|
|
8
|
+
ForkPreGloas,
|
|
9
|
+
KZG_COMMITMENTS_GINDEX,
|
|
10
|
+
NUMBER_OF_COLUMNS,
|
|
11
|
+
} from "@lodestar/params";
|
|
5
12
|
import {signedBlockToSignedHeader} from "@lodestar/state-transition";
|
|
6
13
|
import {
|
|
7
14
|
BeaconBlockBody,
|
|
@@ -303,7 +310,9 @@ export function getDataColumnSidecarsFromBlock(
|
|
|
303
310
|
signedBlock: SignedBeaconBlock<ForkPostFulu>,
|
|
304
311
|
cellsAndKzgProofs: {cells: Uint8Array[]; proofs: Uint8Array[]}[]
|
|
305
312
|
): fulu.DataColumnSidecars {
|
|
306
|
-
|
|
313
|
+
// TODO GLOAS: Need to get blobKzgCommitments from somewhere else
|
|
314
|
+
const blobKzgCommitments = (signedBlock.message.body as BeaconBlockBody<ForkPostFulu & ForkPreGloas>)
|
|
315
|
+
.blobKzgCommitments;
|
|
307
316
|
|
|
308
317
|
// No need to create data column sidecars if there are no blobs
|
|
309
318
|
if (blobKzgCommitments.length === 0) {
|