@lodestar/beacon-node 1.41.0-dev.aeb5a213ee → 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/beacon/state/index.js +8 -8
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +3 -4
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js +4 -4
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- 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/api/impl/node/utils.d.ts +1 -1
- package/lib/api/impl/node/utils.d.ts.map +1 -1
- package/lib/api/impl/node/utils.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +3 -5
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +5 -6
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js +9 -10
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +3 -3
- package/lib/chain/archiveStore/historicalState/worker.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/bls/multithread/index.d.ts +3 -3
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +5 -5
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/jobItem.d.ts +2 -2
- package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
- package/lib/chain/bls/multithread/jobItem.js +2 -2
- package/lib/chain/bls/multithread/jobItem.js.map +1 -1
- package/lib/chain/bls/singleThread.d.ts +4 -4
- package/lib/chain/bls/singleThread.d.ts.map +1 -1
- package/lib/chain/bls/singleThread.js +4 -4
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.d.ts +2 -2
- package/lib/chain/bls/utils.d.ts.map +1 -1
- package/lib/chain/bls/utils.js +7 -4
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/chain.d.ts +4 -7
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +8 -10
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -4
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.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/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +4 -1
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +1 -1
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +8 -1
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +1 -1
- package/lib/db/repositories/blockArchive.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.js +1 -2
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/execution/engine/http.d.ts +1 -0
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +3 -0
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +3 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +5 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/monitoring/service.d.ts +2 -2
- package/lib/monitoring/service.d.ts.map +1 -1
- package/lib/monitoring/service.js +3 -2
- package/lib/monitoring/service.js.map +1 -1
- package/lib/network/core/networkCore.d.ts +3 -3
- package/lib/network/core/networkCore.d.ts.map +1 -1
- package/lib/network/core/networkCore.js.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.d.ts +3 -3
- package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
- package/lib/network/core/types.d.ts +2 -2
- package/lib/network/core/types.d.ts.map +1 -1
- package/lib/network/events.d.ts +2 -1
- package/lib/network/events.d.ts.map +1 -1
- package/lib/network/events.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts +3 -3
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/gossipsub.d.ts +13 -4
- package/lib/network/gossip/gossipsub.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.js +47 -20
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +3 -3
- package/lib/network/gossip/interface.d.ts.map +1 -1
- package/lib/network/gossip/scoringParameters.d.ts +1 -1
- package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
- package/lib/network/gossip/scoringParameters.js +1 -1
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/interface.d.ts +3 -3
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/libp2p/index.d.ts +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +7 -2
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts +2 -2
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js.map +1 -1
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js +3 -0
- package/lib/network/options.js.map +1 -1
- package/lib/network/peers/datastore.d.ts +7 -5
- package/lib/network/peers/datastore.d.ts.map +1 -1
- package/lib/network/peers/datastore.js +10 -10
- package/lib/network/peers/datastore.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts +3 -0
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +103 -53
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/peers/utils/prioritizePeers.d.ts +3 -3
- package/lib/network/peers/utils/prioritizePeers.d.ts.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/network/processor/gossipValidatorFn.js +1 -1
- package/lib/network/processor/types.d.ts +1 -1
- package/lib/network/processor/types.d.ts.map +1 -1
- package/lib/network/reqresp/score.d.ts.map +1 -1
- package/lib/network/reqresp/score.js +0 -1
- package/lib/network/reqresp/score.js.map +1 -1
- package/lib/network/util.js +2 -2
- package/lib/network/util.js.map +1 -1
- package/lib/node/nodejs.d.ts +3 -5
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +6 -4
- package/lib/node/nodejs.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 +38 -41
- package/src/api/impl/beacon/state/index.ts +8 -8
- package/src/api/impl/beacon/state/utils.ts +5 -6
- package/src/api/impl/debug/index.ts +1 -0
- package/src/api/impl/node/utils.ts +3 -3
- package/src/api/impl/validator/index.ts +3 -4
- package/src/chain/archiveStore/historicalState/getHistoricalState.ts +10 -11
- package/src/chain/archiveStore/historicalState/worker.ts +3 -3
- 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/bls/multithread/index.ts +7 -7
- package/src/chain/bls/multithread/jobItem.ts +3 -3
- package/src/chain/bls/singleThread.ts +5 -5
- package/src/chain/bls/utils.ts +8 -5
- package/src/chain/chain.ts +10 -15
- package/src/chain/interface.ts +2 -9
- package/src/chain/seenCache/seenGossipBlockInput.ts +16 -7
- package/src/chain/validation/attestation.ts +4 -1
- package/src/chain/validation/attesterSlashing.ts +1 -1
- package/src/chain/validation/payloadAttestationMessage.ts +9 -1
- package/src/chain/validation/proposerSlashing.ts +1 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +1 -1
- package/src/db/repositories/blockArchive.ts +1 -2
- package/src/execution/engine/http.ts +3 -0
- package/src/metrics/metrics/lodestar.ts +5 -0
- package/src/monitoring/service.ts +3 -2
- package/src/network/core/networkCore.ts +3 -3
- package/src/network/core/networkCoreWorkerHandler.ts +3 -3
- package/src/network/core/types.ts +2 -2
- package/src/network/events.ts +2 -1
- package/src/network/gossip/encoding.ts +3 -3
- package/src/network/gossip/gossipsub.ts +86 -25
- package/src/network/gossip/interface.ts +3 -3
- package/src/network/gossip/scoringParameters.ts +4 -4
- package/src/network/interface.ts +3 -3
- package/src/network/libp2p/index.ts +8 -3
- package/src/network/network.ts +3 -3
- package/src/network/options.ts +3 -0
- package/src/network/peers/datastore.ts +13 -10
- package/src/network/peers/peerManager.ts +118 -54
- package/src/network/peers/utils/prioritizePeers.ts +3 -3
- package/src/network/processor/gossipHandlers.ts +7 -3
- package/src/network/processor/gossipValidatorFn.ts +1 -1
- package/src/network/processor/types.ts +1 -1
- package/src/network/reqresp/score.ts +0 -1
- package/src/network/util.ts +2 -2
- package/src/node/nodejs.ts +8 -9
- package/src/util/clock.ts +9 -4
- package/src/util/workerEvents.ts +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {Message, TopicValidatorResult} from "@libp2p/
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type {Message, TopicValidatorResult} from "@libp2p/gossipsub";
|
|
2
|
+
import type {PeerIdStr} from "@libp2p/gossipsub/types";
|
|
3
|
+
import type {Libp2p} from "libp2p";
|
|
4
4
|
import {BeaconConfig, ForkBoundary} from "@lodestar/config";
|
|
5
5
|
import {
|
|
6
6
|
AttesterSlashing,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
PeerScoreParams,
|
|
3
|
-
PeerScoreThresholds,
|
|
4
|
-
TopicScoreParams,
|
|
2
|
+
type PeerScoreParams,
|
|
3
|
+
type PeerScoreThresholds,
|
|
4
|
+
type TopicScoreParams,
|
|
5
5
|
defaultTopicScoreParams,
|
|
6
|
-
} from "@
|
|
6
|
+
} from "@libp2p/gossipsub/score";
|
|
7
7
|
import {BeaconConfig} from "@lodestar/config";
|
|
8
8
|
import {ATTESTATION_SUBNET_COUNT, PTC_SIZE, SLOTS_PER_EPOCH, TARGET_AGGREGATORS_PER_COMMITTEE} from "@lodestar/params";
|
|
9
9
|
import {computeCommitteeCount} from "@lodestar/state-transition";
|
package/src/network/interface.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {Identify} from "@libp2p/identify";
|
|
2
|
-
import {
|
|
1
|
+
import type {Identify} from "@libp2p/identify";
|
|
2
|
+
import type {
|
|
3
3
|
ComponentLogger,
|
|
4
4
|
ConnectionGater,
|
|
5
5
|
ConnectionProtector,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "@libp2p/interface";
|
|
17
17
|
import type {AddressManager, ConnectionManager, Registrar, TransportManager} from "@libp2p/interface-internal";
|
|
18
18
|
import type {Datastore} from "interface-datastore";
|
|
19
|
-
import {Libp2p as ILibp2p} from "libp2p";
|
|
19
|
+
import type {Libp2p as ILibp2p} from "libp2p";
|
|
20
20
|
import {
|
|
21
21
|
AttesterSlashing,
|
|
22
22
|
DataColumnSidecar,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {bootstrap} from "@libp2p/bootstrap";
|
|
2
2
|
import {identify} from "@libp2p/identify";
|
|
3
|
-
import {PrivateKey} from "@libp2p/interface";
|
|
3
|
+
import type {PrivateKey} from "@libp2p/interface";
|
|
4
4
|
import {mdns} from "@libp2p/mdns";
|
|
5
5
|
import {mplex} from "@libp2p/mplex";
|
|
6
6
|
import {prometheusMetrics} from "@libp2p/prometheus-metrics";
|
|
@@ -39,6 +39,7 @@ export async function createNodeJsLibp2p(
|
|
|
39
39
|
nodeJsLibp2pOpts: NodeJsLibp2pOpts = {}
|
|
40
40
|
): Promise<Libp2p> {
|
|
41
41
|
const localMultiaddrs = networkOpts.localMultiaddrs || defaultNetworkOptions.localMultiaddrs;
|
|
42
|
+
const disconnectThreshold = networkOpts.disconnectThreshold ?? defaultNetworkOptions.disconnectThreshold;
|
|
42
43
|
const {peerStoreDir, disablePeerDiscovery} = nodeJsLibp2pOpts;
|
|
43
44
|
|
|
44
45
|
let datastore: undefined | Eth2PeerDataStore = undefined;
|
|
@@ -74,6 +75,11 @@ export async function createNodeJsLibp2p(
|
|
|
74
75
|
|
|
75
76
|
return createLibp2p({
|
|
76
77
|
privateKey,
|
|
78
|
+
nodeInfo: {
|
|
79
|
+
name: "lodestar",
|
|
80
|
+
version: networkOpts.version ?? "unknown",
|
|
81
|
+
userAgent: networkOpts.private ? "" : networkOpts.version ? `lodestar/${networkOpts.version}` : "lodestar",
|
|
82
|
+
},
|
|
77
83
|
addresses: {
|
|
78
84
|
listen: localMultiaddrs,
|
|
79
85
|
announce: [],
|
|
@@ -93,7 +99,7 @@ export async function createNodeJsLibp2p(
|
|
|
93
99
|
},
|
|
94
100
|
}),
|
|
95
101
|
],
|
|
96
|
-
streamMuxers: [mplex({
|
|
102
|
+
streamMuxers: [mplex({disconnectThreshold})],
|
|
97
103
|
peerDiscovery,
|
|
98
104
|
metrics: nodeJsLibp2pOpts.metrics
|
|
99
105
|
? prometheusMetrics({
|
|
@@ -124,7 +130,6 @@ export async function createNodeJsLibp2p(
|
|
|
124
130
|
datastore,
|
|
125
131
|
services: {
|
|
126
132
|
identify: identify({
|
|
127
|
-
agentVersion: networkOpts.private ? "" : networkOpts.version ? `lodestar/${networkOpts.version}` : "lodestar",
|
|
128
133
|
runOnConnectionOpen: false,
|
|
129
134
|
}),
|
|
130
135
|
// individual components are specified because the components object is a Proxy
|
package/src/network/network.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {PeerScoreStatsDump} from "@libp2p/gossipsub/score";
|
|
2
|
+
import type {PublishOpts} from "@libp2p/gossipsub/types";
|
|
3
|
+
import type {PeerId, PrivateKey} from "@libp2p/interface";
|
|
2
4
|
import {peerIdFromPrivateKey} from "@libp2p/peer-id";
|
|
3
|
-
import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/score";
|
|
4
|
-
import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types";
|
|
5
5
|
import {routes} from "@lodestar/api";
|
|
6
6
|
import {BeaconConfig} from "@lodestar/config";
|
|
7
7
|
import {LoggerNode} from "@lodestar/logger/node";
|
package/src/network/options.ts
CHANGED
|
@@ -72,4 +72,7 @@ export const defaultNetworkOptions: NetworkOptions = {
|
|
|
72
72
|
// - for fusaka-devnets, we have 25-30 peers per subnet
|
|
73
73
|
// - for public testnets or mainnet, average number of peers per group is SAMPLES_PER_SLOT * targetPeers / NUMBER_OF_CUSTODY_GROUPS = 6.25 so this should not be an issue
|
|
74
74
|
targetGroupPeers: 6,
|
|
75
|
+
// Keep this high enough for normal req/resp bursts on stable connections.
|
|
76
|
+
// libp2p-mplex default (5) is too low and can cause frequent connection resets.
|
|
77
|
+
disconnectThreshold: 50,
|
|
75
78
|
};
|
|
@@ -8,6 +8,9 @@ type MemoryItem = {
|
|
|
8
8
|
data: Uint8Array;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
// biome-ignore lint/suspicious/noExplicitAny: used below (copied from upstream)
|
|
12
|
+
type AwaitGenerator<T, TReturn = any, TNext = any> = Generator<T, TReturn, TNext> | AsyncGenerator<T, TReturn, TNext>;
|
|
13
|
+
|
|
11
14
|
/**
|
|
12
15
|
* Before libp2p 0.35, peerstore stays in memory and periodically write to db after n dirty items
|
|
13
16
|
* This has a memory issue because all peer data stays in memory and loaded at startup time
|
|
@@ -93,7 +96,7 @@ export class Eth2PeerDataStore extends BaseDatastore {
|
|
|
93
96
|
* This throws error if not found
|
|
94
97
|
* see https://github.com/ipfs/js-datastore-level/blob/38f44058dd6be858e757a1c90b8edb31590ec0bc/src/index.js#L102
|
|
95
98
|
*/
|
|
96
|
-
async get(key: Key): Promise<Uint8Array> {
|
|
99
|
+
async get(key: Key, options?: AbortOptions): Promise<Uint8Array> {
|
|
97
100
|
const keyStr = key.toString();
|
|
98
101
|
const memoryItem = this._memoryDatastore.get(keyStr);
|
|
99
102
|
if (memoryItem) {
|
|
@@ -102,16 +105,16 @@ export class Eth2PeerDataStore extends BaseDatastore {
|
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
// this throws error if not found
|
|
105
|
-
const dbValue = await this._dbDatastore.get(key);
|
|
108
|
+
const dbValue = await this._dbDatastore.get(key, options);
|
|
106
109
|
// don't call this._memoryDatastore.set directly
|
|
107
110
|
// we want to get through prune() logic with fromDb as true
|
|
108
111
|
await this._put(key, dbValue, true);
|
|
109
112
|
return dbValue;
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
async has(key: Key): Promise<boolean> {
|
|
115
|
+
async has(key: Key, options?: AbortOptions): Promise<boolean> {
|
|
113
116
|
try {
|
|
114
|
-
await this.get(key);
|
|
117
|
+
await this.get(key, options);
|
|
115
118
|
} catch (err) {
|
|
116
119
|
// this is the same to how js-datastore-level handles notFound error
|
|
117
120
|
// https://github.com/ipfs/js-datastore-level/blob/38f44058dd6be858e757a1c90b8edb31590ec0bc/src/index.js#L121
|
|
@@ -121,26 +124,26 @@ export class Eth2PeerDataStore extends BaseDatastore {
|
|
|
121
124
|
return true;
|
|
122
125
|
}
|
|
123
126
|
|
|
124
|
-
async delete(key: Key): Promise<void> {
|
|
127
|
+
async delete(key: Key, options?: AbortOptions): Promise<void> {
|
|
125
128
|
this._memoryDatastore.delete(key.toString());
|
|
126
|
-
await this._dbDatastore.delete(key);
|
|
129
|
+
await this._dbDatastore.delete(key, options);
|
|
127
130
|
}
|
|
128
131
|
|
|
129
|
-
async *_all(q: Query):
|
|
132
|
+
async *_all(q: Query, options?: AbortOptions): AwaitGenerator<Pair> {
|
|
130
133
|
for (const [key, value] of this._memoryDatastore.entries()) {
|
|
131
134
|
yield {
|
|
132
135
|
key: new Key(key),
|
|
133
136
|
value: value.data,
|
|
134
137
|
};
|
|
135
138
|
}
|
|
136
|
-
yield* this._dbDatastore.query(q);
|
|
139
|
+
yield* this._dbDatastore.query(q, options);
|
|
137
140
|
}
|
|
138
141
|
|
|
139
|
-
async *_allKeys(q: KeyQuery):
|
|
142
|
+
async *_allKeys(q: KeyQuery, options?: AbortOptions): AwaitGenerator<Key> {
|
|
140
143
|
for (const key of this._memoryDatastore.keys()) {
|
|
141
144
|
yield new Key(key);
|
|
142
145
|
}
|
|
143
|
-
yield* this._dbDatastore.queryKeys(q);
|
|
146
|
+
yield* this._dbDatastore.queryKeys(q, options);
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
private async _addDirtyItem(keyStr: string): Promise<void> {
|
|
@@ -9,6 +9,7 @@ import {prettyPrintIndices, toHex, withTimeout} from "@lodestar/utils";
|
|
|
9
9
|
import {GOODBYE_KNOWN_CODES, GoodByeReasonCode, Libp2pEvent} from "../../constants/index.js";
|
|
10
10
|
import {IClock} from "../../util/clock.js";
|
|
11
11
|
import {computeColumnsForCustodyGroup, getCustodyGroups} from "../../util/dataColumns.js";
|
|
12
|
+
import {callInNextEventLoop} from "../../util/eventLoop.js";
|
|
12
13
|
import {NetworkCoreMetrics} from "../core/metrics.js";
|
|
13
14
|
import {LodestarDiscv5Opts} from "../discv5/types.js";
|
|
14
15
|
import {INetworkEventBus, NetworkEvent, NetworkEventData} from "../events.js";
|
|
@@ -161,7 +162,6 @@ export class PeerManager {
|
|
|
161
162
|
|
|
162
163
|
// A single map of connected peers with all necessary data to handle PINGs, STATUS, and metrics
|
|
163
164
|
private connectedPeers: Map<PeerIdStr, PeerData>;
|
|
164
|
-
|
|
165
165
|
private opts: PeerManagerOpts;
|
|
166
166
|
private intervals: NodeJS.Timeout[] = [];
|
|
167
167
|
|
|
@@ -196,6 +196,13 @@ export class PeerManager {
|
|
|
196
196
|
|
|
197
197
|
this.lastStatus = this.statusCache.get();
|
|
198
198
|
|
|
199
|
+
// A connection may already be open before listeners are attached.
|
|
200
|
+
// Seed those peers so they are tracked in connectedPeers immediately.
|
|
201
|
+
this.bootstrapAlreadyOpenConnections();
|
|
202
|
+
// Defer status/ping to the next event loop tick so the heartbeat interval and
|
|
203
|
+
// event listeners are fully registered before we begin handshakes.
|
|
204
|
+
callInNextEventLoop(() => this.pingAndStatusTimeouts());
|
|
205
|
+
|
|
199
206
|
// On start-up will connected to existing peers in libp2p.peerStore, same as autoDial behaviour
|
|
200
207
|
this.heartbeat();
|
|
201
208
|
this.intervals = [
|
|
@@ -472,6 +479,14 @@ export class PeerManager {
|
|
|
472
479
|
clientAgent,
|
|
473
480
|
custodyColumns,
|
|
474
481
|
});
|
|
482
|
+
|
|
483
|
+
// Identify peer after status proves the connection is usable.
|
|
484
|
+
// This is the only place we trigger identify — avoids wasted streams on
|
|
485
|
+
// peers that close identify right after connection open or turn out to be
|
|
486
|
+
// irrelevant.
|
|
487
|
+
if (peerData?.agentVersion === null) {
|
|
488
|
+
void this.identifyPeer(peer.toString(), prettyPrintPeerId(peer), getConnection(this.libp2p, peer.toString()));
|
|
489
|
+
}
|
|
475
490
|
}
|
|
476
491
|
}
|
|
477
492
|
|
|
@@ -692,36 +707,39 @@ export class PeerManager {
|
|
|
692
707
|
}
|
|
693
708
|
}
|
|
694
709
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
710
|
+
private bootstrapAlreadyOpenConnections(): void {
|
|
711
|
+
let bootstrapped = 0;
|
|
712
|
+
|
|
713
|
+
for (const {value: connections} of getConnectionsMap(this.libp2p).values()) {
|
|
714
|
+
for (const connection of connections) {
|
|
715
|
+
// trackLibp2pConnection handles deduplication via overwriteExisting: false
|
|
716
|
+
if (this.trackLibp2pConnection(connection, {overwriteExisting: false, triggerHandshakeNow: false})) {
|
|
717
|
+
bootstrapped++;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (bootstrapped > 0) {
|
|
723
|
+
this.logger.verbose("Bootstrapped already-open libp2p peers", {bootstrapped});
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
private trackLibp2pConnection(
|
|
728
|
+
connection: Connection,
|
|
729
|
+
opts: {overwriteExisting: boolean; triggerHandshakeNow: boolean}
|
|
730
|
+
): boolean {
|
|
731
|
+
const {direction, status, remotePeer} = connection;
|
|
704
732
|
const remotePeerStr = remotePeer.toString();
|
|
705
733
|
const remotePeerPrettyStr = prettyPrintPeerId(remotePeer);
|
|
706
|
-
this.logger.verbose("peer connected", {peer: remotePeerPrettyStr, direction, status});
|
|
707
|
-
// NOTE: The peerConnect event is not emitted here here, but after asserting peer relevance
|
|
708
|
-
this.metrics?.peerConnectedEvent.inc({direction, status});
|
|
709
734
|
|
|
710
|
-
if (
|
|
735
|
+
if (status !== "open") {
|
|
711
736
|
this.logger.debug("Peer disconnected before identify protocol initiated", {
|
|
712
737
|
peerId: remotePeerPrettyStr,
|
|
713
|
-
status
|
|
738
|
+
status,
|
|
714
739
|
});
|
|
715
|
-
return;
|
|
740
|
+
return false;
|
|
716
741
|
}
|
|
717
742
|
|
|
718
|
-
// On connection:
|
|
719
|
-
// - Outbound connections: send a STATUS and PING request
|
|
720
|
-
// - Inbound connections: expect to be STATUS'd, schedule STATUS and PING for latter
|
|
721
|
-
// NOTE: libp2p may emit two "peer:connect" events: One for inbound, one for outbound
|
|
722
|
-
// If that happens, it's okay. Only the "outbound" connection triggers immediate action
|
|
723
|
-
const now = Date.now();
|
|
724
|
-
|
|
725
743
|
// Ethereum uses secp256k1 for node IDs, reject peers with other key types
|
|
726
744
|
if (remotePeer.type !== "secp256k1") {
|
|
727
745
|
this.logger.debug("Peer does not have secp256k1 key, disconnecting", {
|
|
@@ -729,52 +747,64 @@ export class PeerManager {
|
|
|
729
747
|
type: remotePeer.type,
|
|
730
748
|
});
|
|
731
749
|
void this.goodbyeAndDisconnect(remotePeer, GoodByeReasonCode.IRRELEVANT_NETWORK);
|
|
732
|
-
return;
|
|
750
|
+
return false;
|
|
733
751
|
}
|
|
734
752
|
|
|
753
|
+
if (!opts.overwriteExisting && this.connectedPeers.has(remotePeerStr)) {
|
|
754
|
+
return false;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// On connection:
|
|
758
|
+
// - Outbound connections: send a STATUS and PING request
|
|
759
|
+
// - Inbound connections: expect to be STATUS'd, schedule STATUS and PING for later
|
|
760
|
+
// NOTE: libp2p may emit two "peer:connect" events: One for inbound, one for outbound
|
|
761
|
+
// If that happens, it's okay. Only the "outbound" connection triggers immediate action
|
|
762
|
+
const now = Date.now();
|
|
763
|
+
const existingPeerData = this.connectedPeers.get(remotePeerStr);
|
|
735
764
|
const nodeId = computeNodeId(remotePeer);
|
|
736
765
|
const peerData: PeerData = {
|
|
737
|
-
|
|
766
|
+
// Keep existing timestamps if this peer already had another open connection.
|
|
767
|
+
// libp2p may emit multiple connection:open events per peer.
|
|
768
|
+
lastReceivedMsgUnixTsMs: existingPeerData?.lastReceivedMsgUnixTsMs ?? (direction === "outbound" ? 0 : now),
|
|
738
769
|
// If inbound, request after STATUS_INBOUND_GRACE_PERIOD
|
|
739
|
-
lastStatusUnixTsMs:
|
|
740
|
-
|
|
741
|
-
|
|
770
|
+
lastStatusUnixTsMs:
|
|
771
|
+
existingPeerData?.lastStatusUnixTsMs ??
|
|
772
|
+
(direction === "outbound" ? 0 : now - STATUS_INTERVAL_MS + STATUS_INBOUND_GRACE_PERIOD),
|
|
773
|
+
connectedUnixTsMs: existingPeerData?.connectedUnixTsMs ?? now,
|
|
774
|
+
relevantStatus: existingPeerData?.relevantStatus ?? RelevantPeerStatus.Unknown,
|
|
742
775
|
direction,
|
|
743
776
|
nodeId,
|
|
744
777
|
peerId: remotePeer,
|
|
745
|
-
status: null,
|
|
746
|
-
metadata: null,
|
|
747
|
-
agentVersion: null,
|
|
748
|
-
agentClient: null,
|
|
749
|
-
encodingPreference: null,
|
|
778
|
+
status: existingPeerData?.status ?? null,
|
|
779
|
+
metadata: existingPeerData?.metadata ?? null,
|
|
780
|
+
agentVersion: existingPeerData?.agentVersion ?? null,
|
|
781
|
+
agentClient: existingPeerData?.agentClient ?? null,
|
|
782
|
+
encodingPreference: existingPeerData?.encodingPreference ?? null,
|
|
750
783
|
};
|
|
751
784
|
this.connectedPeers.set(remotePeerStr, peerData);
|
|
752
785
|
|
|
753
|
-
if (direction === "outbound") {
|
|
754
|
-
// this.pingAndStatusTimeouts();
|
|
786
|
+
if (direction === "outbound" && opts.triggerHandshakeNow) {
|
|
755
787
|
void this.requestPing(remotePeer);
|
|
756
788
|
void this.requestStatus(remotePeer, this.statusCache.get());
|
|
757
789
|
}
|
|
758
790
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
-
});
|
|
791
|
+
return true;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* The libp2p Upgrader has successfully upgraded a peer connection on a particular multiaddress
|
|
796
|
+
* This event is routed through the connectionManager
|
|
797
|
+
*
|
|
798
|
+
* Registers a peer as connected. The `direction` parameter determines if the peer is being
|
|
799
|
+
* dialed or connecting to us.
|
|
800
|
+
*/
|
|
801
|
+
private onLibp2pPeerConnect = (evt: CustomEvent<Connection>): void => {
|
|
802
|
+
const {direction, status, remotePeer} = evt.detail;
|
|
803
|
+
this.logger.verbose("peer connected", {peer: prettyPrintPeerId(remotePeer), direction, status});
|
|
804
|
+
// NOTE: The peerConnect event is not emitted here here, but after asserting peer relevance
|
|
805
|
+
this.metrics?.peerConnectedEvent.inc({direction, status});
|
|
806
|
+
|
|
807
|
+
this.trackLibp2pConnection(evt.detail, {overwriteExisting: true, triggerHandshakeNow: true});
|
|
778
808
|
};
|
|
779
809
|
|
|
780
810
|
/**
|
|
@@ -784,6 +814,19 @@ export class PeerManager {
|
|
|
784
814
|
const {direction, status, remotePeer} = evt.detail;
|
|
785
815
|
const peerIdStr = remotePeer.toString();
|
|
786
816
|
|
|
817
|
+
const openConnections =
|
|
818
|
+
getConnectionsMap(this.libp2p)
|
|
819
|
+
.get(peerIdStr)
|
|
820
|
+
?.value.filter((connection) => connection.status === "open") ?? [];
|
|
821
|
+
if (openConnections.length > 0) {
|
|
822
|
+
this.logger.debug("Ignoring peer disconnect event while another connection is still open", {
|
|
823
|
+
peerId: prettyPrintPeerIdStr(peerIdStr),
|
|
824
|
+
direction,
|
|
825
|
+
status,
|
|
826
|
+
});
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
|
|
787
830
|
let logMessage = "onLibp2pPeerDisconnect";
|
|
788
831
|
const logContext: Record<string, string | number> = {
|
|
789
832
|
peerId: prettyPrintPeerIdStr(peerIdStr),
|
|
@@ -818,6 +861,27 @@ export class PeerManager {
|
|
|
818
861
|
}
|
|
819
862
|
}
|
|
820
863
|
|
|
864
|
+
private async identifyPeer(peerIdStr: string, peerIdPretty: string, connection?: Connection): Promise<void> {
|
|
865
|
+
if (!connection || connection.status !== "open") {
|
|
866
|
+
this.logger.debug("Peer has no open connection for identify", {peerId: peerIdPretty});
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
try {
|
|
871
|
+
const result = await this.libp2p.services.identify.identify(connection);
|
|
872
|
+
const agentVersion = result.agentVersion;
|
|
873
|
+
if (agentVersion) {
|
|
874
|
+
const connectedPeerData = this.connectedPeers.get(peerIdStr);
|
|
875
|
+
if (connectedPeerData) {
|
|
876
|
+
connectedPeerData.agentVersion = agentVersion;
|
|
877
|
+
connectedPeerData.agentClient = getKnownClientFromAgentVersion(agentVersion);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
} catch (e) {
|
|
881
|
+
this.logger.debug("Error setting agentVersion for the peer", {peerId: peerIdPretty}, e as Error);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
821
885
|
private async goodbyeAndDisconnect(peer: PeerId, goodbye: GoodByeReasonCode): Promise<void> {
|
|
822
886
|
const reason = GOODBYE_KNOWN_CODES[goodbye.toString()] || "";
|
|
823
887
|
const peerIdStr = peer.toString();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {MessageStreamDirection, PeerId} from "@libp2p/interface";
|
|
2
2
|
import {BitArray} from "@chainsafe/ssz";
|
|
3
3
|
import {ChainConfig} from "@lodestar/config";
|
|
4
4
|
import {ATTESTATION_SUBNET_COUNT, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params";
|
|
@@ -95,7 +95,7 @@ function computeStatusScore(ours: Status, theirs: Status | null, opts: Prioritiz
|
|
|
95
95
|
|
|
96
96
|
type PeerInfo = {
|
|
97
97
|
id: PeerId;
|
|
98
|
-
direction:
|
|
98
|
+
direction: MessageStreamDirection | null;
|
|
99
99
|
statusScore: StatusScore;
|
|
100
100
|
attnets: phase0.AttestationSubnets;
|
|
101
101
|
syncnets: altair.SyncSubnets;
|
|
@@ -137,7 +137,7 @@ export enum ExcessPeerDisconnectReason {
|
|
|
137
137
|
export function prioritizePeers(
|
|
138
138
|
connectedPeersInfo: {
|
|
139
139
|
id: PeerId;
|
|
140
|
-
direction:
|
|
140
|
+
direction: MessageStreamDirection | null;
|
|
141
141
|
status: Status | null;
|
|
142
142
|
attnets: phase0.AttestationSubnets | null;
|
|
143
143
|
syncnets: altair.SyncSubnets | null;
|
|
@@ -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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {TopicValidatorResult} from "@libp2p/
|
|
1
|
+
import {TopicValidatorResult} from "@libp2p/gossipsub";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
3
|
import {Logger} from "@lodestar/utils";
|
|
4
4
|
import {AttestationError, GossipAction, GossipActionError} from "../../chain/errors/index.js";
|
|
@@ -38,7 +38,6 @@ export function onOutgoingReqRespError(e: RequestError, method: ReqRespMethod):
|
|
|
38
38
|
: PeerAction.LowToleranceError;
|
|
39
39
|
// TODO: Detect SSZDecodeError and return PeerAction.Fatal
|
|
40
40
|
|
|
41
|
-
case RequestErrorCode.TTFB_TIMEOUT:
|
|
42
41
|
case RequestErrorCode.RESP_TIMEOUT:
|
|
43
42
|
switch (method) {
|
|
44
43
|
case ReqRespMethod.Ping:
|
package/src/network/util.ts
CHANGED
|
@@ -23,7 +23,7 @@ export function getConnection(libp2p: Libp2p, peerIdStr: string): Connection | u
|
|
|
23
23
|
return getConnectionsMap(libp2p).get(peerIdStr)?.value[0] ?? undefined;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// https://github.com/
|
|
26
|
+
// https://github.com/libp2p/js-libp2p/blob/f87cba928991736d9646b3e054c367f55cab315c/packages/gossipsub/src/gossipsub.ts#L2076
|
|
27
27
|
export function isPublishToZeroPeersError(e: Error): boolean {
|
|
28
|
-
return e.message.includes("PublishError.
|
|
28
|
+
return e.message.includes("PublishError.NoPeersSubscribedToTopic");
|
|
29
29
|
}
|
package/src/node/nodejs.ts
CHANGED
|
@@ -2,12 +2,11 @@ import {setMaxListeners} from "node:events";
|
|
|
2
2
|
import {PrivateKey} from "@libp2p/interface";
|
|
3
3
|
import {Registry} from "prom-client";
|
|
4
4
|
import {hasher} from "@chainsafe/persistent-merkle-tree";
|
|
5
|
-
import {PubkeyIndexMap} from "@chainsafe/pubkey-index-map";
|
|
6
5
|
import {BeaconApiMethods} from "@lodestar/api/beacon/server";
|
|
7
6
|
import {BeaconConfig} from "@lodestar/config";
|
|
8
7
|
import type {LoggerNode} from "@lodestar/logger/node";
|
|
9
8
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
10
|
-
import {CachedBeaconStateAllForks,
|
|
9
|
+
import {CachedBeaconStateAllForks, PubkeyCache, isExecutionCachedStateType} from "@lodestar/state-transition";
|
|
11
10
|
import {phase0} from "@lodestar/types";
|
|
12
11
|
import {sleep, toRootHex} from "@lodestar/utils";
|
|
13
12
|
import {ProcessShutdownCallback} from "@lodestar/validator";
|
|
@@ -47,8 +46,7 @@ export type BeaconNodeModules = {
|
|
|
47
46
|
export type BeaconNodeInitModules = {
|
|
48
47
|
opts: IBeaconNodeOptions;
|
|
49
48
|
config: BeaconConfig;
|
|
50
|
-
|
|
51
|
-
index2pubkey: Index2PubkeyCache;
|
|
49
|
+
pubkeyCache: PubkeyCache;
|
|
52
50
|
db: IBeaconDb;
|
|
53
51
|
logger: LoggerNode;
|
|
54
52
|
processShutdownCallback: ProcessShutdownCallback;
|
|
@@ -150,8 +148,7 @@ export class BeaconNode {
|
|
|
150
148
|
static async init<T extends BeaconNode = BeaconNode>({
|
|
151
149
|
opts,
|
|
152
150
|
config,
|
|
153
|
-
|
|
154
|
-
index2pubkey,
|
|
151
|
+
pubkeyCache,
|
|
155
152
|
db,
|
|
156
153
|
logger,
|
|
157
154
|
processShutdownCallback,
|
|
@@ -240,8 +237,7 @@ export class BeaconNode {
|
|
|
240
237
|
privateKey,
|
|
241
238
|
config,
|
|
242
239
|
clock,
|
|
243
|
-
|
|
244
|
-
index2pubkey,
|
|
240
|
+
pubkeyCache,
|
|
245
241
|
dataDir,
|
|
246
242
|
db,
|
|
247
243
|
dbName: opts.db.name,
|
|
@@ -364,9 +360,12 @@ export class BeaconNode {
|
|
|
364
360
|
if (this.restApi) await this.restApi.close();
|
|
365
361
|
await this.network.close();
|
|
366
362
|
if (this.metricsServer) await this.metricsServer.close();
|
|
367
|
-
if (this.monitoring) this.monitoring.close();
|
|
363
|
+
if (this.monitoring) await this.monitoring.close();
|
|
368
364
|
await this.chain.persistToDisk();
|
|
369
365
|
await this.chain.close();
|
|
366
|
+
// Abort signal last: close() calls above clear intervals/timeouts so no new
|
|
367
|
+
// operations get scheduled. If we aborted first, a still-pending interval could
|
|
368
|
+
// fire and schedule a new operation after abort, leaving it stuck and delaying shutdown.
|
|
370
369
|
if (this.controller) this.controller.abort();
|
|
371
370
|
await sleep(DELAY_BEFORE_CLOSING_DB_MS);
|
|
372
371
|
await this.db.close();
|
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;
|
package/src/util/workerEvents.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {MessagePort, Worker} from "node:worker_threads";
|
|
2
|
-
import {Message} from "@libp2p/
|
|
2
|
+
import type {Message} from "@libp2p/gossipsub";
|
|
3
3
|
import {Thread} from "@chainsafe/threads";
|
|
4
4
|
import {Logger} from "@lodestar/logger";
|
|
5
5
|
import {sleep} from "@lodestar/utils";
|