@lodestar/beacon-node 1.41.0 → 1.42.0-dev.5f2fffc2ce
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/utils.d.ts +2 -2
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +5 -1
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +0 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +0 -9
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +4 -4
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +4 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +38 -0
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +11 -7
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/chain.d.ts +3 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +16 -7
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +6 -2
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/regen/errors.d.ts +11 -1
- package/lib/chain/regen/errors.d.ts.map +1 -1
- package/lib/chain/regen/errors.js +2 -0
- package/lib/chain/regen/errors.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +12 -6
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/queued.d.ts +11 -6
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +40 -8
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +5 -0
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +33 -6
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/stateCache/datastore/db.d.ts +4 -5
- package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/db.js +32 -10
- package/lib/chain/stateCache/datastore/db.js.map +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/file.js +5 -5
- package/lib/chain/stateCache/datastore/file.js.map +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +7 -4
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +8 -3
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +33 -14
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +217 -119
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +15 -8
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.d.ts.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +2 -2
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/state/utils.ts +2 -2
- package/src/api/impl/validator/index.ts +7 -3
- package/src/chain/archiveStore/archiveStore.ts +0 -10
- package/src/chain/archiveStore/interface.ts +4 -4
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +8 -5
- package/src/chain/archiveStore/utils/archiveBlocks.ts +59 -1
- package/src/chain/blocks/importBlock.ts +11 -6
- package/src/chain/blocks/verifyBlocksSignatures.ts +1 -1
- package/src/chain/chain.ts +23 -12
- package/src/chain/interface.ts +2 -2
- package/src/chain/prepareNextSlot.ts +6 -2
- package/src/chain/regen/errors.ts +6 -1
- package/src/chain/regen/interface.ts +12 -6
- package/src/chain/regen/queued.ts +48 -12
- package/src/chain/regen/regen.ts +37 -7
- package/src/chain/stateCache/datastore/db.ts +33 -10
- package/src/chain/stateCache/datastore/file.ts +6 -5
- package/src/chain/stateCache/datastore/types.ts +3 -2
- package/src/chain/stateCache/fifoBlockStateCache.ts +10 -4
- package/src/chain/stateCache/persistentCheckpointsCache.ts +248 -139
- package/src/chain/stateCache/types.ts +18 -8
- package/src/chain/validation/voluntaryExit.ts +2 -1
- package/lib/chain/archiveStore/utils/archivePayloads.d.ts +0 -7
- package/lib/chain/archiveStore/utils/archivePayloads.d.ts.map +0 -1
- package/lib/chain/archiveStore/utils/archivePayloads.js +0 -10
- package/lib/chain/archiveStore/utils/archivePayloads.js.map +0 -1
- package/src/chain/archiveStore/utils/archivePayloads.ts +0 -15
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { routes } from "@lodestar/api";
|
|
2
2
|
import { CachedBeaconStateAllForks } from "@lodestar/state-transition";
|
|
3
3
|
import { Epoch, RootHex, phase0 } from "@lodestar/types";
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Checkpoint hex representation for state cache keys.
|
|
6
|
+
* Extends CheckpointWithHex (from fork-choice) with payloadPresent.
|
|
7
|
+
*/
|
|
8
|
+
export type CheckpointHexPayload = {
|
|
5
9
|
epoch: Epoch;
|
|
6
10
|
rootHex: RootHex;
|
|
11
|
+
payloadPresent: boolean;
|
|
7
12
|
};
|
|
8
13
|
/**
|
|
9
14
|
* Lodestar currently keeps two state caches around.
|
|
@@ -31,6 +36,8 @@ export interface BlockStateCache {
|
|
|
31
36
|
size: number;
|
|
32
37
|
prune(headStateRootHex: RootHex): void;
|
|
33
38
|
deleteAllBeforeEpoch(finalizedEpoch: Epoch): void;
|
|
39
|
+
/** Upgrade cache capacity for Gloas fork (2x states for block + payload states) */
|
|
40
|
+
upgradeToGloas(): void;
|
|
34
41
|
dumpSummary(): routes.lodestar.StateCacheItem[];
|
|
35
42
|
/** Expose beacon states stored in cache. Use with caution */
|
|
36
43
|
getStates(): IterableIterator<CachedBeaconStateAllForks>;
|
|
@@ -58,13 +65,13 @@ export interface BlockStateCache {
|
|
|
58
65
|
*/
|
|
59
66
|
export interface CheckpointStateCache {
|
|
60
67
|
init?: () => Promise<void>;
|
|
61
|
-
getOrReload(cp:
|
|
62
|
-
getStateOrBytes(cp:
|
|
63
|
-
get(cpOrKey:
|
|
64
|
-
add(cp: phase0.Checkpoint, state: CachedBeaconStateAllForks): void;
|
|
65
|
-
getLatest(rootHex: RootHex, maxEpoch: Epoch): CachedBeaconStateAllForks | null;
|
|
66
|
-
getOrReloadLatest(rootHex: RootHex, maxEpoch: Epoch): Promise<CachedBeaconStateAllForks | null>;
|
|
67
|
-
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch): number | null;
|
|
68
|
+
getOrReload(cp: CheckpointHexPayload): Promise<CachedBeaconStateAllForks | null>;
|
|
69
|
+
getStateOrBytes(cp: CheckpointHexPayload): Promise<CachedBeaconStateAllForks | Uint8Array | null>;
|
|
70
|
+
get(cpOrKey: CheckpointHexPayload | string): CachedBeaconStateAllForks | null;
|
|
71
|
+
add(cp: phase0.Checkpoint, state: CachedBeaconStateAllForks, payloadPresent: boolean): void;
|
|
72
|
+
getLatest(rootHex: RootHex, maxEpoch: Epoch, payloadPresent: boolean): CachedBeaconStateAllForks | null;
|
|
73
|
+
getOrReloadLatest(rootHex: RootHex, maxEpoch: Epoch, payloadPresent: boolean): Promise<CachedBeaconStateAllForks | null>;
|
|
74
|
+
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch, payloadPresent: boolean): number | null;
|
|
68
75
|
prune(finalizedEpoch: Epoch, justifiedEpoch: Epoch): void;
|
|
69
76
|
pruneFinalized(finalizedEpoch: Epoch): void;
|
|
70
77
|
processState(blockRootHex: RootHex, state: CachedBeaconStateAllForks): Promise<number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/chain/stateCache/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,eAAe,CAAC;AACrC,OAAO,EAAC,yBAAyB,EAAC,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEvD,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/chain/stateCache/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,eAAe,CAAC;AACrC,OAAO,EAAC,yBAAyB,EAAC,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEvD;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAAC,KAAK,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAC,CAAC;AAE7F;;;;;;;;GAQG;AAEH;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,yBAAyB,GAAG,IAAI,CAAC;IACxD,GAAG,CAAC,IAAI,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC3C,YAAY,CAAC,IAAI,EAAE,yBAAyB,GAAG,IAAI,GAAG,IAAI,CAAC;IAC3D;;OAEG;IACH,YAAY,IAAI,yBAAyB,CAAC;IAC1C,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,gBAAgB,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC,oBAAoB,CAAC,cAAc,EAAE,KAAK,GAAG,IAAI,CAAC;IAClD,mFAAmF;IACnF,cAAc,IAAI,IAAI,CAAC;IACvB,WAAW,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;IAChD,6DAA6D;IAC7D,SAAS,IAAI,gBAAgB,CAAC,yBAAyB,CAAC,CAAC;CAC1D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,EAAE,oBAAoB,GAAG,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAC;IACjF,eAAe,CAAC,EAAE,EAAE,oBAAoB,GAAG,OAAO,CAAC,yBAAyB,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC;IAClG,GAAG,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,GAAG,yBAAyB,GAAG,IAAI,CAAC;IAC9E,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,yBAAyB,EAAE,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5F,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,GAAG,yBAAyB,GAAG,IAAI,CAAC;IACxG,iBAAiB,CACf,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,KAAK,EACf,cAAc,EAAE,OAAO,GACtB,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAC;IAC7C,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IACpG,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,GAAG,IAAI,CAAC;IAC1D,cAAc,CAAC,cAAc,EAAE,KAAK,GAAG,IAAI,CAAC;IAC5C,YAAY,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvF,KAAK,IAAI,IAAI,CAAC;IACd,WAAW,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;IAChD,6DAA6D;IAC7D,SAAS,IAAI,gBAAgB,CAAC,yBAAyB,CAAC,CAAC;CAC1D;AAED,oBAAY,aAAa;IACvB,SAAS,cAAc;IACvB,QAAQ,cAAc;CACvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/chain/stateCache/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/chain/stateCache/types.ts"],"names":[],"mappings":"SAuFY,aAAa;AAAzB,IAAY,aAGX;AAHD,WAAY,aAAa;IACvB,wCAAuB,CAAA;IACvB,uCAAsB,CAAA;AAAC,CACzB,EAHY,aAAa,KAAb,aAAa,QAGxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voluntaryExit.d.ts","sourceRoot":"","sources":["../../../src/chain/validation/voluntaryExit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"voluntaryExit.d.ts","sourceRoot":"","sources":["../../../src/chain/validation/voluntaryExit.ts"],"names":[],"mappings":"AAMA,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAOvC,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAGzC,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM,CAAC,mBAAmB,GACxC,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,MAAM,CAAC,mBAAmB,GACxC,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VoluntaryExitValidity, getVoluntaryExitSignatureSet, getVoluntaryExitValidity, } from "@lodestar/state-transition";
|
|
1
|
+
import { BeaconStateView, VoluntaryExitValidity, getVoluntaryExitSignatureSet, getVoluntaryExitValidity, } from "@lodestar/state-transition";
|
|
2
2
|
import { GossipAction, VoluntaryExitError, VoluntaryExitErrorCode, voluntaryExitValidityToErrorCode, } from "../errors/index.js";
|
|
3
3
|
import { RegenCaller } from "../regen/index.js";
|
|
4
4
|
export async function validateApiVoluntaryExit(chain, voluntaryExit) {
|
|
@@ -32,7 +32,7 @@ async function validateVoluntaryExit(chain, voluntaryExit, prioritizeBls = false
|
|
|
32
32
|
code: voluntaryExitValidityToErrorCode(validity),
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
const signatureSet = getVoluntaryExitSignatureSet(chain.config, state
|
|
35
|
+
const signatureSet = getVoluntaryExitSignatureSet(chain.config, new BeaconStateView(state), voluntaryExit);
|
|
36
36
|
if (!(await chain.bls.verifySignatureSets([signatureSet], { batchable: true, priority: prioritizeBls }))) {
|
|
37
37
|
throw new VoluntaryExitError(GossipAction.REJECT, {
|
|
38
38
|
code: VoluntaryExitErrorCode.INVALID_SIGNATURE,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voluntaryExit.js","sourceRoot":"","sources":["../../../src/chain/validation/voluntaryExit.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,sBAAsB,EACtB,gCAAgC,GACjC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,KAAmB,EACnB,aAAyC,EAC1B;IACf,MAAM,aAAa,GAAG,IAAI,CAAC;IAC3B,OAAO,qBAAqB,CAAC,KAAK,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AAAA,CACnE;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,KAAmB,EACnB,aAAyC,EAC1B;IACf,OAAO,qBAAqB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;AAAA,CACpD;AAED,KAAK,UAAU,qBAAqB,CAClC,KAAmB,EACnB,aAAyC,EACzC,aAAa,GAAG,KAAK,EACN;IACf,sGAAsG;IACtG,iDAAiD;IACjD,IAAI,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,aAAa,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QAC5E,MAAM,IAAI,kBAAkB,CAAC,YAAY,CAAC,MAAM,EAAE;YAChD,IAAI,EAAE,sBAAsB,CAAC,cAAc;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,wDAAwD;IACxD,EAAE;IACF,gFAAgF;IAChF,6DAA6D;IAC7D,sGAAsG;IACtG,kGAAkG;IAClG,6CAA6C;IAC7C,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,0BAA0B,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;IAE9F,gFAAgF;IAChF,mDAAmD;IACnD,MAAM,QAAQ,GAAG,wBAAwB,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;IAC5G,IAAI,QAAQ,KAAK,qBAAqB,CAAC,KAAK,EAAE,CAAC;QAC7C,MAAM,IAAI,kBAAkB,CAAC,YAAY,CAAC,MAAM,EAAE;YAChD,IAAI,EAAE,gCAAgC,CAAC,QAAQ,CAAC;SACjD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,4BAA4B,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"voluntaryExit.js","sourceRoot":"","sources":["../../../src/chain/validation/voluntaryExit.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,sBAAsB,EACtB,gCAAgC,GACjC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,KAAmB,EACnB,aAAyC,EAC1B;IACf,MAAM,aAAa,GAAG,IAAI,CAAC;IAC3B,OAAO,qBAAqB,CAAC,KAAK,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AAAA,CACnE;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,KAAmB,EACnB,aAAyC,EAC1B;IACf,OAAO,qBAAqB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;AAAA,CACpD;AAED,KAAK,UAAU,qBAAqB,CAClC,KAAmB,EACnB,aAAyC,EACzC,aAAa,GAAG,KAAK,EACN;IACf,sGAAsG;IACtG,iDAAiD;IACjD,IAAI,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,aAAa,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QAC5E,MAAM,IAAI,kBAAkB,CAAC,YAAY,CAAC,MAAM,EAAE;YAChD,IAAI,EAAE,sBAAsB,CAAC,cAAc;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,wDAAwD;IACxD,EAAE;IACF,gFAAgF;IAChF,6DAA6D;IAC7D,sGAAsG;IACtG,kGAAkG;IAClG,6CAA6C;IAC7C,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,0BAA0B,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;IAE9F,gFAAgF;IAChF,mDAAmD;IACnD,MAAM,QAAQ,GAAG,wBAAwB,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;IAC5G,IAAI,QAAQ,KAAK,qBAAqB,CAAC,KAAK,EAAE,CAAC;QAC7C,MAAM,IAAI,kBAAkB,CAAC,YAAY,CAAC,MAAM,EAAE;YAChD,IAAI,EAAE,gCAAgC,CAAC,QAAQ,CAAC;SACjD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,4BAA4B,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,CAAC;IAC3G,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,YAAY,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAC,CAAC,CAAC,EAAE,CAAC;QACvG,MAAM,IAAI,kBAAkB,CAAC,YAAY,CAAC,MAAM,EAAE;YAChD,IAAI,EAAE,sBAAsB,CAAC,iBAAiB;SAC/C,CAAC,CAAC;IACL,CAAC;AAAA,CACF"}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/ChainSafe/lodestar/issues"
|
|
13
13
|
},
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.42.0-dev.5f2fffc2ce",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -135,18 +135,18 @@
|
|
|
135
135
|
"@libp2p/peer-id": "^6.0.4",
|
|
136
136
|
"@libp2p/prometheus-metrics": "^5.0.14",
|
|
137
137
|
"@libp2p/tcp": "^11.0.13",
|
|
138
|
-
"@lodestar/api": "^1.
|
|
139
|
-
"@lodestar/config": "^1.
|
|
140
|
-
"@lodestar/db": "^1.
|
|
141
|
-
"@lodestar/fork-choice": "^1.
|
|
142
|
-
"@lodestar/light-client": "^1.
|
|
143
|
-
"@lodestar/logger": "^1.
|
|
144
|
-
"@lodestar/params": "^1.
|
|
145
|
-
"@lodestar/reqresp": "^1.
|
|
146
|
-
"@lodestar/state-transition": "^1.
|
|
147
|
-
"@lodestar/types": "^1.
|
|
148
|
-
"@lodestar/utils": "^1.
|
|
149
|
-
"@lodestar/validator": "^1.
|
|
138
|
+
"@lodestar/api": "^1.42.0-dev.5f2fffc2ce",
|
|
139
|
+
"@lodestar/config": "^1.42.0-dev.5f2fffc2ce",
|
|
140
|
+
"@lodestar/db": "^1.42.0-dev.5f2fffc2ce",
|
|
141
|
+
"@lodestar/fork-choice": "^1.42.0-dev.5f2fffc2ce",
|
|
142
|
+
"@lodestar/light-client": "^1.42.0-dev.5f2fffc2ce",
|
|
143
|
+
"@lodestar/logger": "^1.42.0-dev.5f2fffc2ce",
|
|
144
|
+
"@lodestar/params": "^1.42.0-dev.5f2fffc2ce",
|
|
145
|
+
"@lodestar/reqresp": "^1.42.0-dev.5f2fffc2ce",
|
|
146
|
+
"@lodestar/state-transition": "^1.42.0-dev.5f2fffc2ce",
|
|
147
|
+
"@lodestar/types": "^1.42.0-dev.5f2fffc2ce",
|
|
148
|
+
"@lodestar/utils": "^1.42.0-dev.5f2fffc2ce",
|
|
149
|
+
"@lodestar/validator": "^1.42.0-dev.5f2fffc2ce",
|
|
150
150
|
"@multiformats/multiaddr": "^13.0.1",
|
|
151
151
|
"datastore-core": "^11.0.2",
|
|
152
152
|
"datastore-fs": "^11.0.2",
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
"@libp2p/interface-internal": "^3.0.13",
|
|
170
170
|
"@libp2p/logger": "^6.2.2",
|
|
171
171
|
"@libp2p/utils": "^7.0.13",
|
|
172
|
-
"@lodestar/spec-test-util": "^1.
|
|
172
|
+
"@lodestar/spec-test-util": "^1.42.0-dev.5f2fffc2ce",
|
|
173
173
|
"@types/js-yaml": "^4.0.5",
|
|
174
174
|
"@types/qs": "^6.9.7",
|
|
175
175
|
"@types/tmp": "^0.2.3",
|
|
@@ -186,5 +186,5 @@
|
|
|
186
186
|
"beacon",
|
|
187
187
|
"blockchain"
|
|
188
188
|
],
|
|
189
|
-
"gitHead": "
|
|
189
|
+
"gitHead": "6190f82ce7dc565e0878bd4b743b13870465469e"
|
|
190
190
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
|
-
import {
|
|
2
|
+
import {CheckpointWithPayloadStatus, IForkChoice} from "@lodestar/fork-choice";
|
|
3
3
|
import {GENESIS_SLOT} from "@lodestar/params";
|
|
4
4
|
import {BeaconStateAllForks, CachedBeaconStateAllForks, PubkeyCache} from "@lodestar/state-transition";
|
|
5
5
|
import {
|
|
@@ -19,7 +19,7 @@ import {ApiError, ValidationError} from "../../errors.js";
|
|
|
19
19
|
export function resolveStateId(
|
|
20
20
|
forkChoice: IForkChoice,
|
|
21
21
|
stateId: routes.beacon.StateId
|
|
22
|
-
): RootHex | Slot |
|
|
22
|
+
): RootHex | Slot | CheckpointWithPayloadStatus {
|
|
23
23
|
if (stateId === "head") {
|
|
24
24
|
return forkChoice.getHead().stateRoot;
|
|
25
25
|
}
|
|
@@ -74,7 +74,7 @@ import {ChainEvent, CommonBlockBody} from "../../../chain/index.js";
|
|
|
74
74
|
import {PREPARE_NEXT_SLOT_BPS} from "../../../chain/prepareNextSlot.js";
|
|
75
75
|
import {BlockType, ProduceFullDeneb, ProduceFullGloas} from "../../../chain/produceBlock/index.js";
|
|
76
76
|
import {RegenCaller} from "../../../chain/regen/index.js";
|
|
77
|
-
import {
|
|
77
|
+
import {CheckpointHexPayload} from "../../../chain/stateCache/types.js";
|
|
78
78
|
import {validateApiAggregateAndProof} from "../../../chain/validation/index.js";
|
|
79
79
|
import {validateSyncCommitteeGossipContributionAndProof} from "../../../chain/validation/syncCommitteeContributionAndProof.js";
|
|
80
80
|
import {ZERO_HASH} from "../../../constants/index.js";
|
|
@@ -303,7 +303,7 @@ export function getValidatorApi(
|
|
|
303
303
|
* |
|
|
304
304
|
* prepareNextSlot (4s before next slot)
|
|
305
305
|
*/
|
|
306
|
-
async function waitForCheckpointState(cpHex:
|
|
306
|
+
async function waitForCheckpointState(cpHex: CheckpointHexPayload): Promise<CachedBeaconStateAllForks | null> {
|
|
307
307
|
const cpState = chain.regen.getCheckpointStateSync(cpHex);
|
|
308
308
|
if (cpState) {
|
|
309
309
|
return cpState;
|
|
@@ -1112,7 +1112,11 @@ export function getValidatorApi(
|
|
|
1112
1112
|
// this is to avoid missed block proposal due to 0 epoch look ahead
|
|
1113
1113
|
if (epoch === nextEpoch && toNextEpochMs < prepareNextSlotLookAheadMs) {
|
|
1114
1114
|
// wait for maximum 1 slot for cp state which is the timeout of validator api
|
|
1115
|
-
const cpState = await waitForCheckpointState({
|
|
1115
|
+
const cpState = await waitForCheckpointState({
|
|
1116
|
+
rootHex: head.blockRoot,
|
|
1117
|
+
epoch,
|
|
1118
|
+
payloadPresent: head.payloadStatus === PayloadStatus.FULL,
|
|
1119
|
+
});
|
|
1116
1120
|
if (cpState) {
|
|
1117
1121
|
state = cpState;
|
|
1118
1122
|
metrics?.duties.requestNextEpochProposalDutiesHit.inc();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {CheckpointWithPayloadStatus} from "@lodestar/fork-choice";
|
|
2
2
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
3
|
-
import {ForkSeq} from "@lodestar/params";
|
|
4
3
|
import {Checkpoint} from "@lodestar/types/phase0";
|
|
5
4
|
import {callFnWhenAwait} from "@lodestar/utils";
|
|
6
5
|
import {IBeaconDb} from "../../db/index.js";
|
|
@@ -14,7 +13,6 @@ import {HistoricalStateRegen} from "./historicalState/historicalStateRegen.js";
|
|
|
14
13
|
import {ArchiveMode, ArchiveStoreOpts, StateArchiveStrategy} from "./interface.js";
|
|
15
14
|
import {FrequencyStateArchiveStrategy} from "./strategies/frequencyStateArchiveStrategy.js";
|
|
16
15
|
import {archiveBlocks} from "./utils/archiveBlocks.js";
|
|
17
|
-
import {archiveExecutionPayloadEnvelopes} from "./utils/archivePayloads.js";
|
|
18
16
|
import {pruneHistory} from "./utils/pruneHistory.js";
|
|
19
17
|
import {updateBackfillRange} from "./utils/updateBackfillRange.js";
|
|
20
18
|
|
|
@@ -29,7 +27,6 @@ type ArchiveStoreInitOpts = ArchiveStoreOpts & {dbName: string; anchorState: {fi
|
|
|
29
27
|
|
|
30
28
|
export enum ArchiveStoreTask {
|
|
31
29
|
ArchiveBlocks = "archive_blocks",
|
|
32
|
-
ArchivePayloads = "archive_payloads",
|
|
33
30
|
PruneHistory = "prune_history",
|
|
34
31
|
OnFinalizedCheckpoint = "on_finalized_checkpoint",
|
|
35
32
|
MaybeArchiveState = "maybe_archive_state",
|
|
@@ -192,7 +189,6 @@ export class ArchiveStore {
|
|
|
192
189
|
private processFinalizedCheckpoint = async (finalized: CheckpointWithPayloadStatus): Promise<void> => {
|
|
193
190
|
try {
|
|
194
191
|
const finalizedEpoch = finalized.epoch;
|
|
195
|
-
const finalizedFork = this.chain.config.getForkSeqAtEpoch(finalizedEpoch);
|
|
196
192
|
this.logger.verbose("Start processing finalized checkpoint", {epoch: finalizedEpoch, rootHex: finalized.rootHex});
|
|
197
193
|
|
|
198
194
|
let timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
@@ -210,12 +206,6 @@ export class ArchiveStore {
|
|
|
210
206
|
);
|
|
211
207
|
timer?.({source: ArchiveStoreTask.ArchiveBlocks});
|
|
212
208
|
|
|
213
|
-
if (finalizedFork >= ForkSeq.gloas) {
|
|
214
|
-
timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
215
|
-
await archiveExecutionPayloadEnvelopes(this.chain, finalized);
|
|
216
|
-
timer?.({source: ArchiveStoreTask.ArchivePayloads});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
209
|
if (this.opts.pruneHistory) {
|
|
220
210
|
timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
221
211
|
await pruneHistory(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {CheckpointWithPayloadStatus} from "@lodestar/fork-choice";
|
|
2
2
|
import {RootHex} from "@lodestar/types";
|
|
3
3
|
import {Metrics} from "../../metrics/metrics.js";
|
|
4
4
|
|
|
@@ -44,9 +44,9 @@ export type FinalizedStats = {
|
|
|
44
44
|
|
|
45
45
|
export interface StateArchiveStrategy {
|
|
46
46
|
onCheckpoint(stateRoot: RootHex, metrics?: Metrics | null): Promise<void>;
|
|
47
|
-
onFinalizedCheckpoint(finalized:
|
|
48
|
-
maybeArchiveState(finalized:
|
|
49
|
-
archiveState(finalized:
|
|
47
|
+
onFinalizedCheckpoint(finalized: CheckpointWithPayloadStatus, metrics?: Metrics | null): Promise<void>;
|
|
48
|
+
maybeArchiveState(finalized: CheckpointWithPayloadStatus, metrics?: Metrics | null): Promise<void>;
|
|
49
|
+
archiveState(finalized: CheckpointWithPayloadStatus, metrics?: Metrics | null): Promise<void>;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export interface IArchiveStore {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {CheckpointWithPayloadStatus} from "@lodestar/fork-choice";
|
|
2
2
|
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
3
3
|
import {computeEpochAtSlot, computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
4
4
|
import {Epoch, RootHex, Slot} from "@lodestar/types";
|
|
@@ -9,6 +9,7 @@ import {AllocSource, BufferPool} from "../../../util/bufferPool.js";
|
|
|
9
9
|
import {getStateSlotFromBytes} from "../../../util/multifork.js";
|
|
10
10
|
import {IStateRegenerator} from "../../regen/interface.js";
|
|
11
11
|
import {serializeState} from "../../serializeState.js";
|
|
12
|
+
import {fcCheckpointToHexPayload} from "../../stateCache/persistentCheckpointsCache.js";
|
|
12
13
|
import {StateArchiveStrategy, StatesArchiveOpts} from "../interface.js";
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -40,7 +41,7 @@ export class FrequencyStateArchiveStrategy implements StateArchiveStrategy {
|
|
|
40
41
|
private readonly bufferPool?: BufferPool | null
|
|
41
42
|
) {}
|
|
42
43
|
|
|
43
|
-
async onFinalizedCheckpoint(_finalized:
|
|
44
|
+
async onFinalizedCheckpoint(_finalized: CheckpointWithPayloadStatus, _metrics?: Metrics | null): Promise<void> {}
|
|
44
45
|
async onCheckpoint(_stateRoot: RootHex, _metrics?: Metrics | null): Promise<void> {}
|
|
45
46
|
|
|
46
47
|
/**
|
|
@@ -55,7 +56,7 @@ export class FrequencyStateArchiveStrategy implements StateArchiveStrategy {
|
|
|
55
56
|
* epoch - 1024*2 epoch - 1024 epoch - 32 epoch
|
|
56
57
|
* ```
|
|
57
58
|
*/
|
|
58
|
-
async maybeArchiveState(finalized:
|
|
59
|
+
async maybeArchiveState(finalized: CheckpointWithPayloadStatus, metrics?: Metrics | null): Promise<void> {
|
|
59
60
|
let timer = metrics?.processFinalizedCheckpoint.frequencyStateArchive.startTimer();
|
|
60
61
|
const lastStoredSlot = await this.db.stateArchive.lastKey();
|
|
61
62
|
timer?.({step: FrequencyStateArchiveStep.LoadLastStoredSlot});
|
|
@@ -104,10 +105,12 @@ export class FrequencyStateArchiveStrategy implements StateArchiveStrategy {
|
|
|
104
105
|
* Archives finalized states from active bucket to archive bucket.
|
|
105
106
|
* Only the new finalized state is stored to disk
|
|
106
107
|
*/
|
|
107
|
-
async archiveState(finalized:
|
|
108
|
+
async archiveState(finalized: CheckpointWithPayloadStatus, metrics?: Metrics | null): Promise<void> {
|
|
108
109
|
// starting from Mar 2024, the finalized state could be from disk or in memory
|
|
109
110
|
let timer = metrics?.processFinalizedCheckpoint.frequencyStateArchive.startTimer();
|
|
110
|
-
|
|
111
|
+
// Convert fork-choice checkpoint to beacon-node checkpoint with payloadPresent
|
|
112
|
+
const finalizedHexPayload = fcCheckpointToHexPayload(finalized);
|
|
113
|
+
const finalizedStateOrBytes = await this.regen.getCheckpointStateOrBytes(finalizedHexPayload);
|
|
111
114
|
timer?.({step: FrequencyStateArchiveStep.GetFinalizedState});
|
|
112
115
|
|
|
113
116
|
const {rootHex} = finalized;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
3
|
import {KeyValue} from "@lodestar/db";
|
|
4
|
-
import {CheckpointWithPayloadStatus, IForkChoice} from "@lodestar/fork-choice";
|
|
4
|
+
import {CheckpointWithPayloadStatus, IForkChoice, PayloadStatus, ProtoBlock} from "@lodestar/fork-choice";
|
|
5
5
|
import {ForkSeq, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
6
6
|
import {computeEpochAtSlot, computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
7
7
|
import {Epoch, Slot} from "@lodestar/types";
|
|
@@ -66,6 +66,7 @@ export async function archiveBlocks(
|
|
|
66
66
|
// NOTE: The finalized block will be exactly the first block of `epoch` or previous
|
|
67
67
|
const finalizedPostDeneb = finalizedCheckpoint.epoch >= config.DENEB_FORK_EPOCH;
|
|
68
68
|
const finalizedPostFulu = finalizedCheckpoint.epoch >= config.FULU_FORK_EPOCH;
|
|
69
|
+
const finalizedPostGloas = finalizedCheckpoint.epoch >= config.GLOAS_FORK_EPOCH;
|
|
69
70
|
|
|
70
71
|
const finalizedCanonicalBlockRoots: BlockRootSlot[] = finalizedCanonicalBlocks.map((block) => ({
|
|
71
72
|
slot: block.slot,
|
|
@@ -103,6 +104,16 @@ export async function archiveBlocks(
|
|
|
103
104
|
);
|
|
104
105
|
logger.verbose("Migrated dataColumnSidecars from hot DB to cold DB", {...logCtx, migratedEntries});
|
|
105
106
|
}
|
|
107
|
+
|
|
108
|
+
if (finalizedPostGloas) {
|
|
109
|
+
const migratedEntries = await migrateExecutionPayloadEnvelopesFromHotToColdDb(
|
|
110
|
+
config,
|
|
111
|
+
db,
|
|
112
|
+
logger,
|
|
113
|
+
finalizedCanonicalBlocks
|
|
114
|
+
);
|
|
115
|
+
logger.verbose("Migrated executionPayloadEnvelopes from hot DB to cold DB", {...logCtx, migratedEntries});
|
|
116
|
+
}
|
|
106
117
|
}
|
|
107
118
|
|
|
108
119
|
// deleteNonCanonicalBlocks
|
|
@@ -144,6 +155,11 @@ export async function archiveBlocks(
|
|
|
144
155
|
await db.dataColumnSidecar.deleteMany(nonCanonicalBlockRoots);
|
|
145
156
|
logger.verbose("Deleted non canonical dataColumnSidecars from hot DB", logCtx);
|
|
146
157
|
}
|
|
158
|
+
|
|
159
|
+
if (finalizedPostGloas) {
|
|
160
|
+
await db.executionPayloadEnvelope.batchDelete(nonCanonicalBlockRoots);
|
|
161
|
+
logger.verbose("Deleted non canonical executionPayloadEnvelopes from hot DB", logCtx);
|
|
162
|
+
}
|
|
147
163
|
}
|
|
148
164
|
|
|
149
165
|
// Delete expired blobs
|
|
@@ -372,6 +388,48 @@ async function migrateDataColumnSidecarsFromHotToColdDb(
|
|
|
372
388
|
return migratedWrappedDataColumns;
|
|
373
389
|
}
|
|
374
390
|
|
|
391
|
+
async function migrateExecutionPayloadEnvelopesFromHotToColdDb(
|
|
392
|
+
config: ChainForkConfig,
|
|
393
|
+
db: IBeaconDb,
|
|
394
|
+
logger: Logger,
|
|
395
|
+
canonicalBlocks: ProtoBlock[]
|
|
396
|
+
): Promise<number> {
|
|
397
|
+
let migratedEnvelopes = 0;
|
|
398
|
+
|
|
399
|
+
const payloadBlocks = canonicalBlocks.filter(
|
|
400
|
+
(block) => config.getForkSeq(block.slot) >= ForkSeq.gloas && block.payloadStatus === PayloadStatus.FULL
|
|
401
|
+
);
|
|
402
|
+
if (payloadBlocks.length === 0) return 0;
|
|
403
|
+
const blocks = payloadBlocks.map((block) => ({slot: block.slot, root: fromHex(block.blockRoot)}));
|
|
404
|
+
|
|
405
|
+
const envelopeEntries: KeyValue<Slot, Uint8Array>[] = [];
|
|
406
|
+
const migratedRoots: Uint8Array[] = [];
|
|
407
|
+
|
|
408
|
+
const envelopeBytesArray = await Promise.all(
|
|
409
|
+
blocks.map((block) => db.executionPayloadEnvelope.getBinary(block.root))
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
413
|
+
const bytes = envelopeBytesArray[i];
|
|
414
|
+
if (bytes !== null) {
|
|
415
|
+
envelopeEntries.push({key: blocks[i].slot, value: bytes});
|
|
416
|
+
migratedRoots.push(blocks[i].root);
|
|
417
|
+
} else {
|
|
418
|
+
logger.debug("Payload in forkchoice but missing in db", {slot: blocks[i].slot, root: toRootHex(blocks[i].root)});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (envelopeEntries.length > 0) {
|
|
423
|
+
await Promise.all([
|
|
424
|
+
db.executionPayloadEnvelopeArchive.batchPutBinary(envelopeEntries),
|
|
425
|
+
db.executionPayloadEnvelope.batchDelete(migratedRoots),
|
|
426
|
+
]);
|
|
427
|
+
migratedEnvelopes = envelopeEntries.length;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return migratedEnvelopes;
|
|
431
|
+
}
|
|
432
|
+
|
|
375
433
|
/**
|
|
376
434
|
* ```
|
|
377
435
|
* class SignedBeaconBlock(Container):
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
ForkChoiceErrorCode,
|
|
8
8
|
NotReorgedReason,
|
|
9
9
|
getSafeExecutionBlockHash,
|
|
10
|
+
isGloasBlock,
|
|
10
11
|
} from "@lodestar/fork-choice";
|
|
11
12
|
import {ForkPostAltair, ForkPostElectra, ForkSeq, MAX_SEED_LOOKAHEAD, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
12
13
|
import {
|
|
@@ -30,7 +31,7 @@ import type {BeaconChain} from "../chain.js";
|
|
|
30
31
|
import {ChainEvent, ReorgEventData} from "../emitter.js";
|
|
31
32
|
import {ForkchoiceCaller} from "../forkChoice/index.js";
|
|
32
33
|
import {REPROCESS_MIN_TIME_TO_NEXT_SLOT_SEC} from "../reprocess.js";
|
|
33
|
-
import {
|
|
34
|
+
import {toCheckpointHexPayload} from "../stateCache/persistentCheckpointsCache.js";
|
|
34
35
|
import {isBlockInputBlobs, isBlockInputColumns} from "./blockInput/blockInput.js";
|
|
35
36
|
import {AttestationImportOpt, FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
|
|
36
37
|
import {getCheckpointFromState} from "./utils/checkpoint.js";
|
|
@@ -116,7 +117,11 @@ export async function importBlock(
|
|
|
116
117
|
|
|
117
118
|
// This adds the state necessary to process the next block
|
|
118
119
|
// Some block event handlers require state being in state cache so need to do this before emitting EventType.block
|
|
119
|
-
|
|
120
|
+
// Pre-Gloas: blockSummary.payloadStatus is always FULL, payloadPresent = true
|
|
121
|
+
// Post-Gloas: blockSummary.payloadStatus is always PENDING, so payloadPresent = false (block state only, no payload processing yet)
|
|
122
|
+
const payloadPresent = !isGloasBlock(blockSummary);
|
|
123
|
+
// processState manages both block state and payload state variants together for memory/disk management
|
|
124
|
+
this.regen.processBlockState(blockRootHex, postState);
|
|
120
125
|
|
|
121
126
|
this.metrics?.importBlock.bySource.inc({source: source.source});
|
|
122
127
|
this.logger.verbose("Added block to forkchoice and state cache", {slot: blockSlot, root: blockRootHex});
|
|
@@ -456,12 +461,12 @@ export async function importBlock(
|
|
|
456
461
|
// Cache state to preserve epoch transition work
|
|
457
462
|
const checkpointState = postState;
|
|
458
463
|
const cp = getCheckpointFromState(checkpointState);
|
|
459
|
-
this.regen.addCheckpointState(cp, checkpointState);
|
|
464
|
+
this.regen.addCheckpointState(cp, checkpointState, payloadPresent);
|
|
460
465
|
// consumers should not mutate state ever
|
|
461
466
|
this.emitter.emit(ChainEvent.checkpoint, cp, checkpointState);
|
|
462
467
|
|
|
463
468
|
// Note: in-lined code from previos handler of ChainEvent.checkpoint
|
|
464
|
-
this.logger.verbose("Checkpoint processed",
|
|
469
|
+
this.logger.verbose("Checkpoint processed", toCheckpointHexPayload(cp, payloadPresent));
|
|
465
470
|
|
|
466
471
|
const activeValidatorsCount = checkpointState.epochCtx.currentShuffling.activeIndices.length;
|
|
467
472
|
this.metrics?.currentActiveValidators.set(activeValidatorsCount);
|
|
@@ -479,7 +484,7 @@ export async function importBlock(
|
|
|
479
484
|
const justifiedEpoch = justifiedCheckpoint.epoch;
|
|
480
485
|
const preJustifiedEpoch = parentBlockSummary.justifiedEpoch;
|
|
481
486
|
if (justifiedEpoch > preJustifiedEpoch) {
|
|
482
|
-
this.logger.verbose("Checkpoint justified",
|
|
487
|
+
this.logger.verbose("Checkpoint justified", toCheckpointHexPayload(justifiedCheckpoint, payloadPresent));
|
|
483
488
|
this.metrics?.previousJustifiedEpoch.set(checkpointState.previousJustifiedCheckpoint.epoch);
|
|
484
489
|
this.metrics?.currentJustifiedEpoch.set(justifiedCheckpoint.epoch);
|
|
485
490
|
}
|
|
@@ -493,7 +498,7 @@ export async function importBlock(
|
|
|
493
498
|
state: toRootHex(checkpointState.hashTreeRoot()),
|
|
494
499
|
executionOptimistic: false,
|
|
495
500
|
});
|
|
496
|
-
this.logger.verbose("Checkpoint finalized",
|
|
501
|
+
this.logger.verbose("Checkpoint finalized", toCheckpointHexPayload(finalizedCheckpoint, payloadPresent));
|
|
497
502
|
this.metrics?.finalizedEpoch.set(finalizedCheckpoint.epoch);
|
|
498
503
|
}
|
|
499
504
|
}
|
|
@@ -41,7 +41,7 @@ export async function verifyBlocksSignatures(
|
|
|
41
41
|
: //
|
|
42
42
|
// Verify signatures per block to track which block is invalid
|
|
43
43
|
bls.verifySignatureSets(
|
|
44
|
-
getBlockSignatureSets(config, currentSyncCommitteeIndexed, block, indexedAttestationsByBlock[i], {
|
|
44
|
+
getBlockSignatureSets(config, currentSyncCommitteeIndexed, preState0, block, indexedAttestationsByBlock[i], {
|
|
45
45
|
skipProposerSignature: opts.validProposerSignature,
|
|
46
46
|
})
|
|
47
47
|
);
|
package/src/chain/chain.ts
CHANGED
|
@@ -3,11 +3,12 @@ import {PrivateKey} from "@libp2p/interface";
|
|
|
3
3
|
import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz";
|
|
4
4
|
import {BeaconConfig} from "@lodestar/config";
|
|
5
5
|
import {
|
|
6
|
-
CheckpointWithHex,
|
|
7
6
|
CheckpointWithPayloadStatus,
|
|
8
7
|
IForkChoice,
|
|
8
|
+
PayloadStatus,
|
|
9
9
|
ProtoBlock,
|
|
10
10
|
UpdateHeadOpt,
|
|
11
|
+
getCheckpointPayloadStatus,
|
|
11
12
|
} from "@lodestar/fork-choice";
|
|
12
13
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
13
14
|
import {
|
|
@@ -126,7 +127,7 @@ import {DbCPStateDatastore, checkpointToDatastoreKey} from "./stateCache/datasto
|
|
|
126
127
|
import {FileCPStateDatastore} from "./stateCache/datastore/file.js";
|
|
127
128
|
import {CPStateDatastore} from "./stateCache/datastore/types.js";
|
|
128
129
|
import {FIFOBlockStateCache} from "./stateCache/fifoBlockStateCache.js";
|
|
129
|
-
import {PersistentCheckpointStateCache} from "./stateCache/persistentCheckpointsCache.js";
|
|
130
|
+
import {PersistentCheckpointStateCache, fcCheckpointToHexPayload} from "./stateCache/persistentCheckpointsCache.js";
|
|
130
131
|
import {CheckpointStateCache} from "./stateCache/types.js";
|
|
131
132
|
import {ValidatorMonitor} from "./validatorMonitor.js";
|
|
132
133
|
|
|
@@ -375,7 +376,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
375
376
|
const {checkpoint} = computeAnchorCheckpoint(config, anchorState);
|
|
376
377
|
blockStateCache.add(anchorState);
|
|
377
378
|
blockStateCache.setHeadState(anchorState);
|
|
378
|
-
|
|
379
|
+
const payloadPresent = getCheckpointPayloadStatus(anchorState, checkpoint.epoch) === PayloadStatus.FULL;
|
|
380
|
+
checkpointStateCache.add(checkpoint, anchorState, payloadPresent);
|
|
379
381
|
|
|
380
382
|
const forkChoice = initializeForkChoice(
|
|
381
383
|
config,
|
|
@@ -648,15 +650,18 @@ export class BeaconChain implements IBeaconChain {
|
|
|
648
650
|
return this.cpStateDatastore.readLatestSafe();
|
|
649
651
|
}
|
|
650
652
|
|
|
651
|
-
|
|
653
|
+
// TODO GLOAS: Need to revisit the design of this api. Currently we just retrieve FULL state of the checkpoint for backwards compatibility.
|
|
654
|
+
// because pre-gloas we always store FULL checkpoint state.
|
|
655
|
+
const persistedKey = checkpointToDatastoreKey(checkpoint, true);
|
|
652
656
|
return this.cpStateDatastore.read(persistedKey);
|
|
653
657
|
}
|
|
654
658
|
|
|
655
659
|
getStateByCheckpoint(
|
|
656
|
-
checkpoint:
|
|
660
|
+
checkpoint: CheckpointWithPayloadStatus
|
|
657
661
|
): {state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean} | null {
|
|
658
662
|
// finalized or justified checkpoint states maynot be available with PersistentCheckpointStateCache, use getCheckpointStateOrBytes() api to get Uint8Array
|
|
659
|
-
const
|
|
663
|
+
const checkpointHexPayload = fcCheckpointToHexPayload(checkpoint);
|
|
664
|
+
const cachedStateCtx = this.regen.getCheckpointStateSync(checkpointHexPayload);
|
|
660
665
|
if (cachedStateCtx) {
|
|
661
666
|
const block = this.forkChoice.getBlockDefaultStatus(cachedStateCtx.latestBlockHeader.hashTreeRoot());
|
|
662
667
|
const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
|
|
@@ -671,9 +676,10 @@ export class BeaconChain implements IBeaconChain {
|
|
|
671
676
|
}
|
|
672
677
|
|
|
673
678
|
async getStateOrBytesByCheckpoint(
|
|
674
|
-
checkpoint:
|
|
679
|
+
checkpoint: CheckpointWithPayloadStatus
|
|
675
680
|
): Promise<{state: CachedBeaconStateAllForks | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
|
|
676
|
-
const
|
|
681
|
+
const checkpointHexPayload = fcCheckpointToHexPayload(checkpoint);
|
|
682
|
+
const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(checkpointHexPayload);
|
|
677
683
|
if (cachedStateCtx) {
|
|
678
684
|
const block = this.forkChoice.getBlockDefaultStatus(checkpoint.root);
|
|
679
685
|
const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
|
|
@@ -1236,7 +1242,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1236
1242
|
checkpoint: CheckpointWithPayloadStatus,
|
|
1237
1243
|
blockState: CachedBeaconStateAllForks
|
|
1238
1244
|
): {state: CachedBeaconStateAllForks; stateId: string; shouldWarn: boolean} {
|
|
1239
|
-
const
|
|
1245
|
+
const checkpointHexPayload = fcCheckpointToHexPayload(checkpoint);
|
|
1246
|
+
const state = this.regen.getCheckpointStateSync(checkpointHexPayload);
|
|
1240
1247
|
if (state) {
|
|
1241
1248
|
return {state, stateId: "checkpoint_state", shouldWarn: false};
|
|
1242
1249
|
}
|
|
@@ -1363,6 +1370,10 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1363
1370
|
private onClockEpoch(epoch: Epoch): void {
|
|
1364
1371
|
this.metrics?.clockEpoch.set(epoch);
|
|
1365
1372
|
|
|
1373
|
+
if (epoch === this.config.GLOAS_FORK_EPOCH) {
|
|
1374
|
+
this.regen.upgradeForGloas(epoch);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1366
1377
|
this.seenAttesters.prune(epoch);
|
|
1367
1378
|
this.seenAggregators.prune(epoch);
|
|
1368
1379
|
this.seenPayloadAttesters.prune(epoch);
|
|
@@ -1376,7 +1387,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1376
1387
|
this.seenContributionAndProof.prune(head.slot);
|
|
1377
1388
|
}
|
|
1378
1389
|
|
|
1379
|
-
private onForkChoiceJustified(this: BeaconChain, cp:
|
|
1390
|
+
private onForkChoiceJustified(this: BeaconChain, cp: CheckpointWithPayloadStatus): void {
|
|
1380
1391
|
this.logger.verbose("Fork choice justified", {epoch: cp.epoch, root: cp.rootHex});
|
|
1381
1392
|
}
|
|
1382
1393
|
|
|
@@ -1387,7 +1398,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1387
1398
|
});
|
|
1388
1399
|
}
|
|
1389
1400
|
|
|
1390
|
-
private async onForkChoiceFinalized(this: BeaconChain, cp:
|
|
1401
|
+
private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithPayloadStatus): Promise<void> {
|
|
1391
1402
|
this.logger.verbose("Fork choice finalized", {epoch: cp.epoch, root: cp.rootHex});
|
|
1392
1403
|
const finalizedSlot = computeStartSlotAtEpoch(cp.epoch);
|
|
1393
1404
|
this.seenBlockProposers.prune(finalizedSlot);
|
|
@@ -1429,7 +1440,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1429
1440
|
}
|
|
1430
1441
|
}
|
|
1431
1442
|
|
|
1432
|
-
private async updateValidatorsCustodyRequirement(finalizedCheckpoint:
|
|
1443
|
+
private async updateValidatorsCustodyRequirement(finalizedCheckpoint: CheckpointWithPayloadStatus): Promise<void> {
|
|
1433
1444
|
if (this.custodyConfig.targetCustodyGroupCount === this.config.NUMBER_OF_CUSTODY_GROUPS) {
|
|
1434
1445
|
// Custody requirements can only be increased, we can disable dynamic custody updates
|
|
1435
1446
|
// if the node already maintains custody of all custody groups in case it is configured
|
package/src/chain/interface.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {CompositeTypeAny, TreeView, Type} from "@chainsafe/ssz";
|
|
2
2
|
import {BeaconConfig} from "@lodestar/config";
|
|
3
|
-
import {CheckpointWithHex, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
3
|
+
import {CheckpointWithHex, CheckpointWithPayloadStatus, IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
4
4
|
import {BeaconStateAllForks, CachedBeaconStateAllForks, EpochShuffling, PubkeyCache} from "@lodestar/state-transition";
|
|
5
5
|
import {
|
|
6
6
|
BeaconBlock,
|
|
@@ -192,7 +192,7 @@ export interface IBeaconChain {
|
|
|
192
192
|
): {state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean} | null;
|
|
193
193
|
/** Return state bytes by checkpoint */
|
|
194
194
|
getStateOrBytesByCheckpoint(
|
|
195
|
-
checkpoint:
|
|
195
|
+
checkpoint: CheckpointWithPayloadStatus
|
|
196
196
|
): Promise<{state: CachedBeaconStateAllForks | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>;
|
|
197
197
|
|
|
198
198
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
|
-
import {getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
3
|
+
import {PayloadStatus, getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
4
4
|
import {ForkPostBellatrix, ForkSeq, SLOTS_PER_EPOCH, isForkPostBellatrix} from "@lodestar/params";
|
|
5
5
|
import {
|
|
6
6
|
CachedBeaconStateAllForks,
|
|
@@ -211,7 +211,11 @@ export class PrepareNextSlotScheduler {
|
|
|
211
211
|
// + if next slot is a skipped slot, it'd help getting target checkpoint state faster to validate attestations
|
|
212
212
|
if (isEpochTransition) {
|
|
213
213
|
this.metrics?.precomputeNextEpochTransition.count.inc({result: "success"}, 1);
|
|
214
|
-
|
|
214
|
+
// Determine payloadPresent from head block's payload status
|
|
215
|
+
// Pre-Gloas: payloadStatus is always FULL → payloadPresent = true
|
|
216
|
+
// Post-Gloas: FULL → true, EMPTY → false, PENDING → false (conservative, treat as block state)
|
|
217
|
+
const payloadPresent = headBlock.payloadStatus === PayloadStatus.FULL;
|
|
218
|
+
const previousHits = this.chain.regen.updatePreComputedCheckpoint(headRoot, nextEpoch, payloadPresent);
|
|
215
219
|
if (previousHits === 0) {
|
|
216
220
|
this.metrics?.precomputeNextEpochTransition.waste.inc();
|
|
217
221
|
}
|