@lodestar/beacon-node 1.47.0-dev.d2f4b96574 → 1.47.0-dev.d79d81f994
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 +47 -18
- 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 +25 -2
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +2 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/events/index.d.ts +1 -1
- package/lib/api/impl/events/index.d.ts.map +1 -1
- package/lib/api/impl/events/index.js +12 -3
- package/lib/api/impl/events/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +12 -13
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +238 -65
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/api/impl/validator/utils.d.ts +5 -0
- package/lib/api/impl/validator/utils.d.ts.map +1 -1
- package/lib/api/impl/validator/utils.js +18 -12
- package/lib/api/impl/validator/utils.js.map +1 -1
- package/lib/api/rest/base.d.ts.map +1 -1
- package/lib/api/rest/base.js +7 -0
- package/lib/api/rest/base.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +1 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.js +21 -0
- package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +2 -7
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +3 -2
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +11 -9
- 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 +15 -7
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +2 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +6 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +14 -5
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.js +5 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +22 -12
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
- package/lib/chain/bls/index.d.ts +1 -1
- package/lib/chain/bls/index.d.ts.map +1 -1
- package/lib/chain/bls/interface.d.ts +5 -5
- package/lib/chain/bls/interface.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.d.ts +5 -11
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +116 -101
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/jobItem.d.ts +5 -19
- package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
- package/lib/chain/bls/multithread/jobItem.js +10 -65
- package/lib/chain/bls/multithread/jobItem.js.map +1 -1
- package/lib/chain/bls/multithread/types.d.ts +29 -8
- package/lib/chain/bls/multithread/types.d.ts.map +1 -1
- package/lib/chain/bls/multithread/types.js +12 -0
- package/lib/chain/bls/multithread/types.js.map +1 -1
- package/lib/chain/bls/multithread/utils.d.ts +4 -0
- package/lib/chain/bls/multithread/utils.d.ts.map +1 -1
- package/lib/chain/bls/multithread/utils.js +10 -0
- package/lib/chain/bls/multithread/utils.js.map +1 -1
- package/lib/chain/bls/multithread/worker.js +49 -23
- package/lib/chain/bls/multithread/worker.js.map +1 -1
- package/lib/chain/bls/singleThread.d.ts +4 -10
- package/lib/chain/bls/singleThread.d.ts.map +1 -1
- package/lib/chain/bls/singleThread.js +8 -45
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.d.ts +4 -4
- package/lib/chain/bls/utils.d.ts.map +1 -1
- package/lib/chain/bls/utils.js +18 -19
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/builderCircuitBreaker.d.ts +6 -5
- package/lib/chain/builderCircuitBreaker.d.ts.map +1 -1
- package/lib/chain/builderCircuitBreaker.js +28 -15
- package/lib/chain/builderCircuitBreaker.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 +24 -9
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +2 -0
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +6 -1
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/proposerPreferences.d.ts +6 -0
- package/lib/chain/errors/proposerPreferences.d.ts.map +1 -1
- package/lib/chain/errors/proposerPreferences.js +1 -0
- package/lib/chain/errors/proposerPreferences.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +4 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +8 -4
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
- 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 +1 -1
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/deferredVoluntaryExitPool.d.ts +16 -0
- package/lib/chain/opPools/deferredVoluntaryExitPool.d.ts.map +1 -0
- package/lib/chain/opPools/deferredVoluntaryExitPool.js +57 -0
- package/lib/chain/opPools/deferredVoluntaryExitPool.js.map +1 -0
- package/lib/chain/opPools/executionPayloadBidPool.d.ts +7 -2
- package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.js +4 -4
- package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
- package/lib/chain/opPools/index.d.ts +2 -1
- 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.js +3 -3
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.js +1 -1
- 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 +1 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +25 -7
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +3 -25
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +2 -0
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +7 -2
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +5 -2
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +3 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +2 -2
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +5 -5
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/seenCache/seenAttesters.d.ts +9 -5
- package/lib/chain/seenCache/seenAttesters.d.ts.map +1 -1
- package/lib/chain/seenCache/seenAttesters.js +25 -4
- package/lib/chain/seenCache/seenAttesters.js.map +1 -1
- package/lib/chain/seenCache/seenBlockProposers.d.ts +5 -1
- package/lib/chain/seenCache/seenBlockProposers.d.ts.map +1 -1
- package/lib/chain/seenCache/seenBlockProposers.js +10 -3
- package/lib/chain/seenCache/seenBlockProposers.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +28 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +121 -13
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +5 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +6 -0
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +47 -5
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +117 -7
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +3 -3
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +1 -4
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +1 -1
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +21 -7
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts +13 -3
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +147 -12
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +5 -14
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts.map +1 -1
- package/lib/chain/validation/proposerPreferences.js +13 -4
- package/lib/chain/validation/proposerPreferences.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.d.ts +9 -1
- package/lib/chain/validation/voluntaryExit.d.ts.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +46 -1
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/execution/builder/apiClient.d.ts +64 -0
- package/lib/execution/builder/apiClient.d.ts.map +1 -0
- package/lib/execution/builder/apiClient.js +184 -0
- package/lib/execution/builder/apiClient.js.map +1 -0
- package/lib/execution/builder/http.d.ts +10 -7
- package/lib/execution/builder/http.d.ts.map +1 -1
- package/lib/execution/builder/http.js +11 -8
- package/lib/execution/builder/http.js.map +1 -1
- package/lib/execution/builder/validateBid.d.ts +22 -0
- package/lib/execution/builder/validateBid.d.ts.map +1 -0
- package/lib/execution/builder/validateBid.js +111 -0
- package/lib/execution/builder/validateBid.js.map +1 -0
- package/lib/metrics/metrics/beacon.d.ts +3 -3
- package/lib/metrics/metrics/beacon.d.ts.map +1 -1
- package/lib/metrics/metrics/beacon.js +9 -9
- package/lib/metrics/metrics/beacon.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +88 -23
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +164 -52
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +13 -0
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +37 -0
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +10 -2
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +23 -43
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/constants.d.ts +7 -0
- package/lib/network/processor/constants.d.ts.map +1 -0
- package/lib/network/processor/constants.js +7 -0
- package/lib/network/processor/constants.js.map +1 -0
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +38 -7
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipQueues/indexed.d.ts.map +1 -1
- package/lib/network/processor/gossipQueues/indexed.js +0 -1
- package/lib/network/processor/gossipQueues/indexed.js.map +1 -1
- package/lib/network/processor/index.d.ts +3 -0
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +41 -17
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/score.d.ts.map +1 -1
- package/lib/network/reqresp/score.js +5 -11
- package/lib/network/reqresp/score.js.map +1 -1
- package/lib/network/util.d.ts +0 -1
- package/lib/network/util.d.ts.map +1 -1
- package/lib/network/util.js +0 -4
- package/lib/network/util.js.map +1 -1
- package/lib/node/deferredVoluntaryExitPublisher.d.ts +15 -0
- package/lib/node/deferredVoluntaryExitPublisher.d.ts.map +1 -0
- package/lib/node/deferredVoluntaryExitPublisher.js +38 -0
- package/lib/node/deferredVoluntaryExitPublisher.js.map +1 -0
- package/lib/node/nodejs.d.ts +2 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +7 -0
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/range/batch.d.ts +23 -5
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +61 -22
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +2 -1
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +23 -10
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/types.d.ts +32 -0
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +33 -0
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +15 -2
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +234 -63
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +16 -11
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +3 -1
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/package.json +35 -35
- package/src/api/impl/beacon/blocks/index.ts +55 -21
- package/src/api/impl/beacon/pool/index.ts +27 -2
- package/src/api/impl/beacon/state/utils.ts +2 -1
- package/src/api/impl/events/index.ts +12 -4
- package/src/api/impl/lodestar/index.ts +12 -13
- package/src/api/impl/validator/index.ts +300 -69
- package/src/api/impl/validator/utils.ts +30 -15
- package/src/api/rest/base.ts +7 -0
- package/src/chain/archiveStore/archiveStore.ts +1 -1
- package/src/chain/archiveStore/historicalState/metrics.ts +22 -0
- package/src/chain/blocks/importBlock.ts +1 -6
- package/src/chain/blocks/importExecutionPayload.ts +12 -11
- package/src/chain/blocks/index.ts +19 -7
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +8 -2
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +17 -4
- package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +25 -16
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +1 -9
- package/src/chain/bls/index.ts +1 -1
- package/src/chain/bls/interface.ts +7 -3
- package/src/chain/bls/multithread/index.ts +148 -120
- package/src/chain/bls/multithread/jobItem.ts +12 -82
- package/src/chain/bls/multithread/types.ts +33 -8
- package/src/chain/bls/multithread/utils.ts +11 -0
- package/src/chain/bls/multithread/worker.ts +85 -27
- package/src/chain/bls/singleThread.ts +11 -55
- package/src/chain/bls/utils.ts +23 -24
- package/src/chain/builderCircuitBreaker.ts +31 -17
- package/src/chain/chain.ts +27 -7
- package/src/chain/errors/blockError.ts +9 -3
- package/src/chain/errors/proposerPreferences.ts +7 -0
- package/src/chain/forkChoice/index.ts +4 -0
- package/src/chain/interface.ts +8 -3
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/opPools/attestationPool.ts +1 -1
- package/src/chain/opPools/deferredVoluntaryExitPool.ts +65 -0
- package/src/chain/opPools/executionPayloadBidPool.ts +13 -7
- package/src/chain/opPools/index.ts +2 -1
- package/src/chain/opPools/payloadAttestationPool.ts +3 -3
- package/src/chain/opPools/syncCommitteeMessagePool.ts +1 -1
- package/src/chain/opPools/syncContributionAndProofPool.ts +1 -1
- package/src/chain/opPools/utils.ts +1 -1
- package/src/chain/options.ts +1 -1
- package/src/chain/prepareNextSlot.ts +25 -7
- package/src/chain/produceBlock/computeNewStateRoot.ts +3 -38
- package/src/chain/produceBlock/produceBlockBody.ts +14 -1
- package/src/chain/regen/interface.ts +5 -2
- package/src/chain/regen/queued.ts +5 -5
- package/src/chain/seenCache/seenAttesters.ts +31 -5
- package/src/chain/seenCache/seenBlockProposers.ts +13 -3
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +143 -14
- package/src/chain/stateCache/fifoBlockStateCache.ts +8 -1
- package/src/chain/stateCache/persistentCheckpointsCache.ts +133 -8
- package/src/chain/stateCache/types.ts +3 -3
- package/src/chain/validation/attestation.ts +1 -7
- package/src/chain/validation/attesterSlashing.ts +1 -8
- package/src/chain/validation/block.ts +21 -7
- package/src/chain/validation/executionPayloadBid.ts +168 -14
- package/src/chain/validation/executionPayloadEnvelope.ts +0 -1
- package/src/chain/validation/payloadAttestationMessage.ts +6 -17
- package/src/chain/validation/proposerPreferences.ts +15 -5
- package/src/chain/validation/proposerSlashing.ts +1 -1
- package/src/chain/validation/voluntaryExit.ts +59 -2
- package/src/execution/builder/apiClient.ts +244 -0
- package/src/execution/builder/http.ts +11 -11
- package/src/execution/builder/validateBid.ts +166 -0
- package/src/metrics/metrics/beacon.ts +9 -9
- package/src/metrics/metrics/lodestar.ts +178 -58
- package/src/network/gossip/topic.ts +38 -0
- package/src/network/libp2p/index.ts +11 -2
- package/src/network/network.ts +29 -54
- package/src/network/processor/constants.ts +6 -0
- package/src/network/processor/gossipHandlers.ts +41 -5
- package/src/network/processor/gossipQueues/indexed.ts +0 -1
- package/src/network/processor/index.ts +53 -21
- package/src/network/reqresp/score.ts +5 -11
- package/src/network/util.ts +0 -5
- package/src/node/deferredVoluntaryExitPublisher.ts +54 -0
- package/src/node/nodejs.ts +10 -1
- package/src/sync/range/batch.ts +83 -28
- package/src/sync/range/chain.ts +26 -11
- package/src/sync/types.ts +36 -1
- package/src/sync/unknownBlock.ts +273 -70
- package/src/sync/utils/downloadByRange.ts +21 -12
- package/src/sync/utils/downloadByRoot.ts +3 -1
- package/lib/chain/bls/maybeBatch.d.ts +0 -12
- package/lib/chain/bls/maybeBatch.d.ts.map +0 -1
- package/lib/chain/bls/maybeBatch.js +0 -35
- package/lib/chain/bls/maybeBatch.js.map +0 -1
- package/src/chain/bls/maybeBatch.ts +0 -45
|
@@ -52,12 +52,16 @@ import {
|
|
|
52
52
|
import {
|
|
53
53
|
GWEI_TO_WEI,
|
|
54
54
|
TimeoutError,
|
|
55
|
+
byteArrayEquals,
|
|
55
56
|
defer,
|
|
56
57
|
formatWeiToEth,
|
|
57
58
|
fromHex,
|
|
59
|
+
prettyGweiToEth,
|
|
58
60
|
prettyWeiToEth,
|
|
59
61
|
resolveOrRacePromises,
|
|
62
|
+
sleep,
|
|
60
63
|
toHex,
|
|
64
|
+
toPrintableUrl,
|
|
61
65
|
toRootHex,
|
|
62
66
|
} from "@lodestar/utils";
|
|
63
67
|
import {MAX_BUILDER_BOOST_FACTOR} from "@lodestar/validator";
|
|
@@ -72,6 +76,7 @@ import {
|
|
|
72
76
|
SyncCommitteeErrorCode,
|
|
73
77
|
} from "../../../chain/errors/index.js";
|
|
74
78
|
import {ChainEvent, CommonBlockBody} from "../../../chain/index.js";
|
|
79
|
+
import {PooledExecutionPayloadBid} from "../../../chain/opPools/index.js";
|
|
75
80
|
import {PREPARE_NEXT_SLOT_BPS} from "../../../chain/prepareNextSlot.js";
|
|
76
81
|
import {BlockType, ProduceFullDeneb, ProduceFullGloas} from "../../../chain/produceBlock/index.js";
|
|
77
82
|
import {RegenCaller} from "../../../chain/regen/index.js";
|
|
@@ -80,7 +85,9 @@ import {validateApiAggregateAndProof} from "../../../chain/validation/index.js";
|
|
|
80
85
|
import {validateGossipProposerPreferences} from "../../../chain/validation/proposerPreferences.js";
|
|
81
86
|
import {validateSyncCommitteeGossipContributionAndProof} from "../../../chain/validation/syncCommitteeContributionAndProof.js";
|
|
82
87
|
import {ZERO_HASH} from "../../../constants/index.js";
|
|
88
|
+
import {BUILDER_BID_DEADLINE_MS, BuilderApiBid, decodeBuilderUrl} from "../../../execution/builder/apiClient.js";
|
|
83
89
|
import {BuilderStatus, NoBidReceived} from "../../../execution/builder/http.js";
|
|
90
|
+
import {getBuilderBidTotalGwei, validateBuilderApiExecutionPayloadBid} from "../../../execution/builder/validateBid.js";
|
|
84
91
|
import {validateGossipFnRetryUnknownRoot} from "../../../network/processor/gossipHandlers.js";
|
|
85
92
|
import {CommitteeSubscription} from "../../../network/subnets/index.js";
|
|
86
93
|
import {callInNextEventLoop} from "../../../util/eventLoop.js";
|
|
@@ -92,7 +99,12 @@ import {getStateResponseWithRegen} from "../beacon/state/utils.js";
|
|
|
92
99
|
import {ApiError, FailureList, IndexedError, NodeIsSyncing, OnlySupportedByDVT} from "../errors.js";
|
|
93
100
|
import {ApiModules} from "../types.js";
|
|
94
101
|
import {notWhileSyncing} from "../utils.js";
|
|
95
|
-
import {
|
|
102
|
+
import {
|
|
103
|
+
computeSubnetForCommitteesAtSlot,
|
|
104
|
+
getPubkeysForIndices,
|
|
105
|
+
selectBlockProductionSource,
|
|
106
|
+
selectBlockProductionSourceByBoostFactor,
|
|
107
|
+
} from "./utils.js";
|
|
96
108
|
|
|
97
109
|
/**
|
|
98
110
|
* Cutoff time to wait from start of the slot for execution and builder block production apis to resolve.
|
|
@@ -107,6 +119,55 @@ import {computeSubnetForCommitteesAtSlot, getPubkeysForIndices, selectBlockProdu
|
|
|
107
119
|
const BLOCK_PRODUCTION_RACE_CUTOFF_MS = 2_000;
|
|
108
120
|
/** Overall timeout for execution and block production apis */
|
|
109
121
|
const BLOCK_PRODUCTION_RACE_TIMEOUT_MS = 12_000;
|
|
122
|
+
/** Rejection message of the bid block branch when there is no viable bid to commit to */
|
|
123
|
+
const NO_BID_AVAILABLE = "No builder bid available";
|
|
124
|
+
|
|
125
|
+
type BidCandidate = {
|
|
126
|
+
signedBid: gloas.SignedExecutionPayloadBid;
|
|
127
|
+
/** Total payment in Gwei, counting the execution payment at most at the entry's cap */
|
|
128
|
+
totalGwei: bigint;
|
|
129
|
+
boostFactor: bigint;
|
|
130
|
+
url?: string;
|
|
131
|
+
/** Time in milliseconds from the slot start when the bid was received */
|
|
132
|
+
receivedMs: number;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Return the best bid by boosted total payment. A candidate with the max boost factor is
|
|
137
|
+
* preferred over any other regardless of value, ties prefer a builder api bid over the
|
|
138
|
+
* p2p bid, and the earlier received bid between builder api bids.
|
|
139
|
+
*/
|
|
140
|
+
function selectBestBid(candidates: BidCandidate[]): BidCandidate | null {
|
|
141
|
+
const boostedValue = ({totalGwei, boostFactor}: BidCandidate): bigint => boostFactor * totalGwei;
|
|
142
|
+
let best: BidCandidate | null = null;
|
|
143
|
+
for (const candidate of candidates) {
|
|
144
|
+
if (best === null) {
|
|
145
|
+
best = candidate;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
// Preserve max boost preference before comparing bid values
|
|
149
|
+
const candidateIsMaxBoost = candidate.boostFactor === MAX_BUILDER_BOOST_FACTOR;
|
|
150
|
+
const bestIsMaxBoost = best.boostFactor === MAX_BUILDER_BOOST_FACTOR;
|
|
151
|
+
if (candidateIsMaxBoost !== bestIsMaxBoost) {
|
|
152
|
+
if (candidateIsMaxBoost) {
|
|
153
|
+
best = candidate;
|
|
154
|
+
}
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const candidateValue = boostedValue(candidate);
|
|
158
|
+
const bestValue = boostedValue(best);
|
|
159
|
+
if (candidateValue > bestValue) {
|
|
160
|
+
best = candidate;
|
|
161
|
+
} else if (
|
|
162
|
+
candidateValue === bestValue &&
|
|
163
|
+
// A tie prefers a builder api bid over the p2p bid, and the earlier received bid otherwise
|
|
164
|
+
(best.url === undefined || (candidate.url !== undefined && candidate.receivedMs < best.receivedMs))
|
|
165
|
+
) {
|
|
166
|
+
best = candidate;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return best;
|
|
170
|
+
}
|
|
110
171
|
|
|
111
172
|
type ProduceBlockContentsRes = {executionPayloadValue: Wei; consensusBlockValue: Wei} & {
|
|
112
173
|
data: BlockContents;
|
|
@@ -577,8 +638,7 @@ export function getValidatorApi(
|
|
|
577
638
|
builderSelection,
|
|
578
639
|
isBuilderEnabled,
|
|
579
640
|
strictFeeRecipientCheck,
|
|
580
|
-
|
|
581
|
-
builderBoostFactor: `${builderBoostFactor}`,
|
|
641
|
+
builderBoostFactor,
|
|
582
642
|
};
|
|
583
643
|
|
|
584
644
|
logger.verbose("Assembling block with produceEngineOrBuilderBlock", loggerContext);
|
|
@@ -851,9 +911,9 @@ export function getValidatorApi(
|
|
|
851
911
|
randaoReveal,
|
|
852
912
|
graffiti,
|
|
853
913
|
feeRecipient,
|
|
914
|
+
strictFeeRecipientCheck,
|
|
854
915
|
includePayload,
|
|
855
|
-
|
|
856
|
-
builderBoostFactor,
|
|
916
|
+
builderConfig,
|
|
857
917
|
}) {
|
|
858
918
|
const fork = config.getForkName(slot);
|
|
859
919
|
|
|
@@ -861,12 +921,7 @@ export function getValidatorApi(
|
|
|
861
921
|
throw new ApiError(400, `produceBlockV4 not supported for pre-gloas fork=${fork}`);
|
|
862
922
|
}
|
|
863
923
|
|
|
864
|
-
|
|
865
|
-
if (builderSelection === routes.validator.BuilderSelection.BuilderOnly) {
|
|
866
|
-
logger.warn("Builder selection builderonly is no longer supported, treating as builderalways");
|
|
867
|
-
builderSelection = routes.validator.BuilderSelection.BuilderAlways;
|
|
868
|
-
}
|
|
869
|
-
builderBoostFactor = builderBoostFactor ?? BigInt(100);
|
|
924
|
+
const builderBoostFactor = builderConfig.builderBoostFactor;
|
|
870
925
|
if (builderBoostFactor > MAX_BUILDER_BOOST_FACTOR) {
|
|
871
926
|
throw new ApiError(400, `Invalid builderBoostFactor=${builderBoostFactor} > MAX_BUILDER_BOOST_FACTOR`);
|
|
872
927
|
}
|
|
@@ -893,35 +948,117 @@ export function getValidatorApi(
|
|
|
893
948
|
})
|
|
894
949
|
);
|
|
895
950
|
|
|
896
|
-
// TODO GLOAS: add external builder api support when it is implemented
|
|
897
951
|
const isBuildingOnFull = chain.forkChoice.shouldBuildOnFull(parentBlock, slot);
|
|
898
952
|
const bidParentBlockHash = isBuildingOnFull ? parentBlock.executionPayloadBlockHash : parentBlock.parentBlockHash;
|
|
899
|
-
//
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
const
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
953
|
+
// Post-gloas every proposal parent has an execution payload hash
|
|
954
|
+
if (bidParentBlockHash === null) {
|
|
955
|
+
throw new ApiError(500, `Unknown parent block hash for proposal parent ${parentBlockRootHex}`);
|
|
956
|
+
}
|
|
957
|
+
const circuitBreakerActive = chain.builderCircuitBreaker.isActive(slot, parentBlock);
|
|
958
|
+
|
|
959
|
+
// Fire builder API bid requests while the local payload is built, one request per entry.
|
|
960
|
+
// Any entry failure yields no bid and never fails block production.
|
|
961
|
+
let builderApiBidsPromise: Promise<BuilderApiBid[]> = Promise.resolve([]);
|
|
962
|
+
if (builderConfig.builders.length > 0 && !circuitBreakerActive) {
|
|
963
|
+
try {
|
|
964
|
+
const proposerIndex = chain.getHeadState().getBeaconProposer(slot);
|
|
965
|
+
const proposerPubkey = chain.pubkeyCache.getOrThrow(proposerIndex).toBytes();
|
|
966
|
+
builderApiBidsPromise = chain.builderApiClient.getExecutionPayloadBids(
|
|
967
|
+
builderConfig.builders,
|
|
968
|
+
slot,
|
|
969
|
+
fromHex(bidParentBlockHash),
|
|
970
|
+
parentBlockRoot,
|
|
971
|
+
proposerPubkey
|
|
972
|
+
);
|
|
973
|
+
} catch (e) {
|
|
974
|
+
logger.warn("Unable to request builder API bids", {slot}, e as Error);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
907
977
|
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
978
|
+
// A builder bid is expected if builders are configured or a p2p bid was already received.
|
|
979
|
+
// Used by the censorship override which may run before the bid deadline
|
|
980
|
+
const builderBidExpected =
|
|
981
|
+
builderConfig.builders.length > 0 ||
|
|
982
|
+
(!circuitBreakerActive &&
|
|
983
|
+
chain.executionPayloadBidPool.getBestBid(slot, bidParentBlockHash, parentBlockRootHex) !== null);
|
|
984
|
+
|
|
985
|
+
// Select the p2p bid once builders had time to bid up, matching the deadline advertised
|
|
986
|
+
// on builder API bid requests, unless the circuit breaker is active
|
|
987
|
+
const p2pBidPromise: Promise<PooledExecutionPayloadBid | null> = circuitBreakerActive
|
|
988
|
+
? Promise.resolve(null)
|
|
989
|
+
: sleep(Math.max(0, BUILDER_BID_DEADLINE_MS - chain.clock.msFromSlot(slot))).then(() => {
|
|
990
|
+
const p2pBid = chain.executionPayloadBidPool.getBestBid(slot, bidParentBlockHash, parentBlockRootHex);
|
|
991
|
+
// Discard p2p bids below the proposer's configured floor on the total payment.
|
|
992
|
+
// A p2p bid's total is just its value since gossip validation enforces executionPayment=0.
|
|
993
|
+
if (p2pBid !== null && BigInt(p2pBid.signedBid.message.value) < builderConfig.minBid) {
|
|
994
|
+
logger.info("Best p2p bid below configured minimum", {
|
|
995
|
+
slot,
|
|
996
|
+
bidValue: prettyGweiToEth(p2pBid.signedBid.message.value),
|
|
997
|
+
minBid: prettyGweiToEth(builderConfig.minBid),
|
|
998
|
+
});
|
|
999
|
+
return null;
|
|
922
1000
|
}
|
|
923
|
-
|
|
924
|
-
|
|
1001
|
+
return p2pBid;
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
// Candidates are ranked by their boosted counted total payment, the p2p bid is governed
|
|
1005
|
+
// by the top-level factors and each builder API bid by its own entry. Ties prefer the
|
|
1006
|
+
// earliest received builder API bid, so the signed block can be routed back to its
|
|
1007
|
+
// builder directly.
|
|
1008
|
+
const bestBidPromise: Promise<BidCandidate | null> = (async () => {
|
|
1009
|
+
const [builderApiBids, p2pBid] = await Promise.all([builderApiBidsPromise, p2pBidPromise]);
|
|
1010
|
+
|
|
1011
|
+
const candidates = (
|
|
1012
|
+
await Promise.all(
|
|
1013
|
+
builderApiBids.map(async ({url, entry, signedBid, receivedMs}): Promise<BidCandidate | null> => {
|
|
1014
|
+
try {
|
|
1015
|
+
await validateBuilderApiExecutionPayloadBid(chain, signedBid, {
|
|
1016
|
+
slot,
|
|
1017
|
+
parentBlock,
|
|
1018
|
+
parentBlockHash: bidParentBlockHash,
|
|
1019
|
+
parentBlockRoot: parentBlockRootHex,
|
|
1020
|
+
entry,
|
|
1021
|
+
});
|
|
1022
|
+
return {
|
|
1023
|
+
signedBid,
|
|
1024
|
+
totalGwei: getBuilderBidTotalGwei(signedBid.message, entry.maxExecutionPayment),
|
|
1025
|
+
boostFactor: entry.builderBoostFactor,
|
|
1026
|
+
url,
|
|
1027
|
+
receivedMs,
|
|
1028
|
+
};
|
|
1029
|
+
} catch (e) {
|
|
1030
|
+
metrics?.builderApi.bidsDiscarded.inc();
|
|
1031
|
+
logger.warn("Ignoring invalid builder API bid", {slot, builder: toPrintableUrl(url)}, e as Error);
|
|
1032
|
+
return null;
|
|
1033
|
+
}
|
|
1034
|
+
})
|
|
1035
|
+
)
|
|
1036
|
+
).filter((candidate): candidate is BidCandidate => candidate !== null);
|
|
1037
|
+
|
|
1038
|
+
if (p2pBid !== null) {
|
|
1039
|
+
candidates.push({
|
|
1040
|
+
signedBid: p2pBid.signedBid,
|
|
1041
|
+
totalGwei: BigInt(p2pBid.signedBid.message.value),
|
|
1042
|
+
boostFactor: builderConfig.builderBoostFactor,
|
|
1043
|
+
receivedMs: p2pBid.receivedMs,
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
const best = selectBestBid(candidates);
|
|
1048
|
+
if (candidates.length > 0) {
|
|
1049
|
+
logger.debug("Ranked builder bid candidates", {
|
|
1050
|
+
slot,
|
|
1051
|
+
candidates: candidates
|
|
1052
|
+
.map(
|
|
1053
|
+
(candidate) =>
|
|
1054
|
+
`${candidate.url ?? "p2p"}:total=${prettyGweiToEth(candidate.totalGwei)}:boost=${candidate.boostFactor}:received=${candidate.receivedMs}ms`
|
|
1055
|
+
)
|
|
1056
|
+
.join(","),
|
|
1057
|
+
bidSource: best?.url ?? "p2p",
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
return best;
|
|
1061
|
+
})();
|
|
925
1062
|
|
|
926
1063
|
const commonBlockBodyPromise = chain.produceCommonBlockBody({
|
|
927
1064
|
slot,
|
|
@@ -936,13 +1073,11 @@ export function getValidatorApi(
|
|
|
936
1073
|
randaoReveal,
|
|
937
1074
|
graffiti: graffitiBytes,
|
|
938
1075
|
feeRecipient,
|
|
1076
|
+
strictFeeRecipientCheck,
|
|
939
1077
|
commonBlockBodyPromise,
|
|
940
1078
|
};
|
|
941
1079
|
|
|
942
1080
|
metrics?.blockProductionRequests.inc({source: ProducedBlockSource.engine});
|
|
943
|
-
if (builderBid !== null) {
|
|
944
|
-
metrics?.blockProductionRequests.inc({source: ProducedBlockSource.builder});
|
|
945
|
-
}
|
|
946
1081
|
|
|
947
1082
|
const timed = <T>(source: ProducedBlockSource, fn: () => Promise<T>): Promise<T> => {
|
|
948
1083
|
const t = metrics?.blockProductionTime.startTimer();
|
|
@@ -959,23 +1094,25 @@ export function getValidatorApi(
|
|
|
959
1094
|
const enginePromise: ReturnType<typeof chain.produceBlock> = timed(ProducedBlockSource.engine, () =>
|
|
960
1095
|
chain.produceBlock(baseAttrs)
|
|
961
1096
|
).then((engineBlock) => {
|
|
962
|
-
// No need to wait for the bid block if the engine block will always be selected
|
|
963
|
-
// suspected builder censorship,
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
builderBoostFactor === BigInt(0) ||
|
|
967
|
-
builderSelection === routes.validator.BuilderSelection.ExecutionAlways
|
|
968
|
-
) {
|
|
1097
|
+
// No need to wait for the bid block if the engine block will always be selected, either
|
|
1098
|
+
// due to suspected builder censorship, or because no builders are configured and the
|
|
1099
|
+
// boost factor of 0 always prefers the local block over p2p bids
|
|
1100
|
+
if (engineBlock.shouldOverrideBuilder || (builderConfig.builders.length === 0 && builderBoostFactor === 0n)) {
|
|
969
1101
|
controller.abort();
|
|
970
1102
|
}
|
|
971
1103
|
return engineBlock;
|
|
972
1104
|
});
|
|
973
|
-
const
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1105
|
+
const bidBlockPromise: ReturnType<typeof chain.produceBlock> = bestBidPromise.then((candidate) => {
|
|
1106
|
+
if (candidate === null) {
|
|
1107
|
+
throw new Error(NO_BID_AVAILABLE);
|
|
1108
|
+
}
|
|
1109
|
+
metrics?.blockProductionRequests.inc({source: ProducedBlockSource.builder});
|
|
1110
|
+
return timed(ProducedBlockSource.builder, () =>
|
|
1111
|
+
chain.produceBlock({...baseAttrs, builderBid: candidate.signedBid})
|
|
1112
|
+
);
|
|
1113
|
+
});
|
|
977
1114
|
|
|
978
|
-
const [engineResult,
|
|
1115
|
+
const [engineResult, bidBlockResult] = await resolveOrRacePromises([enginePromise, bidBlockPromise], {
|
|
979
1116
|
resolveTimeoutMs: cutoffMs,
|
|
980
1117
|
raceTimeoutMs: BLOCK_PRODUCTION_RACE_TIMEOUT_MS,
|
|
981
1118
|
signal: controller.signal,
|
|
@@ -984,30 +1121,74 @@ export function getValidatorApi(
|
|
|
984
1121
|
let bestResult: typeof engineResult | null = null;
|
|
985
1122
|
let source: ProducedBlockSource = ProducedBlockSource.engine;
|
|
986
1123
|
|
|
1124
|
+
// Resolved instantly whenever the bid branch produced a block
|
|
1125
|
+
const bestBid = bidBlockResult.status === "fulfilled" ? await bestBidPromise : null;
|
|
1126
|
+
|
|
1127
|
+
const logCtx = {
|
|
1128
|
+
slot,
|
|
1129
|
+
parentSlot,
|
|
1130
|
+
parentBlockRoot: parentBlockRootHex,
|
|
1131
|
+
parentBlockHash: parentBlock.executionPayloadBlockHash,
|
|
1132
|
+
fork,
|
|
1133
|
+
builderBoostFactor,
|
|
1134
|
+
strictFeeRecipientCheck,
|
|
1135
|
+
circuitBreakerActive,
|
|
1136
|
+
builderEntries: builderConfig.builders.length,
|
|
1137
|
+
...(bestBid !== null
|
|
1138
|
+
? {
|
|
1139
|
+
bidSource: bestBid.url !== undefined ? toPrintableUrl(bestBid.url) : "p2p",
|
|
1140
|
+
bidValue: prettyGweiToEth(bestBid.signedBid.message.value),
|
|
1141
|
+
bidExecutionPayment: prettyGweiToEth(bestBid.signedBid.message.executionPayment),
|
|
1142
|
+
// The full bid total and the counted total used during bid selection
|
|
1143
|
+
bidTotal: prettyGweiToEth(
|
|
1144
|
+
BigInt(bestBid.signedBid.message.value) + bestBid.signedBid.message.executionPayment
|
|
1145
|
+
),
|
|
1146
|
+
bidCountedTotal: prettyGweiToEth(bestBid.totalGwei),
|
|
1147
|
+
bidBoostFactor: bestBid.boostFactor,
|
|
1148
|
+
builderIndex: bestBid.signedBid.message.builderIndex,
|
|
1149
|
+
bidBlockHash: toRootHex(bestBid.signedBid.message.blockHash),
|
|
1150
|
+
bidReceivedMs: bestBid.receivedMs,
|
|
1151
|
+
}
|
|
1152
|
+
: {}),
|
|
1153
|
+
};
|
|
1154
|
+
|
|
987
1155
|
// handle shouldOverrideBuilder separately
|
|
988
|
-
if (
|
|
1156
|
+
if (
|
|
1157
|
+
engineResult.status === "fulfilled" &&
|
|
1158
|
+
engineResult.value.shouldOverrideBuilder &&
|
|
1159
|
+
(builderBidExpected || bidBlockResult.status === "fulfilled")
|
|
1160
|
+
) {
|
|
989
1161
|
source = ProducedBlockSource.engine;
|
|
990
1162
|
bestResult = engineResult;
|
|
991
1163
|
metrics?.blockProductionSelectionResults.inc({
|
|
992
1164
|
source: ProducedBlockSource.engine,
|
|
993
1165
|
reason: EngineBlockSelectionReason.BuilderCensorship,
|
|
994
1166
|
});
|
|
995
|
-
logger.warn("Selected local block: censorship suspected in builder bid",
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1167
|
+
logger.warn("Selected local block: censorship suspected in builder bid", {
|
|
1168
|
+
...logCtx,
|
|
1169
|
+
durationMs: engineResult.durationMs,
|
|
1170
|
+
...getBlockValueLogInfo(engineResult.value),
|
|
1171
|
+
});
|
|
1172
|
+
} else if (engineResult.status === "fulfilled" && bidBlockResult.status === "fulfilled") {
|
|
1173
|
+
const result = selectBlockProductionSourceByBoostFactor({
|
|
1174
|
+
builderBoostFactor: bestBid?.boostFactor ?? builderBoostFactor,
|
|
1000
1175
|
engineExecutionPayloadValue: engineResult.value.executionPayloadValue,
|
|
1001
|
-
// The bid
|
|
1002
|
-
builderExecutionPayloadValue:
|
|
1176
|
+
// The bid total payment is its value plus its counted executionPayment, in Gwei
|
|
1177
|
+
builderExecutionPayloadValue: (bestBid?.totalGwei ?? 0n) * GWEI_TO_WEI,
|
|
1003
1178
|
});
|
|
1004
1179
|
source = result.source;
|
|
1005
1180
|
metrics?.blockProductionSelectionResults.inc(result);
|
|
1006
|
-
logger.info(`Selected ${source} block`, {
|
|
1007
|
-
|
|
1008
|
-
|
|
1181
|
+
logger.info(`Selected ${source} block`, {
|
|
1182
|
+
reason: result.reason,
|
|
1183
|
+
...logCtx,
|
|
1184
|
+
engineDurationMs: engineResult.durationMs,
|
|
1185
|
+
...getBlockValueLogInfo(engineResult.value, ProducedBlockSource.engine),
|
|
1186
|
+
builderDurationMs: bidBlockResult.durationMs,
|
|
1187
|
+
});
|
|
1188
|
+
bestResult = source === ProducedBlockSource.builder ? bidBlockResult : engineResult;
|
|
1189
|
+
} else if (bidBlockResult.status === "fulfilled") {
|
|
1009
1190
|
source = ProducedBlockSource.builder;
|
|
1010
|
-
bestResult =
|
|
1191
|
+
bestResult = bidBlockResult;
|
|
1011
1192
|
const reason =
|
|
1012
1193
|
engineResult.status === "pending"
|
|
1013
1194
|
? BuilderBlockSelectionReason.EnginePending
|
|
@@ -1016,28 +1197,32 @@ export function getValidatorApi(
|
|
|
1016
1197
|
logger.info("Selected builder bid block: no local block produced", {
|
|
1017
1198
|
reason,
|
|
1018
1199
|
...logCtx,
|
|
1200
|
+
durationMs: bidBlockResult.durationMs,
|
|
1201
|
+
...getBlockValueLogInfo(bidBlockResult.value),
|
|
1019
1202
|
error: engineResult.status === "rejected" ? (engineResult.reason as Error).message : undefined,
|
|
1020
1203
|
});
|
|
1021
1204
|
} else if (engineResult.status === "fulfilled") {
|
|
1022
1205
|
source = ProducedBlockSource.engine;
|
|
1023
1206
|
bestResult = engineResult;
|
|
1024
1207
|
const reason =
|
|
1025
|
-
|
|
1208
|
+
bidBlockResult.status === "rejected" && (bidBlockResult.reason as Error).message === NO_BID_AVAILABLE
|
|
1026
1209
|
? EngineBlockSelectionReason.BuilderNoBid
|
|
1027
|
-
:
|
|
1210
|
+
: bidBlockResult.status === "pending"
|
|
1028
1211
|
? EngineBlockSelectionReason.BuilderPending
|
|
1029
1212
|
: EngineBlockSelectionReason.BuilderError;
|
|
1030
1213
|
metrics?.blockProductionSelectionResults.inc({source: ProducedBlockSource.engine, reason});
|
|
1031
1214
|
logger.info("Selected local block: no builder bid block produced", {
|
|
1032
1215
|
reason,
|
|
1033
1216
|
...logCtx,
|
|
1034
|
-
|
|
1217
|
+
durationMs: engineResult.durationMs,
|
|
1218
|
+
...getBlockValueLogInfo(engineResult.value),
|
|
1219
|
+
error: bidBlockResult.status === "rejected" ? (bidBlockResult.reason as Error).message : undefined,
|
|
1035
1220
|
});
|
|
1036
1221
|
}
|
|
1037
1222
|
|
|
1038
1223
|
if (bestResult === null || bestResult.status !== "fulfilled") {
|
|
1039
1224
|
const engineReason = engineResult.status === "rejected" ? engineResult.reason : engineResult.status;
|
|
1040
|
-
const bidReason =
|
|
1225
|
+
const bidReason = bidBlockResult.status === "rejected" ? bidBlockResult.reason : bidBlockResult.status;
|
|
1041
1226
|
logger.error("Block production failed", {
|
|
1042
1227
|
...logCtx,
|
|
1043
1228
|
engineReason: String(engineReason),
|
|
@@ -1061,7 +1246,10 @@ export function getValidatorApi(
|
|
|
1061
1246
|
root: blockRoot,
|
|
1062
1247
|
});
|
|
1063
1248
|
if (chain.opts.persistProducedBlocks) {
|
|
1064
|
-
void chain.persistBlock(
|
|
1249
|
+
void chain.persistBlock(
|
|
1250
|
+
block,
|
|
1251
|
+
source === ProducedBlockSource.builder ? "produced_builder_block" : "produced_engine_block"
|
|
1252
|
+
);
|
|
1065
1253
|
}
|
|
1066
1254
|
|
|
1067
1255
|
// Include the payload for self-builds unless disabled (stateless flow)
|
|
@@ -1098,7 +1286,13 @@ export function getValidatorApi(
|
|
|
1098
1286
|
|
|
1099
1287
|
return {
|
|
1100
1288
|
data: block as gloas.BeaconBlock,
|
|
1101
|
-
meta: {
|
|
1289
|
+
meta: {
|
|
1290
|
+
version: fork,
|
|
1291
|
+
consensusBlockValue,
|
|
1292
|
+
executionPayloadValue,
|
|
1293
|
+
executionPayloadIncluded: false,
|
|
1294
|
+
builderUrl: source === ProducedBlockSource.builder ? bestBid?.url : undefined,
|
|
1295
|
+
},
|
|
1102
1296
|
};
|
|
1103
1297
|
},
|
|
1104
1298
|
|
|
@@ -1882,6 +2076,43 @@ export function getValidatorApi(
|
|
|
1882
2076
|
}
|
|
1883
2077
|
},
|
|
1884
2078
|
|
|
2079
|
+
async submitBuilderPreferences({builderPreferences}) {
|
|
2080
|
+
const failures: FailureList = [];
|
|
2081
|
+
|
|
2082
|
+
await Promise.all(
|
|
2083
|
+
builderPreferences.map(async (entry, i) => {
|
|
2084
|
+
let builder = Buffer.from(entry.url).toString("utf8");
|
|
2085
|
+
try {
|
|
2086
|
+
const url = decodeBuilderUrl(entry.url);
|
|
2087
|
+
builder = toPrintableUrl(url);
|
|
2088
|
+
const proposerIndex = chain.getHeadState().getBeaconProposer(entry.auth.message.slot);
|
|
2089
|
+
const expectedProposerPubkey = chain.pubkeyCache.getOrThrow(proposerIndex).toBytes();
|
|
2090
|
+
if (!byteArrayEquals(entry.proposerPubkey, expectedProposerPubkey)) {
|
|
2091
|
+
throw new ApiError(
|
|
2092
|
+
400,
|
|
2093
|
+
`Invalid proposer pubkey for builder preferences slot=${entry.auth.message.slot}`
|
|
2094
|
+
);
|
|
2095
|
+
}
|
|
2096
|
+
await chain.builderApiClient.submitBuilderPreferences(url, entry.proposerPubkey, {
|
|
2097
|
+
preferences: {maxExecutionPayment: entry.maxExecutionPayment},
|
|
2098
|
+
auth: entry.auth,
|
|
2099
|
+
});
|
|
2100
|
+
} catch (e) {
|
|
2101
|
+
failures.push({index: i, message: (e as Error).message});
|
|
2102
|
+
logger.verbose(
|
|
2103
|
+
`Error on submitBuilderPreferences [${i}]`,
|
|
2104
|
+
{slot: entry.auth.message.slot, builder},
|
|
2105
|
+
e as Error
|
|
2106
|
+
);
|
|
2107
|
+
}
|
|
2108
|
+
})
|
|
2109
|
+
);
|
|
2110
|
+
|
|
2111
|
+
if (failures.length > 0) {
|
|
2112
|
+
throw new IndexedError("Error submitting builder preferences", failures);
|
|
2113
|
+
}
|
|
2114
|
+
},
|
|
2115
|
+
|
|
1885
2116
|
async getExecutionPayloadEnvelope({slot, beaconBlockRoot}) {
|
|
1886
2117
|
const fork = config.getForkName(slot);
|
|
1887
2118
|
|
|
@@ -59,24 +59,39 @@ export function selectBlockProductionSource({
|
|
|
59
59
|
return {source: ProducedBlockSource.engine, reason: EngineBlockSelectionReason.EnginePreferred};
|
|
60
60
|
|
|
61
61
|
case routes.validator.BuilderSelection.Default:
|
|
62
|
-
case routes.validator.BuilderSelection.MaxProfit:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return {source: ProducedBlockSource.builder, reason: BuilderBlockSelectionReason.BuilderPreferred};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (engineExecutionPayloadValue >= (builderExecutionPayloadValue * builderBoostFactor) / BigInt(100)) {
|
|
72
|
-
return {source: ProducedBlockSource.engine, reason: EngineBlockSelectionReason.BlockValue};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return {source: ProducedBlockSource.builder, reason: BuilderBlockSelectionReason.BlockValue};
|
|
76
|
-
}
|
|
62
|
+
case routes.validator.BuilderSelection.MaxProfit:
|
|
63
|
+
return selectBlockProductionSourceByBoostFactor({
|
|
64
|
+
engineExecutionPayloadValue,
|
|
65
|
+
builderExecutionPayloadValue,
|
|
66
|
+
builderBoostFactor,
|
|
67
|
+
});
|
|
77
68
|
|
|
78
69
|
case routes.validator.BuilderSelection.BuilderAlways:
|
|
79
70
|
case routes.validator.BuilderSelection.BuilderOnly:
|
|
80
71
|
return {source: ProducedBlockSource.builder, reason: BuilderBlockSelectionReason.BuilderPreferred};
|
|
81
72
|
}
|
|
82
73
|
}
|
|
74
|
+
|
|
75
|
+
export function selectBlockProductionSourceByBoostFactor({
|
|
76
|
+
engineExecutionPayloadValue,
|
|
77
|
+
builderExecutionPayloadValue,
|
|
78
|
+
builderBoostFactor,
|
|
79
|
+
}: {
|
|
80
|
+
engineExecutionPayloadValue: bigint;
|
|
81
|
+
builderExecutionPayloadValue: bigint;
|
|
82
|
+
builderBoostFactor: bigint;
|
|
83
|
+
}): BlockSelectionResult {
|
|
84
|
+
if (builderBoostFactor === BigInt(0)) {
|
|
85
|
+
return {source: ProducedBlockSource.engine, reason: EngineBlockSelectionReason.EnginePreferred};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (builderBoostFactor === MAX_BUILDER_BOOST_FACTOR) {
|
|
89
|
+
return {source: ProducedBlockSource.builder, reason: BuilderBlockSelectionReason.BuilderPreferred};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (engineExecutionPayloadValue * 100n >= builderExecutionPayloadValue * builderBoostFactor) {
|
|
93
|
+
return {source: ProducedBlockSource.engine, reason: EngineBlockSelectionReason.BlockValue};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {source: ProducedBlockSource.builder, reason: BuilderBlockSelectionReason.BlockValue};
|
|
97
|
+
}
|
package/src/api/rest/base.ts
CHANGED
|
@@ -104,6 +104,13 @@ export class RestApiServer {
|
|
|
104
104
|
|
|
105
105
|
// To parse our ApiError -> statusCode
|
|
106
106
|
server.setErrorHandler<FastifyError | Error>((err, _req, res) => {
|
|
107
|
+
if (res.raw.headersSent) {
|
|
108
|
+
// A status code can no longer be written, e.g. if a long-lived SSE stream failed mid-flight.
|
|
109
|
+
// End the response instead, else the socket is left open and the client never notices.
|
|
110
|
+
if (!res.raw.writableEnded && !res.raw.destroyed) res.raw.end();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
107
114
|
const stacktraces = opts.stacktraces ? err.stack?.split("\n") : undefined;
|
|
108
115
|
if ("validation" in err && err.validation) {
|
|
109
116
|
const {instancePath = "unknown", message} = err.validation?.[0] ?? {};
|
|
@@ -192,7 +192,7 @@ export class ArchiveStore {
|
|
|
192
192
|
|
|
193
193
|
private onCheckpoint = (): void => {
|
|
194
194
|
const headStateRoot = this.chain.forkChoice.getHead().stateRoot;
|
|
195
|
-
this.chain.regen.
|
|
195
|
+
this.chain.regen.onCheckpoint(
|
|
196
196
|
this.chain.forkChoice.getFinalizedCheckpoint().epoch,
|
|
197
197
|
this.chain.forkChoice.getJustifiedCheckpoint().epoch,
|
|
198
198
|
headStateRoot
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {ForkName} from "@lodestar/params";
|
|
1
2
|
import {
|
|
2
3
|
BeaconStateTransitionMetrics,
|
|
3
4
|
EpochTransitionStep,
|
|
@@ -45,6 +46,27 @@ export function createHistoricalStateTransitionMetrics(
|
|
|
45
46
|
labelNames: ["step"],
|
|
46
47
|
buckets: [0.01, 0.05, 0.1, 0.2, 0.5, 0.75, 1],
|
|
47
48
|
}),
|
|
49
|
+
forkUpgradeTime: metricsRegister.histogram<{fork: ForkName}>({
|
|
50
|
+
name: "lodestar_historical_state_stfn_fork_upgrade_seconds",
|
|
51
|
+
help: "Time to upgrade the state at a fork boundary in seconds",
|
|
52
|
+
labelNames: ["fork"],
|
|
53
|
+
buckets: [0.05, 0.1, 0.25, 0.5, 1, 2, 5, 10, 30],
|
|
54
|
+
}),
|
|
55
|
+
onboardBuildersTime: metricsRegister.histogram({
|
|
56
|
+
name: "lodestar_historical_state_stfn_gloas_onboard_builders_seconds",
|
|
57
|
+
help: "Time spent in onboardBuildersFromPendingDeposits at the gloas fork transition",
|
|
58
|
+
buckets: [0.05, 0.1, 0.25, 0.5, 1, 2, 5, 10, 30],
|
|
59
|
+
}),
|
|
60
|
+
onboardBuildersDeposits: metricsRegister.gauge<{outcome: "onboarded" | "topup" | "kept" | "dropped"}>({
|
|
61
|
+
name: "lodestar_historical_state_stfn_gloas_onboard_builders_deposits",
|
|
62
|
+
help: "Pending deposits handled at the gloas fork transition, by outcome",
|
|
63
|
+
labelNames: ["outcome"],
|
|
64
|
+
}),
|
|
65
|
+
onboardBuildersSignatureChecks: metricsRegister.gauge<{source: "cache" | "verified"}>({
|
|
66
|
+
name: "lodestar_historical_state_stfn_gloas_onboard_builders_signature_checks",
|
|
67
|
+
help: "Builder deposit signature checks at the gloas fork transition, by whether the pre-verify cache served them",
|
|
68
|
+
labelNames: ["source"],
|
|
69
|
+
}),
|
|
48
70
|
processBlockTime: metricsRegister.histogram({
|
|
49
71
|
name: "lodestar_historical_state_stfn_process_block_seconds",
|
|
50
72
|
help: "Time to process a single block in seconds",
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
RootCache,
|
|
23
23
|
computeEpochAtSlot,
|
|
24
24
|
computeTimeAtSlot,
|
|
25
|
-
isStartSlotOfEpoch,
|
|
26
25
|
isStatePostAltair,
|
|
27
26
|
isStatePostBellatrix,
|
|
28
27
|
} from "@lodestar/state-transition";
|
|
@@ -404,11 +403,7 @@ export async function importBlock(
|
|
|
404
403
|
notOverrideFcuReason = NotReorgedReason.NotProposerOfNextSlot;
|
|
405
404
|
}
|
|
406
405
|
} catch (e) {
|
|
407
|
-
|
|
408
|
-
notOverrideFcuReason = NotReorgedReason.AtEpochBoundary;
|
|
409
|
-
} else {
|
|
410
|
-
this.logger.warn("Unable to get beacon proposer. Do not override fcu.", {proposalSlot}, e as Error);
|
|
411
|
-
}
|
|
406
|
+
this.logger.warn("Unable to get beacon proposer. Do not override fcu.", {proposalSlot}, e as Error);
|
|
412
407
|
}
|
|
413
408
|
|
|
414
409
|
if (shouldOverrideFcu) {
|