@lodestar/beacon-node 1.50.0-dev.fef46df5ba → 1.50.0-rc.0
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 +6 -1
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/index.js +13 -0
- package/lib/api/impl/beacon/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +4 -4
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/index.js +28 -6
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +26 -18
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts +1 -0
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +49 -1
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +5 -0
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +14 -24
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +2 -2
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js +5 -7
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.d.ts +2 -2
- package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +1 -1
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.d.ts +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.js +2 -1
- package/lib/chain/archiveStore/utils/pruneHistory.js.map +1 -1
- package/lib/chain/beaconProposerCache.d.ts +6 -0
- package/lib/chain/beaconProposerCache.d.ts.map +1 -1
- package/lib/chain/beaconProposerCache.js +16 -0
- package/lib/chain/beaconProposerCache.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +18 -8
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +7 -7
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts +2 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +5 -4
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
- package/lib/chain/chain.d.ts +10 -5
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +105 -36
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +7 -1
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +5 -0
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/envelopeReconstructionError.d.ts +5 -0
- package/lib/chain/errors/envelopeReconstructionError.d.ts.map +1 -1
- package/lib/chain/errors/envelopeReconstructionError.js +2 -0
- package/lib/chain/errors/envelopeReconstructionError.js.map +1 -1
- package/lib/chain/errors/gossipValidation.d.ts +3 -1
- package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
- package/lib/chain/errors/gossipValidation.js +2 -0
- package/lib/chain/errors/gossipValidation.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +2 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +5 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts +4 -2
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +30 -8
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/opPool.d.ts +5 -4
- package/lib/chain/opPools/opPool.d.ts.map +1 -1
- package/lib/chain/opPools/opPool.js +60 -38
- package/lib/chain/opPools/opPool.js.map +1 -1
- package/lib/chain/opPools/proposerPreferencesPool.d.ts +8 -4
- package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
- package/lib/chain/opPools/proposerPreferencesPool.js +27 -12
- package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
- package/lib/chain/opPools/utils.d.ts +15 -1
- package/lib/chain/opPools/utils.d.ts.map +1 -1
- package/lib/chain/opPools/utils.js +33 -1
- package/lib/chain/opPools/utils.js.map +1 -1
- package/lib/chain/options.d.ts +2 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +1 -1
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +16 -5
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +11 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +46 -30
- package/lib/chain/produceBlock/produceBlockBody.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 +10 -4
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -0
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +21 -0
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +9 -2
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +23 -13
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/shufflingCache.d.ts +18 -8
- package/lib/chain/shufflingCache.d.ts.map +1 -1
- package/lib/chain/shufflingCache.js +72 -18
- package/lib/chain/shufflingCache.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts +4 -4
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +3 -0
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.d.ts +3 -3
- package/lib/chain/validation/proposerSlashing.d.ts.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +3 -0
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +5 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +64 -54
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/db/beacon.d.ts +4 -1
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +6 -1
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/buckets.d.ts +3 -1
- package/lib/db/buckets.d.ts.map +1 -1
- package/lib/db/buckets.js +2 -0
- package/lib/db/buckets.js.map +1 -1
- package/lib/db/interface.d.ts +4 -1
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/earliestAvailableSlot.d.ts +11 -0
- package/lib/db/repositories/earliestAvailableSlot.d.ts.map +1 -0
- package/lib/db/repositories/earliestAvailableSlot.js +19 -0
- package/lib/db/repositories/earliestAvailableSlot.js.map +1 -0
- package/lib/db/repositories/index.d.ts +1 -0
- package/lib/db/repositories/index.d.ts.map +1 -1
- package/lib/db/repositories/index.js +1 -0
- package/lib/db/repositories/index.js.map +1 -1
- package/lib/db/repositories/proposerPreferences.d.ts +14 -0
- package/lib/db/repositories/proposerPreferences.d.ts.map +1 -0
- package/lib/db/repositories/proposerPreferences.js +21 -0
- package/lib/db/repositories/proposerPreferences.js.map +1 -0
- package/lib/db/repositories/proposerSlashing.d.ts +1 -0
- package/lib/db/repositories/proposerSlashing.d.ts.map +1 -1
- package/lib/db/repositories/proposerSlashing.js +5 -1
- package/lib/db/repositories/proposerSlashing.js.map +1 -1
- package/lib/execution/engine/blobVersionedHashes.d.ts +9 -0
- package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -0
- package/lib/execution/engine/blobVersionedHashes.js +74 -0
- package/lib/execution/engine/blobVersionedHashes.js.map +1 -0
- package/lib/execution/engine/disabled.d.ts +0 -2
- package/lib/execution/engine/disabled.d.ts.map +1 -1
- package/lib/execution/engine/disabled.js +0 -6
- package/lib/execution/engine/disabled.js.map +1 -1
- package/lib/execution/engine/http.d.ts +46 -16
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +236 -213
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/index.d.ts +3 -2
- package/lib/execution/engine/index.d.ts.map +1 -1
- package/lib/execution/engine/index.js +33 -8
- package/lib/execution/engine/index.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +2 -4
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/jsonRpcTransport.d.ts +25 -0
- package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -0
- package/lib/execution/engine/jsonRpcTransport.js +158 -0
- package/lib/execution/engine/jsonRpcTransport.js.map +1 -0
- package/lib/execution/engine/mock.d.ts +0 -2
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +0 -8
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/restHttpClient.d.ts +71 -0
- package/lib/execution/engine/restHttpClient.d.ts.map +1 -0
- package/lib/execution/engine/restHttpClient.js +201 -0
- package/lib/execution/engine/restHttpClient.js.map +1 -0
- package/lib/execution/engine/restTransport.d.ts +46 -0
- package/lib/execution/engine/restTransport.d.ts.map +1 -0
- package/lib/execution/engine/restTransport.js +399 -0
- package/lib/execution/engine/restTransport.js.map +1 -0
- package/lib/execution/engine/sszTypes.d.ts +1261 -0
- package/lib/execution/engine/sszTypes.d.ts.map +1 -0
- package/lib/execution/engine/sszTypes.js +216 -0
- package/lib/execution/engine/sszTypes.js.map +1 -0
- package/lib/execution/engine/transport.d.ts +39 -0
- package/lib/execution/engine/transport.d.ts.map +1 -0
- package/lib/execution/engine/transport.js +2 -0
- package/lib/execution/engine/transport.js.map +1 -0
- package/lib/execution/engine/types.d.ts +2 -8
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +24 -57
- 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 +9 -2
- package/lib/execution/engine/utils.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +10 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +22 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/metrics/metrics.d.ts +7 -3
- package/lib/metrics/metrics.d.ts.map +1 -1
- package/lib/metrics/metrics.js +4 -4
- package/lib/metrics/metrics.js.map +1 -1
- package/lib/network/core/events.d.ts +5 -1
- package/lib/network/core/events.d.ts.map +1 -1
- package/lib/network/core/events.js +8 -0
- package/lib/network/core/events.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +67 -68
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipValidatorFn.d.ts +7 -3
- package/lib/network/processor/gossipValidatorFn.d.ts.map +1 -1
- package/lib/network/processor/gossipValidatorFn.js +7 -3
- package/lib/network/processor/gossipValidatorFn.js.map +1 -1
- package/lib/network/processor/index.d.ts +9 -0
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +77 -10
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.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 +27 -4
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/options.d.ts +3 -2
- package/lib/node/options.d.ts.map +1 -1
- package/lib/node/options.js +2 -2
- package/lib/node/options.js.map +1 -1
- package/lib/sync/range/batch.d.ts +11 -5
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +21 -17
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +4 -4
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +12 -6
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/range/range.d.ts.map +1 -1
- package/lib/sync/range/range.js +75 -29
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +5 -2
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +49 -24
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +38 -14
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +84 -39
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/util/asyncIterableToEvents.d.ts +10 -2
- package/lib/util/asyncIterableToEvents.d.ts.map +1 -1
- package/lib/util/asyncIterableToEvents.js +29 -3
- package/lib/util/asyncIterableToEvents.js.map +1 -1
- package/lib/util/execution.d.ts +9 -11
- package/lib/util/execution.d.ts.map +1 -1
- package/lib/util/execution.js +5 -1
- package/lib/util/execution.js.map +1 -1
- package/lib/util/metadata.d.ts.map +1 -1
- package/lib/util/metadata.js +2 -1
- package/lib/util/metadata.js.map +1 -1
- package/package.json +18 -17
- package/src/api/impl/beacon/blocks/index.ts +7 -4
- package/src/api/impl/beacon/index.ts +15 -0
- package/src/api/impl/beacon/pool/index.ts +4 -4
- package/src/api/impl/beacon/state/index.ts +43 -6
- package/src/api/impl/debug/index.ts +28 -19
- package/src/api/impl/validator/index.ts +61 -2
- package/src/chain/archiveStore/archiveStore.ts +19 -25
- package/src/chain/archiveStore/historicalState/getHistoricalState.ts +5 -7
- package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -1
- package/src/chain/archiveStore/historicalState/types.ts +2 -2
- package/src/chain/archiveStore/historicalState/worker.ts +1 -2
- package/src/chain/archiveStore/interface.ts +1 -1
- package/src/chain/archiveStore/utils/pruneHistory.ts +4 -1
- package/src/chain/beaconProposerCache.ts +19 -1
- package/src/chain/blocks/importBlock.ts +21 -7
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
- package/src/chain/blocks/verifyBlock.ts +8 -6
- package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +6 -3
- package/src/chain/chain.ts +135 -38
- package/src/chain/emitter.ts +7 -1
- package/src/chain/errors/envelopeReconstructionError.ts +3 -0
- package/src/chain/errors/gossipValidation.ts +2 -0
- package/src/chain/forkChoice/index.ts +2 -0
- package/src/chain/interface.ts +5 -2
- package/src/chain/opPools/aggregatedAttestationPool.ts +34 -10
- package/src/chain/opPools/opPool.ts +89 -46
- package/src/chain/opPools/proposerPreferencesPool.ts +34 -11
- package/src/chain/opPools/utils.ts +62 -3
- package/src/chain/options.ts +3 -3
- package/src/chain/prepareNextSlot.ts +21 -6
- package/src/chain/produceBlock/computeNewStateRoot.ts +1 -1
- package/src/chain/produceBlock/produceBlockBody.ts +76 -35
- package/src/chain/regen/regen.ts +12 -4
- package/src/chain/seenCache/seenGossipBlockInput.ts +23 -0
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +31 -13
- package/src/chain/shufflingCache.ts +84 -22
- package/src/chain/validation/attesterSlashing.ts +7 -4
- package/src/chain/validation/proposerSlashing.ts +7 -4
- package/src/chain/validatorMonitor.ts +75 -57
- package/src/db/beacon.ts +6 -0
- package/src/db/buckets.ts +2 -0
- package/src/db/interface.ts +4 -0
- package/src/db/repositories/earliestAvailableSlot.ts +19 -0
- package/src/db/repositories/index.ts +1 -0
- package/src/db/repositories/proposerPreferences.ts +23 -0
- package/src/db/repositories/proposerSlashing.ts +6 -1
- package/src/execution/engine/blobVersionedHashes.ts +72 -0
- package/src/execution/engine/disabled.ts +0 -8
- package/src/execution/engine/http.ts +304 -300
- package/src/execution/engine/index.ts +41 -7
- package/src/execution/engine/interface.ts +2 -6
- package/src/execution/engine/jsonRpcTransport.ts +247 -0
- package/src/execution/engine/mock.ts +1 -19
- package/src/execution/engine/restHttpClient.ts +269 -0
- package/src/execution/engine/restTransport.ts +544 -0
- package/src/execution/engine/sszTypes.ts +354 -0
- package/src/execution/engine/transport.ts +61 -0
- package/src/execution/engine/types.ts +34 -84
- package/src/execution/engine/utils.ts +12 -2
- package/src/metrics/metrics/lodestar.ts +23 -0
- package/src/metrics/metrics.ts +21 -6
- package/src/network/core/events.ts +16 -1
- package/src/network/processor/gossipHandlers.ts +98 -81
- package/src/network/processor/gossipValidatorFn.ts +13 -3
- package/src/network/processor/index.ts +89 -10
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +1 -1
- package/src/node/nodejs.ts +35 -3
- package/src/node/options.ts +10 -1
- package/src/sync/range/batch.ts +25 -19
- package/src/sync/range/chain.ts +15 -8
- package/src/sync/range/range.ts +76 -30
- package/src/sync/unknownBlock.ts +62 -25
- package/src/sync/utils/downloadByRange.ts +123 -58
- package/src/util/asyncIterableToEvents.ts +44 -5
- package/src/util/execution.ts +16 -8
- package/src/util/metadata.ts +2 -1
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { ForkName, ForkSeq, SLOTS_PER_EPOCH, isForkPostFulu } from "@lodestar/params";
|
|
2
|
-
import {
|
|
1
|
+
import { ForkName, ForkSeq, SLOTS_PER_EPOCH, isForkPostBellatrix, isForkPostFulu, } from "@lodestar/params";
|
|
2
|
+
import { isErrorAborted } from "@lodestar/utils";
|
|
3
3
|
import { EPOCHS_PER_BATCH } from "../../sync/constants.js";
|
|
4
4
|
import { getLodestarClientVersion } from "../../util/metadata.js";
|
|
5
|
+
import { isQueueErrorAborted } from "../../util/queue/errors.js";
|
|
5
6
|
import { JobItemQueue } from "../../util/queue/index.js";
|
|
6
|
-
import {
|
|
7
|
-
import { ErrorJsonRpcResponse, HttpRpcError, JsonRpcHttpClientEvent
|
|
7
|
+
import { ExecutionEngineState, ExecutionPayloadStatus, } from "./interface.js";
|
|
8
|
+
import { ErrorJsonRpcResponse, HttpRpcError, JsonRpcHttpClientEvent } from "./jsonRpcHttpClient.js";
|
|
8
9
|
import { PayloadIdCache } from "./payloadIdCache.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
10
|
+
import { EngineRestError, EngineRestResponseError, isRetryableEngineRestError } from "./restHttpClient.js";
|
|
11
|
+
import { executionForkName } from "./sszTypes.js";
|
|
12
|
+
import { serializePayloadAttributes } from "./types.js";
|
|
13
|
+
import { getExecutionEngineState } from "./utils.js";
|
|
14
|
+
export const engineApiModes = ["auto", "ssz", "json-rpc"];
|
|
11
15
|
export const defaultExecutionEngineHttpOpts = {
|
|
12
16
|
/**
|
|
13
17
|
* By default ELs host engine api on an auth protected 8551 port, would need a jwt secret to be
|
|
@@ -18,38 +22,26 @@ export const defaultExecutionEngineHttpOpts = {
|
|
|
18
22
|
retries: 2,
|
|
19
23
|
retryDelay: 2000,
|
|
20
24
|
timeout: 12000,
|
|
25
|
+
engineApi: "auto",
|
|
21
26
|
};
|
|
22
27
|
/**
|
|
23
28
|
* Size for the serializing queue for fcUs and new payloads, the max length could be equal to
|
|
24
29
|
* EPOCHS_PER_BATCH * 2 in case new payloads are also not awaited serially
|
|
25
30
|
*/
|
|
26
31
|
const QUEUE_MAX_LENGTH = EPOCHS_PER_BATCH * SLOTS_PER_EPOCH * 2;
|
|
32
|
+
/** Minimum delay between capabilities probes while the execution client is unreachable */
|
|
33
|
+
const REST_PROBE_RETRY_MS = 12_000;
|
|
27
34
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* https://github.com/ethereum/execution-apis/
|
|
31
|
-
*/
|
|
32
|
-
const MAX_VERSIONED_HASHES = 128;
|
|
33
|
-
// Define static options once to prevent extra allocations
|
|
34
|
-
const notifyNewPayloadOpts = { routeId: "notifyNewPayload" };
|
|
35
|
-
const forkchoiceUpdatedV1Opts = { routeId: "forkchoiceUpdated" };
|
|
36
|
-
const getPayloadOpts = { routeId: "getPayload" };
|
|
37
|
-
const getPayloadBodiesByHashOpts = { routeId: "getPayloadBodiesByHash" };
|
|
38
|
-
const getPayloadBodiesByRangeOpts = { routeId: "getPayloadBodiesByRange" };
|
|
39
|
-
const getBlobsV1Opts = { routeId: "getBlobsV1" };
|
|
40
|
-
const getBlobsV2Opts = { routeId: "getBlobsV2" };
|
|
41
|
-
const getClientVersionOpts = { routeId: "getClientVersion" };
|
|
42
|
-
/**
|
|
43
|
-
* based on Ethereum JSON-RPC API and inherits the following properties of this standard:
|
|
44
|
-
* - Supported communication protocols (HTTP and WebSocket)
|
|
45
|
-
* - Message format and encoding notation
|
|
46
|
-
* - Error codes improvement proposal
|
|
35
|
+
* Drives the execution client over the engine API, either the legacy `engine_*` JSON-RPC methods
|
|
36
|
+
* or the REST API with SSZ encoded bodies.
|
|
37
|
+
* https://github.com/ethereum/execution-apis/tree/main/src/engine
|
|
47
38
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
39
|
+
* In `auto` mode a capabilities response from a server without the REST API, a 4xx other than
|
|
40
|
+
* 401/403, selects JSON-RPC until the EL reconnects. Transient discovery failures use JSON-RPC while
|
|
41
|
+
* awaiting another probe; authentication failures fail visibly, malformed capabilities fall back to
|
|
42
|
+
* JSON-RPC with a warning. Forks and blob revisions the EL does not advertise also use JSON-RPC.
|
|
50
43
|
*/
|
|
51
44
|
export class ExecutionEngineHttp {
|
|
52
|
-
rpc;
|
|
53
45
|
opts;
|
|
54
46
|
logger;
|
|
55
47
|
metrics;
|
|
@@ -69,29 +61,41 @@ export class ExecutionEngineHttp {
|
|
|
69
61
|
* the order of new payloads and fcUs is pretty important to EL, this queue will serialize the calls in the
|
|
70
62
|
* order with which we make them.
|
|
71
63
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
64
|
+
queue;
|
|
65
|
+
jsonRpc;
|
|
66
|
+
rest;
|
|
67
|
+
engineApi;
|
|
68
|
+
restSupport = { state: "pending" };
|
|
69
|
+
restProbe = null;
|
|
70
|
+
lastRestProbeMs = Number.NEGATIVE_INFINITY;
|
|
71
|
+
loggedRestFallbacks = new Set();
|
|
72
|
+
constructor({ jsonRpc, rest }, { metrics, signal, logger }, opts) {
|
|
78
73
|
this.opts = opts;
|
|
79
|
-
this.
|
|
74
|
+
this.queue = new JobItemQueue((job) => job(), { maxLength: QUEUE_MAX_LENGTH, maxConcurrency: 1, noYieldIfOneItem: true, signal }, metrics?.engineHttpProcessorQueue);
|
|
80
75
|
this.logger = logger;
|
|
81
76
|
this.metrics = metrics ?? null;
|
|
82
|
-
this.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
this.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
this.updateEngineState(getExecutionEngineState({ targetState: ExecutionEngineState.ONLINE, oldState: this.state }));
|
|
77
|
+
this.jsonRpc = jsonRpc;
|
|
78
|
+
this.rest = rest ?? null;
|
|
79
|
+
this.engineApi = opts?.engineApi ?? "auto";
|
|
80
|
+
if (this.engineApi === "ssz" && this.rest === null) {
|
|
81
|
+
throw Error("REST transport is required for engineApi=ssz");
|
|
82
|
+
}
|
|
83
|
+
// REST errors are handled in withTransport after compatibility fallback.
|
|
84
|
+
this.jsonRpc.emitter.on(JsonRpcHttpClientEvent.ERROR, ({ error }) => {
|
|
85
|
+
this.updateEngineState(getExecutionEngineState({ payloadError: error, oldState: this.state }), error);
|
|
94
86
|
});
|
|
87
|
+
for (const transport of [this.jsonRpc, this.rest]) {
|
|
88
|
+
transport?.emitter.on(JsonRpcHttpClientEvent.RESPONSE, () => {
|
|
89
|
+
if (this.clientVersion === undefined) {
|
|
90
|
+
this.clientVersion = null;
|
|
91
|
+
// This statement should only be called first time receiving response after startup
|
|
92
|
+
this.getClientVersion(getLodestarClientVersion(this.opts)).catch((e) => {
|
|
93
|
+
this.logger.debug("Unable to get execution client version", {}, e);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
this.updateEngineState(getExecutionEngineState({ targetState: ExecutionEngineState.ONLINE, oldState: this.state }));
|
|
97
|
+
});
|
|
98
|
+
}
|
|
95
99
|
}
|
|
96
100
|
/**
|
|
97
101
|
* `engine_newPayloadV1`
|
|
@@ -116,17 +120,7 @@ export class ExecutionEngineHttp {
|
|
|
116
120
|
* If any of the above fails due to errors unrelated to the normal processing flow of the method, client software MUST respond with an error object.
|
|
117
121
|
*/
|
|
118
122
|
async notifyNewPayload(fork, executionPayload, versionedHashes, parentBlockRoot, executionRequests) {
|
|
119
|
-
|
|
120
|
-
? "engine_newPayloadV5"
|
|
121
|
-
: ForkSeq[fork] >= ForkSeq.electra
|
|
122
|
-
? "engine_newPayloadV4"
|
|
123
|
-
: ForkSeq[fork] >= ForkSeq.deneb
|
|
124
|
-
? "engine_newPayloadV3"
|
|
125
|
-
: ForkSeq[fork] >= ForkSeq.capella
|
|
126
|
-
? "engine_newPayloadV2"
|
|
127
|
-
: "engine_newPayloadV1";
|
|
128
|
-
const serializedExecutionPayload = serializeExecutionPayload(fork, executionPayload);
|
|
129
|
-
let engineRequest;
|
|
123
|
+
// Validate before queueing, argument errors must not be reported as an unavailable execution client
|
|
130
124
|
if (ForkSeq[fork] >= ForkSeq.deneb) {
|
|
131
125
|
if (versionedHashes === undefined) {
|
|
132
126
|
throw Error(`versionedHashes required in notifyNewPayload for fork=${fork}`);
|
|
@@ -134,46 +128,26 @@ export class ExecutionEngineHttp {
|
|
|
134
128
|
if (parentBlockRoot === undefined) {
|
|
135
129
|
throw Error(`parentBlockRoot required in notifyNewPayload for fork=${fork}`);
|
|
136
130
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (ForkSeq[fork] >= ForkSeq.electra) {
|
|
140
|
-
if (executionRequests === undefined) {
|
|
141
|
-
throw Error(`executionRequests required in notifyNewPayload for fork=${fork}`);
|
|
142
|
-
}
|
|
143
|
-
const serializedExecutionRequests = serializeExecutionRequests(fork, executionRequests);
|
|
144
|
-
engineRequest = {
|
|
145
|
-
method: ForkSeq[fork] >= ForkSeq.gloas ? "engine_newPayloadV5" : "engine_newPayloadV4",
|
|
146
|
-
params: [
|
|
147
|
-
serializedExecutionPayload,
|
|
148
|
-
serializedVersionedHashes,
|
|
149
|
-
parentBeaconBlockRoot,
|
|
150
|
-
serializedExecutionRequests,
|
|
151
|
-
],
|
|
152
|
-
methodOpts: notifyNewPayloadOpts,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
engineRequest = {
|
|
157
|
-
method: "engine_newPayloadV3",
|
|
158
|
-
params: [serializedExecutionPayload, serializedVersionedHashes, parentBeaconBlockRoot],
|
|
159
|
-
methodOpts: notifyNewPayloadOpts,
|
|
160
|
-
};
|
|
131
|
+
if (ForkSeq[fork] >= ForkSeq.electra && executionRequests === undefined) {
|
|
132
|
+
throw Error(`executionRequests required in notifyNewPayload for fork=${fork}`);
|
|
161
133
|
}
|
|
162
134
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
method,
|
|
167
|
-
params: [serializedExecutionPayload],
|
|
168
|
-
methodOpts: notifyNewPayloadOpts,
|
|
169
|
-
};
|
|
135
|
+
let result;
|
|
136
|
+
try {
|
|
137
|
+
result = await this.enqueue(() => this.withTransport(fork, undefined, (transport) => transport.newPayload(fork, executionPayload, versionedHashes, parentBlockRoot, executionRequests)));
|
|
170
138
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
139
|
+
catch (e) {
|
|
140
|
+
const status = isEngineResponseError(e)
|
|
141
|
+
? ExecutionPayloadStatus.ELERROR
|
|
142
|
+
: ExecutionPayloadStatus.UNAVAILABLE;
|
|
143
|
+
// Only newPayload treats an unreachable execution client, including a timeout, as offline
|
|
144
|
+
const newState = status === ExecutionPayloadStatus.UNAVAILABLE && !isErrorAborted(e) && !isQueueErrorAborted(e)
|
|
145
|
+
? getExecutionEngineState({ payloadStatus: status, oldState: this.state })
|
|
146
|
+
: getExecutionEngineState({ payloadError: e, oldState: this.state });
|
|
147
|
+
this.updateEngineState(newState, e);
|
|
148
|
+
return { status, latestValidHash: null, validationError: e.message };
|
|
149
|
+
}
|
|
150
|
+
const { status, latestValidHash, validationError } = result;
|
|
177
151
|
this.updateEngineState(getExecutionEngineState({ payloadStatus: status, oldState: this.state }));
|
|
178
152
|
switch (status) {
|
|
179
153
|
case ExecutionPayloadStatus.VALID:
|
|
@@ -228,38 +202,21 @@ export class ExecutionEngineHttp {
|
|
|
228
202
|
* If any of the above fails due to errors unrelated to the normal processing flow of the method, client software MUST respond with an error object.
|
|
229
203
|
*/
|
|
230
204
|
async notifyForkchoiceUpdate(fork, headBlockHash, safeBlockHash, finalizedBlockHash, payloadAttributes) {
|
|
231
|
-
|
|
232
|
-
// not provided
|
|
233
|
-
const method = ForkSeq[fork] >= ForkSeq.gloas
|
|
234
|
-
? "engine_forkchoiceUpdatedV4"
|
|
235
|
-
: ForkSeq[fork] >= ForkSeq.deneb
|
|
236
|
-
? "engine_forkchoiceUpdatedV3"
|
|
237
|
-
: ForkSeq[fork] >= ForkSeq.capella
|
|
238
|
-
? "engine_forkchoiceUpdatedV2"
|
|
239
|
-
: "engine_forkchoiceUpdatedV1";
|
|
240
|
-
const payloadAttributesRpc = payloadAttributes ? serializePayloadAttributes(payloadAttributes) : undefined;
|
|
241
|
-
// If we are just fcUing and not asking execution for payload, retry is not required
|
|
242
|
-
// and we can move on, as the next fcU will be issued soon on the new slot
|
|
243
|
-
const fcUReqOpts = payloadAttributes !== undefined ? forkchoiceUpdatedV1Opts : { ...forkchoiceUpdatedV1Opts, retries: 0 };
|
|
244
|
-
const request = this.rpcFetchQueue.push({
|
|
245
|
-
method,
|
|
246
|
-
params: [{ headBlockHash, safeBlockHash, finalizedBlockHash }, payloadAttributesRpc],
|
|
247
|
-
methodOpts: fcUReqOpts,
|
|
248
|
-
});
|
|
249
|
-
const { payloadStatus: { status, latestValidHash: _latestValidHash, validationError }, payloadId, } = await request;
|
|
205
|
+
const { payloadStatus: { status, validationError }, payloadId, } = await this.enqueue(() => this.withTransport(fork, undefined, (transport) => transport.forkchoiceUpdated(fork, headBlockHash, safeBlockHash, finalizedBlockHash, payloadAttributes)));
|
|
250
206
|
this.updateEngineState(getExecutionEngineState({ payloadStatus: status, oldState: this.state }));
|
|
251
207
|
this.metrics?.engineNotifyForkchoiceUpdateResult.inc({ result: status });
|
|
252
208
|
switch (status) {
|
|
253
209
|
case ExecutionPayloadStatus.VALID:
|
|
254
210
|
// if payloadAttributes are provided, a valid payloadId is expected
|
|
255
|
-
if (
|
|
256
|
-
if (
|
|
211
|
+
if (payloadAttributes) {
|
|
212
|
+
if (payloadId === null) {
|
|
257
213
|
throw Error(`Received invalid payloadId=${payloadId}`);
|
|
258
214
|
}
|
|
215
|
+
const payloadAttributesRpc = serializePayloadAttributes(payloadAttributes);
|
|
259
216
|
this.payloadIdCache.add({ headBlockHash, finalizedBlockHash, ...payloadAttributesRpc }, payloadId);
|
|
260
217
|
void this.prunePayloadIdCache();
|
|
261
218
|
}
|
|
262
|
-
return payloadId
|
|
219
|
+
return payloadId;
|
|
263
220
|
case ExecutionPayloadStatus.SYNCING:
|
|
264
221
|
// Throw error on syncing if requested to produce a block, else silently ignore
|
|
265
222
|
if (payloadAttributes) {
|
|
@@ -280,118 +237,154 @@ export class ExecutionEngineHttp {
|
|
|
280
237
|
* 3. Client software MAY stop the corresponding building process after serving this call.
|
|
281
238
|
*/
|
|
282
239
|
async getPayload(fork, payloadId) {
|
|
283
|
-
|
|
284
|
-
switch (fork) {
|
|
285
|
-
case ForkName.phase0:
|
|
286
|
-
case ForkName.altair:
|
|
287
|
-
case ForkName.bellatrix:
|
|
288
|
-
method = "engine_getPayloadV1";
|
|
289
|
-
break;
|
|
290
|
-
case ForkName.capella:
|
|
291
|
-
method = "engine_getPayloadV2";
|
|
292
|
-
break;
|
|
293
|
-
case ForkName.deneb:
|
|
294
|
-
method = "engine_getPayloadV3";
|
|
295
|
-
break;
|
|
296
|
-
case ForkName.electra:
|
|
297
|
-
method = "engine_getPayloadV4";
|
|
298
|
-
break;
|
|
299
|
-
case ForkName.fulu:
|
|
300
|
-
method = "engine_getPayloadV5";
|
|
301
|
-
break;
|
|
302
|
-
default:
|
|
303
|
-
method = "engine_getPayloadV6";
|
|
304
|
-
break;
|
|
305
|
-
}
|
|
306
|
-
const payloadResponse = await this.rpc.fetchWithRetries({
|
|
307
|
-
method,
|
|
308
|
-
params: [payloadId],
|
|
309
|
-
}, getPayloadOpts);
|
|
310
|
-
return parseExecutionPayload(fork, payloadResponse);
|
|
240
|
+
return this.withTransport(fork, undefined, (transport) => transport.getPayload(fork, payloadId));
|
|
311
241
|
}
|
|
312
242
|
async prunePayloadIdCache() {
|
|
313
243
|
this.payloadIdCache.prune();
|
|
314
244
|
}
|
|
315
|
-
async getPayloadBodiesByHash(_fork, blockHashes) {
|
|
316
|
-
const method = "engine_getPayloadBodiesByHashV1";
|
|
317
|
-
assertReqSizeLimit(blockHashes.length, 32);
|
|
318
|
-
const response = await this.rpc.fetchWithRetries({ method, params: [blockHashes] }, getPayloadBodiesByHashOpts);
|
|
319
|
-
return response.map(deserializeExecutionPayloadBody);
|
|
320
|
-
}
|
|
321
245
|
async getPayloadBodiesByHashV2(blockHashes) {
|
|
322
|
-
|
|
323
|
-
assertReqSizeLimit(blockHashes.length, 32);
|
|
324
|
-
const response = await this.rpc.fetchWithRetries({ method, params: [blockHashes] }, getPayloadBodiesByHashOpts);
|
|
325
|
-
return response.map(deserializeExecutionPayloadBodyV2);
|
|
326
|
-
}
|
|
327
|
-
async getPayloadBodiesByRange(_fork, startBlockNumber, blockCount) {
|
|
328
|
-
const method = "engine_getPayloadBodiesByRangeV1";
|
|
329
|
-
assertReqSizeLimit(blockCount, 32);
|
|
330
|
-
const start = numToQuantity(startBlockNumber);
|
|
331
|
-
const count = numToQuantity(blockCount);
|
|
332
|
-
const response = await this.rpc.fetchWithRetries({ method, params: [start, count] }, getPayloadBodiesByRangeOpts);
|
|
333
|
-
return response.map(deserializeExecutionPayloadBody);
|
|
246
|
+
return this.withTransport(ForkName.gloas, undefined, (transport) => transport.getPayloadBodiesByHashV2(blockHashes));
|
|
334
247
|
}
|
|
335
248
|
async getBlobs(fork, versionedHashes, buffers) {
|
|
336
|
-
assertReqSizeLimit(versionedHashes.length, MAX_VERSIONED_HASHES);
|
|
337
|
-
const versionedHashesHex = versionedHashes.map(bytesToData);
|
|
338
249
|
if (isForkPostFulu(fork)) {
|
|
339
|
-
return
|
|
250
|
+
return this.withTransport(undefined, "v2", (transport) => transport.getBlobsV2(versionedHashes, buffers));
|
|
340
251
|
}
|
|
341
|
-
return
|
|
252
|
+
return this.withTransport(undefined, "v1", (transport) => transport.getBlobsV1(versionedHashes));
|
|
342
253
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
method: "engine_getBlobsV1",
|
|
346
|
-
params: [versionedHashesHex],
|
|
347
|
-
}, getBlobsV1Opts);
|
|
348
|
-
const invalidLength = response.length !== versionedHashesHex.length;
|
|
349
|
-
if (invalidLength) {
|
|
350
|
-
const error = `Invalid engine_getBlobsV1 response length=${response.length} versionedHashes=${versionedHashesHex.length}`;
|
|
351
|
-
this.logger.error(error);
|
|
352
|
-
throw Error(error);
|
|
353
|
-
}
|
|
354
|
-
return response.map(deserializeBlobAndProofs);
|
|
254
|
+
enqueue(job) {
|
|
255
|
+
return this.queue.push(job);
|
|
355
256
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Run a call on the selected transport. An execution client that advertises a fork in its
|
|
259
|
+
* capabilities but rejects it with `unsupported-fork` is not spec compliant, keep the node
|
|
260
|
+
* functional by serving that fork over JSON-RPC from then on.
|
|
261
|
+
*/
|
|
262
|
+
async withTransport(fork, blobsRevision, fn) {
|
|
263
|
+
const transport = await this.getTransport(fork, blobsRevision);
|
|
264
|
+
this.metrics?.engineApiRequests.inc({ transport: transport === this.rest ? "ssz" : "json-rpc" });
|
|
265
|
+
try {
|
|
266
|
+
return await fn(transport);
|
|
267
|
+
}
|
|
268
|
+
catch (e) {
|
|
269
|
+
if (fork !== undefined && transport === this.rest && this.engineApi === "auto" && isUnsupportedForkError(e)) {
|
|
270
|
+
this.disableRestForFork(fork, e);
|
|
271
|
+
this.metrics?.engineApiRequests.inc({ transport: "json-rpc" });
|
|
272
|
+
return fn(this.jsonRpc);
|
|
273
|
+
}
|
|
274
|
+
if (transport === this.rest) {
|
|
275
|
+
this.updateEngineState(getExecutionEngineState({ payloadError: e, oldState: this.state }), e);
|
|
361
276
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
277
|
+
throw e;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
disableRestForFork(fork, e) {
|
|
281
|
+
const executionFork = isForkPostBellatrix(fork) ? executionForkName[fork] : null;
|
|
282
|
+
if (this.restSupport.state === "supported" && executionFork !== null) {
|
|
283
|
+
this.restSupport.capabilities.supportedForks.delete(executionFork);
|
|
284
|
+
}
|
|
285
|
+
if (!this.loggedRestFallbacks.has(fork)) {
|
|
286
|
+
this.loggedRestFallbacks.add(fork);
|
|
287
|
+
this.logger.debug("REST engine API rejected an advertised fork, using JSON-RPC until reconnect", {
|
|
288
|
+
fork,
|
|
289
|
+
executionFork,
|
|
290
|
+
status: e.status,
|
|
291
|
+
type: e.type,
|
|
292
|
+
detail: e.detail,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Pick the transport for a call. Fork-scoped calls only go over REST if the execution client
|
|
298
|
+
* advertises that fork, blob requests only if it serves the needed `/blobs/vN` revision.
|
|
299
|
+
*/
|
|
300
|
+
async getTransport(fork, blobsRevision) {
|
|
301
|
+
if (this.rest === null || this.engineApi === "json-rpc") {
|
|
302
|
+
return this.jsonRpc;
|
|
303
|
+
}
|
|
304
|
+
const restSupport = await this.probeRestSupport(this.rest);
|
|
305
|
+
if (restSupport.state === "pending" && restSupport.error) {
|
|
306
|
+
this.updateEngineState(getExecutionEngineState({ payloadError: restSupport.error, oldState: this.state }), restSupport.error);
|
|
307
|
+
throw restSupport.error;
|
|
308
|
+
}
|
|
309
|
+
if (this.engineApi === "ssz") {
|
|
310
|
+
return this.rest;
|
|
311
|
+
}
|
|
312
|
+
if (restSupport.state !== "supported") {
|
|
313
|
+
return this.jsonRpc;
|
|
314
|
+
}
|
|
315
|
+
if (fork !== undefined) {
|
|
316
|
+
const executionFork = isForkPostBellatrix(fork) ? executionForkName[fork] : null;
|
|
317
|
+
if (executionFork === null || !restSupport.capabilities.supportedForks.has(executionFork)) {
|
|
318
|
+
if (!this.loggedRestFallbacks.has(fork)) {
|
|
319
|
+
this.loggedRestFallbacks.add(fork);
|
|
320
|
+
this.logger.debug("Using JSON-RPC for a fork not advertised by the REST engine API", { fork, executionFork });
|
|
365
321
|
}
|
|
322
|
+
return this.jsonRpc;
|
|
366
323
|
}
|
|
367
324
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if (invalidLength) {
|
|
375
|
-
const error = `Invalid engine_getBlobsV2 response length=${response?.length ?? "null"} versionedHashes=${versionedHashesHex.length}`;
|
|
376
|
-
this.logger.error(error);
|
|
377
|
-
throw Error(error);
|
|
325
|
+
if (blobsRevision !== undefined && !restSupport.capabilities.blobsRevisions.has(blobsRevision)) {
|
|
326
|
+
if (!this.loggedRestFallbacks.has(blobsRevision)) {
|
|
327
|
+
this.loggedRestFallbacks.add(blobsRevision);
|
|
328
|
+
this.logger.debug("Using JSON-RPC for a blob revision not advertised by the REST engine API", { blobsRevision });
|
|
329
|
+
}
|
|
330
|
+
return this.jsonRpc;
|
|
378
331
|
}
|
|
379
|
-
|
|
380
|
-
|
|
332
|
+
return this.rest;
|
|
333
|
+
}
|
|
334
|
+
probeRestSupport(rest) {
|
|
335
|
+
if (this.restSupport.state !== "pending") {
|
|
336
|
+
return Promise.resolve(this.restSupport);
|
|
337
|
+
}
|
|
338
|
+
if (this.restProbe !== null) {
|
|
339
|
+
return this.restProbe;
|
|
381
340
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return
|
|
341
|
+
// Transport errors keep the probe pending, do not retry on every call while the EL is down
|
|
342
|
+
if (Date.now() - this.lastRestProbeMs < REST_PROBE_RETRY_MS) {
|
|
343
|
+
return Promise.resolve(this.restSupport);
|
|
385
344
|
}
|
|
386
|
-
|
|
345
|
+
this.restProbe = rest
|
|
346
|
+
.getCapabilities()
|
|
347
|
+
.then((capabilities) => {
|
|
348
|
+
this.restSupport = { state: "supported", capabilities };
|
|
349
|
+
this.loggedRestFallbacks.clear();
|
|
350
|
+
this.logger.debug("Discovered REST engine API capabilities", {
|
|
351
|
+
supportedForks: Array.from(capabilities.supportedForks).join(","),
|
|
352
|
+
blobsRevisions: Array.from(capabilities.blobsRevisions).join(","),
|
|
353
|
+
...capabilities.limits,
|
|
354
|
+
});
|
|
355
|
+
return this.restSupport;
|
|
356
|
+
}, (e) => {
|
|
357
|
+
if (this.engineApi === "auto" && isRestApiAbsent(e)) {
|
|
358
|
+
this.restSupport = { state: "unsupported" };
|
|
359
|
+
this.logger.debug("Execution client does not support engine API over REST, using JSON-RPC", {
|
|
360
|
+
status: e.status,
|
|
361
|
+
type: e.type ?? "unknown",
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
else if (this.engineApi === "auto" && e instanceof EngineRestResponseError) {
|
|
365
|
+
// The REST API answered but cannot be trusted, auto mode must keep the node on a working transport
|
|
366
|
+
this.restSupport = { state: "unsupported" };
|
|
367
|
+
this.logger.warn("Invalid engine API capabilities, using JSON-RPC until reconnect", {}, e);
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
const transient = isRetryableEngineRestError(e);
|
|
371
|
+
this.restSupport = { state: "pending", error: this.engineApi === "auto" && transient ? undefined : e };
|
|
372
|
+
this.logger.debug("Unable to probe engine API capabilities", {
|
|
373
|
+
engineApi: this.engineApi,
|
|
374
|
+
fallback: this.restSupport.error ? "none" : "json-rpc",
|
|
375
|
+
retryAfterMs: REST_PROBE_RETRY_MS,
|
|
376
|
+
}, e);
|
|
377
|
+
}
|
|
378
|
+
return this.restSupport;
|
|
379
|
+
})
|
|
380
|
+
.finally(() => {
|
|
381
|
+
this.restProbe = null;
|
|
382
|
+
this.lastRestProbeMs = Date.now();
|
|
383
|
+
});
|
|
384
|
+
return this.restProbe;
|
|
387
385
|
}
|
|
388
386
|
async getClientVersion(clientVersion) {
|
|
389
|
-
const
|
|
390
|
-
const response = await this.rpc.fetchWithRetries({ method, params: [{ ...clientVersion, commit: `0x${clientVersion.commit}` }] }, getClientVersionOpts);
|
|
391
|
-
const clientVersions = response.map((cv) => {
|
|
392
|
-
const code = cv.code in ClientCode ? ClientCode[cv.code] : ClientCode.XX;
|
|
393
|
-
return { code, name: cv.name, version: cv.version, commit: strip0xPrefix(cv.commit) };
|
|
394
|
-
});
|
|
387
|
+
const clientVersions = await this.withTransport(undefined, undefined, (transport) => transport.getClientVersion(clientVersion));
|
|
395
388
|
if (clientVersions.length === 0) {
|
|
396
389
|
throw Error("Received empty client versions array");
|
|
397
390
|
}
|
|
@@ -399,32 +392,62 @@ export class ExecutionEngineHttp {
|
|
|
399
392
|
this.logger.debug("Execution client version updated", this.clientVersion);
|
|
400
393
|
return clientVersions;
|
|
401
394
|
}
|
|
402
|
-
updateEngineState(newState) {
|
|
395
|
+
updateEngineState(newState, error) {
|
|
403
396
|
const oldState = this.state;
|
|
404
397
|
if (oldState === newState)
|
|
405
398
|
return;
|
|
406
399
|
switch (newState) {
|
|
407
400
|
case ExecutionEngineState.ONLINE:
|
|
408
401
|
this.logger.info("Execution client became online", { oldState, newState });
|
|
402
|
+
if (oldState === ExecutionEngineState.AUTH_FAILED) {
|
|
403
|
+
this.restSupport = { state: "pending" };
|
|
404
|
+
this.lastRestProbeMs = Number.NEGATIVE_INFINITY;
|
|
405
|
+
}
|
|
409
406
|
this.getClientVersion(getLodestarClientVersion(this.opts)).catch((e) => {
|
|
410
407
|
this.logger.debug("Unable to get execution client version", {}, e);
|
|
411
408
|
this.clientVersion = null;
|
|
412
409
|
});
|
|
413
410
|
break;
|
|
414
411
|
case ExecutionEngineState.OFFLINE:
|
|
415
|
-
|
|
412
|
+
// Reprobe before choosing a transport for the next call after a disconnect.
|
|
413
|
+
this.restSupport = { state: "pending" };
|
|
414
|
+
this.lastRestProbeMs = Number.NEGATIVE_INFINITY;
|
|
415
|
+
this.logger.error("Execution client went offline", { oldState, newState }, error);
|
|
416
416
|
break;
|
|
417
417
|
case ExecutionEngineState.SYNCED:
|
|
418
418
|
this.logger.info("Execution client is synced", { oldState, newState });
|
|
419
419
|
break;
|
|
420
420
|
case ExecutionEngineState.SYNCING:
|
|
421
|
-
this.logger.warn("Execution client is syncing", { oldState, newState });
|
|
421
|
+
this.logger.warn(error ? "Execution client request failed" : "Execution client is syncing", { oldState, newState }, error);
|
|
422
422
|
break;
|
|
423
423
|
case ExecutionEngineState.AUTH_FAILED:
|
|
424
|
-
this.logger.error("Execution client authentication failed", { oldState, newState });
|
|
424
|
+
this.logger.error("Execution client authentication failed", { oldState, newState }, error);
|
|
425
425
|
break;
|
|
426
426
|
}
|
|
427
427
|
this.state = newState;
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
|
+
/** The execution client answered, as opposed to being unreachable */
|
|
431
|
+
function isEngineResponseError(e) {
|
|
432
|
+
return (e instanceof HttpRpcError ||
|
|
433
|
+
e instanceof ErrorJsonRpcResponse ||
|
|
434
|
+
e instanceof EngineRestError ||
|
|
435
|
+
e instanceof EngineRestResponseError);
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Legacy JSON-RPC servers and proxies reject the capabilities probe in different ways, a 404 or
|
|
439
|
+
* another client error such as 405. Neither serves the REST API. Authentication failures and
|
|
440
|
+
* transient client errors say nothing about REST support.
|
|
441
|
+
*/
|
|
442
|
+
function isRestApiAbsent(e) {
|
|
443
|
+
return (e instanceof EngineRestError &&
|
|
444
|
+
e.status >= 400 &&
|
|
445
|
+
e.status < 500 &&
|
|
446
|
+
e.status !== 401 &&
|
|
447
|
+
e.status !== 403 &&
|
|
448
|
+
!isRetryableEngineRestError(e));
|
|
449
|
+
}
|
|
450
|
+
function isUnsupportedForkError(e) {
|
|
451
|
+
return e instanceof EngineRestError && e.status === 400 && e.type === "/engine-api/errors/unsupported-fork";
|
|
452
|
+
}
|
|
430
453
|
//# sourceMappingURL=http.js.map
|