@lodestar/beacon-node 1.51.0-dev.88c15a0731 → 1.51.0-dev.8d5cdd33be
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 +36 -88
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +22 -2
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/validator/index.d.ts +6 -0
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +42 -26
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +13 -2
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +69 -35
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +1 -0
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +4 -0
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +7 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +11 -56
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +5 -241
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/blockInput/errors.d.ts +2 -4
- package/lib/chain/blocks/blockInput/errors.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/errors.js.map +1 -1
- package/lib/chain/blocks/blockInput/types.d.ts +2 -18
- package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/types.js +0 -1
- package/lib/chain/blocks/blockInput/types.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +40 -56
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +10 -11
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +32 -18
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +4 -4
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +12 -9
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +24 -19
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +4 -20
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/types.js +0 -24
- package/lib/chain/blocks/types.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +18 -7
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js +14 -2
- package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +7 -3
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +4 -0
- package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +7 -5
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +3 -3
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +11 -6
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts +0 -2
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +6 -24
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/bls/interface.d.ts +2 -0
- package/lib/chain/bls/interface.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +13 -11
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/types.d.ts +1 -1
- package/lib/chain/bls/multithread/types.d.ts.map +1 -1
- package/lib/chain/bls/multithread/worker.js +1 -1
- package/lib/chain/bls/multithread/worker.js.map +1 -1
- package/lib/chain/bls/singleThread.js +1 -1
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.js +1 -1
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/chain.d.ts +25 -4
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +124 -43
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +7 -7
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +5 -5
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +1 -1
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +1 -1
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +7 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/errors/index.d.ts +0 -1
- package/lib/chain/errors/index.d.ts.map +1 -1
- package/lib/chain/errors/index.js +0 -1
- package/lib/chain/errors/index.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts +11 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +11 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/forkChoiceExecutionEngine.d.ts +51 -0
- package/lib/chain/forkChoiceExecutionEngine.d.ts.map +1 -0
- package/lib/chain/forkChoiceExecutionEngine.js +117 -0
- package/lib/chain/forkChoiceExecutionEngine.js.map +1 -0
- package/lib/chain/interface.d.ts +9 -7
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts +17 -4
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +199 -46
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/attestationPool.d.ts +1 -1
- package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/attestationPool.js +15 -4
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/index.d.ts +1 -0
- package/lib/chain/opPools/index.d.ts.map +1 -1
- package/lib/chain/opPools/index.js +1 -0
- package/lib/chain/opPools/index.js.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.js +17 -7
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/opPools/singleAttestationPool.d.ts +77 -0
- package/lib/chain/opPools/singleAttestationPool.d.ts.map +1 -0
- package/lib/chain/opPools/singleAttestationPool.js +209 -0
- package/lib/chain/opPools/singleAttestationPool.js.map +1 -0
- package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +9 -3
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.d.ts.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.js +11 -3
- package/lib/chain/opPools/syncContributionAndProofPool.js.map +1 -1
- package/lib/chain/opPools/utils.d.ts +1 -1
- package/lib/chain/opPools/utils.d.ts.map +1 -1
- package/lib/chain/opPools/utils.js +1 -1
- package/lib/chain/opPools/utils.js.map +1 -1
- package/lib/chain/options.d.ts +5 -3
- 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/produceBlock/produceBlockBody.d.ts +3 -2
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +3 -2
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/proposerTracker.d.ts +31 -0
- package/lib/chain/proposerTracker.d.ts.map +1 -0
- package/lib/chain/proposerTracker.js +75 -0
- package/lib/chain/proposerTracker.js.map +1 -0
- package/lib/chain/regen/interface.d.ts +1 -1
- package/lib/chain/regen/interface.d.ts.map +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 +5 -3
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -14
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +6 -65
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +13 -13
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts +6 -0
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +53 -0
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +1 -2
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +0 -3
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/db/beacon.d.ts +7 -0
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +32 -0
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/dataColumnStore.d.ts +1 -1
- package/lib/db/dataColumnStore.d.ts.map +1 -1
- package/lib/db/dataColumnStore.js +1 -4
- package/lib/db/dataColumnStore.js.map +1 -1
- package/lib/db/flatFileStore/flatFileStore.js +5 -5
- package/lib/db/flatFileStore/flatFileStore.js.map +1 -1
- package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -1
- package/lib/db/flatFileStore/slotIndex.js +2 -2
- package/lib/db/flatFileStore/slotIndex.js.map +1 -1
- package/lib/db/interface.d.ts +1 -0
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blobSidecars.d.ts +0 -1
- package/lib/db/repositories/blobSidecars.d.ts.map +1 -1
- package/lib/db/repositories/blobSidecars.js +0 -1
- package/lib/db/repositories/blobSidecars.js.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts +6 -0
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.js +19 -0
- package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
- package/lib/execution/builder/apiClient.d.ts +14 -8
- package/lib/execution/builder/apiClient.d.ts.map +1 -1
- package/lib/execution/builder/apiClient.js +12 -10
- package/lib/execution/builder/apiClient.js.map +1 -1
- package/lib/execution/builder/http.d.ts +2 -0
- package/lib/execution/builder/http.d.ts.map +1 -1
- package/lib/execution/builder/http.js +2 -0
- package/lib/execution/builder/http.js.map +1 -1
- package/lib/execution/engine/http.d.ts +4 -6
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +8 -10
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/index.d.ts +1 -1
- package/lib/execution/engine/index.d.ts.map +1 -1
- package/lib/execution/engine/index.js +1 -1
- package/lib/execution/engine/index.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +18 -6
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/interface.js.map +1 -1
- package/lib/execution/engine/jsonRpcTransport.d.ts +2 -4
- package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -1
- package/lib/execution/engine/jsonRpcTransport.js +2 -12
- package/lib/execution/engine/jsonRpcTransport.js.map +1 -1
- package/lib/execution/engine/mock.d.ts +0 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +0 -4
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/restTransport.d.ts +2 -4
- package/lib/execution/engine/restTransport.d.ts.map +1 -1
- package/lib/execution/engine/restTransport.js +1 -15
- package/lib/execution/engine/restTransport.js.map +1 -1
- package/lib/execution/engine/sszTypes.d.ts +0 -9
- package/lib/execution/engine/sszTypes.d.ts.map +1 -1
- package/lib/execution/engine/sszTypes.js +0 -5
- package/lib/execution/engine/sszTypes.js.map +1 -1
- package/lib/execution/engine/transport.d.ts +1 -14
- package/lib/execution/engine/transport.d.ts.map +1 -1
- package/lib/execution/engine/types.d.ts +0 -8
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +2 -10
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/execution/engine/utils.d.ts.map +1 -1
- package/lib/execution/engine/utils.js +3 -2
- package/lib/execution/engine/utils.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/metrics/metrics/beacon.d.ts +0 -9
- package/lib/metrics/metrics/beacon.d.ts.map +1 -1
- package/lib/metrics/metrics/beacon.js +0 -30
- package/lib/metrics/metrics/beacon.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +30 -8
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +79 -18
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/metrics/server/http.js +5 -5
- package/lib/metrics/server/http.js.map +1 -1
- package/lib/monitoring/service.js +1 -1
- package/lib/monitoring/service.js.map +1 -1
- package/lib/network/core/networkCore.d.ts +4 -1
- package/lib/network/core/networkCore.d.ts.map +1 -1
- package/lib/network/core/networkCore.js +7 -0
- package/lib/network/core/networkCore.js.map +1 -1
- package/lib/network/core/networkCoreWorker.js +2 -0
- package/lib/network/core/networkCoreWorker.js.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.d.ts +4 -1
- package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.js +6 -0
- package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
- package/lib/network/core/types.d.ts +6 -1
- package/lib/network/core/types.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.d.ts +1 -0
- package/lib/network/gossip/gossipsub.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.js +10 -0
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +1 -8
- package/lib/network/gossip/interface.d.ts.map +1 -1
- package/lib/network/gossip/interface.js +0 -1
- package/lib/network/gossip/interface.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +0 -16
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +0 -23
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/interface.d.ts +4 -5
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +5 -1
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts +8 -7
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +53 -35
- package/lib/network/network.js.map +1 -1
- package/lib/network/options.d.ts +2 -0
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js +2 -0
- package/lib/network/options.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts +2 -1
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +28 -1
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/peers/utils/assertPeerRelevance.d.ts +9 -1
- package/lib/network/peers/utils/assertPeerRelevance.d.ts.map +1 -1
- package/lib/network/peers/utils/assertPeerRelevance.js +32 -21
- package/lib/network/peers/utils/assertPeerRelevance.js.map +1 -1
- package/lib/network/peers/utils/prioritizePeers.d.ts +4 -1
- package/lib/network/peers/utils/prioritizePeers.d.ts.map +1 -1
- package/lib/network/peers/utils/prioritizePeers.js +8 -16
- package/lib/network/peers/utils/prioritizePeers.js.map +1 -1
- package/lib/network/peers/utils/subnetMap.d.ts +5 -2
- package/lib/network/peers/utils/subnetMap.d.ts.map +1 -1
- package/lib/network/peers/utils/subnetMap.js +6 -3
- package/lib/network/peers/utils/subnetMap.js.map +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
- package/lib/network/processor/extractSlotRootFns.js +1 -8
- package/lib/network/processor/extractSlotRootFns.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +52 -131
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
- package/lib/network/processor/gossipQueues/index.js +0 -6
- package/lib/network/processor/gossipQueues/index.js.map +1 -1
- package/lib/network/processor/gossipValidatorFn.d.ts.map +1 -1
- package/lib/network/processor/gossipValidatorFn.js +1 -5
- package/lib/network/processor/gossipValidatorFn.js.map +1 -1
- package/lib/network/processor/index.d.ts +6 -0
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +29 -4
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.d.ts.map +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.js +0 -3
- package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts +2 -2
- package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/index.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/index.js +1 -12
- package/lib/network/reqresp/handlers/index.js.map +1 -1
- package/lib/network/reqresp/protocols.d.ts +0 -2
- package/lib/network/reqresp/protocols.d.ts.map +1 -1
- package/lib/network/reqresp/protocols.js +0 -10
- package/lib/network/reqresp/protocols.js.map +1 -1
- package/lib/network/reqresp/rateLimit.d.ts.map +1 -1
- package/lib/network/reqresp/rateLimit.js +1 -17
- package/lib/network/reqresp/rateLimit.js.map +1 -1
- package/lib/network/reqresp/types.d.ts +2 -8
- package/lib/network/reqresp/types.d.ts.map +1 -1
- package/lib/network/reqresp/types.js +1 -7
- package/lib/network/reqresp/types.js.map +1 -1
- package/lib/network/subnets/attnetsService.d.ts +35 -5
- package/lib/network/subnets/attnetsService.d.ts.map +1 -1
- package/lib/network/subnets/attnetsService.js +84 -6
- package/lib/network/subnets/attnetsService.js.map +1 -1
- package/lib/network/subnets/interface.d.ts +7 -0
- package/lib/network/subnets/interface.d.ts.map +1 -1
- package/lib/network/subnets/interface.js.map +1 -1
- package/lib/node/nodejs.d.ts +3 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +47 -21
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/options.d.ts +3 -1
- package/lib/node/options.d.ts.map +1 -1
- package/lib/node/options.js +4 -2
- package/lib/node/options.js.map +1 -1
- package/lib/sync/interface.d.ts.map +1 -1
- package/lib/sync/interface.js.map +1 -1
- package/lib/sync/range/batch.d.ts +2 -3
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +9 -22
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +2 -15
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/sync.d.ts +7 -0
- package/lib/sync/sync.d.ts.map +1 -1
- package/lib/sync/sync.js +61 -3
- package/lib/sync/sync.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +1 -7
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +6 -34
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +24 -128
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts +2 -18
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +14 -99
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/util/blobs.d.ts +1 -7
- package/lib/util/blobs.d.ts.map +1 -1
- package/lib/util/blobs.js +0 -19
- package/lib/util/blobs.js.map +1 -1
- package/lib/util/execution.d.ts +3 -4
- package/lib/util/execution.d.ts.map +1 -1
- package/lib/util/execution.js +1 -73
- package/lib/util/execution.js.map +1 -1
- package/lib/util/file.d.ts.map +1 -1
- package/lib/util/file.js +8 -9
- package/lib/util/file.js.map +1 -1
- package/lib/util/queue/itemQueue.js +1 -1
- package/lib/util/queue/itemQueue.js.map +1 -1
- package/lib/util/sszBytes.d.ts +5 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +36 -19
- package/lib/util/sszBytes.js.map +1 -1
- package/lib/util/types.d.ts +0 -5
- package/lib/util/types.d.ts.map +1 -1
- package/lib/util/types.js +1 -2
- package/lib/util/types.js.map +1 -1
- package/package.json +16 -17
- package/src/api/impl/beacon/blocks/index.ts +59 -109
- package/src/api/impl/beacon/pool/index.ts +31 -1
- package/src/api/impl/beacon/state/utils.ts +1 -1
- package/src/api/impl/validator/index.ts +47 -30
- package/src/chain/GetBlobsTracker.ts +82 -52
- package/src/chain/archiveStore/archiveStore.ts +1 -0
- package/src/chain/archiveStore/utils/archiveBlocks.ts +12 -4
- package/src/chain/blocks/blockInput/blockInput.ts +11 -343
- package/src/chain/blocks/blockInput/errors.ts +1 -2
- package/src/chain/blocks/blockInput/types.ts +2 -20
- package/src/chain/blocks/importBlock.ts +61 -76
- package/src/chain/blocks/importExecutionPayload.ts +55 -34
- package/src/chain/blocks/index.ts +11 -4
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +35 -24
- package/src/chain/blocks/types.ts +5 -31
- package/src/chain/blocks/verifyBlock.ts +31 -16
- package/src/chain/blocks/verifyBlocksDataAvailability.ts +16 -2
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +9 -6
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +4 -1
- package/src/chain/blocks/verifyBlocksSignatures.ts +7 -5
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +14 -6
- package/src/chain/blocks/writeBlockInputToDb.ts +6 -29
- package/src/chain/bls/interface.ts +2 -0
- package/src/chain/bls/multithread/index.ts +14 -10
- package/src/chain/bls/multithread/types.ts +1 -1
- package/src/chain/bls/multithread/worker.ts +1 -5
- package/src/chain/bls/singleThread.ts +1 -1
- package/src/chain/bls/utils.ts +1 -1
- package/src/chain/chain.ts +140 -42
- package/src/chain/emitter.ts +8 -8
- package/src/chain/errors/blockError.ts +1 -1
- package/src/chain/errors/executionPayloadEnvelope.ts +8 -0
- package/src/chain/errors/index.ts +0 -1
- package/src/chain/forkChoice/index.ts +11 -0
- package/src/chain/forkChoiceExecutionEngine.ts +183 -0
- package/src/chain/interface.ts +9 -6
- package/src/chain/opPools/aggregatedAttestationPool.ts +246 -43
- package/src/chain/opPools/attestationPool.ts +16 -4
- package/src/chain/opPools/index.ts +1 -0
- package/src/chain/opPools/payloadAttestationPool.ts +18 -7
- package/src/chain/opPools/singleAttestationPool.ts +287 -0
- package/src/chain/opPools/syncCommitteeMessagePool.ts +10 -3
- package/src/chain/opPools/syncContributionAndProofPool.ts +13 -3
- package/src/chain/opPools/utils.ts +1 -1
- package/src/chain/options.ts +5 -4
- package/src/chain/produceBlock/produceBlockBody.ts +7 -3
- package/src/chain/proposerTracker.ts +94 -0
- package/src/chain/regen/interface.ts +1 -1
- package/src/chain/regen/queued.ts +6 -4
- package/src/chain/seenCache/seenGossipBlockInput.ts +9 -93
- package/src/chain/validation/executionPayloadBid.ts +14 -13
- package/src/chain/validation/executionPayloadEnvelope.ts +68 -1
- package/src/chain/validatorMonitor.ts +0 -6
- package/src/db/beacon.ts +39 -0
- package/src/db/dataColumnStore.ts +2 -4
- package/src/db/flatFileStore/flatFileStore.ts +7 -7
- package/src/db/flatFileStore/slotIndex.ts +4 -3
- package/src/db/interface.ts +2 -0
- package/src/db/repositories/blobSidecars.ts +0 -1
- package/src/db/repositories/dataColumnSidecarArchive.ts +20 -0
- package/src/execution/builder/apiClient.ts +16 -13
- package/src/execution/builder/http.ts +4 -0
- package/src/execution/engine/http.ts +19 -42
- package/src/execution/engine/index.ts +1 -1
- package/src/execution/engine/interface.ts +19 -10
- package/src/execution/engine/jsonRpcTransport.ts +10 -22
- package/src/execution/engine/mock.ts +0 -7
- package/src/execution/engine/restTransport.ts +3 -22
- package/src/execution/engine/sszTypes.ts +0 -9
- package/src/execution/engine/transport.ts +8 -17
- package/src/execution/engine/types.ts +3 -18
- package/src/execution/engine/utils.ts +4 -2
- package/src/index.ts +1 -1
- package/src/metrics/metrics/beacon.ts +0 -30
- package/src/metrics/metrics/lodestar.ts +80 -18
- package/src/metrics/server/http.ts +5 -5
- package/src/monitoring/service.ts +1 -1
- package/src/network/core/networkCore.ts +11 -1
- package/src/network/core/networkCoreWorker.ts +2 -0
- package/src/network/core/networkCoreWorkerHandler.ts +8 -1
- package/src/network/core/types.ts +6 -1
- package/src/network/gossip/gossipsub.ts +11 -0
- package/src/network/gossip/interface.ts +0 -5
- package/src/network/gossip/topic.ts +0 -25
- package/src/network/interface.ts +2 -5
- package/src/network/libp2p/index.ts +5 -1
- package/src/network/network.ts +55 -58
- package/src/network/options.ts +4 -0
- package/src/network/peers/peerManager.ts +28 -3
- package/src/network/peers/utils/assertPeerRelevance.ts +39 -23
- package/src/network/peers/utils/prioritizePeers.ts +14 -22
- package/src/network/peers/utils/subnetMap.ts +6 -3
- package/src/network/processor/extractSlotRootFns.ts +0 -9
- package/src/network/processor/gossipHandlers.ts +65 -164
- package/src/network/processor/gossipQueues/index.ts +0 -6
- package/src/network/processor/gossipValidatorFn.ts +0 -5
- package/src/network/processor/index.ts +25 -4
- package/src/network/reqresp/ReqRespBeaconNode.ts +0 -7
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +2 -2
- package/src/network/reqresp/handlers/index.ts +0 -17
- package/src/network/reqresp/protocols.ts +0 -12
- package/src/network/reqresp/rateLimit.ts +1 -17
- package/src/network/reqresp/types.ts +0 -13
- package/src/network/subnets/attnetsService.ts +94 -6
- package/src/network/subnets/interface.ts +7 -0
- package/src/node/nodejs.ts +58 -22
- package/src/node/options.ts +9 -6
- package/src/sync/interface.ts +1 -0
- package/src/sync/range/batch.ts +9 -21
- package/src/sync/range/chain.ts +2 -14
- package/src/sync/sync.ts +65 -4
- package/src/sync/unknownBlock.ts +1 -8
- package/src/sync/utils/downloadByRange.ts +31 -230
- package/src/sync/utils/downloadByRoot.ts +15 -142
- package/src/util/blobs.ts +0 -34
- package/src/util/execution.ts +8 -102
- package/src/util/file.ts +8 -9
- package/src/util/queue/itemQueue.ts +1 -1
- package/src/util/sszBytes.ts +42 -24
- package/src/util/types.ts +1 -8
- package/lib/chain/errors/blobSidecarError.d.ts +0 -108
- package/lib/chain/errors/blobSidecarError.d.ts.map +0 -1
- package/lib/chain/errors/blobSidecarError.js +0 -38
- package/lib/chain/errors/blobSidecarError.js.map +0 -1
- package/lib/chain/validation/blobSidecar.d.ts +0 -16
- package/lib/chain/validation/blobSidecar.d.ts.map +0 -1
- package/lib/chain/validation/blobSidecar.js +0 -276
- package/lib/chain/validation/blobSidecar.js.map +0 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts +0 -9
- package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +0 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js +0 -91
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +0 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts +0 -5
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts.map +0 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +0 -46
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js.map +0 -1
- package/src/chain/errors/blobSidecarError.ts +0 -70
- package/src/chain/validation/blobSidecar.ts +0 -357
- package/src/network/reqresp/handlers/blobSidecarsByRange.ts +0 -133
- package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +0 -69
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {BitArray} from "@chainsafe/ssz";
|
|
2
2
|
import {routes} from "@lodestar/api";
|
|
3
3
|
import {
|
|
4
|
-
AncestorStatus,
|
|
5
|
-
ExecutionStatus,
|
|
6
4
|
ForkChoiceError,
|
|
7
5
|
ForkChoiceErrorCode,
|
|
6
|
+
InvalidBlockCode,
|
|
8
7
|
NotReorgedReason,
|
|
8
|
+
ProtoBlock,
|
|
9
9
|
getFinalizedExecutionBlockHash,
|
|
10
10
|
getSafeExecutionBlockHash,
|
|
11
11
|
} from "@lodestar/fork-choice";
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
IBeaconStateView,
|
|
22
22
|
RootCache,
|
|
23
23
|
computeEpochAtSlot,
|
|
24
|
-
|
|
24
|
+
computeTimeAtSlotMs,
|
|
25
25
|
getBeaconCommittees,
|
|
26
26
|
isStatePostAltair,
|
|
27
27
|
isStatePostBellatrix,
|
|
@@ -43,11 +43,13 @@ import {callInNextEventLoop} from "../../util/eventLoop.js";
|
|
|
43
43
|
import {isOptimisticBlock} from "../../util/forkChoice.js";
|
|
44
44
|
import {isQueueErrorAborted} from "../../util/queue/index.js";
|
|
45
45
|
import type {BeaconChain} from "../chain.js";
|
|
46
|
-
import {ChainEvent
|
|
46
|
+
import {ChainEvent} from "../emitter.js";
|
|
47
|
+
import {BlockError, BlockErrorCode} from "../errors/index.js";
|
|
47
48
|
import {ForkchoiceCaller} from "../forkChoice/index.js";
|
|
49
|
+
import {IncludedAttesters} from "../opPools/singleAttestationPool.js";
|
|
48
50
|
import {REPROCESS_MIN_TIME_TO_NEXT_SLOT_BPS} from "../reprocess.js";
|
|
49
51
|
import {toCheckpointHex} from "../stateCache/persistentCheckpointsCache.js";
|
|
50
|
-
import {
|
|
52
|
+
import {isBlockInputColumns} from "./blockInput/blockInput.js";
|
|
51
53
|
import {AttestationImportOpt, FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
|
|
52
54
|
import {getCheckpointFromState} from "./utils/checkpoint.js";
|
|
53
55
|
|
|
@@ -94,8 +96,8 @@ export async function importBlock(
|
|
|
94
96
|
fullyVerifiedBlock: FullyVerifiedBlock,
|
|
95
97
|
opts: ImportBlockOpts
|
|
96
98
|
): Promise<void> {
|
|
97
|
-
const {blockInput, postState, parentBlockSlot, dataAvailabilityStatus, indexedAttestations} =
|
|
98
|
-
|
|
99
|
+
const {blockInput, postState, parentBlockSlot, executionStatus, dataAvailabilityStatus, indexedAttestations} =
|
|
100
|
+
fullyVerifiedBlock;
|
|
99
101
|
const block = blockInput.getBlock();
|
|
100
102
|
const source = blockInput.getBlockSource();
|
|
101
103
|
const {slot: blockSlot} = block.message;
|
|
@@ -105,8 +107,9 @@ export async function importBlock(
|
|
|
105
107
|
const currentEpoch = computeEpochAtSlot(currentSlot);
|
|
106
108
|
const blockEpoch = computeEpochAtSlot(blockSlot);
|
|
107
109
|
const prevFinalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
|
|
108
|
-
const
|
|
109
|
-
fullyVerifiedBlock.seenTimestampSec
|
|
110
|
+
const receiveDelayMs =
|
|
111
|
+
Math.round(fullyVerifiedBlock.seenTimestampSec * 1000) -
|
|
112
|
+
computeTimeAtSlotMs(this.config, blockSlot, postState.genesisTime * 1000);
|
|
110
113
|
const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
|
|
111
114
|
const fork = this.config.getForkSeq(blockSlot);
|
|
112
115
|
|
|
@@ -130,35 +133,30 @@ export async function importBlock(
|
|
|
130
133
|
|
|
131
134
|
// Should compute checkpoint balances before forkchoice.onBlock
|
|
132
135
|
this.checkpointBalancesCache.processState(blockRootHex, postState);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
136
|
+
const importDelayMs = this.clock.msFromSlot(blockSlot);
|
|
137
|
+
let blockSummary: ProtoBlock;
|
|
138
|
+
try {
|
|
139
|
+
blockSummary = this.forkChoice.onBlock(
|
|
140
|
+
block.message,
|
|
141
|
+
postState,
|
|
142
|
+
receiveDelayMs,
|
|
143
|
+
importDelayMs,
|
|
144
|
+
currentSlot,
|
|
145
|
+
executionStatus,
|
|
146
|
+
dataAvailabilityStatus
|
|
147
|
+
);
|
|
148
|
+
} catch (e) {
|
|
149
|
+
// The parent can be invalidated by a forkchoiceUpdated verdict after verifyBlocksSanityChecks passed
|
|
150
|
+
if (
|
|
151
|
+
e instanceof ForkChoiceError &&
|
|
152
|
+
e.type.code === ForkChoiceErrorCode.INVALID_BLOCK &&
|
|
153
|
+
e.type.err.code === InvalidBlockCode.PARENT_EXECUTION_INVALID
|
|
154
|
+
) {
|
|
155
|
+
throw new BlockError(block, {code: BlockErrorCode.PARENT_EXECUTION_INVALID, parentRoot: e.type.err.root});
|
|
147
156
|
}
|
|
148
|
-
|
|
157
|
+
throw e;
|
|
149
158
|
}
|
|
150
159
|
|
|
151
|
-
const importDelaySec = this.clock.secFromSlot(blockSlot);
|
|
152
|
-
const blockSummary = this.forkChoice.onBlock(
|
|
153
|
-
block.message,
|
|
154
|
-
postState,
|
|
155
|
-
receiveDelaySec,
|
|
156
|
-
importDelaySec,
|
|
157
|
-
currentSlot,
|
|
158
|
-
executionStatus,
|
|
159
|
-
dataAvailabilityStatus
|
|
160
|
-
);
|
|
161
|
-
|
|
162
160
|
// This adds the state necessary to process the next block
|
|
163
161
|
// Some block event handlers require state being in state cache so need to do this before emitting EventType.block
|
|
164
162
|
this.regen.processState(blockRootHex, postState);
|
|
@@ -175,6 +173,9 @@ export async function importBlock(
|
|
|
175
173
|
// Only process attestations of blocks with relevant attestations for the fork-choice:
|
|
176
174
|
// If current epoch is N, and block is epoch X, block may include attestations for epoch X or X - 1.
|
|
177
175
|
// The latest block that is useful is at epoch N - 1 which may include attestations for epoch N - 1 or N - 2.
|
|
176
|
+
// the pool is empty outside the slots before a local block proposal, nothing to prune then
|
|
177
|
+
const pruneSingleAttestations = fork >= ForkSeq.electra && !this.singleAttestationPool.isEmpty();
|
|
178
|
+
const includedAttesters: IncludedAttesters[] = [];
|
|
178
179
|
if (importsBlockAttestations(opts, blockEpoch, currentEpoch)) {
|
|
179
180
|
const attestations = block.message.body.attestations;
|
|
180
181
|
const rootCache = new RootCache(postState);
|
|
@@ -189,6 +190,14 @@ export async function importBlock(
|
|
|
189
190
|
const {target, beaconBlockRoot} = attestation.data;
|
|
190
191
|
|
|
191
192
|
const attDataRoot = toRootHex(ssz.phase0.AttestationData.hashTreeRoot(indexedAttestation.data));
|
|
193
|
+
// the block includes these attesters even if fork choice below rejects the vote
|
|
194
|
+
if (pruneSingleAttestations) {
|
|
195
|
+
includedAttesters.push({
|
|
196
|
+
slot: attestation.data.slot,
|
|
197
|
+
attDataRootHex: attDataRoot,
|
|
198
|
+
attestingIndices: indexedAttestation.attestingIndices,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
192
201
|
addAttestation.call(
|
|
193
202
|
this,
|
|
194
203
|
postState,
|
|
@@ -320,19 +329,19 @@ export async function importBlock(
|
|
|
320
329
|
});
|
|
321
330
|
}
|
|
322
331
|
|
|
332
|
+
// only a block that becomes head prunes, not a side-branch import
|
|
333
|
+
if (pruneSingleAttestations && newHead.blockRoot === blockRootHex) {
|
|
334
|
+
callInNextEventLoop(() => {
|
|
335
|
+
const deleted = this.singleAttestationPool.onHead(blockRootHex, newHead.parentRoot, includedAttesters);
|
|
336
|
+
this.metrics?.opPool.singleAttestationPool.deletedByBlock.inc(deleted);
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
323
340
|
if (newHead.blockRoot !== oldHead.blockRoot) {
|
|
324
|
-
|
|
325
|
-
this.regen.updateHeadState(newHead, postState);
|
|
341
|
+
this.onHeadChanged(oldHead, newHead, postState);
|
|
326
342
|
|
|
327
343
|
const delaySec = this.clock.secFromSlot(newHead.slot);
|
|
328
|
-
this.logger.verbose("New chain head", {
|
|
329
|
-
slot: newHead.slot,
|
|
330
|
-
root: newHead.blockRoot,
|
|
331
|
-
delaySec,
|
|
332
|
-
});
|
|
333
|
-
|
|
334
344
|
if (this.metrics) {
|
|
335
|
-
this.metrics.headSlot.set(newHead.slot);
|
|
336
345
|
// Only track "recent" blocks. Otherwise sync can distort this metrics heavily.
|
|
337
346
|
// We want to track recent blocks coming from gossip, unknown block sync, and API.
|
|
338
347
|
const headFork = this.config.getForkName(newHead.slot);
|
|
@@ -345,32 +354,6 @@ export async function importBlock(
|
|
|
345
354
|
}
|
|
346
355
|
}
|
|
347
356
|
|
|
348
|
-
this.onNewHead(newHead);
|
|
349
|
-
|
|
350
|
-
this.metrics?.forkChoice.changedHead.inc();
|
|
351
|
-
|
|
352
|
-
const ancestorResult = this.forkChoice.getCommonAncestorDepth(oldHead, newHead);
|
|
353
|
-
if (ancestorResult.code === AncestorStatus.CommonAncestor) {
|
|
354
|
-
// CommonAncestor = chain reorg, old head and new head not direct descendants
|
|
355
|
-
|
|
356
|
-
const forkChoiceReorgEventData: ReorgEventData = {
|
|
357
|
-
depth: ancestorResult.depth,
|
|
358
|
-
epoch: computeEpochAtSlot(newHead.slot),
|
|
359
|
-
slot: newHead.slot,
|
|
360
|
-
newHeadBlock: newHead.blockRoot,
|
|
361
|
-
oldHeadBlock: oldHead.blockRoot,
|
|
362
|
-
newHeadState: newHead.stateRoot,
|
|
363
|
-
oldHeadState: oldHead.stateRoot,
|
|
364
|
-
executionOptimistic: isOptimisticBlock(newHead),
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
this.emitter.emit(routes.events.EventType.chainReorg, forkChoiceReorgEventData);
|
|
368
|
-
this.logger.verbose("Chain reorg", forkChoiceReorgEventData);
|
|
369
|
-
|
|
370
|
-
this.metrics?.forkChoice.reorg.inc();
|
|
371
|
-
this.metrics?.forkChoice.reorgDistance.observe(ancestorResult.depth);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
357
|
// Lightclient server support (only after altair)
|
|
375
358
|
// - Persist state witness
|
|
376
359
|
// - Use block's syncAggregate
|
|
@@ -417,7 +400,7 @@ export async function importBlock(
|
|
|
417
400
|
// 4) Block meets the criteria of being re-orged out (this is also checked inside the function)
|
|
418
401
|
const result = this.forkChoice.shouldOverrideForkChoiceUpdate(
|
|
419
402
|
blockSummary,
|
|
420
|
-
this.clock.
|
|
403
|
+
this.clock.msFromSlot(currentSlot),
|
|
421
404
|
currentSlot
|
|
422
405
|
);
|
|
423
406
|
shouldOverrideFcu = result.shouldOverrideFcu;
|
|
@@ -469,7 +452,13 @@ export async function importBlock(
|
|
|
469
452
|
const finalizedBlockHash = getFinalizedExecutionBlockHash(this.forkChoice);
|
|
470
453
|
if (headBlockHash !== ZERO_HASH_HEX) {
|
|
471
454
|
this.executionEngine
|
|
472
|
-
.notifyForkchoiceUpdate(
|
|
455
|
+
.notifyForkchoiceUpdate(
|
|
456
|
+
this.config.getForkName(fcuHead.slot),
|
|
457
|
+
fcuHead.blockRoot,
|
|
458
|
+
headBlockHash,
|
|
459
|
+
safeBlockHash,
|
|
460
|
+
finalizedBlockHash
|
|
461
|
+
)
|
|
473
462
|
.catch((e) => {
|
|
474
463
|
if (!isErrorAborted(e) && !isQueueErrorAborted(e)) {
|
|
475
464
|
this.logger.error("Error pushing notifyForkchoiceUpdate()", {headBlockHash, finalizedBlockHash}, e);
|
|
@@ -591,10 +580,6 @@ export async function importBlock(
|
|
|
591
580
|
for (const {source} of blockInput.getSampledColumnsWithSource()) {
|
|
592
581
|
this.metrics?.dataColumns.bySource.inc({source});
|
|
593
582
|
}
|
|
594
|
-
} else if (isBlockInputBlobs(blockInput)) {
|
|
595
|
-
for (const {source} of blockInput.getAllBlobsWithSource()) {
|
|
596
|
-
this.metrics?.importBlock.blobsBySource.inc({blobsSource: source});
|
|
597
|
-
}
|
|
598
583
|
}
|
|
599
584
|
|
|
600
585
|
const reprocessGuardSec =
|
|
@@ -2,6 +2,9 @@ import {SerializedList} from "@chainsafe/ssz";
|
|
|
2
2
|
import {routes} from "@lodestar/api";
|
|
3
3
|
import {
|
|
4
4
|
ExecutionStatus,
|
|
5
|
+
ForkChoiceError,
|
|
6
|
+
ForkChoiceErrorCode,
|
|
7
|
+
InvalidBlockCode,
|
|
5
8
|
PayloadExecutionStatus,
|
|
6
9
|
getFinalizedExecutionBlockHash,
|
|
7
10
|
getSafeExecutionBlockHash,
|
|
@@ -26,7 +29,6 @@ import {
|
|
|
26
29
|
verifyExecutionPayloadEnvelope,
|
|
27
30
|
verifyExecutionPayloadEnvelopeSignature,
|
|
28
31
|
} from "./verifyExecutionPayloadEnvelope.js";
|
|
29
|
-
import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
|
|
30
32
|
|
|
31
33
|
const EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS = 64;
|
|
32
34
|
|
|
@@ -34,9 +36,11 @@ export enum PayloadErrorCode {
|
|
|
34
36
|
EXECUTION_ENGINE_INVALID = "PAYLOAD_ERROR_EXECUTION_ENGINE_INVALID",
|
|
35
37
|
EXECUTION_ENGINE_ERROR = "PAYLOAD_ERROR_EXECUTION_ENGINE_ERROR",
|
|
36
38
|
BLOCK_NOT_IN_FORK_CHOICE = "PAYLOAD_ERROR_BLOCK_NOT_IN_FORK_CHOICE",
|
|
39
|
+
BLOCK_EXECUTION_INVALID = "PAYLOAD_ERROR_BLOCK_EXECUTION_INVALID",
|
|
37
40
|
MISS_BLOCK_STATE = "PAYLOAD_ERROR_MISS_BLOCK_STATE",
|
|
38
41
|
ENVELOPE_VERIFICATION_ERROR = "PAYLOAD_ERROR_ENVELOPE_VERIFICATION_ERROR",
|
|
39
42
|
INVALID_SIGNATURE = "PAYLOAD_ERROR_INVALID_SIGNATURE",
|
|
43
|
+
DATA_UNAVAILABLE = "PAYLOAD_ERROR_DATA_UNAVAILABLE",
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
export type PayloadErrorType =
|
|
@@ -54,6 +58,10 @@ export type PayloadErrorType =
|
|
|
54
58
|
code: PayloadErrorCode.BLOCK_NOT_IN_FORK_CHOICE;
|
|
55
59
|
blockRootHex: string;
|
|
56
60
|
}
|
|
61
|
+
| {
|
|
62
|
+
code: PayloadErrorCode.BLOCK_EXECUTION_INVALID;
|
|
63
|
+
blockRootHex: string;
|
|
64
|
+
}
|
|
57
65
|
| {
|
|
58
66
|
code: PayloadErrorCode.MISS_BLOCK_STATE;
|
|
59
67
|
blockRootHex: string;
|
|
@@ -64,6 +72,9 @@ export type PayloadErrorType =
|
|
|
64
72
|
}
|
|
65
73
|
| {
|
|
66
74
|
code: PayloadErrorCode.INVALID_SIGNATURE;
|
|
75
|
+
}
|
|
76
|
+
| {
|
|
77
|
+
code: PayloadErrorCode.DATA_UNAVAILABLE;
|
|
67
78
|
};
|
|
68
79
|
|
|
69
80
|
export class PayloadError extends Error {
|
|
@@ -95,7 +106,8 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
|
|
|
95
106
|
* are applied on the next block via processParentExecutionPayload.
|
|
96
107
|
*
|
|
97
108
|
* The DA wait must have run upstream (range sync awaits DA in `verifyBlocksInEpoch` for the
|
|
98
|
-
* whole segment; gossip / API path
|
|
109
|
+
* whole segment; the gossip / API / unknown-payload sync path waits in `PayloadEnvelopeProcessor`
|
|
110
|
+
* before the import is queued).
|
|
99
111
|
*
|
|
100
112
|
* Steps:
|
|
101
113
|
* 1. Emit `execution_payload_available` event for payload attestation
|
|
@@ -140,6 +152,13 @@ export async function importExecutionPayload(
|
|
|
140
152
|
blockRootHex,
|
|
141
153
|
});
|
|
142
154
|
}
|
|
155
|
+
// The payload chain this block builds on was invalidated, a VALID verdict here would contradict it
|
|
156
|
+
if (protoBlock.executionStatus === ExecutionStatus.Invalid) {
|
|
157
|
+
throw new PayloadError(payloadInput, {
|
|
158
|
+
code: PayloadErrorCode.BLOCK_EXECUTION_INVALID,
|
|
159
|
+
blockRootHex,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
143
162
|
|
|
144
163
|
// 3. Regenerate state for envelope verification
|
|
145
164
|
const blockState = await this.regen
|
|
@@ -318,25 +337,45 @@ export async function importExecutionPayload(
|
|
|
318
337
|
|
|
319
338
|
// 6. Update fork choice, transitions the block's PENDING variant to FULL
|
|
320
339
|
const execStatus = toForkChoiceExecutionStatus(execResult.status);
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
340
|
+
try {
|
|
341
|
+
this.forkChoice.onExecutionPayload(
|
|
342
|
+
blockRootHex,
|
|
343
|
+
blockHashHex,
|
|
344
|
+
envelope.payload.blockNumber,
|
|
345
|
+
envelope.payload.gasLimit,
|
|
346
|
+
execStatus,
|
|
347
|
+
dataAvailabilityStatus
|
|
348
|
+
);
|
|
349
|
+
} catch (e) {
|
|
350
|
+
// The payload chain can be invalidated by a forkchoiceUpdated verdict while the engine was awaited
|
|
351
|
+
if (
|
|
352
|
+
e instanceof ForkChoiceError &&
|
|
353
|
+
e.type.code === ForkChoiceErrorCode.INVALID_BLOCK &&
|
|
354
|
+
e.type.err.code === InvalidBlockCode.PARENT_EXECUTION_INVALID
|
|
355
|
+
) {
|
|
356
|
+
throw new PayloadError(payloadInput, {code: PayloadErrorCode.BLOCK_EXECUTION_INVALID, blockRootHex});
|
|
357
|
+
}
|
|
358
|
+
throw e;
|
|
359
|
+
}
|
|
329
360
|
|
|
330
361
|
// 7. Queue notifyForkchoiceUpdate to engine api
|
|
331
362
|
const head = this.forkChoice.getHead();
|
|
332
|
-
if (
|
|
363
|
+
if (
|
|
364
|
+
!this.opts.disableImportExecutionFcU &&
|
|
365
|
+
blockRootHex === head.blockRoot &&
|
|
366
|
+
// Skip a payload that does not satisfy the inclusion list constraints, fork choice keeps the EMPTY
|
|
367
|
+
// variant as head and the next prepare fcU keeps the engine on the parent payload
|
|
368
|
+
this.forkChoice.isPayloadInclusionListSatisfied(blockRootHex)
|
|
369
|
+
) {
|
|
333
370
|
const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice, this.logger);
|
|
334
371
|
const finalizedBlockHash = getFinalizedExecutionBlockHash(this.forkChoice);
|
|
335
|
-
this.executionEngine
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
372
|
+
this.executionEngine
|
|
373
|
+
.notifyForkchoiceUpdate(fork, blockRootHex, blockHashHex, safeBlockHash, finalizedBlockHash)
|
|
374
|
+
.catch((e) => {
|
|
375
|
+
if (!isErrorAborted(e) && !isQueueErrorAborted(e)) {
|
|
376
|
+
this.logger.error("Error pushing notifyForkchoiceUpdate()", {blockHashHex, finalizedBlockHash}, e);
|
|
377
|
+
}
|
|
378
|
+
});
|
|
340
379
|
}
|
|
341
380
|
|
|
342
381
|
// 8. Record metrics for payload envelope and column sources
|
|
@@ -368,21 +407,3 @@ export async function importExecutionPayload(
|
|
|
368
407
|
delaySec,
|
|
369
408
|
});
|
|
370
409
|
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Process an execution payload envelope end-to-end: wait for DA, then import.
|
|
374
|
-
*
|
|
375
|
-
* Used by the PayloadEnvelopeProcessor queue (gossip / API / unknown-payload sync) — i.e.
|
|
376
|
-
* callers that have NOT already awaited DA themselves. Range sync's inline dispatch in
|
|
377
|
-
* processBlocks skips this wrapper and calls `importExecutionPayload` directly, since
|
|
378
|
-
* `verifyBlocksInEpoch` already awaited DA for the segment.
|
|
379
|
-
*/
|
|
380
|
-
export async function processExecutionPayload(
|
|
381
|
-
this: BeaconChain,
|
|
382
|
-
payloadInput: PayloadEnvelopeInput,
|
|
383
|
-
signal: AbortSignal,
|
|
384
|
-
opts: ImportPayloadOpts = {}
|
|
385
|
-
): Promise<void> {
|
|
386
|
-
const {dataAvailabilityStatuses} = await verifyPayloadsDataAvailability([payloadInput], signal);
|
|
387
|
-
await importExecutionPayload.call(this, payloadInput, dataAvailabilityStatuses[0], opts);
|
|
388
|
-
}
|
|
@@ -7,7 +7,7 @@ import {nextEventLoop} from "../../util/eventLoop.js";
|
|
|
7
7
|
import {JobItemQueue, isQueueErrorAborted} from "../../util/queue/index.js";
|
|
8
8
|
import type {BeaconChain} from "../chain.js";
|
|
9
9
|
import {BlockError, BlockErrorCode, isBlockErrorAborted} from "../errors/index.js";
|
|
10
|
-
import {ForkchoiceCaller} from "../forkChoice/index.js";
|
|
10
|
+
import {ExecutionInvalidSource, ForkchoiceCaller} from "../forkChoice/index.js";
|
|
11
11
|
import {BlockProcessOpts} from "../options.js";
|
|
12
12
|
import {IBlockInput} from "./blockInput/types.js";
|
|
13
13
|
import {importBlock, importsBlockAttestations} from "./importBlock.js";
|
|
@@ -123,7 +123,10 @@ export async function processBlocks(
|
|
|
123
123
|
// and we need to further propagate
|
|
124
124
|
if (segmentExecStatus.execAborted !== null) {
|
|
125
125
|
if (segmentExecStatus.invalidSegmentLVH !== undefined) {
|
|
126
|
-
this.
|
|
126
|
+
this.executionEngine.invalidateExecutionPayloads(
|
|
127
|
+
segmentExecStatus.invalidSegmentLVH,
|
|
128
|
+
ExecutionInvalidSource.blockSegment
|
|
129
|
+
);
|
|
127
130
|
}
|
|
128
131
|
throw segmentExecStatus.execAborted.execError;
|
|
129
132
|
}
|
|
@@ -147,7 +150,7 @@ export async function processBlocks(
|
|
|
147
150
|
proposerBalanceDelta: proposerBalanceDeltas[i],
|
|
148
151
|
indexedAttestations: indexedAttestationsByBlock[i],
|
|
149
152
|
// TODO: Make this param mandatory and capture in gossip
|
|
150
|
-
seenTimestampSec: opts.seenTimestampSec ??
|
|
153
|
+
seenTimestampSec: opts.seenTimestampSec ?? Date.now() / 1000,
|
|
151
154
|
});
|
|
152
155
|
}
|
|
153
156
|
|
|
@@ -292,7 +295,11 @@ async function importPayloadEnvelopesOfKnownBlocks(
|
|
|
292
295
|
return result;
|
|
293
296
|
}
|
|
294
297
|
|
|
295
|
-
const {dataAvailabilityStatuses} = await verifyPayloadsDataAvailability(
|
|
298
|
+
const {dataAvailabilityStatuses} = await verifyPayloadsDataAvailability(
|
|
299
|
+
this.config,
|
|
300
|
+
payloadInputs,
|
|
301
|
+
new AbortController().signal
|
|
302
|
+
);
|
|
296
303
|
for (let i = 0; i < payloadInputs.length; i++) {
|
|
297
304
|
this.logger.debug("Importing payload envelope of known block", {
|
|
298
305
|
slot: payloadInputs[i].slot,
|
|
@@ -1,32 +1,37 @@
|
|
|
1
|
+
import {DataAvailabilityStatus} from "@lodestar/state-transition";
|
|
1
2
|
import {Metrics} from "../../metrics/metrics.js";
|
|
2
3
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
3
4
|
import type {BeaconChain} from "../chain.js";
|
|
4
5
|
import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
|
|
5
|
-
import {
|
|
6
|
+
import {importExecutionPayload} from "./importExecutionPayload.js";
|
|
6
7
|
import {ImportPayloadOpts} from "./types.js";
|
|
8
|
+
import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
|
|
7
9
|
|
|
8
10
|
// TODO GLOAS: Set to be equal to DEFAULT_MAX_PENDING_UNFINALIZED_PAYLOAD_ENVELOPE_WRITES for now
|
|
9
11
|
const QUEUE_MAX_LENGTH = 16;
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
|
-
* PayloadEnvelopeProcessor
|
|
14
|
+
* PayloadEnvelopeProcessor imports payload envelopes in a queued fashion, one after the other.
|
|
13
15
|
*
|
|
14
|
-
* Jobs are
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* and spin re-processing the same root until OOM while the import is blocked (e.g. EL syncing).
|
|
16
|
+
* Jobs are triggered only on envelope arrival (gossip or API). The envelope may reach us before the
|
|
17
|
+
* sampled data columns, the data availability wait runs before the job is queued. Duplicate
|
|
18
|
+
* triggers for the same payloadInput are deduped by sharing the in-flight promise: every caller
|
|
19
|
+
* observes the real import outcome. Resolving duplicates early instead would let
|
|
20
|
+
* BlockInputSync mark a still-pending payload as processed, re-queue it, and spin re-processing
|
|
21
|
+
* the same root until OOM while the import is blocked (e.g. EL syncing).
|
|
21
22
|
*/
|
|
22
23
|
export class PayloadEnvelopeProcessor {
|
|
23
|
-
readonly jobQueue: JobItemQueue<[PayloadEnvelopeInput, ImportPayloadOpts], void>;
|
|
24
|
+
readonly jobQueue: JobItemQueue<[PayloadEnvelopeInput, DataAvailabilityStatus, ImportPayloadOpts], void>;
|
|
24
25
|
private readonly imports = new WeakMap<PayloadEnvelopeInput, Promise<void>>();
|
|
25
26
|
|
|
26
|
-
constructor(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
constructor(
|
|
28
|
+
private readonly chain: BeaconChain,
|
|
29
|
+
metrics: Metrics | null,
|
|
30
|
+
private readonly signal: AbortSignal
|
|
31
|
+
) {
|
|
32
|
+
this.jobQueue = new JobItemQueue<[PayloadEnvelopeInput, DataAvailabilityStatus, ImportPayloadOpts], void>(
|
|
33
|
+
(payloadInput, dataAvailabilityStatus, opts) => {
|
|
34
|
+
return importExecutionPayload.call(chain, payloadInput, dataAvailabilityStatus, opts);
|
|
30
35
|
},
|
|
31
36
|
{maxLength: QUEUE_MAX_LENGTH, noYieldIfOneItem: true, signal},
|
|
32
37
|
metrics?.payloadEnvelopeProcessorQueue ?? undefined
|
|
@@ -35,19 +40,11 @@ export class PayloadEnvelopeProcessor {
|
|
|
35
40
|
|
|
36
41
|
async processPayloadEnvelopeJob(payloadInput: PayloadEnvelopeInput, opts: ImportPayloadOpts = {}): Promise<void> {
|
|
37
42
|
const existing = this.imports.get(payloadInput);
|
|
38
|
-
if (existing) {
|
|
43
|
+
if (existing !== undefined) {
|
|
39
44
|
return existing;
|
|
40
45
|
}
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// Re-check after await, as another call may have queued this payload.
|
|
45
|
-
const queued = this.imports.get(payloadInput);
|
|
46
|
-
if (queued) {
|
|
47
|
-
return queued;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const importPromise = this.jobQueue.push(payloadInput, opts);
|
|
47
|
+
const importPromise = this.waitForDataAndImport(payloadInput, opts);
|
|
51
48
|
this.imports.set(payloadInput, importPromise);
|
|
52
49
|
|
|
53
50
|
try {
|
|
@@ -59,4 +56,18 @@ export class PayloadEnvelopeProcessor {
|
|
|
59
56
|
throw e;
|
|
60
57
|
}
|
|
61
58
|
}
|
|
59
|
+
|
|
60
|
+
private async waitForDataAndImport(payloadInput: PayloadEnvelopeInput, opts: ImportPayloadOpts): Promise<void> {
|
|
61
|
+
const {dataAvailabilityStatuses} = await verifyPayloadsDataAvailability(
|
|
62
|
+
this.chain.config,
|
|
63
|
+
[payloadInput],
|
|
64
|
+
this.signal
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
while (this.jobQueue.jobLen >= QUEUE_MAX_LENGTH) {
|
|
68
|
+
await this.jobQueue.waitForSpace();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return this.jobQueue.push(payloadInput, dataAvailabilityStatuses[0], opts);
|
|
72
|
+
}
|
|
62
73
|
}
|
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import type {ChainForkConfig} from "@lodestar/config";
|
|
2
1
|
import type {BlockExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
|
|
3
|
-
import {
|
|
4
|
-
import {DataAvailabilityStatus, IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
|
|
2
|
+
import {DataAvailabilityStatus, IBeaconStateView} from "@lodestar/state-transition";
|
|
5
3
|
import type {IndexedAttestation, Slot, fulu} from "@lodestar/types";
|
|
6
4
|
import {IBlockInput} from "./blockInput/types.js";
|
|
7
5
|
import {OrphanedPayloadEnvelope} from "./utils/chainSegment.js";
|
|
8
6
|
|
|
9
|
-
export enum GossipedInputType {
|
|
10
|
-
block = "block",
|
|
11
|
-
blob = "blob",
|
|
12
|
-
dataColumn = "data_column",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
7
|
export enum InclusionListSource {
|
|
16
8
|
gossip = "gossip",
|
|
17
9
|
api = "api",
|
|
@@ -23,30 +15,11 @@ type DataColumnData = {
|
|
|
23
15
|
};
|
|
24
16
|
export type DataColumnsCacheMap = Map<number, DataColumnData>;
|
|
25
17
|
|
|
26
|
-
export function blockRequiresBlobs(config: ChainForkConfig, blockSlot: Slot, clockSlot: Slot): boolean {
|
|
27
|
-
return (
|
|
28
|
-
config.getForkSeq(blockSlot) >= ForkSeq.deneb &&
|
|
29
|
-
// Only request blobs if they are recent enough
|
|
30
|
-
computeEpochAtSlot(blockSlot) >= computeEpochAtSlot(clockSlot) - config.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
18
|
export enum AttestationImportOpt {
|
|
35
19
|
Skip,
|
|
36
20
|
Force,
|
|
37
21
|
}
|
|
38
22
|
|
|
39
|
-
export enum BlobSidecarValidation {
|
|
40
|
-
/** When recieved in gossip the blobs are individually verified before import */
|
|
41
|
-
Individual,
|
|
42
|
-
/**
|
|
43
|
-
* Blobs when recieved in req/resp can be fully verified before import
|
|
44
|
-
* but currently used in spec tests where blobs come without proofs and assumed
|
|
45
|
-
* to be valid
|
|
46
|
-
*/
|
|
47
|
-
Full,
|
|
48
|
-
}
|
|
49
|
-
|
|
50
23
|
export type ImportPayloadOpts = {
|
|
51
24
|
/**
|
|
52
25
|
* Set to true when the envelope was already validated upstream (e.g., gossip/API validation):
|
|
@@ -89,8 +62,6 @@ export type ImportBlockOpts = {
|
|
|
89
62
|
* Metadata: `true` if all the signatures including the proposer signature have been verified
|
|
90
63
|
*/
|
|
91
64
|
validSignatures?: boolean;
|
|
92
|
-
/** Set to true if already run `validateBlobSidecars()` sucessfully on the blobs */
|
|
93
|
-
validBlobSidecars?: BlobSidecarValidation;
|
|
94
65
|
/** Seen timestamp seconds */
|
|
95
66
|
seenTimestampSec?: number;
|
|
96
67
|
};
|
|
@@ -109,7 +80,10 @@ export type FullyVerifiedBlock = {
|
|
|
109
80
|
parentBlockSlot: Slot;
|
|
110
81
|
proposerBalanceDelta: number;
|
|
111
82
|
dataAvailabilityStatus: DataAvailabilityStatus;
|
|
112
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* Pre-computed indexed attestations from signature verification to avoid duplicate work.
|
|
85
|
+
* Their `attestingIndices` are in committee order, not sorted, so they are not spec-valid `IndexedAttestation`s.
|
|
86
|
+
*/
|
|
113
87
|
indexedAttestations: IndexedAttestation[];
|
|
114
88
|
/** Seen timestamp seconds */
|
|
115
89
|
seenTimestampSec: number;
|