@lodestar/beacon-node 1.40.0-dev.9defa5c09b → 1.40.0-dev.ade3accfa0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +15 -9
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +24 -0
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/api/rest/base.d.ts.map +1 -1
- package/lib/api/rest/base.js +12 -10
- package/lib/api/rest/base.js.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts +2 -0
- package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.js +7 -3
- package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +10 -4
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js +2 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +28 -0
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +38 -3
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +10 -2
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +1 -1
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts +2 -2
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +2 -2
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +1 -2
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +8 -0
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/bls/multithread/index.d.ts +3 -1
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +5 -3
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/jobItem.d.ts +2 -2
- package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
- package/lib/chain/bls/multithread/jobItem.js +2 -2
- package/lib/chain/bls/multithread/jobItem.js.map +1 -1
- package/lib/chain/bls/singleThread.d.ts +4 -2
- package/lib/chain/bls/singleThread.d.ts.map +1 -1
- package/lib/chain/bls/singleThread.js +4 -2
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.d.ts +2 -2
- package/lib/chain/bls/utils.d.ts.map +1 -1
- package/lib/chain/bls/utils.js +9 -6
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/chain.d.ts +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +24 -33
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/initState.d.ts.map +1 -1
- package/lib/chain/initState.js +2 -2
- package/lib/chain/initState.js.map +1 -1
- package/lib/chain/lightClient/index.d.ts +2 -0
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +11 -6
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/options.d.ts +0 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +0 -1
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +1 -1
- package/lib/chain/regen/queued.d.ts +1 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +2 -0
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +4 -1
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -7
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +23 -12
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/serializeState.d.ts.map +1 -1
- package/lib/chain/serializeState.js +2 -1
- package/lib/chain/serializeState.js.map +1 -1
- package/lib/chain/stateCache/index.d.ts +0 -2
- package/lib/chain/stateCache/index.d.ts.map +1 -1
- package/lib/chain/stateCache/index.js +0 -2
- package/lib/chain/stateCache/index.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +2 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +3 -0
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/validation/aggregateAndProof.js +3 -4
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts +2 -2
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +4 -4
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +1 -1
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
- package/lib/chain/validation/blobSidecar.js +4 -4
- package/lib/chain/validation/blobSidecar.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +2 -3
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +4 -4
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +4 -3
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validation/signatureSets/aggregateAndProof.d.ts +2 -3
- package/lib/chain/validation/signatureSets/aggregateAndProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/aggregateAndProof.js +8 -3
- package/lib/chain/validation/signatureSets/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts +2 -2
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.js +3 -3
- package/lib/chain/validation/signatureSets/contributionAndProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/selectionProof.d.ts +2 -3
- package/lib/chain/validation/signatureSets/selectionProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/selectionProof.js +8 -3
- package/lib/chain/validation/signatureSets/selectionProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts +2 -2
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.js +3 -3
- package/lib/chain/validation/signatureSets/syncCommittee.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.d.ts +1 -2
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.js +2 -2
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts +2 -2
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js +3 -3
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js.map +1 -1
- package/lib/chain/validation/syncCommittee.js +1 -1
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +3 -5
- package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +1 -1
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +7 -4
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/network/core/networkCore.d.ts +3 -0
- package/lib/network/core/networkCore.d.ts.map +1 -1
- package/lib/network/core/networkCore.js +9 -0
- package/lib/network/core/networkCore.js.map +1 -1
- package/lib/network/core/networkCoreWorker.js +3 -0
- package/lib/network/core/networkCoreWorker.js.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.d.ts +3 -0
- package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.js +9 -0
- package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
- package/lib/network/core/types.d.ts +3 -0
- package/lib/network/core/types.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.d.ts +34 -0
- package/lib/network/gossip/gossipsub.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.js +123 -0
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/network.d.ts +3 -0
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +9 -0
- package/lib/network/network.js.map +1 -1
- package/lib/network/options.d.ts +6 -0
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +9 -0
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/processor/gossipHandlers.js +1 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/sync/backfill/backfill.d.ts.map +1 -1
- package/lib/sync/backfill/backfill.js +3 -4
- package/lib/sync/backfill/backfill.js.map +1 -1
- package/lib/sync/backfill/verify.d.ts +1 -2
- package/lib/sync/backfill/verify.d.ts.map +1 -1
- package/lib/sync/backfill/verify.js +2 -2
- package/lib/sync/backfill/verify.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +2 -2
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +1 -2
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/util/queue/itemQueue.d.ts +10 -0
- package/lib/util/queue/itemQueue.d.ts.map +1 -1
- package/lib/util/queue/itemQueue.js +57 -0
- package/lib/util/queue/itemQueue.js.map +1 -1
- package/package.json +16 -16
- package/src/api/impl/beacon/blocks/index.ts +31 -19
- package/src/api/impl/lodestar/index.ts +29 -0
- package/src/api/impl/validator/index.ts +2 -1
- package/src/api/rest/base.ts +15 -13
- package/src/chain/ColumnReconstructionTracker.ts +8 -4
- package/src/chain/archiveStore/archiveStore.ts +10 -4
- package/src/chain/archiveStore/historicalState/getHistoricalState.ts +2 -1
- package/src/chain/blocks/blockInput/blockInput.ts +47 -4
- package/src/chain/blocks/importBlock.ts +10 -2
- package/src/chain/blocks/verifyBlock.ts +0 -1
- package/src/chain/blocks/verifyBlocksSignatures.ts +4 -12
- package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +1 -2
- package/src/chain/blocks/writeBlockInputToDb.ts +9 -0
- package/src/chain/bls/multithread/index.ts +7 -4
- package/src/chain/bls/multithread/jobItem.ts +7 -3
- package/src/chain/bls/singleThread.ts +5 -3
- package/src/chain/bls/utils.ts +15 -7
- package/src/chain/chain.ts +29 -37
- package/src/chain/initState.ts +2 -2
- package/src/chain/lightClient/index.ts +12 -6
- package/src/chain/options.ts +0 -2
- package/src/chain/regen/interface.ts +1 -1
- package/src/chain/regen/queued.ts +1 -2
- package/src/chain/regen/regen.ts +6 -1
- package/src/chain/seenCache/seenGossipBlockInput.ts +31 -12
- package/src/chain/serializeState.ts +2 -1
- package/src/chain/stateCache/index.ts +0 -2
- package/src/chain/stateCache/persistentCheckpointsCache.ts +6 -2
- package/src/chain/validation/aggregateAndProof.ts +3 -4
- package/src/chain/validation/attestation.ts +9 -13
- package/src/chain/validation/attesterSlashing.ts +1 -6
- package/src/chain/validation/blobSidecar.ts +3 -8
- package/src/chain/validation/block.ts +2 -3
- package/src/chain/validation/dataColumnSidecar.ts +3 -8
- package/src/chain/validation/executionPayloadBid.ts +5 -4
- package/src/chain/validation/payloadAttestationMessage.ts +1 -1
- package/src/chain/validation/proposerSlashing.ts +1 -6
- package/src/chain/validation/signatureSets/aggregateAndProof.ts +9 -14
- package/src/chain/validation/signatureSets/contributionAndProof.ts +2 -4
- package/src/chain/validation/signatureSets/selectionProof.ts +9 -9
- package/src/chain/validation/signatureSets/syncCommittee.ts +2 -4
- package/src/chain/validation/signatureSets/syncCommitteeContribution.ts +2 -3
- package/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts +2 -4
- package/src/chain/validation/syncCommittee.ts +1 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +3 -5
- package/src/chain/validation/voluntaryExit.ts +1 -1
- package/src/chain/validatorMonitor.ts +10 -5
- package/src/network/core/networkCore.ts +12 -0
- package/src/network/core/networkCoreWorker.ts +3 -0
- package/src/network/core/networkCoreWorkerHandler.ts +9 -0
- package/src/network/core/types.ts +6 -0
- package/src/network/gossip/gossipsub.ts +147 -1
- package/src/network/network.ts +12 -0
- package/src/network/options.ts +6 -0
- package/src/network/peers/peerManager.ts +11 -0
- package/src/network/processor/gossipHandlers.ts +1 -1
- package/src/sync/backfill/backfill.ts +3 -4
- package/src/sync/backfill/verify.ts +2 -3
- package/src/sync/utils/downloadByRange.ts +2 -2
- package/src/sync/utils/downloadByRoot.ts +1 -2
- package/src/util/queue/itemQueue.ts +62 -0
- package/lib/chain/stateCache/blockStateCacheImpl.d.ts +0 -54
- package/lib/chain/stateCache/blockStateCacheImpl.d.ts.map +0 -1
- package/lib/chain/stateCache/blockStateCacheImpl.js +0 -130
- package/lib/chain/stateCache/blockStateCacheImpl.js.map +0 -1
- package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts +0 -60
- package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts.map +0 -1
- package/lib/chain/stateCache/inMemoryCheckpointsCache.js +0 -156
- package/lib/chain/stateCache/inMemoryCheckpointsCache.js.map +0 -1
- package/lib/util/bytes.d.ts +0 -3
- package/lib/util/bytes.d.ts.map +0 -1
- package/lib/util/bytes.js +0 -11
- package/lib/util/bytes.js.map +0 -1
- package/src/chain/stateCache/blockStateCacheImpl.ts +0 -149
- package/src/chain/stateCache/inMemoryCheckpointsCache.ts +0 -192
- package/src/util/bytes.ts +0 -11
package/src/chain/chain.ts
CHANGED
|
@@ -107,12 +107,10 @@ import {SeenAttestationDatas} from "./seenCache/seenAttestationData.js";
|
|
|
107
107
|
import {SeenBlockAttesters} from "./seenCache/seenBlockAttesters.js";
|
|
108
108
|
import {SeenBlockInput} from "./seenCache/seenGossipBlockInput.js";
|
|
109
109
|
import {ShufflingCache} from "./shufflingCache.js";
|
|
110
|
-
import {BlockStateCacheImpl} from "./stateCache/blockStateCacheImpl.js";
|
|
111
110
|
import {DbCPStateDatastore, checkpointToDatastoreKey} from "./stateCache/datastore/db.js";
|
|
112
111
|
import {FileCPStateDatastore} from "./stateCache/datastore/file.js";
|
|
113
112
|
import {CPStateDatastore} from "./stateCache/datastore/types.js";
|
|
114
113
|
import {FIFOBlockStateCache} from "./stateCache/fifoBlockStateCache.js";
|
|
115
|
-
import {InMemoryCheckpointStateCache} from "./stateCache/inMemoryCheckpointsCache.js";
|
|
116
114
|
import {PersistentCheckpointStateCache} from "./stateCache/persistentCheckpointsCache.js";
|
|
117
115
|
import {CheckpointStateCache} from "./stateCache/types.js";
|
|
118
116
|
import {ValidatorMonitor} from "./validatorMonitor.js";
|
|
@@ -128,8 +126,11 @@ const DEFAULT_MAX_CACHED_PRODUCED_RESULTS = 4;
|
|
|
128
126
|
|
|
129
127
|
/**
|
|
130
128
|
* The maximum number of pending unfinalized block writes to the database before backpressure is applied.
|
|
129
|
+
* Write queue entries hold references to block inputs, keeping them in memory even after cache eviction.
|
|
130
|
+
* This is especially important for supernodes which store all 128 columns per block — each pending
|
|
131
|
+
* write can hold significant memory. Keep moderate to avoid OOM during sync.
|
|
131
132
|
*/
|
|
132
|
-
const DEFAULT_MAX_PENDING_UNFINALIZED_BLOCK_WRITES =
|
|
133
|
+
const DEFAULT_MAX_PENDING_UNFINALIZED_BLOCK_WRITES = 16;
|
|
133
134
|
|
|
134
135
|
export class BeaconChain implements IBeaconChain {
|
|
135
136
|
readonly genesisTime: UintNum64;
|
|
@@ -142,7 +143,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
142
143
|
readonly logger: Logger;
|
|
143
144
|
readonly metrics: Metrics | null;
|
|
144
145
|
readonly validatorMonitor: ValidatorMonitor | null;
|
|
145
|
-
readonly bufferPool: BufferPool
|
|
146
|
+
readonly bufferPool: BufferPool;
|
|
146
147
|
|
|
147
148
|
readonly anchorStateLatestBlockSlot: Slot;
|
|
148
149
|
|
|
@@ -278,8 +279,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
278
279
|
const emitter = new ChainEventEmitter();
|
|
279
280
|
// by default, verify signatures on both main threads and worker threads
|
|
280
281
|
const bls = opts.blsVerifyAllMainThread
|
|
281
|
-
? new BlsSingleThreadVerifier({metrics})
|
|
282
|
-
: new BlsMultiThreadWorkerPool(opts, {logger, metrics});
|
|
282
|
+
? new BlsSingleThreadVerifier({metrics, index2pubkey})
|
|
283
|
+
: new BlsMultiThreadWorkerPool(opts, {logger, metrics, index2pubkey});
|
|
283
284
|
|
|
284
285
|
if (!clock) clock = new Clock({config, genesisTime: this.genesisTime, signal});
|
|
285
286
|
|
|
@@ -339,32 +340,22 @@ export class BeaconChain implements IBeaconChain {
|
|
|
339
340
|
this.index2pubkey = index2pubkey;
|
|
340
341
|
|
|
341
342
|
const fileDataStore = opts.nHistoricalStatesFileDataStore ?? true;
|
|
342
|
-
const blockStateCache = this.opts
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
this.
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
clock,
|
|
359
|
-
blockStateCache,
|
|
360
|
-
bufferPool: this.bufferPool,
|
|
361
|
-
datastore: this.cpStateDatastore,
|
|
362
|
-
},
|
|
363
|
-
this.opts
|
|
364
|
-
);
|
|
365
|
-
} else {
|
|
366
|
-
checkpointStateCache = new InMemoryCheckpointStateCache({metrics});
|
|
367
|
-
}
|
|
343
|
+
const blockStateCache = new FIFOBlockStateCache(this.opts, {metrics});
|
|
344
|
+
this.bufferPool = new BufferPool(anchorState.type.tree_serializedSize(anchorState.node), metrics);
|
|
345
|
+
|
|
346
|
+
this.cpStateDatastore = fileDataStore ? new FileCPStateDatastore(dataDir) : new DbCPStateDatastore(this.db);
|
|
347
|
+
const checkpointStateCache: CheckpointStateCache = new PersistentCheckpointStateCache(
|
|
348
|
+
{
|
|
349
|
+
config,
|
|
350
|
+
metrics,
|
|
351
|
+
logger,
|
|
352
|
+
clock,
|
|
353
|
+
blockStateCache,
|
|
354
|
+
bufferPool: this.bufferPool,
|
|
355
|
+
datastore: this.cpStateDatastore,
|
|
356
|
+
},
|
|
357
|
+
this.opts
|
|
358
|
+
);
|
|
368
359
|
|
|
369
360
|
const {checkpoint} = computeAnchorCheckpoint(config, anchorState);
|
|
370
361
|
blockStateCache.add(anchorState);
|
|
@@ -387,6 +378,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
387
378
|
forkChoice,
|
|
388
379
|
blockStateCache,
|
|
389
380
|
checkpointStateCache,
|
|
381
|
+
seenBlockInputCache: this.seenBlockInputCache,
|
|
390
382
|
db,
|
|
391
383
|
metrics,
|
|
392
384
|
validatorMonitor,
|
|
@@ -396,7 +388,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
396
388
|
});
|
|
397
389
|
|
|
398
390
|
if (!opts.disableLightClientServer) {
|
|
399
|
-
this.lightClientServer = new LightClientServer(opts, {config, clock, db, metrics, emitter, logger});
|
|
391
|
+
this.lightClientServer = new LightClientServer(opts, {config, clock, db, metrics, emitter, logger, signal});
|
|
400
392
|
}
|
|
401
393
|
|
|
402
394
|
this.reprocessController = new ReprocessController(this.metrics);
|
|
@@ -1368,13 +1360,13 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1368
1360
|
// TODO: Improve using regen here
|
|
1369
1361
|
const {blockRoot, stateRoot, slot} = this.forkChoice.getHead();
|
|
1370
1362
|
const headState = this.regen.getStateSync(stateRoot);
|
|
1371
|
-
const
|
|
1372
|
-
if (
|
|
1373
|
-
throw Error(`Head block ${slot}
|
|
1363
|
+
const blockResult = await this.getBlockByRoot(blockRoot);
|
|
1364
|
+
if (blockResult == null) {
|
|
1365
|
+
throw Error(`Head block for ${slot} is not available in cache or database`);
|
|
1374
1366
|
}
|
|
1375
1367
|
|
|
1376
1368
|
if (headState) {
|
|
1377
|
-
this.opPool.pruneAll(
|
|
1369
|
+
this.opPool.pruneAll(blockResult.block, headState);
|
|
1378
1370
|
}
|
|
1379
1371
|
|
|
1380
1372
|
if (headState === null) {
|
package/src/chain/initState.ts
CHANGED
|
@@ -2,7 +2,7 @@ import {ChainForkConfig} from "@lodestar/config";
|
|
|
2
2
|
import {ZERO_HASH} from "@lodestar/params";
|
|
3
3
|
import {BeaconStateAllForks, computeEpochAtSlot, computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
4
4
|
import {SignedBeaconBlock, ssz} from "@lodestar/types";
|
|
5
|
-
import {Logger, toHex, toRootHex} from "@lodestar/utils";
|
|
5
|
+
import {Logger, byteArrayEquals, toHex, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {GENESIS_SLOT} from "../constants/index.js";
|
|
7
7
|
import {IBeaconDb} from "../db/index.js";
|
|
8
8
|
import {Metrics} from "../metrics/index.js";
|
|
@@ -26,7 +26,7 @@ export async function persistAnchorState(
|
|
|
26
26
|
|
|
27
27
|
const latestBlockRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(latestBlockHeader);
|
|
28
28
|
|
|
29
|
-
if (
|
|
29
|
+
if (!byteArrayEquals(blockRoot, latestBlockRoot)) {
|
|
30
30
|
throw Error(
|
|
31
31
|
`Genesis block root ${toRootHex(blockRoot)} does not match genesis state latest block root ${toRootHex(latestBlockRoot)}`
|
|
32
32
|
);
|
|
@@ -46,12 +46,11 @@ import {
|
|
|
46
46
|
ssz,
|
|
47
47
|
sszTypesFor,
|
|
48
48
|
} from "@lodestar/types";
|
|
49
|
-
import {Logger, MapDef, pruneSetToMax, toRootHex} from "@lodestar/utils";
|
|
49
|
+
import {Logger, MapDef, byteArrayEquals, pruneSetToMax, toRootHex} from "@lodestar/utils";
|
|
50
50
|
import {ZERO_HASH} from "../../constants/index.js";
|
|
51
51
|
import {IBeaconDb} from "../../db/index.js";
|
|
52
52
|
import {NUM_WITNESS, NUM_WITNESS_ELECTRA} from "../../db/repositories/lightclientSyncCommitteeWitness.js";
|
|
53
53
|
import {Metrics} from "../../metrics/index.js";
|
|
54
|
-
import {byteArrayEquals} from "../../util/bytes.js";
|
|
55
54
|
import {IClock} from "../../util/clock.js";
|
|
56
55
|
import {ChainEventEmitter} from "../emitter.js";
|
|
57
56
|
import {LightClientServerError, LightClientServerErrorCode} from "../errors/lightClientError.js";
|
|
@@ -93,6 +92,7 @@ type LightClientServerModules = {
|
|
|
93
92
|
metrics: Metrics | null;
|
|
94
93
|
emitter: ChainEventEmitter;
|
|
95
94
|
logger: Logger;
|
|
95
|
+
signal: AbortSignal;
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
const MAX_CACHED_FINALIZED_HEADERS = 3;
|
|
@@ -205,6 +205,7 @@ export class LightClientServer {
|
|
|
205
205
|
private readonly emitter: ChainEventEmitter;
|
|
206
206
|
private readonly logger: Logger;
|
|
207
207
|
private readonly clock: IClock;
|
|
208
|
+
private readonly signal: AbortSignal;
|
|
208
209
|
private readonly knownSyncCommittee = new MapDef<SyncPeriod, Set<DependentRootHex>>(() => new Set());
|
|
209
210
|
private storedCurrentSyncCommittee = false;
|
|
210
211
|
|
|
@@ -225,13 +226,14 @@ export class LightClientServer {
|
|
|
225
226
|
private readonly opts: LightClientServerOpts,
|
|
226
227
|
modules: LightClientServerModules
|
|
227
228
|
) {
|
|
228
|
-
const {config, clock, db, metrics, emitter, logger} = modules;
|
|
229
|
+
const {config, clock, db, metrics, emitter, logger, signal} = modules;
|
|
229
230
|
this.config = config;
|
|
230
231
|
this.clock = clock;
|
|
231
232
|
this.db = db;
|
|
232
233
|
this.metrics = metrics;
|
|
233
234
|
this.emitter = emitter;
|
|
234
235
|
this.logger = logger;
|
|
236
|
+
this.signal = signal;
|
|
235
237
|
|
|
236
238
|
this.zero = {
|
|
237
239
|
// Assign the hightest fork's default value because it can always be typecasted down to correct fork
|
|
@@ -288,12 +290,16 @@ export class LightClientServer {
|
|
|
288
290
|
const syncPeriod = computeSyncPeriodAtSlot(block.slot);
|
|
289
291
|
|
|
290
292
|
this.onSyncAggregate(syncPeriod, block.body.syncAggregate, block.slot, signedBlockRoot).catch((e) => {
|
|
291
|
-
this.
|
|
292
|
-
|
|
293
|
+
if (!this.signal.aborted) {
|
|
294
|
+
this.logger.error("Error onSyncAggregate", {}, e);
|
|
295
|
+
this.metrics?.lightclientServer.onSyncAggregate.inc({event: "error"});
|
|
296
|
+
}
|
|
293
297
|
});
|
|
294
298
|
|
|
295
299
|
this.persistPostBlockImportData(block, postState, parentBlockSlot).catch((e) => {
|
|
296
|
-
this.
|
|
300
|
+
if (!this.signal.aborted) {
|
|
301
|
+
this.logger.error("Error persistPostBlockImportData", {}, e);
|
|
302
|
+
}
|
|
297
303
|
});
|
|
298
304
|
}
|
|
299
305
|
|
package/src/chain/options.ts
CHANGED
|
@@ -45,7 +45,6 @@ export type IChainOptions = BlockProcessOpts &
|
|
|
45
45
|
broadcastValidationStrictness?: string;
|
|
46
46
|
minSameMessageSignatureSetsToBatch: number;
|
|
47
47
|
archiveDateEpochs?: number;
|
|
48
|
-
nHistoricalStates?: boolean;
|
|
49
48
|
nHistoricalStatesFileDataStore?: boolean;
|
|
50
49
|
};
|
|
51
50
|
|
|
@@ -119,7 +118,6 @@ export const defaultChainOptions: IChainOptions = {
|
|
|
119
118
|
// batching too much may block the I/O thread so if useWorker=false, suggest this value to be 32
|
|
120
119
|
// since this batch attestation work is designed to work with useWorker=true, make this the lowest value
|
|
121
120
|
minSameMessageSignatureSetsToBatch: 2,
|
|
122
|
-
nHistoricalStates: true,
|
|
123
121
|
// as of Feb 2025, this option turned out to be very useful:
|
|
124
122
|
// - it allows to share a persisted checkpoint state to other nodes
|
|
125
123
|
// - users can prune the persisted checkpoint state files manually to save disc space
|
|
@@ -2,7 +2,7 @@ import {routes} from "@lodestar/api";
|
|
|
2
2
|
import {ProtoBlock} from "@lodestar/fork-choice";
|
|
3
3
|
import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
|
|
4
4
|
import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
5
|
-
import {CheckpointHex} from "../stateCache/
|
|
5
|
+
import {CheckpointHex} from "../stateCache/types.js";
|
|
6
6
|
|
|
7
7
|
export enum RegenCaller {
|
|
8
8
|
getDuties = "getDuties",
|
|
@@ -5,8 +5,7 @@ import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
|
5
5
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {Metrics} from "../../metrics/index.js";
|
|
7
7
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
8
|
-
import {CheckpointHex} from "../stateCache/
|
|
9
|
-
import {BlockStateCache, CheckpointStateCache} from "../stateCache/types.js";
|
|
8
|
+
import {BlockStateCache, CheckpointHex, CheckpointStateCache} from "../stateCache/types.js";
|
|
10
9
|
import {RegenError, RegenErrorCode} from "./errors.js";
|
|
11
10
|
import {
|
|
12
11
|
IStateRegenerator,
|
package/src/chain/regen/regen.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {Metrics} from "../../metrics/index.js";
|
|
|
18
18
|
import {nextEventLoop} from "../../util/eventLoop.js";
|
|
19
19
|
import {getCheckpointFromState} from "../blocks/utils/checkpoint.js";
|
|
20
20
|
import {ChainEvent, ChainEventEmitter} from "../emitter.js";
|
|
21
|
+
import {SeenBlockInput} from "../seenCache/seenGossipBlockInput.js";
|
|
21
22
|
import {BlockStateCache, CheckpointStateCache} from "../stateCache/types.js";
|
|
22
23
|
import {ValidatorMonitor} from "../validatorMonitor.js";
|
|
23
24
|
import {RegenError, RegenErrorCode} from "./errors.js";
|
|
@@ -28,6 +29,7 @@ export type RegenModules = {
|
|
|
28
29
|
forkChoice: IForkChoice;
|
|
29
30
|
blockStateCache: BlockStateCache;
|
|
30
31
|
checkpointStateCache: CheckpointStateCache;
|
|
32
|
+
seenBlockInputCache: SeenBlockInput;
|
|
31
33
|
config: ChainForkConfig;
|
|
32
34
|
emitter: ChainEventEmitter;
|
|
33
35
|
logger: Logger;
|
|
@@ -191,7 +193,10 @@ export class StateRegenerator implements IStateRegeneratorInternal {
|
|
|
191
193
|
const protoBlocksAsc = blocksToReplay.reverse();
|
|
192
194
|
for (const [i, protoBlock] of protoBlocksAsc.entries()) {
|
|
193
195
|
replaySlots[i] = protoBlock.slot;
|
|
194
|
-
|
|
196
|
+
const blockInput = this.modules.seenBlockInputCache.get(protoBlock.blockRoot);
|
|
197
|
+
blockPromises[i] = blockInput?.hasBlock()
|
|
198
|
+
? Promise.resolve(blockInput.getBlock())
|
|
199
|
+
: this.modules.db.block.get(fromHex(protoBlock.blockRoot));
|
|
195
200
|
}
|
|
196
201
|
|
|
197
202
|
const logCtx = {stateRoot, caller, replaySlots: replaySlots.join(",")};
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
2
|
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ForkName,
|
|
5
|
+
ForkPostFulu,
|
|
6
|
+
ForkPreGloas,
|
|
7
|
+
SLOTS_PER_EPOCH,
|
|
8
|
+
isForkPostDeneb,
|
|
9
|
+
isForkPostFulu,
|
|
10
|
+
isForkPostGloas,
|
|
11
|
+
} from "@lodestar/params";
|
|
4
12
|
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
5
13
|
import {BLSSignature, RootHex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
|
|
6
|
-
import {LodestarError, Logger, pruneSetToMax} from "@lodestar/utils";
|
|
14
|
+
import {LodestarError, Logger, byteArrayEquals, pruneSetToMax} from "@lodestar/utils";
|
|
7
15
|
import {Metrics} from "../../metrics/metrics.js";
|
|
16
|
+
import {MAX_LOOK_AHEAD_EPOCHS} from "../../sync/constants.js";
|
|
8
17
|
import {IClock} from "../../util/clock.js";
|
|
9
18
|
import {CustodyConfig} from "../../util/dataColumns.js";
|
|
10
19
|
import {
|
|
@@ -26,7 +35,17 @@ import {
|
|
|
26
35
|
} from "../blocks/blockInput/index.js";
|
|
27
36
|
import {ChainEvent, ChainEventEmitter} from "../emitter.js";
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
// Target size for the block input cache, enforced by pruneToMaxSize() which runs after prune()
|
|
39
|
+
// and onFinalized() — NOT on insertion. The cache can temporarily exceed this during range sync
|
|
40
|
+
// (e.g. 32 blocks inserted per batch) but is trimmed back after blocks are processed.
|
|
41
|
+
//
|
|
42
|
+
// Must be large enough to hold blocks from all concurrently downloaded range sync batches.
|
|
43
|
+
// Range sync downloads up to MAX_LOOK_AHEAD_EPOCHS batches ahead of the processing head,
|
|
44
|
+
// so up to (MAX_LOOK_AHEAD_EPOCHS + 1) batches (current + look-ahead) of SLOTS_PER_EPOCH
|
|
45
|
+
// blocks can be in the cache simultaneously. If this value is too small, pruneToMaxSize()
|
|
46
|
+
// will evict blocks from the batch being processed before they are persisted to the database,
|
|
47
|
+
// causing errors when async handlers like onForkChoiceFinalized run.
|
|
48
|
+
const MAX_BLOCK_INPUT_CACHE_SIZE = (MAX_LOOK_AHEAD_EPOCHS + 1) * SLOTS_PER_EPOCH;
|
|
30
49
|
|
|
31
50
|
export type SeenBlockInputCacheModules = {
|
|
32
51
|
config: ChainForkConfig;
|
|
@@ -64,14 +83,14 @@ export type GetByBlobOptions = {
|
|
|
64
83
|
* - onFinalized event handler will help to prune any non-canonical forks once the chain finalizes. Any block-slots that
|
|
65
84
|
* are before the finalized checkpoint will be pruned.
|
|
66
85
|
* - Range-sync periods. The range process uses this cache to store and sync blocks with DA data as the chain is pulled
|
|
67
|
-
* from peers. We pull batches, by epoch, so 32 slots are pulled at a time and several batches are
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
86
|
+
* from peers. We pull batches, by epoch, so 32 slots are pulled at a time and several batches are downloaded
|
|
87
|
+
* concurrently (up to MAX_LOOK_AHEAD_EPOCHS ahead). All downloaded blocks are added to this shared cache, so it
|
|
88
|
+
* must be large enough to hold blocks from all concurrent batches. If pruneToMaxSize() evicts blocks from the batch
|
|
89
|
+
* currently being processed, those blocks may not yet be persisted to the database, causing getBlockByRoot() to fail
|
|
90
|
+
* when async event handlers (e.g. onForkChoiceFinalized) try to look them up.
|
|
71
91
|
* - Non-Finality times. This is a bit more tricky. There can be long periods of non-finality and storing everything
|
|
72
|
-
* will cause OOM. The
|
|
73
|
-
*
|
|
74
|
-
* practice this value may need to be massaged in the future if we find issues when debugging non-finality
|
|
92
|
+
* will cause OOM. The pruneToMaxSize will help ensure the number of stored blocks (with DA) is trimmed back to
|
|
93
|
+
* MAX_BLOCK_INPUT_CACHE_SIZE after each prune() or onFinalized() call
|
|
75
94
|
*/
|
|
76
95
|
|
|
77
96
|
export class SeenBlockInput {
|
|
@@ -344,7 +363,7 @@ export class SeenBlockInput {
|
|
|
344
363
|
return false;
|
|
345
364
|
}
|
|
346
365
|
// Only consider verified if the signature matches
|
|
347
|
-
return
|
|
366
|
+
return byteArrayEquals(cachedSignature, signature);
|
|
348
367
|
}
|
|
349
368
|
|
|
350
369
|
/**
|
|
@@ -379,7 +398,7 @@ export class SeenBlockInput {
|
|
|
379
398
|
let itemsToDelete = this.blockInputs.size - MAX_BLOCK_INPUT_CACHE_SIZE;
|
|
380
399
|
|
|
381
400
|
if (itemsToDelete > 0) {
|
|
382
|
-
const sorted = [...this.blockInputs.entries()].sort((a, b) =>
|
|
401
|
+
const sorted = [...this.blockInputs.entries()].sort((a, b) => a[1].slot - b[1].slot);
|
|
383
402
|
for (const [rootHex] of sorted) {
|
|
384
403
|
this.blockInputs.delete(rootHex);
|
|
385
404
|
itemsToDelete--;
|
|
@@ -20,7 +20,8 @@ export async function serializeState<T>(
|
|
|
20
20
|
stateBytes = bufferWithKey.buffer;
|
|
21
21
|
const dataView = new DataView(stateBytes.buffer, stateBytes.byteOffset, stateBytes.byteLength);
|
|
22
22
|
state.serializeToBytes({uint8Array: stateBytes, dataView}, 0);
|
|
23
|
-
|
|
23
|
+
// Await to ensure buffer is not released back to pool until processFn completes
|
|
24
|
+
return await processFn(stateBytes);
|
|
24
25
|
}
|
|
25
26
|
// release the buffer back to the pool automatically
|
|
26
27
|
}
|
|
@@ -31,7 +31,7 @@ type PersistentCheckpointStateCacheModules = {
|
|
|
31
31
|
signal?: AbortSignal;
|
|
32
32
|
datastore: CPStateDatastore;
|
|
33
33
|
blockStateCache: BlockStateCache;
|
|
34
|
-
bufferPool?: BufferPool
|
|
34
|
+
bufferPool?: BufferPool;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
/** checkpoint serialized as a string */
|
|
@@ -119,7 +119,7 @@ export class PersistentCheckpointStateCache implements CheckpointStateCache {
|
|
|
119
119
|
private readonly maxEpochsOnDisk: number;
|
|
120
120
|
private readonly datastore: CPStateDatastore;
|
|
121
121
|
private readonly blockStateCache: BlockStateCache;
|
|
122
|
-
private readonly bufferPool?: BufferPool
|
|
122
|
+
private readonly bufferPool?: BufferPool;
|
|
123
123
|
|
|
124
124
|
constructor(
|
|
125
125
|
{
|
|
@@ -851,6 +851,10 @@ export function toCheckpointHex(checkpoint: phase0.Checkpoint): CheckpointHex {
|
|
|
851
851
|
};
|
|
852
852
|
}
|
|
853
853
|
|
|
854
|
+
export function toCheckpointKey(cp: CheckpointHex): string {
|
|
855
|
+
return `${cp.rootHex}:${cp.epoch}`;
|
|
856
|
+
}
|
|
857
|
+
|
|
854
858
|
function toCacheKey(cp: CheckpointHex | phase0.Checkpoint): CacheKey {
|
|
855
859
|
if (isCheckpointHex(cp)) {
|
|
856
860
|
return `${cp.rootHex}_${cp.epoch}`;
|
|
@@ -239,16 +239,15 @@ async function validateAggregateAndProof(
|
|
|
239
239
|
// by the validator with index aggregate_and_proof.aggregator_index.
|
|
240
240
|
// [REJECT] The aggregator signature, signed_aggregate_and_proof.signature, is valid.
|
|
241
241
|
// [REJECT] The signature of aggregate is valid.
|
|
242
|
-
const aggregator = chain.index2pubkey[aggregateAndProof.aggregatorIndex];
|
|
243
242
|
const signingRoot = cachedAttData ? cachedAttData.signingRoot : getAttestationDataSigningRoot(chain.config, attData);
|
|
244
243
|
const indexedAttestationSignatureSet = createAggregateSignatureSetFromComponents(
|
|
245
|
-
indexedAttestation.attestingIndices
|
|
244
|
+
indexedAttestation.attestingIndices,
|
|
246
245
|
signingRoot,
|
|
247
246
|
indexedAttestation.signature
|
|
248
247
|
);
|
|
249
248
|
const signatureSets = [
|
|
250
|
-
getSelectionProofSignatureSet(chain.config, attSlot,
|
|
251
|
-
getAggregateAndProofSignatureSet(chain.config, attEpoch,
|
|
249
|
+
getSelectionProofSignatureSet(chain.config, attSlot, aggregatorIndex, signedAggregateAndProof),
|
|
250
|
+
getAggregateAndProofSignatureSet(chain.config, attEpoch, aggregatorIndex, signedAggregateAndProof),
|
|
252
251
|
indexedAttestationSignatureSet,
|
|
253
252
|
];
|
|
254
253
|
// no need to write to SeenAttestationDatas
|
|
@@ -14,13 +14,13 @@ import {
|
|
|
14
14
|
} from "@lodestar/params";
|
|
15
15
|
import {
|
|
16
16
|
EpochShuffling,
|
|
17
|
+
IndexedSignatureSet,
|
|
17
18
|
ShufflingError,
|
|
18
19
|
ShufflingErrorCode,
|
|
19
|
-
SingleSignatureSet,
|
|
20
20
|
computeEpochAtSlot,
|
|
21
21
|
computeSigningRoot,
|
|
22
22
|
computeStartSlotAtEpoch,
|
|
23
|
-
|
|
23
|
+
createIndexedSignatureSetFromComponents,
|
|
24
24
|
} from "@lodestar/state-transition";
|
|
25
25
|
import {
|
|
26
26
|
CommitteeIndex,
|
|
@@ -90,7 +90,7 @@ export type GossipAttestation = {
|
|
|
90
90
|
};
|
|
91
91
|
|
|
92
92
|
export type Step0Result = AttestationValidationResult & {
|
|
93
|
-
signatureSet:
|
|
93
|
+
signatureSet: IndexedSignatureSet;
|
|
94
94
|
validatorIndex: number;
|
|
95
95
|
};
|
|
96
96
|
|
|
@@ -125,7 +125,7 @@ export async function validateGossipAttestationsSameAttData(
|
|
|
125
125
|
// step1: verify signatures of all valid attestations
|
|
126
126
|
// map new index to index in resultOrErrors
|
|
127
127
|
const newIndexToOldIndex = new Map<number, number>();
|
|
128
|
-
const signatureSets:
|
|
128
|
+
const signatureSets: IndexedSignatureSet[] = [];
|
|
129
129
|
let newIndex = 0;
|
|
130
130
|
const step0Results: Step0Result[] = [];
|
|
131
131
|
for (const [i, resultOrError] of step0ResultOrErrors.entries()) {
|
|
@@ -143,7 +143,7 @@ export async function validateGossipAttestationsSameAttData(
|
|
|
143
143
|
if (batchableBls) {
|
|
144
144
|
// all signature sets should have same signing root since we filtered in network processor
|
|
145
145
|
signatureValids = await chain.bls.verifySignatureSetsSameMessage(
|
|
146
|
-
signatureSets.map((set) => ({publicKey: set.
|
|
146
|
+
signatureSets.map((set) => ({publicKey: chain.index2pubkey[set.index], signature: set.signature})),
|
|
147
147
|
signatureSets[0].signingRoot
|
|
148
148
|
);
|
|
149
149
|
} else {
|
|
@@ -498,7 +498,7 @@ async function validateAttestationNoSignatureCheck(
|
|
|
498
498
|
|
|
499
499
|
// [REJECT] The signature of attestation is valid.
|
|
500
500
|
const attestingIndices = [validatorIndex];
|
|
501
|
-
let signatureSet:
|
|
501
|
+
let signatureSet: IndexedSignatureSet;
|
|
502
502
|
let attDataRootHex: RootHex;
|
|
503
503
|
const signature = attestationOrCache.attestation
|
|
504
504
|
? attestationOrCache.attestation.signature
|
|
@@ -513,18 +513,14 @@ async function validateAttestationNoSignatureCheck(
|
|
|
513
513
|
|
|
514
514
|
if (attestationOrCache.cache) {
|
|
515
515
|
// there could be up to 6% of cpu time to compute signing root if we don't clone the signature set
|
|
516
|
-
signatureSet =
|
|
517
|
-
|
|
516
|
+
signatureSet = createIndexedSignatureSetFromComponents(
|
|
517
|
+
validatorIndex,
|
|
518
518
|
attestationOrCache.cache.signingRoot,
|
|
519
519
|
signature
|
|
520
520
|
);
|
|
521
521
|
attDataRootHex = attestationOrCache.cache.attDataRootHex;
|
|
522
522
|
} else {
|
|
523
|
-
signatureSet =
|
|
524
|
-
chain.index2pubkey[validatorIndex],
|
|
525
|
-
getSigningRoot(),
|
|
526
|
-
signature
|
|
527
|
-
);
|
|
523
|
+
signatureSet = createIndexedSignatureSetFromComponents(validatorIndex, getSigningRoot(), signature);
|
|
528
524
|
|
|
529
525
|
// add cached attestation data before verifying signature
|
|
530
526
|
attDataRootHex = toRootHex(ssz.phase0.AttestationData.hashTreeRoot(attData));
|
|
@@ -58,12 +58,7 @@ export async function validateAttesterSlashing(
|
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
const signatureSets = getAttesterSlashingSignatureSets(
|
|
62
|
-
chain.config,
|
|
63
|
-
chain.index2pubkey,
|
|
64
|
-
state.slot,
|
|
65
|
-
attesterSlashing
|
|
66
|
-
);
|
|
61
|
+
const signatureSets = getAttesterSlashingSignatureSets(chain.config, state.slot, attesterSlashing);
|
|
67
62
|
if (!(await chain.bls.verifySignatureSets(signatureSets, {batchable: true, priority: prioritizeBls}))) {
|
|
68
63
|
throw new AttesterSlashingError(GossipAction.REJECT, {
|
|
69
64
|
code: AttesterSlashingErrorCode.INVALID,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
getBlockHeaderProposerSignatureSetByParentStateSlot,
|
|
13
13
|
} from "@lodestar/state-transition";
|
|
14
14
|
import {BlobIndex, Root, Slot, SubnetID, deneb, ssz} from "@lodestar/types";
|
|
15
|
-
import {toRootHex, verifyMerkleBranch} from "@lodestar/utils";
|
|
15
|
+
import {byteArrayEquals, toRootHex, verifyMerkleBranch} from "@lodestar/utils";
|
|
16
16
|
import {kzg} from "../../util/kzg.js";
|
|
17
17
|
import {BlobSidecarErrorCode, BlobSidecarGossipError, BlobSidecarValidationError} from "../errors/blobSidecarError.js";
|
|
18
18
|
import {GossipAction} from "../errors/gossipValidation.js";
|
|
@@ -139,7 +139,6 @@ export async function validateGossipBlobSidecar(
|
|
|
139
139
|
if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blobSlot, blockHex, signature)) {
|
|
140
140
|
const signatureSet = getBlockHeaderProposerSignatureSetByParentStateSlot(
|
|
141
141
|
chain.config,
|
|
142
|
-
chain.index2pubkey,
|
|
143
142
|
blockState.slot,
|
|
144
143
|
blobSidecar.signedBlockHeader
|
|
145
144
|
);
|
|
@@ -227,7 +226,7 @@ export async function validateBlockBlobSidecars(
|
|
|
227
226
|
const firstSidecarSignedBlockHeader = blobSidecars[0].signedBlockHeader;
|
|
228
227
|
const firstSidecarBlockHeader = firstSidecarSignedBlockHeader.message;
|
|
229
228
|
const firstBlockRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(firstSidecarBlockHeader);
|
|
230
|
-
if (
|
|
229
|
+
if (!byteArrayEquals(blockRoot, firstBlockRoot)) {
|
|
231
230
|
throw new BlobSidecarValidationError(
|
|
232
231
|
{
|
|
233
232
|
code: BlobSidecarErrorCode.INCORRECT_BLOCK,
|
|
@@ -244,11 +243,7 @@ export async function validateBlockBlobSidecars(
|
|
|
244
243
|
const blockRootHex = toRootHex(blockRoot);
|
|
245
244
|
const signature = firstSidecarSignedBlockHeader.signature;
|
|
246
245
|
if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRootHex, signature)) {
|
|
247
|
-
const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(
|
|
248
|
-
chain.config,
|
|
249
|
-
chain.index2pubkey,
|
|
250
|
-
firstSidecarSignedBlockHeader
|
|
251
|
-
);
|
|
246
|
+
const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(chain.config, firstSidecarSignedBlockHeader);
|
|
252
247
|
|
|
253
248
|
if (
|
|
254
249
|
!(await chain.bls.verifySignatureSets([signatureSet], {
|
|
@@ -138,11 +138,10 @@ export async function validateGossipBlock(
|
|
|
138
138
|
// in forky condition, make sure to populate ShufflingCache with regened state
|
|
139
139
|
chain.shufflingCache.processState(blockState);
|
|
140
140
|
|
|
141
|
-
// Extra conditions for merge fork blocks
|
|
142
141
|
// [REJECT] The block's execution payload timestamp is correct with respect to the slot
|
|
143
142
|
// -- i.e. execution_payload.timestamp == compute_timestamp_at_slot(state, block.slot).
|
|
144
143
|
if (isForkPostBellatrix(fork) && !isForkPostGloas(fork)) {
|
|
145
|
-
if (!isExecutionBlockBodyType(block.body)) throw Error("Not
|
|
144
|
+
if (!isExecutionBlockBodyType(block.body)) throw Error("Not execution block body type");
|
|
146
145
|
const executionPayload = block.body.executionPayload;
|
|
147
146
|
if (isExecutionStateType(blockState) && isExecutionEnabled(blockState, block)) {
|
|
148
147
|
const expectedTimestamp = computeTimeAtSlot(config, blockSlot, chain.genesisTime);
|
|
@@ -158,7 +157,7 @@ export async function validateGossipBlock(
|
|
|
158
157
|
|
|
159
158
|
// [REJECT] The proposer signature, signed_beacon_block.signature, is valid with respect to the proposer_index pubkey.
|
|
160
159
|
if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockSlot, blockRoot, signedBlock.signature)) {
|
|
161
|
-
const signatureSet = getBlockProposerSignatureSet(chain.config,
|
|
160
|
+
const signatureSet = getBlockProposerSignatureSet(chain.config, signedBlock);
|
|
162
161
|
// Don't batch so verification is not delayed
|
|
163
162
|
if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: true}))) {
|
|
164
163
|
throw new BlockGossipError(GossipAction.REJECT, {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
getBlockHeaderProposerSignatureSetByParentStateSlot,
|
|
12
12
|
} from "@lodestar/state-transition";
|
|
13
13
|
import {Root, Slot, SubnetID, fulu, ssz} from "@lodestar/types";
|
|
14
|
-
import {toRootHex, verifyMerkleBranch} from "@lodestar/utils";
|
|
14
|
+
import {byteArrayEquals, toRootHex, verifyMerkleBranch} from "@lodestar/utils";
|
|
15
15
|
import {Metrics} from "../../metrics/metrics.js";
|
|
16
16
|
import {kzg} from "../../util/kzg.js";
|
|
17
17
|
import {
|
|
@@ -136,7 +136,6 @@ export async function validateGossipDataColumnSidecar(
|
|
|
136
136
|
if (!chain.seenBlockInputCache.isVerifiedProposerSignature(blockHeader.slot, blockRootHex, signature)) {
|
|
137
137
|
const signatureSet = getBlockHeaderProposerSignatureSetByParentStateSlot(
|
|
138
138
|
chain.config,
|
|
139
|
-
chain.index2pubkey,
|
|
140
139
|
blockState.slot,
|
|
141
140
|
dataColumnSidecar.signedBlockHeader
|
|
142
141
|
);
|
|
@@ -319,7 +318,7 @@ export async function validateBlockDataColumnSidecars(
|
|
|
319
318
|
const firstSidecarSignedBlockHeader = dataColumnSidecars[0].signedBlockHeader;
|
|
320
319
|
const firstSidecarBlockHeader = firstSidecarSignedBlockHeader.message;
|
|
321
320
|
const firstBlockRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(firstSidecarBlockHeader);
|
|
322
|
-
if (
|
|
321
|
+
if (!byteArrayEquals(blockRoot, firstBlockRoot)) {
|
|
323
322
|
throw new DataColumnSidecarValidationError(
|
|
324
323
|
{
|
|
325
324
|
code: DataColumnSidecarErrorCode.INCORRECT_BLOCK,
|
|
@@ -337,11 +336,7 @@ export async function validateBlockDataColumnSidecars(
|
|
|
337
336
|
const slot = firstSidecarSignedBlockHeader.message.slot;
|
|
338
337
|
const signature = firstSidecarSignedBlockHeader.signature;
|
|
339
338
|
if (!chain.seenBlockInputCache.isVerifiedProposerSignature(slot, rootHex, signature)) {
|
|
340
|
-
const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(
|
|
341
|
-
chain.config,
|
|
342
|
-
chain.index2pubkey,
|
|
343
|
-
firstSidecarSignedBlockHeader
|
|
344
|
-
);
|
|
339
|
+
const signatureSet = getBlockHeaderProposerSignatureSetByHeaderSlot(chain.config, firstSidecarSignedBlockHeader);
|
|
345
340
|
|
|
346
341
|
if (
|
|
347
342
|
!(await chain.bls.verifySignatureSets([signatureSet], {
|
|
@@ -53,7 +53,8 @@ async function validateExecutionPayloadBid(
|
|
|
53
53
|
|
|
54
54
|
// [REJECT] `bid.builder_index` is a valid/active builder index -- i.e.
|
|
55
55
|
// `is_active_builder(state, bid.builder_index)` returns `True`.
|
|
56
|
-
|
|
56
|
+
const builder = state.builders.getReadonly(bid.builderIndex);
|
|
57
|
+
if (!isActiveBuilder(builder, state.finalizedCheckpoint.epoch)) {
|
|
57
58
|
throw new ExecutionPayloadBidError(GossipAction.REJECT, {
|
|
58
59
|
code: ExecutionPayloadBidErrorCode.BUILDER_NOT_ELIGIBLE,
|
|
59
60
|
builderIndex: bid.builderIndex,
|
|
@@ -102,7 +103,7 @@ async function validateExecutionPayloadBid(
|
|
|
102
103
|
throw new ExecutionPayloadBidError(GossipAction.IGNORE, {
|
|
103
104
|
code: ExecutionPayloadBidErrorCode.BID_TOO_HIGH,
|
|
104
105
|
bidValue: bid.value,
|
|
105
|
-
builderBalance:
|
|
106
|
+
builderBalance: builder.balance,
|
|
106
107
|
});
|
|
107
108
|
}
|
|
108
109
|
|
|
@@ -122,8 +123,8 @@ async function validateExecutionPayloadBid(
|
|
|
122
123
|
|
|
123
124
|
// [REJECT] `signed_execution_payload_bid.signature` is valid with respect to the `bid.builder_index`.
|
|
124
125
|
const signatureSet = createSingleSignatureSetFromComponents(
|
|
125
|
-
PublicKey.fromBytes(
|
|
126
|
-
getExecutionPayloadBidSigningRoot(chain.config, state
|
|
126
|
+
PublicKey.fromBytes(builder.pubkey),
|
|
127
|
+
getExecutionPayloadBidSigningRoot(chain.config, state.slot, bid),
|
|
127
128
|
signedExecutionPayloadBid.signature
|
|
128
129
|
);
|
|
129
130
|
|