@lodestar/beacon-node 1.40.0-dev.1cab20c166 → 1.40.0-dev.2a72cee670
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 +7 -7
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +10 -0
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts +2 -0
- package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.js +7 -3
- package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +28 -0
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +36 -1
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/importBlock.js +1 -1
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +1 -1
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts +2 -2
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +2 -2
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +8 -0
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/bls/multithread/index.d.ts +3 -1
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +5 -3
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/jobItem.d.ts +2 -2
- package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
- package/lib/chain/bls/multithread/jobItem.js +2 -2
- package/lib/chain/bls/multithread/jobItem.js.map +1 -1
- package/lib/chain/bls/singleThread.d.ts +4 -2
- package/lib/chain/bls/singleThread.d.ts.map +1 -1
- package/lib/chain/bls/singleThread.js +4 -2
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.d.ts +2 -2
- package/lib/chain/bls/utils.d.ts.map +1 -1
- package/lib/chain/bls/utils.js +9 -6
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/chain.d.ts +8 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +39 -33
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/attestationError.d.ts +14 -1
- package/lib/chain/errors/attestationError.d.ts.map +1 -1
- package/lib/chain/errors/attestationError.js +8 -0
- package/lib/chain/errors/attestationError.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +48 -0
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -0
- package/lib/chain/errors/executionPayloadBid.js +15 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +48 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/errors/executionPayloadEnvelope.js +16 -0
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -0
- package/lib/chain/errors/index.d.ts +3 -0
- package/lib/chain/errors/index.d.ts.map +1 -1
- package/lib/chain/errors/index.js +3 -0
- package/lib/chain/errors/index.js.map +1 -1
- package/lib/chain/errors/payloadAttestation.d.ts +34 -0
- package/lib/chain/errors/payloadAttestation.d.ts.map +1 -0
- package/lib/chain/errors/payloadAttestation.js +13 -0
- package/lib/chain/errors/payloadAttestation.js.map +1 -0
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +18 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +7 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.d.ts +21 -0
- package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -0
- package/lib/chain/opPools/executionPayloadBidPool.js +57 -0
- package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -0
- package/lib/chain/opPools/index.d.ts +2 -0
- package/lib/chain/opPools/index.d.ts.map +1 -1
- package/lib/chain/opPools/index.js +2 -0
- package/lib/chain/opPools/index.js.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.d.ts +24 -0
- package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -0
- package/lib/chain/opPools/payloadAttestationPool.js +109 -0
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -0
- package/lib/chain/options.d.ts +0 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +0 -1
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +2 -1
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +1 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +1 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +2 -0
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +4 -1
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/index.d.ts +3 -1
- package/lib/chain/seenCache/index.d.ts.map +1 -1
- package/lib/chain/seenCache/index.js +3 -1
- package/lib/chain/seenCache/index.js.map +1 -1
- package/lib/chain/seenCache/seenAttesters.d.ts +5 -0
- package/lib/chain/seenCache/seenAttesters.d.ts.map +1 -1
- package/lib/chain/seenCache/seenAttesters.js +5 -0
- package/lib/chain/seenCache/seenAttesters.js.map +1 -1
- package/lib/chain/seenCache/seenExecutionPayloadBids.d.ts +12 -0
- package/lib/chain/seenCache/seenExecutionPayloadBids.d.ts.map +1 -0
- package/lib/chain/seenCache/seenExecutionPayloadBids.js +30 -0
- package/lib/chain/seenCache/seenExecutionPayloadBids.js.map +1 -0
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts +15 -0
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js +28 -0
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js.map +1 -0
- package/lib/chain/seenCache/seenGossipBlockInput.js +1 -1
- package/lib/chain/stateCache/index.d.ts +0 -2
- package/lib/chain/stateCache/index.d.ts.map +1 -1
- package/lib/chain/stateCache/index.js +0 -2
- package/lib/chain/stateCache/index.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +2 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +3 -0
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/validation/aggregateAndProof.js +35 -14
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts +2 -2
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +27 -8
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +1 -1
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/blobSidecar.d.ts.map +1 -1
- package/lib/chain/validation/blobSidecar.js +2 -2
- package/lib/chain/validation/blobSidecar.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +6 -6
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +2 -2
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts +5 -0
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -0
- package/lib/chain/validation/executionPayloadBid.js +104 -0
- package/lib/chain/validation/executionPayloadBid.js.map +1 -0
- package/lib/chain/validation/executionPayloadEnvelope.d.ts +5 -0
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/validation/executionPayloadEnvelope.js +89 -0
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -0
- package/lib/chain/validation/payloadAttestationMessage.d.ts +9 -0
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -0
- package/lib/chain/validation/payloadAttestationMessage.js +72 -0
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -0
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validation/signatureSets/aggregateAndProof.d.ts +2 -3
- package/lib/chain/validation/signatureSets/aggregateAndProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/aggregateAndProof.js +8 -3
- package/lib/chain/validation/signatureSets/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts +2 -2
- package/lib/chain/validation/signatureSets/contributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/contributionAndProof.js +3 -3
- package/lib/chain/validation/signatureSets/contributionAndProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/selectionProof.d.ts +2 -3
- package/lib/chain/validation/signatureSets/selectionProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/selectionProof.js +8 -3
- package/lib/chain/validation/signatureSets/selectionProof.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts +2 -2
- package/lib/chain/validation/signatureSets/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommittee.js +3 -3
- package/lib/chain/validation/signatureSets/syncCommittee.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.d.ts +1 -2
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.js +2 -2
- package/lib/chain/validation/signatureSets/syncCommitteeContribution.js.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts +2 -2
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.d.ts.map +1 -1
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js +3 -3
- package/lib/chain/validation/signatureSets/syncCommitteeSelectionProof.js.map +1 -1
- package/lib/chain/validation/syncCommittee.js +1 -1
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.d.ts.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +3 -5
- package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +1 -1
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +7 -4
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +20 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +40 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +20 -2
- package/lib/network/gossip/interface.d.ts.map +1 -1
- package/lib/network/gossip/interface.js +3 -0
- package/lib/network/gossip/interface.js.map +1 -1
- package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
- package/lib/network/gossip/scoringParameters.js +38 -2
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +77 -1
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +20 -0
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +9 -0
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +35 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
- package/lib/network/processor/gossipQueues/index.js +16 -0
- package/lib/network/processor/gossipQueues/index.js.map +1 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +3 -0
- package/lib/network/processor/index.js.map +1 -1
- package/lib/sync/backfill/backfill.js +2 -2
- package/lib/sync/backfill/backfill.js.map +1 -1
- package/lib/sync/backfill/verify.d.ts +1 -2
- package/lib/sync/backfill/verify.d.ts.map +1 -1
- package/lib/sync/backfill/verify.js +2 -2
- package/lib/sync/backfill/verify.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +9 -7
- package/src/api/impl/lodestar/index.ts +12 -0
- package/src/api/impl/validator/index.ts +2 -1
- package/src/chain/ColumnReconstructionTracker.ts +8 -4
- package/src/chain/blocks/blockInput/blockInput.ts +45 -2
- package/src/chain/blocks/importBlock.ts +1 -1
- package/src/chain/blocks/verifyBlock.ts +0 -1
- package/src/chain/blocks/verifyBlocksSignatures.ts +4 -12
- package/src/chain/blocks/writeBlockInputToDb.ts +9 -0
- package/src/chain/bls/multithread/index.ts +7 -4
- package/src/chain/bls/multithread/jobItem.ts +7 -3
- package/src/chain/bls/singleThread.ts +5 -3
- package/src/chain/bls/utils.ts +15 -7
- package/src/chain/chain.ts +46 -34
- package/src/chain/errors/attestationError.ts +11 -1
- package/src/chain/errors/executionPayloadBid.ts +35 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +34 -0
- package/src/chain/errors/index.ts +3 -0
- package/src/chain/errors/payloadAttestation.ts +25 -0
- package/src/chain/forkChoice/index.ts +19 -0
- package/src/chain/interface.ts +16 -1
- package/src/chain/opPools/executionPayloadBidPool.ts +77 -0
- package/src/chain/opPools/index.ts +2 -0
- package/src/chain/opPools/payloadAttestationPool.ts +157 -0
- package/src/chain/options.ts +0 -2
- package/src/chain/regen/interface.ts +2 -1
- package/src/chain/regen/queued.ts +1 -2
- package/src/chain/regen/regen.ts +6 -1
- package/src/chain/seenCache/index.ts +3 -1
- package/src/chain/seenCache/seenAttesters.ts +5 -0
- package/src/chain/seenCache/seenExecutionPayloadBids.ts +35 -0
- package/src/chain/seenCache/seenExecutionPayloadEnvelope.ts +34 -0
- package/src/chain/seenCache/seenGossipBlockInput.ts +1 -1
- package/src/chain/stateCache/index.ts +0 -2
- package/src/chain/stateCache/persistentCheckpointsCache.ts +6 -2
- package/src/chain/validation/aggregateAndProof.ts +36 -14
- package/src/chain/validation/attestation.ts +33 -16
- package/src/chain/validation/attesterSlashing.ts +1 -6
- package/src/chain/validation/blobSidecar.ts +1 -6
- package/src/chain/validation/block.ts +6 -6
- package/src/chain/validation/dataColumnSidecar.ts +1 -6
- package/src/chain/validation/executionPayloadBid.ts +141 -0
- package/src/chain/validation/executionPayloadEnvelope.ts +122 -0
- package/src/chain/validation/payloadAttestationMessage.ts +109 -0
- package/src/chain/validation/proposerSlashing.ts +1 -6
- package/src/chain/validation/signatureSets/aggregateAndProof.ts +9 -14
- package/src/chain/validation/signatureSets/contributionAndProof.ts +2 -4
- package/src/chain/validation/signatureSets/selectionProof.ts +9 -9
- package/src/chain/validation/signatureSets/syncCommittee.ts +2 -4
- package/src/chain/validation/signatureSets/syncCommitteeContribution.ts +2 -3
- package/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts +2 -4
- package/src/chain/validation/syncCommittee.ts +1 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +3 -5
- package/src/chain/validation/voluntaryExit.ts +1 -1
- package/src/chain/validatorMonitor.ts +10 -5
- package/src/metrics/metrics/lodestar.ts +40 -0
- package/src/network/gossip/interface.ts +17 -0
- package/src/network/gossip/scoringParameters.ts +44 -2
- package/src/network/gossip/topic.ts +21 -0
- package/src/network/peers/peerManager.ts +11 -0
- package/src/network/processor/gossipHandlers.ts +49 -1
- package/src/network/processor/gossipQueues/index.ts +16 -0
- package/src/network/processor/index.ts +3 -0
- package/src/sync/backfill/backfill.ts +2 -2
- package/src/sync/backfill/verify.ts +2 -3
- package/lib/chain/stateCache/blockStateCacheImpl.d.ts +0 -54
- package/lib/chain/stateCache/blockStateCacheImpl.d.ts.map +0 -1
- package/lib/chain/stateCache/blockStateCacheImpl.js +0 -130
- package/lib/chain/stateCache/blockStateCacheImpl.js.map +0 -1
- package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts +0 -60
- package/lib/chain/stateCache/inMemoryCheckpointsCache.d.ts.map +0 -1
- package/lib/chain/stateCache/inMemoryCheckpointsCache.js +0 -156
- package/lib/chain/stateCache/inMemoryCheckpointsCache.js.map +0 -1
- package/src/chain/stateCache/blockStateCacheImpl.ts +0 -149
- package/src/chain/stateCache/inMemoryCheckpointsCache.ts +0 -192
|
@@ -139,6 +139,14 @@ export enum AttestationErrorCode {
|
|
|
139
139
|
* Electra: Attester not in committee
|
|
140
140
|
*/
|
|
141
141
|
ATTESTER_NOT_IN_COMMITTEE = "ATTESTATION_ERROR_ATTESTER_NOT_IN_COMMITTEE",
|
|
142
|
+
/**
|
|
143
|
+
* Gloas: Invalid attestationData index: is non-zero and non-one
|
|
144
|
+
*/
|
|
145
|
+
INVALID_PAYLOAD_STATUS_VALUE = "ATTESTATION_ERROR_INVALID_PAYLOAD_STATUS_VALUE",
|
|
146
|
+
/**
|
|
147
|
+
* Gloas: Current slot attestation is marking payload as present
|
|
148
|
+
*/
|
|
149
|
+
PREMATURELY_INDICATED_PAYLOAD_PRESENT = "ATTESTATION_ERROR_PREMATURELY_INDICATED_PAYLOAD_PRESENT",
|
|
142
150
|
}
|
|
143
151
|
|
|
144
152
|
export type AttestationErrorType =
|
|
@@ -175,7 +183,9 @@ export type AttestationErrorType =
|
|
|
175
183
|
| {code: AttestationErrorCode.TOO_MANY_SKIPPED_SLOTS; headBlockSlot: Slot; attestationSlot: Slot}
|
|
176
184
|
| {code: AttestationErrorCode.NOT_EXACTLY_ONE_COMMITTEE_BIT_SET}
|
|
177
185
|
| {code: AttestationErrorCode.NON_ZERO_ATTESTATION_DATA_INDEX}
|
|
178
|
-
| {code: AttestationErrorCode.ATTESTER_NOT_IN_COMMITTEE}
|
|
186
|
+
| {code: AttestationErrorCode.ATTESTER_NOT_IN_COMMITTEE}
|
|
187
|
+
| {code: AttestationErrorCode.INVALID_PAYLOAD_STATUS_VALUE; attDataIndex: number}
|
|
188
|
+
| {code: AttestationErrorCode.PREMATURELY_INDICATED_PAYLOAD_PRESENT};
|
|
179
189
|
|
|
180
190
|
export class AttestationError extends GossipActionError<AttestationErrorType> {
|
|
181
191
|
getMetadata(): Record<string, string | number | null> {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {BuilderIndex, RootHex, Slot} from "@lodestar/types";
|
|
2
|
+
import {GossipActionError} from "./gossipValidation.ts";
|
|
3
|
+
|
|
4
|
+
export enum ExecutionPayloadBidErrorCode {
|
|
5
|
+
BUILDER_NOT_ELIGIBLE = "EXECUTION_PAYLOAD_BID_ERROR_BUILDER_NOT_ELIGIBLE",
|
|
6
|
+
NON_ZERO_EXECUTION_PAYMENT = "EXECUTION_PAYLOAD_BID_ERROR_NON_ZERO_EXECUTION_PAYMENT",
|
|
7
|
+
BID_ALREADY_KNOWN = "EXECUTION_PAYLOAD_BID_ERROR_BID_ALREADY_KNOWN",
|
|
8
|
+
BID_TOO_LOW = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_LOW",
|
|
9
|
+
BID_TOO_HIGH = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_HIGH",
|
|
10
|
+
UNKNOWN_BLOCK_ROOT = "EXECUTION_PAYLOAD_BID_ERROR_UNKNOWN_BLOCK_ROOT",
|
|
11
|
+
INVALID_SLOT = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SLOT",
|
|
12
|
+
INVALID_SIGNATURE = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SIGNATURE",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type ExecutionPayloadBidErrorType =
|
|
16
|
+
| {code: ExecutionPayloadBidErrorCode.BUILDER_NOT_ELIGIBLE; builderIndex: BuilderIndex}
|
|
17
|
+
| {
|
|
18
|
+
code: ExecutionPayloadBidErrorCode.NON_ZERO_EXECUTION_PAYMENT;
|
|
19
|
+
builderIndex: BuilderIndex;
|
|
20
|
+
executionPayment: number;
|
|
21
|
+
}
|
|
22
|
+
| {
|
|
23
|
+
code: ExecutionPayloadBidErrorCode.BID_ALREADY_KNOWN;
|
|
24
|
+
builderIndex: BuilderIndex;
|
|
25
|
+
slot: Slot;
|
|
26
|
+
parentBlockRoot: RootHex;
|
|
27
|
+
parentBlockHash: RootHex;
|
|
28
|
+
}
|
|
29
|
+
| {code: ExecutionPayloadBidErrorCode.BID_TOO_LOW; bidValue: number; currentHighestBid: number}
|
|
30
|
+
| {code: ExecutionPayloadBidErrorCode.BID_TOO_HIGH; bidValue: number; builderBalance: number}
|
|
31
|
+
| {code: ExecutionPayloadBidErrorCode.UNKNOWN_BLOCK_ROOT; parentBlockRoot: RootHex}
|
|
32
|
+
| {code: ExecutionPayloadBidErrorCode.INVALID_SLOT; builderIndex: BuilderIndex; slot: Slot}
|
|
33
|
+
| {code: ExecutionPayloadBidErrorCode.INVALID_SIGNATURE; builderIndex: BuilderIndex; slot: Slot};
|
|
34
|
+
|
|
35
|
+
export class ExecutionPayloadBidError extends GossipActionError<ExecutionPayloadBidErrorType> {}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {BuilderIndex, RootHex, Slot} from "@lodestar/types";
|
|
2
|
+
import {GossipActionError} from "./gossipValidation.js";
|
|
3
|
+
|
|
4
|
+
export enum ExecutionPayloadEnvelopeErrorCode {
|
|
5
|
+
BELONG_TO_FINALIZED_BLOCK = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BELONG_TO_FINALIZED_BLOCK",
|
|
6
|
+
BLOCK_ROOT_UNKNOWN = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BLOCK_ROOT_UNKNOWN",
|
|
7
|
+
ENVELOPE_ALREADY_KNOWN = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_ALREADY_KNOWN",
|
|
8
|
+
INVALID_BLOCK = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_INVALID_BLOCK",
|
|
9
|
+
SLOT_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_SLOT_MISMATCH",
|
|
10
|
+
BUILDER_INDEX_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BUILDER_INDEX_MISMATCH",
|
|
11
|
+
BLOCK_HASH_MISMATCH = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_BLOCK_HASH_MISMATCH",
|
|
12
|
+
INVALID_SIGNATURE = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_INVALID_SIGNATURE",
|
|
13
|
+
CACHE_FAIL = "EXECUTION_PAYLOAD_ENVELOPE_ERROR_CACHE_FAIL",
|
|
14
|
+
}
|
|
15
|
+
export type ExecutionPayloadEnvelopeErrorType =
|
|
16
|
+
| {code: ExecutionPayloadEnvelopeErrorCode.BELONG_TO_FINALIZED_BLOCK; envelopeSlot: Slot; finalizedSlot: Slot}
|
|
17
|
+
| {code: ExecutionPayloadEnvelopeErrorCode.BLOCK_ROOT_UNKNOWN; blockRoot: RootHex}
|
|
18
|
+
| {
|
|
19
|
+
code: ExecutionPayloadEnvelopeErrorCode.ENVELOPE_ALREADY_KNOWN;
|
|
20
|
+
blockRoot: RootHex;
|
|
21
|
+
slot: Slot;
|
|
22
|
+
}
|
|
23
|
+
| {code: ExecutionPayloadEnvelopeErrorCode.INVALID_BLOCK; blockRoot: RootHex}
|
|
24
|
+
| {code: ExecutionPayloadEnvelopeErrorCode.SLOT_MISMATCH; envelopeSlot: Slot; blockSlot: Slot}
|
|
25
|
+
| {
|
|
26
|
+
code: ExecutionPayloadEnvelopeErrorCode.BUILDER_INDEX_MISMATCH;
|
|
27
|
+
envelopeBuilderIndex: BuilderIndex;
|
|
28
|
+
bidBuilderIndex: BuilderIndex;
|
|
29
|
+
}
|
|
30
|
+
| {code: ExecutionPayloadEnvelopeErrorCode.BLOCK_HASH_MISMATCH; envelopeBlockHash: RootHex; bidBlockHash: RootHex}
|
|
31
|
+
| {code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE}
|
|
32
|
+
| {code: ExecutionPayloadEnvelopeErrorCode.CACHE_FAIL; blockRoot: RootHex};
|
|
33
|
+
|
|
34
|
+
export class ExecutionPayloadEnvelopeError extends GossipActionError<ExecutionPayloadEnvelopeErrorType> {}
|
|
@@ -4,7 +4,10 @@ export * from "./blobSidecarError.js";
|
|
|
4
4
|
export * from "./blockError.js";
|
|
5
5
|
export * from "./blsToExecutionChangeError.js";
|
|
6
6
|
export * from "./dataColumnSidecarError.js";
|
|
7
|
+
export * from "./executionPayloadBid.js";
|
|
8
|
+
export * from "./executionPayloadEnvelope.js";
|
|
7
9
|
export * from "./gossipValidation.js";
|
|
10
|
+
export * from "./payloadAttestation.js";
|
|
8
11
|
export * from "./proposerSlashingError.js";
|
|
9
12
|
export * from "./syncCommitteeError.js";
|
|
10
13
|
export * from "./voluntaryExitError.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {RootHex, Slot, ValidatorIndex} from "@lodestar/types";
|
|
2
|
+
import {GossipActionError} from "./gossipValidation.ts";
|
|
3
|
+
|
|
4
|
+
export enum PayloadAttestationErrorCode {
|
|
5
|
+
NOT_CURRENT_SLOT = "PAYLOAD_ATTESTATION_ERROR_NOT_CURRENT_SLOT",
|
|
6
|
+
PAYLOAD_ATTESTATION_ALREADY_KNOWN = "PAYLOAD_ATTESTATION_ERROR_PAYLOAD_ATTESTATION_ALREADY_KNOWN",
|
|
7
|
+
UNKNOWN_BLOCK_ROOT = "PAYLOAD_ATTESTATION_ERROR_UNKNOWN_BLOCK_ROOT",
|
|
8
|
+
INVALID_BLOCK = "PAYLOAD_ATTESTATION_ERROR_INVALID_BLOCK",
|
|
9
|
+
INVALID_ATTESTER = "PAYLOAD_ATTESTATION_ERROR_INVALID_ATTESTER",
|
|
10
|
+
INVALID_SIGNATURE = "PAYLOAD_ATTESTATION_ERROR_INVALID_SIGNATURE",
|
|
11
|
+
}
|
|
12
|
+
export type PayloadAttestationErrorType =
|
|
13
|
+
| {code: PayloadAttestationErrorCode.NOT_CURRENT_SLOT; currentSlot: Slot; slot: Slot}
|
|
14
|
+
| {
|
|
15
|
+
code: PayloadAttestationErrorCode.PAYLOAD_ATTESTATION_ALREADY_KNOWN;
|
|
16
|
+
validatorIndex: ValidatorIndex;
|
|
17
|
+
slot: Slot;
|
|
18
|
+
blockRoot: RootHex;
|
|
19
|
+
}
|
|
20
|
+
| {code: PayloadAttestationErrorCode.UNKNOWN_BLOCK_ROOT; blockRoot: RootHex}
|
|
21
|
+
| {code: PayloadAttestationErrorCode.INVALID_BLOCK; blockRoot: RootHex}
|
|
22
|
+
| {code: PayloadAttestationErrorCode.INVALID_ATTESTER; attesterIndex: ValidatorIndex}
|
|
23
|
+
| {code: PayloadAttestationErrorCode.INVALID_SIGNATURE};
|
|
24
|
+
|
|
25
|
+
export class PayloadAttestationError extends GossipActionError<PayloadAttestationErrorType> {}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
12
12
|
import {
|
|
13
13
|
CachedBeaconStateAllForks,
|
|
14
|
+
CachedBeaconStateGloas,
|
|
14
15
|
DataAvailabilityStatus,
|
|
15
16
|
computeAnchorCheckpoint,
|
|
16
17
|
computeEpochAtSlot,
|
|
@@ -144,6 +145,15 @@ export function initializeForkChoiceFromFinalizedState(
|
|
|
144
145
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
|
145
146
|
|
|
146
147
|
dataAvailabilityStatus: DataAvailabilityStatus.PreData,
|
|
148
|
+
...(computeEpochAtSlot(blockHeader.slot) < state.config.GLOAS_FORK_EPOCH
|
|
149
|
+
? {
|
|
150
|
+
builderIndex: undefined,
|
|
151
|
+
blockHashHex: undefined,
|
|
152
|
+
}
|
|
153
|
+
: {
|
|
154
|
+
builderIndex: (state as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex,
|
|
155
|
+
blockHashHex: toRootHex((state as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash),
|
|
156
|
+
}),
|
|
147
157
|
},
|
|
148
158
|
currentSlot
|
|
149
159
|
),
|
|
@@ -225,6 +235,15 @@ export function initializeForkChoiceFromUnfinalizedState(
|
|
|
225
235
|
: {executionPayloadBlockHash: null, executionStatus: ExecutionStatus.PreMerge}),
|
|
226
236
|
|
|
227
237
|
dataAvailabilityStatus: DataAvailabilityStatus.PreData,
|
|
238
|
+
...(computeEpochAtSlot(blockHeader.slot) < unfinalizedState.config.GLOAS_FORK_EPOCH
|
|
239
|
+
? {
|
|
240
|
+
builderIndex: undefined,
|
|
241
|
+
blockHashHex: undefined,
|
|
242
|
+
}
|
|
243
|
+
: {
|
|
244
|
+
builderIndex: (unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.builderIndex,
|
|
245
|
+
blockHashHex: toRootHex((unfinalizedState as CachedBeaconStateGloas).latestExecutionPayloadBid.blockHash),
|
|
246
|
+
}),
|
|
228
247
|
};
|
|
229
248
|
|
|
230
249
|
const parentSlot = blockHeader.slot - 1;
|
package/src/chain/interface.ts
CHANGED
|
@@ -46,7 +46,14 @@ import {ForkchoiceCaller} from "./forkChoice/index.js";
|
|
|
46
46
|
import {GetBlobsTracker} from "./GetBlobsTracker.js";
|
|
47
47
|
import {LightClientServer} from "./lightClient/index.js";
|
|
48
48
|
import {AggregatedAttestationPool} from "./opPools/aggregatedAttestationPool.js";
|
|
49
|
-
import {
|
|
49
|
+
import {
|
|
50
|
+
AttestationPool,
|
|
51
|
+
ExecutionPayloadBidPool,
|
|
52
|
+
OpPool,
|
|
53
|
+
PayloadAttestationPool,
|
|
54
|
+
SyncCommitteeMessagePool,
|
|
55
|
+
SyncContributionAndProofPool,
|
|
56
|
+
} from "./opPools/index.js";
|
|
50
57
|
import {IChainOptions} from "./options.js";
|
|
51
58
|
import {AssembledBlockType, BlockAttributes, BlockType, ProduceResult} from "./produceBlock/produceBlockBody.js";
|
|
52
59
|
import {IStateRegenerator, RegenCaller} from "./regen/index.js";
|
|
@@ -56,6 +63,9 @@ import {
|
|
|
56
63
|
SeenAttesters,
|
|
57
64
|
SeenBlockProposers,
|
|
58
65
|
SeenContributionAndProof,
|
|
66
|
+
SeenExecutionPayloadBids,
|
|
67
|
+
SeenExecutionPayloadEnvelopes,
|
|
68
|
+
SeenPayloadAttesters,
|
|
59
69
|
SeenSyncCommitteeMessages,
|
|
60
70
|
} from "./seenCache/index.js";
|
|
61
71
|
import {SeenAggregatedAttestations} from "./seenCache/seenAggregateAndProof.js";
|
|
@@ -116,12 +126,17 @@ export interface IBeaconChain {
|
|
|
116
126
|
readonly aggregatedAttestationPool: AggregatedAttestationPool;
|
|
117
127
|
readonly syncCommitteeMessagePool: SyncCommitteeMessagePool;
|
|
118
128
|
readonly syncContributionAndProofPool: SyncContributionAndProofPool;
|
|
129
|
+
readonly executionPayloadBidPool: ExecutionPayloadBidPool;
|
|
130
|
+
readonly payloadAttestationPool: PayloadAttestationPool;
|
|
119
131
|
readonly opPool: OpPool;
|
|
120
132
|
|
|
121
133
|
// Gossip seen cache
|
|
122
134
|
readonly seenAttesters: SeenAttesters;
|
|
123
135
|
readonly seenAggregators: SeenAggregators;
|
|
136
|
+
readonly seenPayloadAttesters: SeenPayloadAttesters;
|
|
124
137
|
readonly seenAggregatedAttestations: SeenAggregatedAttestations;
|
|
138
|
+
readonly seenExecutionPayloadEnvelopes: SeenExecutionPayloadEnvelopes;
|
|
139
|
+
readonly seenExecutionPayloadBids: SeenExecutionPayloadBids;
|
|
125
140
|
readonly seenBlockProposers: SeenBlockProposers;
|
|
126
141
|
readonly seenSyncCommitteeMessages: SeenSyncCommitteeMessages;
|
|
127
142
|
readonly seenContributionAndProof: SeenContributionAndProof;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {Slot, gloas} from "@lodestar/types";
|
|
2
|
+
import {MapDef, toRootHex} from "@lodestar/utils";
|
|
3
|
+
import {InsertOutcome} from "./types.js";
|
|
4
|
+
import {pruneBySlot} from "./utils.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* TODO GLOAS: Revisit this value and add rational for choosing it
|
|
8
|
+
*/
|
|
9
|
+
const SLOTS_RETAINED = 2;
|
|
10
|
+
|
|
11
|
+
type BlockRootHex = string;
|
|
12
|
+
type BlockHashHex = string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Store the best execution payload bid per slot / (parent block root, parent block hash).
|
|
16
|
+
*/
|
|
17
|
+
export class ExecutionPayloadBidPool {
|
|
18
|
+
private readonly bidByParentHashByParentRootBySlot = new MapDef<
|
|
19
|
+
Slot,
|
|
20
|
+
MapDef<BlockRootHex, Map<BlockHashHex, gloas.ExecutionPayloadBid>>
|
|
21
|
+
>(() => new MapDef<BlockRootHex, Map<BlockHashHex, gloas.ExecutionPayloadBid>>(() => new Map()));
|
|
22
|
+
private lowestPermissibleSlot = 0;
|
|
23
|
+
|
|
24
|
+
get size(): number {
|
|
25
|
+
let count = 0;
|
|
26
|
+
for (const byParentRoot of this.bidByParentHashByParentRootBySlot.values()) {
|
|
27
|
+
for (const byParentHash of byParentRoot.values()) {
|
|
28
|
+
count += byParentHash.size;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return count;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
add(bid: gloas.ExecutionPayloadBid): InsertOutcome {
|
|
35
|
+
const {slot, parentBlockRoot, parentBlockHash, value} = bid;
|
|
36
|
+
const lowestPermissibleSlot = this.lowestPermissibleSlot;
|
|
37
|
+
|
|
38
|
+
if (slot < lowestPermissibleSlot) {
|
|
39
|
+
return InsertOutcome.Old;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const parentRootHex = toRootHex(parentBlockRoot);
|
|
43
|
+
const parentHashHex = toRootHex(parentBlockHash);
|
|
44
|
+
const bidByParentHash = this.bidByParentHashByParentRootBySlot.getOrDefault(slot).getOrDefault(parentRootHex);
|
|
45
|
+
const existing = bidByParentHash.get(parentHashHex);
|
|
46
|
+
|
|
47
|
+
if (existing) {
|
|
48
|
+
const existingValue = existing.value;
|
|
49
|
+
const newValue = value;
|
|
50
|
+
if (newValue > existingValue) {
|
|
51
|
+
bidByParentHash.set(parentHashHex, bid);
|
|
52
|
+
return InsertOutcome.NewData;
|
|
53
|
+
}
|
|
54
|
+
return newValue === existingValue ? InsertOutcome.AlreadyKnown : InsertOutcome.NotBetterThan;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
bidByParentHash.set(parentHashHex, bid);
|
|
58
|
+
return InsertOutcome.NewData;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Return the highest-value bid matching slot, parent block root, and parent block hash.
|
|
63
|
+
* Used for gossip validation and block production.
|
|
64
|
+
*/
|
|
65
|
+
getBestBid(
|
|
66
|
+
parentBlockRoot: BlockRootHex,
|
|
67
|
+
parentBlockHash: BlockHashHex,
|
|
68
|
+
slot: Slot
|
|
69
|
+
): gloas.ExecutionPayloadBid | null {
|
|
70
|
+
const bidByParentHash = this.bidByParentHashByParentRootBySlot.get(slot)?.get(parentBlockRoot);
|
|
71
|
+
return bidByParentHash?.get(parentBlockHash) ?? null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
prune(clockSlot: Slot): void {
|
|
75
|
+
this.lowestPermissibleSlot = pruneBySlot(this.bidByParentHashByParentRootBySlot, clockSlot, SLOTS_RETAINED);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export {AggregatedAttestationPool} from "./aggregatedAttestationPool.js";
|
|
2
2
|
export {AttestationPool} from "./attestationPool.js";
|
|
3
|
+
export {ExecutionPayloadBidPool} from "./executionPayloadBidPool.js";
|
|
3
4
|
export {OpPool} from "./opPool.js";
|
|
5
|
+
export {PayloadAttestationPool} from "./payloadAttestationPool.js";
|
|
4
6
|
export {SyncCommitteeMessagePool} from "./syncCommitteeMessagePool.js";
|
|
5
7
|
export {SyncContributionAndProofPool} from "./syncContributionAndProofPool.js";
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import {Signature, aggregateSignatures} from "@chainsafe/blst";
|
|
2
|
+
import {BitArray} from "@chainsafe/ssz";
|
|
3
|
+
import {ChainForkConfig} from "@lodestar/config";
|
|
4
|
+
import {MAX_COMMITTEES_PER_SLOT, PTC_SIZE} from "@lodestar/params";
|
|
5
|
+
import {RootHex, Slot, gloas} from "@lodestar/types";
|
|
6
|
+
import {MapDef, toRootHex} from "@lodestar/utils";
|
|
7
|
+
import {Metrics} from "../../metrics/metrics.js";
|
|
8
|
+
import {IClock} from "../../util/clock.js";
|
|
9
|
+
import {InsertOutcome, OpPoolError, OpPoolErrorCode} from "./types.js";
|
|
10
|
+
import {pruneBySlot, signatureFromBytesNoCheck} from "./utils.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* TODO GLOAS: Revisit this value and add rational for choosing it
|
|
14
|
+
*/
|
|
15
|
+
const SLOTS_RETAINED = 2;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The maximum number of distinct `PayloadAttestationData` that will be stored in each slot.
|
|
19
|
+
*
|
|
20
|
+
* This is a DoS protection measure.
|
|
21
|
+
*/
|
|
22
|
+
// TODO GLOAS: Revisit this value. Educated guess would be MAX_ATTESTATIONS_PER_SLOT in AttestationPool divided by MAX_COMMITTEES_PER_SLOT
|
|
23
|
+
const MAX_PAYLOAD_ATTESTATIONS_PER_SLOT = 16_384 / MAX_COMMITTEES_PER_SLOT;
|
|
24
|
+
|
|
25
|
+
type DataRootHex = string;
|
|
26
|
+
type BlockRootHex = string;
|
|
27
|
+
|
|
28
|
+
type AggregateFast = {
|
|
29
|
+
aggregationBits: BitArray;
|
|
30
|
+
data: gloas.PayloadAttestationData;
|
|
31
|
+
signature: Signature;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export class PayloadAttestationPool {
|
|
35
|
+
private readonly aggregateByDataRootByBlockRootBySlot = new MapDef<
|
|
36
|
+
Slot,
|
|
37
|
+
Map<BlockRootHex, Map<DataRootHex, AggregateFast>>
|
|
38
|
+
>(() => new Map<BlockRootHex, Map<DataRootHex, AggregateFast>>());
|
|
39
|
+
private lowestPermissibleSlot = 0;
|
|
40
|
+
|
|
41
|
+
constructor(
|
|
42
|
+
private readonly config: ChainForkConfig,
|
|
43
|
+
private readonly clock: IClock,
|
|
44
|
+
private readonly metrics: Metrics | null = null
|
|
45
|
+
) {}
|
|
46
|
+
|
|
47
|
+
get size(): number {
|
|
48
|
+
let count = 0;
|
|
49
|
+
for (const aggregateByDataRootByBlockRoot of this.aggregateByDataRootByBlockRootBySlot.values()) {
|
|
50
|
+
for (const aggregateByDataRoot of aggregateByDataRootByBlockRoot.values()) {
|
|
51
|
+
count += aggregateByDataRoot.size;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return count;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
add(
|
|
58
|
+
message: gloas.PayloadAttestationMessage,
|
|
59
|
+
payloadAttDataRootHex: RootHex,
|
|
60
|
+
validatorCommitteeIndex: number
|
|
61
|
+
): InsertOutcome {
|
|
62
|
+
const slot = message.data.slot;
|
|
63
|
+
const lowestPermissibleSlot = this.lowestPermissibleSlot;
|
|
64
|
+
|
|
65
|
+
if (slot < lowestPermissibleSlot) {
|
|
66
|
+
return InsertOutcome.Old;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (slot < this.clock.slotWithPastTolerance(this.config.MAXIMUM_GOSSIP_CLOCK_DISPARITY / 1000)) {
|
|
70
|
+
return InsertOutcome.Late;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const aggregateByDataRootByBlockRoot = this.aggregateByDataRootByBlockRootBySlot.getOrDefault(slot);
|
|
74
|
+
let aggregateByDataRoot = aggregateByDataRootByBlockRoot.get(toRootHex(message.data.beaconBlockRoot));
|
|
75
|
+
|
|
76
|
+
if (!aggregateByDataRoot) {
|
|
77
|
+
aggregateByDataRoot = new Map<DataRootHex, AggregateFast>();
|
|
78
|
+
aggregateByDataRootByBlockRoot.set(toRootHex(message.data.beaconBlockRoot), aggregateByDataRoot);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (aggregateByDataRoot.size >= MAX_PAYLOAD_ATTESTATIONS_PER_SLOT) {
|
|
82
|
+
throw new OpPoolError({code: OpPoolErrorCode.REACHED_MAX_PER_SLOT});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const aggregate = aggregateByDataRoot.get(payloadAttDataRootHex);
|
|
86
|
+
if (aggregate) {
|
|
87
|
+
// Aggregate msg into aggregate
|
|
88
|
+
return aggregateMessageInto(message, validatorCommitteeIndex, aggregate);
|
|
89
|
+
}
|
|
90
|
+
// Create a new aggregate with data
|
|
91
|
+
aggregateByDataRoot.set(payloadAttDataRootHex, messageToAggregate(message, validatorCommitteeIndex));
|
|
92
|
+
|
|
93
|
+
return InsertOutcome.NewData;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get payload attestations to be included in a block.
|
|
98
|
+
* Pick the top `maxAttestation` number of attestations with the most votes
|
|
99
|
+
*/
|
|
100
|
+
getPayloadAttestationsForBlock(
|
|
101
|
+
beaconBlockRoot: BlockRootHex,
|
|
102
|
+
slot: Slot,
|
|
103
|
+
maxAttestation: number
|
|
104
|
+
): gloas.PayloadAttestation[] {
|
|
105
|
+
const aggregateByDataRootByBlockRoot = this.aggregateByDataRootByBlockRootBySlot.get(slot);
|
|
106
|
+
|
|
107
|
+
if (!aggregateByDataRootByBlockRoot) {
|
|
108
|
+
this.metrics?.opPool.payloadAttestationPool.getPayloadAttestationsCacheMisses.inc();
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const aggregateByDataRoot = aggregateByDataRootByBlockRoot.get(beaconBlockRoot);
|
|
113
|
+
|
|
114
|
+
if (!aggregateByDataRoot) {
|
|
115
|
+
this.metrics?.opPool.payloadAttestationPool.getPayloadAttestationsCacheMisses.inc();
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return Array.from(aggregateByDataRoot.values())
|
|
120
|
+
.slice()
|
|
121
|
+
.sort((a, b) => b.aggregationBits.getTrueBitIndexes().length - a.aggregationBits.getTrueBitIndexes().length)
|
|
122
|
+
.slice(0, maxAttestation)
|
|
123
|
+
.map(fastToPayloadAttestation);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
prune(clockSlot: Slot): void {
|
|
127
|
+
pruneBySlot(this.aggregateByDataRootByBlockRootBySlot, clockSlot, SLOTS_RETAINED);
|
|
128
|
+
this.lowestPermissibleSlot = clockSlot;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function messageToAggregate(message: gloas.PayloadAttestationMessage, validatorCommitteeIndex: number): AggregateFast {
|
|
133
|
+
return {
|
|
134
|
+
aggregationBits: BitArray.fromSingleBit(PTC_SIZE, validatorCommitteeIndex),
|
|
135
|
+
data: message.data,
|
|
136
|
+
signature: signatureFromBytesNoCheck(message.signature),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function aggregateMessageInto(
|
|
141
|
+
message: gloas.PayloadAttestationMessage,
|
|
142
|
+
validatorCommitteeIndex: number,
|
|
143
|
+
aggregate: AggregateFast
|
|
144
|
+
): InsertOutcome {
|
|
145
|
+
if (aggregate.aggregationBits.get(validatorCommitteeIndex) === true) {
|
|
146
|
+
return InsertOutcome.AlreadyKnown;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
aggregate.aggregationBits.set(validatorCommitteeIndex, true);
|
|
150
|
+
aggregate.signature = aggregateSignatures([aggregate.signature, signatureFromBytesNoCheck(message.signature)]);
|
|
151
|
+
|
|
152
|
+
return InsertOutcome.Aggregated;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function fastToPayloadAttestation(aggFast: AggregateFast): gloas.PayloadAttestation {
|
|
156
|
+
return {...aggFast, signature: aggFast.signature.toBytes()};
|
|
157
|
+
}
|
package/src/chain/options.ts
CHANGED
|
@@ -45,7 +45,6 @@ export type IChainOptions = BlockProcessOpts &
|
|
|
45
45
|
broadcastValidationStrictness?: string;
|
|
46
46
|
minSameMessageSignatureSetsToBatch: number;
|
|
47
47
|
archiveDateEpochs?: number;
|
|
48
|
-
nHistoricalStates?: boolean;
|
|
49
48
|
nHistoricalStatesFileDataStore?: boolean;
|
|
50
49
|
};
|
|
51
50
|
|
|
@@ -119,7 +118,6 @@ export const defaultChainOptions: IChainOptions = {
|
|
|
119
118
|
// batching too much may block the I/O thread so if useWorker=false, suggest this value to be 32
|
|
120
119
|
// since this batch attestation work is designed to work with useWorker=true, make this the lowest value
|
|
121
120
|
minSameMessageSignatureSetsToBatch: 2,
|
|
122
|
-
nHistoricalStates: true,
|
|
123
121
|
// as of Feb 2025, this option turned out to be very useful:
|
|
124
122
|
// - it allows to share a persisted checkpoint state to other nodes
|
|
125
123
|
// - users can prune the persisted checkpoint state files manually to save disc space
|
|
@@ -2,7 +2,7 @@ import {routes} from "@lodestar/api";
|
|
|
2
2
|
import {ProtoBlock} from "@lodestar/fork-choice";
|
|
3
3
|
import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
|
|
4
4
|
import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
5
|
-
import {CheckpointHex} from "../stateCache/
|
|
5
|
+
import {CheckpointHex} from "../stateCache/types.js";
|
|
6
6
|
|
|
7
7
|
export enum RegenCaller {
|
|
8
8
|
getDuties = "getDuties",
|
|
@@ -18,6 +18,7 @@ export enum RegenCaller {
|
|
|
18
18
|
validateGossipAggregateAndProof = "validateGossipAggregateAndProof",
|
|
19
19
|
validateGossipAttestation = "validateGossipAttestation",
|
|
20
20
|
validateGossipVoluntaryExit = "validateGossipVoluntaryExit",
|
|
21
|
+
validateGossipExecutionPayloadBid = "validateGossipExecutionPayloadBid",
|
|
21
22
|
onForkChoiceFinalized = "onForkChoiceFinalized",
|
|
22
23
|
restApi = "restApi",
|
|
23
24
|
}
|
|
@@ -5,8 +5,7 @@ import {BeaconBlock, Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
|
5
5
|
import {Logger, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {Metrics} from "../../metrics/index.js";
|
|
7
7
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
8
|
-
import {CheckpointHex} from "../stateCache/
|
|
9
|
-
import {BlockStateCache, CheckpointStateCache} from "../stateCache/types.js";
|
|
8
|
+
import {BlockStateCache, CheckpointHex, CheckpointStateCache} from "../stateCache/types.js";
|
|
10
9
|
import {RegenError, RegenErrorCode} from "./errors.js";
|
|
11
10
|
import {
|
|
12
11
|
IStateRegenerator,
|
package/src/chain/regen/regen.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {Metrics} from "../../metrics/index.js";
|
|
|
18
18
|
import {nextEventLoop} from "../../util/eventLoop.js";
|
|
19
19
|
import {getCheckpointFromState} from "../blocks/utils/checkpoint.js";
|
|
20
20
|
import {ChainEvent, ChainEventEmitter} from "../emitter.js";
|
|
21
|
+
import {SeenBlockInput} from "../seenCache/seenGossipBlockInput.js";
|
|
21
22
|
import {BlockStateCache, CheckpointStateCache} from "../stateCache/types.js";
|
|
22
23
|
import {ValidatorMonitor} from "../validatorMonitor.js";
|
|
23
24
|
import {RegenError, RegenErrorCode} from "./errors.js";
|
|
@@ -28,6 +29,7 @@ export type RegenModules = {
|
|
|
28
29
|
forkChoice: IForkChoice;
|
|
29
30
|
blockStateCache: BlockStateCache;
|
|
30
31
|
checkpointStateCache: CheckpointStateCache;
|
|
32
|
+
seenBlockInputCache: SeenBlockInput;
|
|
31
33
|
config: ChainForkConfig;
|
|
32
34
|
emitter: ChainEventEmitter;
|
|
33
35
|
logger: Logger;
|
|
@@ -191,7 +193,10 @@ export class StateRegenerator implements IStateRegeneratorInternal {
|
|
|
191
193
|
const protoBlocksAsc = blocksToReplay.reverse();
|
|
192
194
|
for (const [i, protoBlock] of protoBlocksAsc.entries()) {
|
|
193
195
|
replaySlots[i] = protoBlock.slot;
|
|
194
|
-
|
|
196
|
+
const blockInput = this.modules.seenBlockInputCache.get(protoBlock.blockRoot);
|
|
197
|
+
blockPromises[i] = blockInput?.hasBlock()
|
|
198
|
+
? Promise.resolve(blockInput.getBlock())
|
|
199
|
+
: this.modules.db.block.get(fromHex(protoBlock.blockRoot));
|
|
195
200
|
}
|
|
196
201
|
|
|
197
202
|
const logCtx = {stateRoot, caller, replaySlots: replaySlots.join(",")};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export {SeenAggregators, SeenAttesters} from "./seenAttesters.js";
|
|
1
|
+
export {SeenAggregators, SeenAttesters, SeenPayloadAttesters} from "./seenAttesters.js";
|
|
2
2
|
export {SeenBlockProposers} from "./seenBlockProposers.js";
|
|
3
3
|
export {SeenSyncCommitteeMessages} from "./seenCommittee.js";
|
|
4
4
|
export {SeenContributionAndProof} from "./seenCommitteeContribution.js";
|
|
5
|
+
export {SeenExecutionPayloadBids} from "./seenExecutionPayloadBids.js";
|
|
6
|
+
export {SeenExecutionPayloadEnvelopes} from "./seenExecutionPayloadEnvelope.js";
|
|
5
7
|
export {SeenBlockInput} from "./seenGossipBlockInput.js";
|
|
@@ -56,3 +56,8 @@ export class SeenAttesters {
|
|
|
56
56
|
* Keeps a cache to filter aggregated attestations from the same aggregators in the same epoch
|
|
57
57
|
*/
|
|
58
58
|
export class SeenAggregators extends SeenAttesters {}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Keeps a cache to filter payload attestations from the same attesters in the same epoch
|
|
62
|
+
*/
|
|
63
|
+
export class SeenPayloadAttesters extends SeenAttesters {}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {BuilderIndex, Slot} from "@lodestar/types";
|
|
2
|
+
import {MapDef} from "@lodestar/utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* TODO GLOAS: Revisit this value and add rational for choosing it
|
|
6
|
+
*/
|
|
7
|
+
const SLOTS_RETAINED = 2;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Tracks execution payload bids we've already seen per (slot, builder).
|
|
11
|
+
*/
|
|
12
|
+
export class SeenExecutionPayloadBids {
|
|
13
|
+
private readonly builderIndexesBySlot = new MapDef<Slot, Set<BuilderIndex>>(() => new Set<BuilderIndex>());
|
|
14
|
+
private lowestPermissibleSlot: Slot = 0;
|
|
15
|
+
|
|
16
|
+
isKnown(slot: Slot, builderIndex: BuilderIndex): boolean {
|
|
17
|
+
return this.builderIndexesBySlot.get(slot)?.has(builderIndex) === true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
add(slot: Slot, builderIndex: BuilderIndex): void {
|
|
21
|
+
if (slot < this.lowestPermissibleSlot) {
|
|
22
|
+
throw Error(`slot ${slot} < lowestPermissibleSlot ${this.lowestPermissibleSlot}`);
|
|
23
|
+
}
|
|
24
|
+
this.builderIndexesBySlot.getOrDefault(slot).add(builderIndex);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
prune(currentSlot: Slot): void {
|
|
28
|
+
this.lowestPermissibleSlot = Math.max(currentSlot - SLOTS_RETAINED, 0);
|
|
29
|
+
for (const slot of this.builderIndexesBySlot.keys()) {
|
|
30
|
+
if (slot < this.lowestPermissibleSlot) {
|
|
31
|
+
this.builderIndexesBySlot.delete(slot);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {RootHex, Slot} from "@lodestar/types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cache to prevent processing multiple execution payload envelopes for the same block root.
|
|
5
|
+
* Only one builder qualifies to submit an execution payload for a given slot.
|
|
6
|
+
* We only keep track of envelopes of unfinalized slots.
|
|
7
|
+
* [IGNORE] The node has not seen another valid `SignedExecutionPayloadEnvelope` for this block root.
|
|
8
|
+
*/
|
|
9
|
+
export class SeenExecutionPayloadEnvelopes {
|
|
10
|
+
private readonly slotByBlockRoot = new Map<RootHex, Slot>();
|
|
11
|
+
private finalizedSlot: Slot = 0;
|
|
12
|
+
|
|
13
|
+
isKnown(blockRoot: RootHex): boolean {
|
|
14
|
+
return this.slotByBlockRoot.has(blockRoot);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
add(blockRoot: RootHex, slot: Slot): void {
|
|
18
|
+
if (slot < this.finalizedSlot) {
|
|
19
|
+
throw Error(`slot ${slot} < finalizedSlot ${this.finalizedSlot}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.slotByBlockRoot.set(blockRoot, slot);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
prune(finalizedSlot: Slot): void {
|
|
26
|
+
this.finalizedSlot = finalizedSlot;
|
|
27
|
+
|
|
28
|
+
for (const [blockRoot, slot] of this.slotByBlockRoot.entries()) {
|
|
29
|
+
if (slot < finalizedSlot) {
|
|
30
|
+
this.slotByBlockRoot.delete(blockRoot);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -379,7 +379,7 @@ export class SeenBlockInput {
|
|
|
379
379
|
let itemsToDelete = this.blockInputs.size - MAX_BLOCK_INPUT_CACHE_SIZE;
|
|
380
380
|
|
|
381
381
|
if (itemsToDelete > 0) {
|
|
382
|
-
const sorted = [...this.blockInputs.entries()].sort((a, b) =>
|
|
382
|
+
const sorted = [...this.blockInputs.entries()].sort((a, b) => a[1].slot - b[1].slot);
|
|
383
383
|
for (const [rootHex] of sorted) {
|
|
384
384
|
this.blockInputs.delete(rootHex);
|
|
385
385
|
itemsToDelete--;
|