@lodestar/beacon-node 1.18.0-dev.1d86cd0b26 → 1.18.0-dev.20bc193da0
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/validator/index.js +3 -3
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +0 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +4 -6
- package/lib/chain/stateCache/persistentCheckpointsCache.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/core/metrics.d.ts +2 -3
- package/lib/network/core/metrics.js.map +1 -1
- package/lib/network/core/networkCore.js +1 -4
- package/lib/network/core/networkCore.js.map +1 -1
- package/lib/network/gossip/gossipsub.js +2 -2
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/options.js +0 -2
- package/lib/network/options.js.map +1 -1
- package/lib/network/subnets/index.d.ts +0 -1
- package/lib/network/subnets/index.js +0 -1
- package/lib/network/subnets/index.js.map +1 -1
- package/lib/network/subnets/interface.d.ts +0 -1
- package/lib/util/profile.js +4 -1
- package/lib/util/profile.js.map +1 -1
- package/package.json +14 -14
- package/lib/network/subnets/attnetsService.d.ts +0 -118
- package/lib/network/subnets/attnetsService.js +0 -325
- package/lib/network/subnets/attnetsService.js.map +0 -1
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
import { computeStartSlotAtEpoch } from "@lodestar/state-transition";
|
|
2
|
-
import { ATTESTATION_SUBNET_COUNT, EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION, RANDOM_SUBNETS_PER_VALIDATOR, SLOTS_PER_EPOCH, } from "@lodestar/params";
|
|
3
|
-
import { ssz } from "@lodestar/types";
|
|
4
|
-
import { MapDef, randBetween } from "@lodestar/utils";
|
|
5
|
-
import { shuffle } from "../../util/shuffle.js";
|
|
6
|
-
import { ClockEvent } from "../../util/clock.js";
|
|
7
|
-
import { GossipType } from "../gossip/index.js";
|
|
8
|
-
import { SubnetMap } from "../peers/utils/index.js";
|
|
9
|
-
import { getActiveForks } from "../forks.js";
|
|
10
|
-
/**
|
|
11
|
-
* The time (in slots) before a last seen validator is considered absent and we unsubscribe from the random
|
|
12
|
-
* gossip topics that we subscribed to due to the validator connection.
|
|
13
|
-
*/
|
|
14
|
-
const LAST_SEEN_VALIDATOR_TIMEOUT = 150;
|
|
15
|
-
const gossipType = GossipType.beacon_attestation;
|
|
16
|
-
export var SubnetSource;
|
|
17
|
-
(function (SubnetSource) {
|
|
18
|
-
SubnetSource["committee"] = "committee";
|
|
19
|
-
SubnetSource["random"] = "random";
|
|
20
|
-
})(SubnetSource || (SubnetSource = {}));
|
|
21
|
-
/**
|
|
22
|
-
* Manage random (long lived) subnets and committee (short lived) subnets.
|
|
23
|
-
* - PeerManager uses attnetsService to know which peers are required for duties
|
|
24
|
-
* - Network call addCommitteeSubscriptions() from API calls
|
|
25
|
-
* - Gossip handler checks shouldProcess to know if validator is aggregator
|
|
26
|
-
*/
|
|
27
|
-
export class AttnetsService {
|
|
28
|
-
constructor(config, clock, gossip, metadata, logger, metrics, opts) {
|
|
29
|
-
this.config = config;
|
|
30
|
-
this.clock = clock;
|
|
31
|
-
this.gossip = gossip;
|
|
32
|
-
this.metadata = metadata;
|
|
33
|
-
this.logger = logger;
|
|
34
|
-
this.metrics = metrics;
|
|
35
|
-
this.opts = opts;
|
|
36
|
-
/** Committee subnets - PeerManager must find peers for those */
|
|
37
|
-
this.committeeSubnets = new SubnetMap();
|
|
38
|
-
/**
|
|
39
|
-
* All currently subscribed short-lived subnets, for attestation aggregation
|
|
40
|
-
* This class will tell gossip to subscribe and un-subscribe
|
|
41
|
-
* If a value exists for `SubscriptionId` it means that gossip subscription is active in network.gossip
|
|
42
|
-
*/
|
|
43
|
-
this.subscriptionsCommittee = new SubnetMap();
|
|
44
|
-
/** Same as `subscriptionsCommittee` but for long-lived subnets. May overlap with `subscriptionsCommittee` */
|
|
45
|
-
this.subscriptionsRandom = new SubnetMap();
|
|
46
|
-
/**
|
|
47
|
-
* Map of an aggregator at a slot and subnet
|
|
48
|
-
* Used to determine if we should process an attestation.
|
|
49
|
-
*/
|
|
50
|
-
this.aggregatorSlotSubnet = new MapDef(() => new Set());
|
|
51
|
-
/**
|
|
52
|
-
* A collection of seen validators. These dictate how many random subnets we should be
|
|
53
|
-
* subscribed to. As these time out, we unsubscribe from the required random subnets and update our ENR.
|
|
54
|
-
* This is a map of validator index and its last active slot.
|
|
55
|
-
*/
|
|
56
|
-
this.knownValidators = new Map();
|
|
57
|
-
/**
|
|
58
|
-
* Run per slot.
|
|
59
|
-
* - Subscribe to gossip subnets 2 slots in advance
|
|
60
|
-
* - Unsubscribe from expired subnets
|
|
61
|
-
*/
|
|
62
|
-
this.onSlot = (clockSlot) => {
|
|
63
|
-
try {
|
|
64
|
-
for (const [dutiedSlot, subnets] of this.aggregatorSlotSubnet.entries()) {
|
|
65
|
-
if (dutiedSlot === clockSlot + this.opts.slotsToSubscribeBeforeAggregatorDuty) {
|
|
66
|
-
// Trigger gossip subscription first, in batch
|
|
67
|
-
if (subnets.size > 0) {
|
|
68
|
-
this.subscribeToSubnets(Array.from(subnets), SubnetSource.committee);
|
|
69
|
-
}
|
|
70
|
-
// Then, register the subscriptions
|
|
71
|
-
Array.from(subnets).map((subnet) => this.subscriptionsCommittee.request({ subnet, toSlot: dutiedSlot }));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// For node >= 64 validators, we should consistently subscribe to all subnets
|
|
75
|
-
// it's important to check random subnets first
|
|
76
|
-
// See https://github.com/ChainSafe/lodestar/issues/4929
|
|
77
|
-
this.unsubscribeExpiredRandomSubnets(clockSlot);
|
|
78
|
-
this.unsubscribeExpiredCommitteeSubnets(clockSlot);
|
|
79
|
-
}
|
|
80
|
-
catch (e) {
|
|
81
|
-
this.logger.error("Error on AttnetsService.onSlot", { slot: clockSlot }, e);
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* Run per epoch, clean-up operations that are not urgent
|
|
86
|
-
*/
|
|
87
|
-
this.onEpoch = (epoch) => {
|
|
88
|
-
try {
|
|
89
|
-
const slot = computeStartSlotAtEpoch(epoch);
|
|
90
|
-
this.pruneExpiredKnownValidators(slot);
|
|
91
|
-
this.pruneExpiredAggregator(slot);
|
|
92
|
-
}
|
|
93
|
-
catch (e) {
|
|
94
|
-
this.logger.error("Error on AttnetsService.onEpoch", { epoch }, e);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
// if subscribeAllSubnets, we act like we have >= ATTESTATION_SUBNET_COUNT validators connecting to this node
|
|
98
|
-
// so that we have enough subnet topic peers, see https://github.com/ChainSafe/lodestar/issues/4921
|
|
99
|
-
if (this.opts.subscribeAllSubnets) {
|
|
100
|
-
for (let subnet = 0; subnet < ATTESTATION_SUBNET_COUNT; subnet++) {
|
|
101
|
-
this.committeeSubnets.request({ subnet, toSlot: Infinity });
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
this.randBetweenFn = this.opts.randBetweenFn ?? randBetween;
|
|
105
|
-
this.shuffleFn = this.opts.shuffleFn ?? shuffle;
|
|
106
|
-
if (metrics) {
|
|
107
|
-
metrics.attnetsService.subscriptionsRandom.addCollect(() => this.onScrapeLodestarMetrics(metrics));
|
|
108
|
-
}
|
|
109
|
-
this.clock.on(ClockEvent.slot, this.onSlot);
|
|
110
|
-
this.clock.on(ClockEvent.epoch, this.onEpoch);
|
|
111
|
-
}
|
|
112
|
-
close() {
|
|
113
|
-
this.clock.off(ClockEvent.slot, this.onSlot);
|
|
114
|
-
this.clock.off(ClockEvent.epoch, this.onEpoch);
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Get all active subnets for the hearbeat.
|
|
118
|
-
*/
|
|
119
|
-
getActiveSubnets() {
|
|
120
|
-
// Omit subscriptionsRandom, not necessary to force the network component to keep peers on that subnets
|
|
121
|
-
return this.committeeSubnets.getActiveTtl(this.clock.currentSlot);
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Called from the API when validator is a part of a committee.
|
|
125
|
-
*/
|
|
126
|
-
addCommitteeSubscriptions(subscriptions) {
|
|
127
|
-
const currentSlot = this.clock.currentSlot;
|
|
128
|
-
let addedknownValidators = false;
|
|
129
|
-
for (const { validatorIndex, subnet, slot, isAggregator } of subscriptions) {
|
|
130
|
-
// Add known validator
|
|
131
|
-
if (!this.knownValidators.has(validatorIndex))
|
|
132
|
-
addedknownValidators = true;
|
|
133
|
-
this.knownValidators.set(validatorIndex, currentSlot);
|
|
134
|
-
// the peer-manager heartbeat will help find the subnet
|
|
135
|
-
this.committeeSubnets.request({ subnet, toSlot: slot + 1 });
|
|
136
|
-
if (isAggregator) {
|
|
137
|
-
// need exact slot here
|
|
138
|
-
this.aggregatorSlotSubnet.getOrDefault(slot).add(subnet);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
if (addedknownValidators)
|
|
142
|
-
this.rebalanceRandomSubnets();
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Check if a subscription is still active before handling a gossip object
|
|
146
|
-
*/
|
|
147
|
-
shouldProcess(subnet, slot) {
|
|
148
|
-
if (!this.aggregatorSlotSubnet.has(slot)) {
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
return this.aggregatorSlotSubnet.getOrDefault(slot).has(subnet);
|
|
152
|
-
}
|
|
153
|
-
/** Call ONLY ONCE: Two epoch before the fork, re-subscribe all existing random subscriptions to the new fork */
|
|
154
|
-
subscribeSubnetsToNextFork(nextFork) {
|
|
155
|
-
this.logger.info("Subscribing to random attnets to next fork", { nextFork });
|
|
156
|
-
for (const subnet of this.subscriptionsRandom.getAll()) {
|
|
157
|
-
this.gossip.subscribeTopic({ type: gossipType, fork: nextFork, subnet });
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
/** Call ONLY ONCE: Two epochs after the fork, un-subscribe all subnets from the old fork */
|
|
161
|
-
unsubscribeSubnetsFromPrevFork(prevFork) {
|
|
162
|
-
this.logger.info("Unsubscribing to random attnets from prev fork", { prevFork });
|
|
163
|
-
for (let subnet = 0; subnet < ATTESTATION_SUBNET_COUNT; subnet++) {
|
|
164
|
-
if (!this.opts.subscribeAllSubnets) {
|
|
165
|
-
this.gossip.unsubscribeTopic({ type: gossipType, fork: prevFork, subnet });
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Unsubscribe to a committee subnet from subscribedCommitteeSubnets.
|
|
171
|
-
* If a random subnet is present, we do not unsubscribe from it.
|
|
172
|
-
*/
|
|
173
|
-
unsubscribeExpiredCommitteeSubnets(slot) {
|
|
174
|
-
const expired = this.subscriptionsCommittee.getExpired(slot);
|
|
175
|
-
if (expired.length > 0) {
|
|
176
|
-
this.unsubscribeSubnets(expired, slot, SubnetSource.committee);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* A random subnet has expired.
|
|
181
|
-
* This function selects a new subnet to join, or extends the expiry if there are no more
|
|
182
|
-
* available subnets to choose from.
|
|
183
|
-
*/
|
|
184
|
-
unsubscribeExpiredRandomSubnets(slot) {
|
|
185
|
-
const expired = this.subscriptionsRandom.getExpired(slot);
|
|
186
|
-
const currentSlot = this.clock.currentSlot;
|
|
187
|
-
if (expired.length === 0) {
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
if (this.knownValidators.size * RANDOM_SUBNETS_PER_VALIDATOR >= ATTESTATION_SUBNET_COUNT) {
|
|
191
|
-
// Optimization: If we have to be subcribed to all subnets, no need to unsubscribe. Just extend the timeout
|
|
192
|
-
for (const subnet of expired) {
|
|
193
|
-
this.subscriptionsRandom.request({ subnet, toSlot: this.randomSubscriptionSlotLen() + currentSlot });
|
|
194
|
-
}
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
// Prune subnets and re-subcribe to new ones
|
|
198
|
-
this.unsubscribeSubnets(expired, slot, SubnetSource.random);
|
|
199
|
-
this.rebalanceRandomSubnets();
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* A known validator has not sent a subscription in a while. They are considered offline and the
|
|
203
|
-
* beacon node no longer needs to be subscribed to the allocated random subnets.
|
|
204
|
-
*
|
|
205
|
-
* We don't keep track of a specific validator to random subnet, rather the ratio of active
|
|
206
|
-
* validators to random subnets. So when a validator goes offline, we can simply remove the
|
|
207
|
-
* allocated amount of random subnets.
|
|
208
|
-
*/
|
|
209
|
-
pruneExpiredKnownValidators(currentSlot) {
|
|
210
|
-
let deletedKnownValidators = false;
|
|
211
|
-
for (const [index, slot] of this.knownValidators.entries()) {
|
|
212
|
-
if (currentSlot > slot + LAST_SEEN_VALIDATOR_TIMEOUT) {
|
|
213
|
-
const deleted = this.knownValidators.delete(index);
|
|
214
|
-
if (deleted)
|
|
215
|
-
deletedKnownValidators = true;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
if (deletedKnownValidators)
|
|
219
|
-
this.rebalanceRandomSubnets();
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* No need to track aggregator for past slots.
|
|
223
|
-
* @param currentSlot
|
|
224
|
-
*/
|
|
225
|
-
pruneExpiredAggregator(currentSlot) {
|
|
226
|
-
for (const slot of this.aggregatorSlotSubnet.keys()) {
|
|
227
|
-
if (currentSlot > slot) {
|
|
228
|
-
this.aggregatorSlotSubnet.delete(slot);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Called when we have new validators or expired validators.
|
|
234
|
-
* knownValidators should be updated before this function.
|
|
235
|
-
*/
|
|
236
|
-
rebalanceRandomSubnets() {
|
|
237
|
-
const slot = this.clock.currentSlot;
|
|
238
|
-
// By limiting to ATTESTATION_SUBNET_COUNT, if target is still over subnetDiff equals 0
|
|
239
|
-
const targetRandomSubnetCount = Math.min(this.knownValidators.size * RANDOM_SUBNETS_PER_VALIDATOR, ATTESTATION_SUBNET_COUNT);
|
|
240
|
-
const subnetDiff = targetRandomSubnetCount - this.subscriptionsRandom.size;
|
|
241
|
-
// subscribe to more random subnets
|
|
242
|
-
if (subnetDiff > 0) {
|
|
243
|
-
const activeSubnets = new Set(this.subscriptionsRandom.getActive(slot));
|
|
244
|
-
const allSubnets = Array.from({ length: ATTESTATION_SUBNET_COUNT }, (_, i) => i);
|
|
245
|
-
const availableSubnets = allSubnets.filter((subnet) => !activeSubnets.has(subnet));
|
|
246
|
-
const subnetsToConnect = this.shuffleFn(availableSubnets).slice(0, subnetDiff);
|
|
247
|
-
// Tell gossip to connect to the subnets if not connected already
|
|
248
|
-
this.subscribeToSubnets(subnetsToConnect, SubnetSource.random);
|
|
249
|
-
// Register these new subnets until some future slot
|
|
250
|
-
for (const subnet of subnetsToConnect) {
|
|
251
|
-
// the heartbeat will help connect to respective peers
|
|
252
|
-
this.subscriptionsRandom.request({ subnet, toSlot: this.randomSubscriptionSlotLen() + slot });
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
// unsubscribe some random subnets
|
|
256
|
-
if (subnetDiff < 0) {
|
|
257
|
-
const activeRandomSubnets = this.subscriptionsRandom.getActive(slot);
|
|
258
|
-
// TODO: Do we want to remove the oldest subnets or the newest subnets?
|
|
259
|
-
// .slice(-2) will extract the last two items of the array
|
|
260
|
-
const toRemoveSubnets = activeRandomSubnets.slice(subnetDiff);
|
|
261
|
-
for (const subnet of toRemoveSubnets) {
|
|
262
|
-
this.subscriptionsRandom.delete(subnet);
|
|
263
|
-
}
|
|
264
|
-
this.unsubscribeSubnets(toRemoveSubnets, slot, SubnetSource.random);
|
|
265
|
-
}
|
|
266
|
-
// If there has been a change update the local ENR bitfield
|
|
267
|
-
if (subnetDiff !== 0) {
|
|
268
|
-
this.updateMetadata();
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
/** Update ENR */
|
|
272
|
-
updateMetadata() {
|
|
273
|
-
const subnets = ssz.phase0.AttestationSubnets.defaultValue();
|
|
274
|
-
for (const subnet of this.subscriptionsRandom.getAll()) {
|
|
275
|
-
subnets.set(subnet, true);
|
|
276
|
-
}
|
|
277
|
-
// Only update metadata if necessary, setting `metadata.[key]` triggers a write to disk
|
|
278
|
-
if (!ssz.phase0.AttestationSubnets.equals(subnets, this.metadata.attnets)) {
|
|
279
|
-
this.metadata.attnets = subnets;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
/** Tigger a gossip subcription only if not already subscribed */
|
|
283
|
-
subscribeToSubnets(subnets, src) {
|
|
284
|
-
const forks = getActiveForks(this.config, this.clock.currentEpoch);
|
|
285
|
-
for (const subnet of subnets) {
|
|
286
|
-
if (!this.subscriptionsCommittee.has(subnet) && !this.subscriptionsRandom.has(subnet)) {
|
|
287
|
-
for (const fork of forks) {
|
|
288
|
-
this.gossip.subscribeTopic({ type: gossipType, fork, subnet });
|
|
289
|
-
}
|
|
290
|
-
this.metrics?.attnetsService.subscribeSubnets.inc({ subnet, src });
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
/** Trigger a gossip un-subscrition only if no-one is still subscribed */
|
|
295
|
-
unsubscribeSubnets(subnets, slot, src) {
|
|
296
|
-
// No need to unsubscribeTopic(). Return early to prevent repetitive extra work
|
|
297
|
-
if (this.opts.subscribeAllSubnets)
|
|
298
|
-
return;
|
|
299
|
-
const forks = getActiveForks(this.config, this.clock.currentEpoch);
|
|
300
|
-
for (const subnet of subnets) {
|
|
301
|
-
if (!this.subscriptionsCommittee.isActiveAtSlot(subnet, slot) &&
|
|
302
|
-
!this.subscriptionsRandom.isActiveAtSlot(subnet, slot)) {
|
|
303
|
-
for (const fork of forks) {
|
|
304
|
-
this.gossip.unsubscribeTopic({ type: gossipType, fork, subnet });
|
|
305
|
-
}
|
|
306
|
-
this.metrics?.attnetsService.unsubscribeSubnets.inc({ subnet, src });
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
randomSubscriptionSlotLen() {
|
|
311
|
-
return (this.randBetweenFn(EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION, 2 * EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION) *
|
|
312
|
-
SLOTS_PER_EPOCH);
|
|
313
|
-
}
|
|
314
|
-
onScrapeLodestarMetrics(metrics) {
|
|
315
|
-
metrics.attnetsService.committeeSubnets.set(this.committeeSubnets.size);
|
|
316
|
-
metrics.attnetsService.subscriptionsCommittee.set(this.subscriptionsCommittee.size);
|
|
317
|
-
metrics.attnetsService.subscriptionsRandom.set(this.subscriptionsRandom.size);
|
|
318
|
-
let aggregatorCount = 0;
|
|
319
|
-
for (const subnets of this.aggregatorSlotSubnet.values()) {
|
|
320
|
-
aggregatorCount += subnets.size;
|
|
321
|
-
}
|
|
322
|
-
metrics.attnetsService.aggregatorSlotSubnetCount.set(aggregatorCount);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
//# sourceMappingURL=attnetsService.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attnetsService.js","sourceRoot":"","sources":["../../../src/network/subnets/attnetsService.ts"],"names":[],"mappings":"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"}
|