@lodestar/beacon-node 1.17.0-dev.3ef43ef0fe → 1.17.0-dev.52ac1555c7
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/rewards/index.js +5 -0
- package/lib/api/impl/beacon/rewards/index.js.map +1 -1
- package/lib/chain/archiver/archiveStates.js +21 -6
- package/lib/chain/archiver/archiveStates.js.map +1 -1
- package/lib/chain/blocks/importBlock.js +2 -1
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +3 -1
- package/lib/chain/blocks/types.js +16 -1
- package/lib/chain/blocks/types.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +1 -0
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js +4 -3
- package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
- package/lib/chain/chain.d.ts +2 -0
- package/lib/chain/chain.js +9 -1
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -0
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/prepareNextSlot.js +1 -0
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/regen/errors.d.ts +7 -1
- package/lib/chain/regen/errors.js +1 -0
- package/lib/chain/regen/errors.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +2 -1
- package/lib/chain/regen/queued.d.ts +19 -4
- package/lib/chain/regen/queued.js +42 -13
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +15 -6
- package/lib/chain/regen/regen.js +62 -24
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/rewards/syncCommitteeRewards.d.ts +6 -0
- package/lib/chain/rewards/syncCommitteeRewards.js +36 -0
- package/lib/chain/rewards/syncCommitteeRewards.js.map +1 -0
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +6 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +9 -17
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +2 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +2 -2
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +6 -5
- package/lib/chain/stateCache/persistentCheckpointsCache.js +18 -17
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/stateContextCache.d.ts +2 -1
- package/lib/chain/stateCache/stateContextCache.js +2 -2
- package/lib/chain/stateCache/stateContextCache.js.map +1 -1
- package/lib/chain/stateCache/stateContextCheckpointsCache.d.ts +5 -4
- package/lib/chain/stateCache/stateContextCheckpointsCache.js +10 -9
- package/lib/chain/stateCache/stateContextCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +6 -5
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +8 -1
- package/lib/metrics/metrics/lodestar.js +10 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/events.d.ts +5 -0
- package/lib/network/events.js +2 -0
- package/lib/network/events.js.map +1 -1
- package/lib/network/processor/gossipHandlers.js +7 -4
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/reqresp/beaconBlocksMaybeBlobsByRoot.d.ts +2 -0
- package/lib/network/reqresp/beaconBlocksMaybeBlobsByRoot.js +39 -1
- package/lib/network/reqresp/beaconBlocksMaybeBlobsByRoot.js.map +1 -1
- package/lib/sync/interface.d.ts +15 -4
- package/lib/sync/interface.js +1 -0
- package/lib/sync/interface.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +9 -0
- package/lib/sync/unknownBlock.js +127 -14
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/pendingBlocksTree.js +5 -2
- package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
- package/lib/util/multifork.d.ts +2 -1
- package/lib/util/multifork.js +4 -1
- package/lib/util/multifork.js.map +1 -1
- package/package.json +15 -17
|
@@ -32,6 +32,7 @@ export interface IStateRegenerator extends IStateRegeneratorInternal {
|
|
|
32
32
|
dumpCacheSummary(): routes.lodestar.StateCacheItem[];
|
|
33
33
|
getStateSync(stateRoot: RootHex): CachedBeaconStateAllForks | null;
|
|
34
34
|
getPreStateSync(block: allForks.BeaconBlock): CachedBeaconStateAllForks | null;
|
|
35
|
+
getCheckpointStateOrBytes(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | Uint8Array | null>;
|
|
35
36
|
getCheckpointStateSync(cp: CheckpointHex): CachedBeaconStateAllForks | null;
|
|
36
37
|
getClosestHeadState(head: ProtoBlock): CachedBeaconStateAllForks | null;
|
|
37
38
|
pruneOnCheckpoint(finalizedEpoch: Epoch, justifiedEpoch: Epoch, headStateRoot: RootHex): void;
|
|
@@ -62,6 +63,6 @@ export interface IStateRegeneratorInternal {
|
|
|
62
63
|
/**
|
|
63
64
|
* Return the exact state with `stateRoot`
|
|
64
65
|
*/
|
|
65
|
-
getState(stateRoot: RootHex, rCaller: RegenCaller): Promise<CachedBeaconStateAllForks>;
|
|
66
|
+
getState(stateRoot: RootHex, rCaller: RegenCaller, opts?: StateCloneOpts): Promise<CachedBeaconStateAllForks>;
|
|
66
67
|
}
|
|
67
68
|
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { phase0, Slot, allForks, RootHex, Epoch } from "@lodestar/types";
|
|
2
2
|
import { ProtoBlock } from "@lodestar/fork-choice";
|
|
3
3
|
import { CachedBeaconStateAllForks } from "@lodestar/state-transition";
|
|
4
|
-
import { Logger } from "@lodestar/utils";
|
|
5
4
|
import { routes } from "@lodestar/api";
|
|
6
5
|
import { CheckpointHex } from "../stateCache/index.js";
|
|
7
6
|
import { JobItemQueue } from "../../util/queue/index.js";
|
|
@@ -9,7 +8,6 @@ import { IStateRegenerator, IStateRegeneratorInternal, RegenCaller, StateCloneOp
|
|
|
9
8
|
import { RegenModules } from "./regen.js";
|
|
10
9
|
type QueuedStateRegeneratorModules = RegenModules & {
|
|
11
10
|
signal: AbortSignal;
|
|
12
|
-
logger: Logger;
|
|
13
11
|
};
|
|
14
12
|
type RegenRequestKey = keyof IStateRegeneratorInternal;
|
|
15
13
|
type RegenRequestByKey = {
|
|
@@ -33,12 +31,29 @@ export declare class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
33
31
|
private readonly metrics;
|
|
34
32
|
private readonly logger;
|
|
35
33
|
constructor(modules: QueuedStateRegeneratorModules);
|
|
34
|
+
init(): Promise<void>;
|
|
36
35
|
canAcceptWork(): boolean;
|
|
37
36
|
dropCache(): void;
|
|
38
37
|
dumpCacheSummary(): routes.lodestar.StateCacheItem[];
|
|
38
|
+
/**
|
|
39
|
+
* Get a state from block state cache.
|
|
40
|
+
* This is not for block processing so don't transfer cache
|
|
41
|
+
*/
|
|
39
42
|
getStateSync(stateRoot: RootHex): CachedBeaconStateAllForks | null;
|
|
40
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Get state for block processing.
|
|
45
|
+
* By default, do not transfer cache except for the block at clock slot
|
|
46
|
+
* which is usually the gossip block.
|
|
47
|
+
*/
|
|
48
|
+
getPreStateSync(block: allForks.BeaconBlock, opts?: StateCloneOpts): CachedBeaconStateAllForks | null;
|
|
49
|
+
getCheckpointStateOrBytes(cp: CheckpointHex): Promise<CachedBeaconStateAllForks | Uint8Array | null>;
|
|
50
|
+
/**
|
|
51
|
+
* Get checkpoint state from cache, this function is not for block processing so don't transfer cache
|
|
52
|
+
*/
|
|
41
53
|
getCheckpointStateSync(cp: CheckpointHex): CachedBeaconStateAllForks | null;
|
|
54
|
+
/**
|
|
55
|
+
* Get state closest to head, this function is not for block processing so don't transfer cache
|
|
56
|
+
*/
|
|
42
57
|
getClosestHeadState(head: ProtoBlock): CachedBeaconStateAllForks | null;
|
|
43
58
|
pruneOnCheckpoint(finalizedEpoch: Epoch, justifiedEpoch: Epoch, headStateRoot: RootHex): void;
|
|
44
59
|
pruneOnFinalized(finalizedEpoch: number): void;
|
|
@@ -59,7 +74,7 @@ export declare class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
59
74
|
* @returns
|
|
60
75
|
*/
|
|
61
76
|
getBlockSlotState(blockRoot: RootHex, slot: Slot, opts: StateCloneOpts, rCaller: RegenCaller): Promise<CachedBeaconStateAllForks>;
|
|
62
|
-
getState(stateRoot: RootHex, rCaller: RegenCaller): Promise<CachedBeaconStateAllForks>;
|
|
77
|
+
getState(stateRoot: RootHex, rCaller: RegenCaller, opts?: StateCloneOpts): Promise<CachedBeaconStateAllForks>;
|
|
63
78
|
private jobQueueProcessor;
|
|
64
79
|
}
|
|
65
80
|
export {};
|
|
@@ -51,6 +51,11 @@ export class QueuedStateRegenerator {
|
|
|
51
51
|
this.metrics = modules.metrics;
|
|
52
52
|
this.logger = modules.logger;
|
|
53
53
|
}
|
|
54
|
+
async init() {
|
|
55
|
+
if (this.checkpointStateCache.init) {
|
|
56
|
+
return this.checkpointStateCache.init();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
54
59
|
canAcceptWork() {
|
|
55
60
|
return this.jobQueue.jobLen < REGEN_CAN_ACCEPT_WORK_THRESHOLD;
|
|
56
61
|
}
|
|
@@ -61,10 +66,19 @@ export class QueuedStateRegenerator {
|
|
|
61
66
|
dumpCacheSummary() {
|
|
62
67
|
return [...this.stateCache.dumpSummary(), ...this.checkpointStateCache.dumpSummary()];
|
|
63
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Get a state from block state cache.
|
|
71
|
+
* This is not for block processing so don't transfer cache
|
|
72
|
+
*/
|
|
64
73
|
getStateSync(stateRoot) {
|
|
65
|
-
return this.stateCache.get(stateRoot);
|
|
74
|
+
return this.stateCache.get(stateRoot, { dontTransferCache: true });
|
|
66
75
|
}
|
|
67
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Get state for block processing.
|
|
78
|
+
* By default, do not transfer cache except for the block at clock slot
|
|
79
|
+
* which is usually the gossip block.
|
|
80
|
+
*/
|
|
81
|
+
getPreStateSync(block, opts = { dontTransferCache: true }) {
|
|
68
82
|
const parentRoot = toHexString(block.parentRoot);
|
|
69
83
|
const parentBlock = this.forkChoice.getBlockHex(parentRoot);
|
|
70
84
|
if (!parentBlock) {
|
|
@@ -77,7 +91,7 @@ export class QueuedStateRegenerator {
|
|
|
77
91
|
const blockEpoch = computeEpochAtSlot(block.slot);
|
|
78
92
|
// Check the checkpoint cache (if the pre-state is a checkpoint state)
|
|
79
93
|
if (parentEpoch < blockEpoch) {
|
|
80
|
-
const checkpointState = this.checkpointStateCache.getLatest(parentRoot, blockEpoch);
|
|
94
|
+
const checkpointState = this.checkpointStateCache.getLatest(parentRoot, blockEpoch, opts);
|
|
81
95
|
if (checkpointState && computeEpochAtSlot(checkpointState.slot) === blockEpoch) {
|
|
82
96
|
return checkpointState;
|
|
83
97
|
}
|
|
@@ -86,18 +100,28 @@ export class QueuedStateRegenerator {
|
|
|
86
100
|
// Otherwise the state transition may not be cached and wasted. Queue for regen since the
|
|
87
101
|
// work required will still be significant.
|
|
88
102
|
if (parentEpoch === blockEpoch) {
|
|
89
|
-
const state = this.stateCache.get(parentBlock.stateRoot);
|
|
103
|
+
const state = this.stateCache.get(parentBlock.stateRoot, opts);
|
|
90
104
|
if (state) {
|
|
91
105
|
return state;
|
|
92
106
|
}
|
|
93
107
|
}
|
|
94
108
|
return null;
|
|
95
109
|
}
|
|
110
|
+
async getCheckpointStateOrBytes(cp) {
|
|
111
|
+
return this.checkpointStateCache.getStateOrBytes(cp);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get checkpoint state from cache, this function is not for block processing so don't transfer cache
|
|
115
|
+
*/
|
|
96
116
|
getCheckpointStateSync(cp) {
|
|
97
|
-
return this.checkpointStateCache.get(cp);
|
|
117
|
+
return this.checkpointStateCache.get(cp, { dontTransferCache: true });
|
|
98
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Get state closest to head, this function is not for block processing so don't transfer cache
|
|
121
|
+
*/
|
|
99
122
|
getClosestHeadState(head) {
|
|
100
|
-
|
|
123
|
+
const opts = { dontTransferCache: true };
|
|
124
|
+
return (this.checkpointStateCache.getLatest(head.blockRoot, Infinity, opts) || this.stateCache.get(head.stateRoot, opts));
|
|
101
125
|
}
|
|
102
126
|
pruneOnCheckpoint(finalizedEpoch, justifiedEpoch, headStateRoot) {
|
|
103
127
|
this.checkpointStateCache.prune(finalizedEpoch, justifiedEpoch);
|
|
@@ -117,19 +141,24 @@ export class QueuedStateRegenerator {
|
|
|
117
141
|
this.checkpointStateCache.add(cp, item);
|
|
118
142
|
}
|
|
119
143
|
updateHeadState(newHeadStateRoot, maybeHeadState) {
|
|
144
|
+
// the resulting state will be added to block state cache so we transfer the cache in this flow
|
|
145
|
+
const cloneOpts = { dontTransferCache: true };
|
|
120
146
|
const headState = newHeadStateRoot === toHexString(maybeHeadState.hashTreeRoot())
|
|
121
147
|
? maybeHeadState
|
|
122
|
-
: this.stateCache.get(newHeadStateRoot);
|
|
148
|
+
: this.stateCache.get(newHeadStateRoot, cloneOpts);
|
|
123
149
|
if (headState) {
|
|
124
150
|
this.stateCache.setHeadState(headState);
|
|
125
151
|
}
|
|
126
152
|
else {
|
|
127
153
|
// Trigger regen on head change if necessary
|
|
128
154
|
this.logger.warn("Head state not available, triggering regen", { stateRoot: newHeadStateRoot });
|
|
155
|
+
// it's important to reload state to regen head state here
|
|
156
|
+
const allowDiskReload = true;
|
|
129
157
|
// head has changed, so the existing cached head state is no longer useful. Set strong reference to null to free
|
|
130
158
|
// up memory for regen step below. During regen, node won't be functional but eventually head will be available
|
|
159
|
+
// for legacy StateContextCache only
|
|
131
160
|
this.stateCache.setHeadState(null);
|
|
132
|
-
this.regen.getState(newHeadStateRoot, RegenCaller.processBlock).then((headStateRegen) => this.stateCache.setHeadState(headStateRegen), (e) => this.logger.error("Error on head state regen", {}, e));
|
|
161
|
+
this.regen.getState(newHeadStateRoot, RegenCaller.processBlock, cloneOpts, allowDiskReload).then((headStateRegen) => this.stateCache.setHeadState(headStateRegen), (e) => this.logger.error("Error on head state regen", {}, e));
|
|
133
162
|
}
|
|
134
163
|
}
|
|
135
164
|
updatePreComputedCheckpoint(rootHex, epoch) {
|
|
@@ -142,7 +171,7 @@ export class QueuedStateRegenerator {
|
|
|
142
171
|
async getPreState(block, opts, rCaller) {
|
|
143
172
|
this.metrics?.regenFnCallTotal.inc({ caller: rCaller, entrypoint: RegenFnName.getPreState });
|
|
144
173
|
// First attempt to fetch the state from caches before queueing
|
|
145
|
-
const cachedState = this.getPreStateSync(block);
|
|
174
|
+
const cachedState = this.getPreStateSync(block, opts);
|
|
146
175
|
if (cachedState !== null) {
|
|
147
176
|
return cachedState;
|
|
148
177
|
}
|
|
@@ -153,7 +182,7 @@ export class QueuedStateRegenerator {
|
|
|
153
182
|
async getCheckpointState(cp, opts, rCaller) {
|
|
154
183
|
this.metrics?.regenFnCallTotal.inc({ caller: rCaller, entrypoint: RegenFnName.getCheckpointState });
|
|
155
184
|
// First attempt to fetch the state from cache before queueing
|
|
156
|
-
const checkpointState = this.checkpointStateCache.get(toCheckpointHex(cp));
|
|
185
|
+
const checkpointState = this.checkpointStateCache.get(toCheckpointHex(cp), opts);
|
|
157
186
|
if (checkpointState) {
|
|
158
187
|
return checkpointState;
|
|
159
188
|
}
|
|
@@ -172,16 +201,16 @@ export class QueuedStateRegenerator {
|
|
|
172
201
|
// The state is not immediately available in the caches, enqueue the job
|
|
173
202
|
return this.jobQueue.push({ key: "getBlockSlotState", args: [blockRoot, slot, opts, rCaller] });
|
|
174
203
|
}
|
|
175
|
-
async getState(stateRoot, rCaller) {
|
|
204
|
+
async getState(stateRoot, rCaller, opts = { dontTransferCache: true }) {
|
|
176
205
|
this.metrics?.regenFnCallTotal.inc({ caller: rCaller, entrypoint: RegenFnName.getState });
|
|
177
206
|
// First attempt to fetch the state from cache before queueing
|
|
178
|
-
const state = this.stateCache.get(stateRoot);
|
|
207
|
+
const state = this.stateCache.get(stateRoot, opts);
|
|
179
208
|
if (state) {
|
|
180
209
|
return state;
|
|
181
210
|
}
|
|
182
211
|
// The state is not immediately available in the cache, enqueue the job
|
|
183
212
|
this.metrics?.regenFnQueuedTotal.inc({ caller: rCaller, entrypoint: RegenFnName.getState });
|
|
184
|
-
return this.jobQueue.push({ key: "getState", args: [stateRoot, rCaller] });
|
|
213
|
+
return this.jobQueue.push({ key: "getState", args: [stateRoot, rCaller, opts] });
|
|
185
214
|
}
|
|
186
215
|
}
|
|
187
216
|
//# sourceMappingURL=queued.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queued.js","sourceRoot":"","sources":["../../../src/chain/regen/queued.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EAA4B,kBAAkB,EAAC,MAAM,4BAA4B,CAAC;AAGzF,OAAO,EAAgB,eAAe,EAAC,MAAM,wBAAwB,CAAC;AAEtE,OAAO,EAAC,YAAY,EAAC,MAAM,2BAA2B,CAAC;AAEvD,OAAO,EAA+C,WAAW,EAAE,WAAW,EAAiB,MAAM,gBAAgB,CAAC;AACtH,OAAO,EAAC,gBAAgB,EAAe,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAC,UAAU,EAAE,cAAc,EAAC,MAAM,aAAa,CAAC;AAEvD,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,iEAAiE;AACjE,MAAM,+BAA+B,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"queued.js","sourceRoot":"","sources":["../../../src/chain/regen/queued.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
import { allForks, phase0, Slot, RootHex } from "@lodestar/types";
|
|
2
2
|
import { CachedBeaconStateAllForks } from "@lodestar/state-transition";
|
|
3
3
|
import { IForkChoice } from "@lodestar/fork-choice";
|
|
4
|
+
import { Logger } from "@lodestar/utils";
|
|
4
5
|
import { ChainForkConfig } from "@lodestar/config";
|
|
5
6
|
import { Metrics } from "../../metrics/index.js";
|
|
6
7
|
import { IBeaconDb } from "../../db/index.js";
|
|
7
|
-
import { CheckpointStateCache, StateContextCache } from "../stateCache/index.js";
|
|
8
8
|
import { ChainEventEmitter } from "../emitter.js";
|
|
9
|
+
import { CheckpointStateCache, BlockStateCache } from "../stateCache/types.js";
|
|
9
10
|
import { IStateRegeneratorInternal, RegenCaller, StateCloneOpts } from "./interface.js";
|
|
10
11
|
export type RegenModules = {
|
|
11
12
|
db: IBeaconDb;
|
|
12
13
|
forkChoice: IForkChoice;
|
|
13
|
-
stateCache:
|
|
14
|
+
stateCache: BlockStateCache;
|
|
14
15
|
checkpointStateCache: CheckpointStateCache;
|
|
15
16
|
config: ChainForkConfig;
|
|
16
17
|
emitter: ChainEventEmitter;
|
|
18
|
+
logger: Logger;
|
|
17
19
|
metrics: Metrics | null;
|
|
18
20
|
};
|
|
19
21
|
/**
|
|
20
22
|
* Regenerates states that have already been processed by the fork choice
|
|
23
|
+
* Since Feb 2024, we support reloading checkpoint state from disk via allowDiskReload flag. Due to its performance impact
|
|
24
|
+
* this flag is only set to true in this case:
|
|
25
|
+
* - getPreState: this is for block processing, it's important to reload state in unfinality time
|
|
26
|
+
* - updateHeadState: rarely happen, but it's important to make sure we always can regen head state
|
|
21
27
|
*/
|
|
22
28
|
export declare class StateRegenerator implements IStateRegeneratorInternal {
|
|
23
29
|
private readonly modules;
|
|
@@ -26,21 +32,24 @@ export declare class StateRegenerator implements IStateRegeneratorInternal {
|
|
|
26
32
|
* Get the state to run with `block`. May be:
|
|
27
33
|
* - If parent is in same epoch -> Exact state at `block.parentRoot`
|
|
28
34
|
* - If parent is in prev epoch -> State after `block.parentRoot` dialed forward through epoch transition
|
|
35
|
+
* - reload state if needed in this flow
|
|
29
36
|
*/
|
|
30
|
-
getPreState(block: allForks.BeaconBlock, opts: StateCloneOpts,
|
|
37
|
+
getPreState(block: allForks.BeaconBlock, opts: StateCloneOpts, regenCaller: RegenCaller): Promise<CachedBeaconStateAllForks>;
|
|
31
38
|
/**
|
|
32
39
|
* Get state after block `cp.root` dialed forward to first slot of `cp.epoch`
|
|
33
40
|
*/
|
|
34
|
-
getCheckpointState(cp: phase0.Checkpoint, opts: StateCloneOpts,
|
|
41
|
+
getCheckpointState(cp: phase0.Checkpoint, opts: StateCloneOpts, regenCaller: RegenCaller, allowDiskReload?: boolean): Promise<CachedBeaconStateAllForks>;
|
|
35
42
|
/**
|
|
36
43
|
* Get state after block `blockRoot` dialed forward to `slot`
|
|
44
|
+
* - allowDiskReload should be used with care, as it will cause the state to be reloaded from disk
|
|
37
45
|
*/
|
|
38
|
-
getBlockSlotState(blockRoot: RootHex, slot: Slot, opts: StateCloneOpts,
|
|
46
|
+
getBlockSlotState(blockRoot: RootHex, slot: Slot, opts: StateCloneOpts, regenCaller: RegenCaller, allowDiskReload?: boolean): Promise<CachedBeaconStateAllForks>;
|
|
39
47
|
/**
|
|
40
48
|
* Get state by exact root. If not in cache directly, requires finding the block that references the state from the
|
|
41
49
|
* forkchoice and replaying blocks to get to it.
|
|
50
|
+
* - allowDiskReload should be used with care, as it will cause the state to be reloaded from disk
|
|
42
51
|
*/
|
|
43
|
-
getState(stateRoot: RootHex, _rCaller: RegenCaller): Promise<CachedBeaconStateAllForks>;
|
|
52
|
+
getState(stateRoot: RootHex, _rCaller: RegenCaller, opts?: StateCloneOpts, allowDiskReload?: boolean): Promise<CachedBeaconStateAllForks>;
|
|
44
53
|
private findFirstStateBlock;
|
|
45
54
|
}
|
|
46
55
|
//# sourceMappingURL=regen.d.ts.map
|
package/lib/chain/regen/regen.js
CHANGED
|
@@ -7,6 +7,10 @@ import { ChainEvent } from "../emitter.js";
|
|
|
7
7
|
import { RegenError, RegenErrorCode } from "./errors.js";
|
|
8
8
|
/**
|
|
9
9
|
* Regenerates states that have already been processed by the fork choice
|
|
10
|
+
* Since Feb 2024, we support reloading checkpoint state from disk via allowDiskReload flag. Due to its performance impact
|
|
11
|
+
* this flag is only set to true in this case:
|
|
12
|
+
* - getPreState: this is for block processing, it's important to reload state in unfinality time
|
|
13
|
+
* - updateHeadState: rarely happen, but it's important to make sure we always can regen head state
|
|
10
14
|
*/
|
|
11
15
|
export class StateRegenerator {
|
|
12
16
|
constructor(modules) {
|
|
@@ -16,8 +20,9 @@ export class StateRegenerator {
|
|
|
16
20
|
* Get the state to run with `block`. May be:
|
|
17
21
|
* - If parent is in same epoch -> Exact state at `block.parentRoot`
|
|
18
22
|
* - If parent is in prev epoch -> State after `block.parentRoot` dialed forward through epoch transition
|
|
23
|
+
* - reload state if needed in this flow
|
|
19
24
|
*/
|
|
20
|
-
async getPreState(block, opts,
|
|
25
|
+
async getPreState(block, opts, regenCaller) {
|
|
21
26
|
const parentBlock = this.modules.forkChoice.getBlock(block.parentRoot);
|
|
22
27
|
if (!parentBlock) {
|
|
23
28
|
throw new RegenError({
|
|
@@ -27,28 +32,30 @@ export class StateRegenerator {
|
|
|
27
32
|
}
|
|
28
33
|
const parentEpoch = computeEpochAtSlot(parentBlock.slot);
|
|
29
34
|
const blockEpoch = computeEpochAtSlot(block.slot);
|
|
35
|
+
const allowDiskReload = true;
|
|
30
36
|
// This may save us at least one epoch transition.
|
|
31
37
|
// If the requested state crosses an epoch boundary
|
|
32
38
|
// then we may use the checkpoint state before the block
|
|
33
39
|
// We may have the checkpoint state with parent root inside the checkpoint state cache
|
|
34
40
|
// through gossip validation.
|
|
35
41
|
if (parentEpoch < blockEpoch) {
|
|
36
|
-
return this.getCheckpointState({ root: block.parentRoot, epoch: blockEpoch }, opts,
|
|
42
|
+
return this.getCheckpointState({ root: block.parentRoot, epoch: blockEpoch }, opts, regenCaller, allowDiskReload);
|
|
37
43
|
}
|
|
38
44
|
// Otherwise, get the state normally.
|
|
39
|
-
return this.getState(parentBlock.stateRoot,
|
|
45
|
+
return this.getState(parentBlock.stateRoot, regenCaller, opts, allowDiskReload);
|
|
40
46
|
}
|
|
41
47
|
/**
|
|
42
48
|
* Get state after block `cp.root` dialed forward to first slot of `cp.epoch`
|
|
43
49
|
*/
|
|
44
|
-
async getCheckpointState(cp, opts,
|
|
50
|
+
async getCheckpointState(cp, opts, regenCaller, allowDiskReload = false) {
|
|
45
51
|
const checkpointStartSlot = computeStartSlotAtEpoch(cp.epoch);
|
|
46
|
-
return this.getBlockSlotState(toHexString(cp.root), checkpointStartSlot, opts,
|
|
52
|
+
return this.getBlockSlotState(toHexString(cp.root), checkpointStartSlot, opts, regenCaller, allowDiskReload);
|
|
47
53
|
}
|
|
48
54
|
/**
|
|
49
55
|
* Get state after block `blockRoot` dialed forward to `slot`
|
|
56
|
+
* - allowDiskReload should be used with care, as it will cause the state to be reloaded from disk
|
|
50
57
|
*/
|
|
51
|
-
async getBlockSlotState(blockRoot, slot, opts,
|
|
58
|
+
async getBlockSlotState(blockRoot, slot, opts, regenCaller, allowDiskReload = false) {
|
|
52
59
|
const block = this.modules.forkChoice.getBlockHex(blockRoot);
|
|
53
60
|
if (!block) {
|
|
54
61
|
throw new RegenError({
|
|
@@ -63,25 +70,32 @@ export class StateRegenerator {
|
|
|
63
70
|
blockSlot: block.slot,
|
|
64
71
|
});
|
|
65
72
|
}
|
|
66
|
-
const
|
|
73
|
+
const { checkpointStateCache } = this.modules;
|
|
74
|
+
const epoch = computeEpochAtSlot(slot);
|
|
75
|
+
const latestCheckpointStateCtx = allowDiskReload
|
|
76
|
+
? await checkpointStateCache.getOrReloadLatest(blockRoot, epoch, opts)
|
|
77
|
+
: checkpointStateCache.getLatest(blockRoot, epoch, opts);
|
|
67
78
|
// If a checkpoint state exists with the given checkpoint root, it either is in requested epoch
|
|
68
79
|
// or needs to have empty slots processed until the requested epoch
|
|
69
80
|
if (latestCheckpointStateCtx) {
|
|
70
|
-
return processSlotsByCheckpoint(this.modules, latestCheckpointStateCtx, slot, opts);
|
|
81
|
+
return processSlotsByCheckpoint(this.modules, latestCheckpointStateCtx, slot, regenCaller, opts);
|
|
71
82
|
}
|
|
72
83
|
// Otherwise, use the fork choice to get the stateRoot from block at the checkpoint root
|
|
73
84
|
// regenerate that state,
|
|
74
85
|
// then process empty slots until the requested epoch
|
|
75
|
-
const blockStateCtx = await this.getState(block.stateRoot,
|
|
76
|
-
return processSlotsByCheckpoint(this.modules, blockStateCtx, slot, opts);
|
|
86
|
+
const blockStateCtx = await this.getState(block.stateRoot, regenCaller, opts, allowDiskReload);
|
|
87
|
+
return processSlotsByCheckpoint(this.modules, blockStateCtx, slot, regenCaller, opts);
|
|
77
88
|
}
|
|
78
89
|
/**
|
|
79
90
|
* Get state by exact root. If not in cache directly, requires finding the block that references the state from the
|
|
80
91
|
* forkchoice and replaying blocks to get to it.
|
|
92
|
+
* - allowDiskReload should be used with care, as it will cause the state to be reloaded from disk
|
|
81
93
|
*/
|
|
82
|
-
async getState(stateRoot, _rCaller
|
|
94
|
+
async getState(stateRoot, _rCaller, opts,
|
|
95
|
+
// internal option, don't want to expose to external caller
|
|
96
|
+
allowDiskReload = false) {
|
|
83
97
|
// Trivial case, state at stateRoot is already cached
|
|
84
|
-
const cachedStateCtx = this.modules.stateCache.get(stateRoot);
|
|
98
|
+
const cachedStateCtx = this.modules.stateCache.get(stateRoot, opts);
|
|
85
99
|
if (cachedStateCtx) {
|
|
86
100
|
return cachedStateCtx;
|
|
87
101
|
}
|
|
@@ -93,12 +107,17 @@ export class StateRegenerator {
|
|
|
93
107
|
// gets reversed when replayed
|
|
94
108
|
const blocksToReplay = [block];
|
|
95
109
|
let state = null;
|
|
96
|
-
|
|
97
|
-
|
|
110
|
+
const { checkpointStateCache } = this.modules;
|
|
111
|
+
// iterateAncestorBlocks only returns ancestor blocks, not the block itself
|
|
112
|
+
for (const b of this.modules.forkChoice.iterateAncestorBlocks(block.blockRoot)) {
|
|
113
|
+
state = this.modules.stateCache.get(b.stateRoot, opts);
|
|
98
114
|
if (state) {
|
|
99
115
|
break;
|
|
100
116
|
}
|
|
101
|
-
|
|
117
|
+
const epoch = computeEpochAtSlot(blocksToReplay[blocksToReplay.length - 1].slot - 1);
|
|
118
|
+
state = allowDiskReload
|
|
119
|
+
? await checkpointStateCache.getOrReloadLatest(b.blockRoot, epoch, opts)
|
|
120
|
+
: checkpointStateCache.getLatest(b.blockRoot, epoch, opts);
|
|
102
121
|
if (state) {
|
|
103
122
|
break;
|
|
104
123
|
}
|
|
@@ -116,6 +135,8 @@ export class StateRegenerator {
|
|
|
116
135
|
stateRoot,
|
|
117
136
|
});
|
|
118
137
|
}
|
|
138
|
+
const replaySlots = blocksToReplay.map((b) => b.slot).join(",");
|
|
139
|
+
this.modules.logger.debug("Replaying blocks to get state", { stateRoot, replaySlots });
|
|
119
140
|
for (const b of blocksToReplay.reverse()) {
|
|
120
141
|
const block = await this.modules.db.block.get(fromHexString(b.blockRoot));
|
|
121
142
|
if (!block) {
|
|
@@ -134,9 +155,20 @@ export class StateRegenerator {
|
|
|
134
155
|
verifyStateRoot: false,
|
|
135
156
|
verifyProposer: false,
|
|
136
157
|
verifySignatures: false,
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
|
|
158
|
+
}, this.modules.metrics);
|
|
159
|
+
const stateRoot = toHexString(state.hashTreeRoot());
|
|
160
|
+
if (b.stateRoot !== stateRoot) {
|
|
161
|
+
throw new RegenError({
|
|
162
|
+
slot: b.slot,
|
|
163
|
+
code: RegenErrorCode.INVALID_STATE_ROOT,
|
|
164
|
+
actual: stateRoot,
|
|
165
|
+
expected: b.stateRoot,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (allowDiskReload) {
|
|
169
|
+
// also with allowDiskReload flag, we "reload" it to the state cache too
|
|
170
|
+
this.modules.stateCache.add(state);
|
|
171
|
+
}
|
|
140
172
|
// this avoids keeping our node busy processing blocks
|
|
141
173
|
await sleep(0);
|
|
142
174
|
}
|
|
@@ -147,11 +179,12 @@ export class StateRegenerator {
|
|
|
147
179
|
});
|
|
148
180
|
}
|
|
149
181
|
}
|
|
182
|
+
this.modules.logger.debug("Replayed blocks to get state", { stateRoot, replaySlots });
|
|
150
183
|
return state;
|
|
151
184
|
}
|
|
152
185
|
findFirstStateBlock(stateRoot) {
|
|
153
186
|
for (const block of this.modules.forkChoice.forwarditerateAncestorBlocks()) {
|
|
154
|
-
if (block
|
|
187
|
+
if (block.stateRoot === stateRoot) {
|
|
155
188
|
return block;
|
|
156
189
|
}
|
|
157
190
|
}
|
|
@@ -166,8 +199,8 @@ export class StateRegenerator {
|
|
|
166
199
|
* process slots forward towards `slot`,
|
|
167
200
|
* emitting "checkpoint" events after every epoch processed.
|
|
168
201
|
*/
|
|
169
|
-
async function processSlotsByCheckpoint(modules, preState, slot, opts) {
|
|
170
|
-
let postState = await processSlotsToNearestCheckpoint(modules, preState, slot, opts);
|
|
202
|
+
async function processSlotsByCheckpoint(modules, preState, slot, regenCaller, opts) {
|
|
203
|
+
let postState = await processSlotsToNearestCheckpoint(modules, preState, slot, regenCaller, opts);
|
|
171
204
|
if (postState.slot < slot) {
|
|
172
205
|
postState = processSlots(postState, slot, opts, modules.metrics);
|
|
173
206
|
}
|
|
@@ -180,7 +213,7 @@ async function processSlotsByCheckpoint(modules, preState, slot, opts) {
|
|
|
180
213
|
*
|
|
181
214
|
* Stops processing after no more full epochs can be processed.
|
|
182
215
|
*/
|
|
183
|
-
async function processSlotsToNearestCheckpoint(modules, preState, slot, opts) {
|
|
216
|
+
async function processSlotsToNearestCheckpoint(modules, preState, slot, regenCaller, opts) {
|
|
184
217
|
const preSlot = preState.slot;
|
|
185
218
|
const postSlot = slot;
|
|
186
219
|
const preEpoch = computeEpochAtSlot(preSlot);
|
|
@@ -189,11 +222,16 @@ async function processSlotsToNearestCheckpoint(modules, preState, slot, opts) {
|
|
|
189
222
|
for (let nextEpochSlot = computeStartSlotAtEpoch(preEpoch + 1); nextEpochSlot <= postSlot; nextEpochSlot += SLOTS_PER_EPOCH) {
|
|
190
223
|
// processSlots calls .clone() before mutating
|
|
191
224
|
postState = processSlots(postState, nextEpochSlot, opts, metrics);
|
|
192
|
-
|
|
225
|
+
modules.metrics?.epochTransitionByCaller.inc({ caller: regenCaller });
|
|
226
|
+
// this is usually added when we prepare for next slot or validate gossip block
|
|
227
|
+
// then when we process the 1st block of epoch, we don't have to do state transition again
|
|
228
|
+
// This adds Previous Root Checkpoint State to the checkpoint state cache
|
|
229
|
+
// This may becomes the "official" checkpoint state if the 1st block of epoch is skipped
|
|
193
230
|
const checkpointState = postState;
|
|
194
231
|
const cp = getCheckpointFromState(checkpointState);
|
|
195
232
|
checkpointStateCache.add(cp, checkpointState);
|
|
196
|
-
|
|
233
|
+
// consumers should not mutate or get the transfered cache
|
|
234
|
+
emitter.emit(ChainEvent.checkpoint, cp, checkpointState.clone(true));
|
|
197
235
|
// this avoids keeping our node busy processing blocks
|
|
198
236
|
await sleep(0);
|
|
199
237
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regen.js","sourceRoot":"","sources":["../../../src/chain/regen/regen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAE,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EAEL,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,EACtB,mBAAmB,EACnB,YAAY,EACZ,eAAe,GAChB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,
|
|
1
|
+
{"version":3,"file":"regen.js","sourceRoot":"","sources":["../../../src/chain/regen/regen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CachedBeaconStateAllForks } from "@lodestar/state-transition";
|
|
2
|
+
import { ValidatorIndex, allForks } from "@lodestar/types";
|
|
3
|
+
import { routes } from "@lodestar/api";
|
|
4
|
+
export type SyncCommitteeRewards = routes.beacon.SyncCommitteeRewards;
|
|
5
|
+
export declare function computeSyncCommitteeRewards(block: allForks.BeaconBlock, preState: CachedBeaconStateAllForks, validatorIds?: (ValidatorIndex | string)[]): Promise<SyncCommitteeRewards>;
|
|
6
|
+
//# sourceMappingURL=syncCommitteeRewards.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ForkName, SYNC_COMMITTEE_SIZE } from "@lodestar/params";
|
|
2
|
+
export async function computeSyncCommitteeRewards(block, preState, validatorIds) {
|
|
3
|
+
const fork = preState.config.getForkName(block.slot);
|
|
4
|
+
if (fork === ForkName.phase0) {
|
|
5
|
+
throw Error("Cannot get sync rewards as phase0 block does not have sync committee");
|
|
6
|
+
}
|
|
7
|
+
const altairBlock = block;
|
|
8
|
+
const preStateAltair = preState;
|
|
9
|
+
const { index2pubkey } = preStateAltair.epochCtx;
|
|
10
|
+
// Bound committeeIndices in case it goes beyond SYNC_COMMITTEE_SIZE just to be safe
|
|
11
|
+
const committeeIndices = preStateAltair.epochCtx.currentSyncCommitteeIndexed.validatorIndices.slice(0, SYNC_COMMITTEE_SIZE);
|
|
12
|
+
const { syncParticipantReward } = preStateAltair.epochCtx;
|
|
13
|
+
const { syncCommitteeBits } = altairBlock.body.syncAggregate;
|
|
14
|
+
// Use balance of each committee as starting point such that we cap the penalty to avoid balance dropping below 0
|
|
15
|
+
const balances = new Map(committeeIndices.map((i) => [i, { val: preStateAltair.balances.get(i) }]));
|
|
16
|
+
for (const i of committeeIndices) {
|
|
17
|
+
const balanceRecord = balances.get(i);
|
|
18
|
+
if (syncCommitteeBits.get(i)) {
|
|
19
|
+
// Positive rewards for participants
|
|
20
|
+
balanceRecord.val += syncParticipantReward;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
// Negative rewards for non participants
|
|
24
|
+
balanceRecord.val = Math.max(0, balanceRecord.val - syncParticipantReward);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const rewards = Array.from(balances, ([validatorIndex, v]) => ({ validatorIndex, reward: v.val }));
|
|
28
|
+
if (validatorIds !== undefined) {
|
|
29
|
+
const filtersSet = new Set(validatorIds);
|
|
30
|
+
return rewards.filter((reward) => filtersSet.has(reward.validatorIndex) || filtersSet.has(index2pubkey[reward.validatorIndex].toHex()));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
return rewards;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=syncCommitteeRewards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syncCommitteeRewards.js","sourceRoot":"","sources":["../../../src/chain/rewards/syncCommitteeRewards.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,QAAQ,EAAE,mBAAmB,EAAC,MAAM,kBAAkB,CAAC;AAM/D,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,KAA2B,EAC3B,QAAmC,EACnC,YAA0C;IAE1C,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrD,IAAI,IAAI,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,KAAK,CAAC,sEAAsE,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,WAAW,GAAG,KAA2B,CAAC;IAChD,MAAM,cAAc,GAAG,QAAmC,CAAC;IAC3D,MAAM,EAAC,YAAY,EAAC,GAAG,cAAc,CAAC,QAAQ,CAAC;IAE/C,oFAAoF;IACpF,MAAM,gBAAgB,GAAG,cAAc,CAAC,QAAQ,CAAC,2BAA2B,CAAC,gBAAgB,CAAC,KAAK,CACjG,CAAC,EACD,mBAAmB,CACpB,CAAC;IACF,MAAM,EAAC,qBAAqB,EAAC,GAAG,cAAc,CAAC,QAAQ,CAAC;IACxD,MAAM,EAAC,iBAAiB,EAAC,GAAG,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC;IAE3D,iHAAiH;IACjH,MAAM,QAAQ,GAAuC,IAAI,GAAG,CAC1D,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CACxE,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAkB,CAAC;QACvD,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7B,oCAAoC;YACpC,aAAa,CAAC,GAAG,IAAI,qBAAqB,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,wCAAwC;YACxC,aAAa,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,GAAG,qBAAqB,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAC,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,EAAC,CAAC,CAAC,CAAC;IAEjG,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC,MAAM,CACnB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,CAAC,CACjH,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { deneb, RootHex, allForks } from "@lodestar/types";
|
|
2
2
|
import { ChainForkConfig } from "@lodestar/config";
|
|
3
3
|
import { BlockInput, GossipedInputType } from "../blocks/types.js";
|
|
4
|
+
import { Metrics } from "../../metrics/index.js";
|
|
5
|
+
export declare enum BlockInputAvailabilitySource {
|
|
6
|
+
GOSSIP = "gossip",
|
|
7
|
+
UNKNOWN_SYNC = "unknown_sync"
|
|
8
|
+
}
|
|
4
9
|
type GossipedBlockInput = {
|
|
5
10
|
type: GossipedInputType.block;
|
|
6
11
|
signedBlock: allForks.SignedBeaconBlock;
|
|
@@ -25,7 +30,7 @@ export declare class SeenGossipBlockInput {
|
|
|
25
30
|
private blockInputCache;
|
|
26
31
|
prune(): void;
|
|
27
32
|
hasBlock(blockRoot: RootHex): boolean;
|
|
28
|
-
getGossipBlockInput(config: ChainForkConfig, gossipedInput: GossipedBlockInput): {
|
|
33
|
+
getGossipBlockInput(config: ChainForkConfig, gossipedInput: GossipedBlockInput, metrics: Metrics | null): {
|
|
29
34
|
blockInput: BlockInput;
|
|
30
35
|
blockInputMeta: {
|
|
31
36
|
pending: GossipedInputType.blob | null;
|