@lodestar/beacon-node 1.41.0 → 1.42.0-dev.4118b5b440
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 +35 -16
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +2 -2
- 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/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +6 -2
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +0 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +0 -9
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +4 -4
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +4 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +38 -0
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/blockInput/types.d.ts +4 -3
- package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/types.js +1 -0
- package/lib/chain/blocks/blockInput/types.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +29 -9
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +48 -0
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -0
- package/lib/chain/blocks/importExecutionPayload.js +159 -0
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/index.d.ts +3 -0
- package/lib/chain/blocks/payloadEnvelopeInput/index.d.ts.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/index.js +3 -0
- package/lib/chain/blocks/payloadEnvelopeInput/index.js.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +80 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +248 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +29 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.js +11 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.js.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +15 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +46 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -0
- package/lib/chain/blocks/types.d.ts +7 -0
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +12 -0
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -0
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +40 -0
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -0
- package/lib/chain/chain.d.ts +10 -5
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +44 -10
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +12 -2
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +3 -1
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +0 -10
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +8 -5
- package/lib/chain/interface.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/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +6 -2
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +6 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/errors.d.ts +11 -1
- package/lib/chain/regen/errors.d.ts.map +1 -1
- package/lib/chain/regen/errors.js +2 -0
- package/lib/chain/regen/errors.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +14 -6
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +2 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +11 -6
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +40 -8
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +5 -0
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +33 -6
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/index.d.ts +1 -1
- package/lib/chain/seenCache/index.d.ts.map +1 -1
- package/lib/chain/seenCache/index.js +1 -1
- package/lib/chain/seenCache/index.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +38 -0
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -0
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +76 -0
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -0
- package/lib/chain/stateCache/datastore/db.d.ts +4 -5
- package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/db.js +32 -10
- package/lib/chain/stateCache/datastore/db.js.map +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/file.js +5 -5
- package/lib/chain/stateCache/datastore/file.js.map +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +7 -4
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +8 -3
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +33 -14
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +217 -119
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +15 -8
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +30 -19
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/lightClientFinalityUpdate.js +1 -1
- package/lib/chain/validation/lightClientFinalityUpdate.js.map +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.js +1 -1
- package/lib/chain/validation/lightClientOptimisticUpdate.js.map +1 -1
- package/lib/chain/validation/syncCommittee.d.ts +2 -2
- package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/syncCommittee.js +12 -11
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.d.ts.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +2 -2
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +2 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +4 -1
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +2 -2
- package/lib/metrics/metrics/lodestar.d.ts +40 -4
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +93 -15
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +15 -0
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/interface.d.ts +1 -1
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +1 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +4 -4
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
- package/lib/network/processor/extractSlotRootFns.js +15 -5
- package/lib/network/processor/extractSlotRootFns.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +39 -9
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +12 -7
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +99 -78
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.d.ts +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.js +1 -1
- package/lib/sync/backfill/backfill.d.ts +1 -1
- package/lib/sync/backfill/backfill.js +1 -1
- package/lib/sync/constants.d.ts +1 -1
- package/lib/sync/constants.js +1 -1
- package/lib/sync/unknownBlock.d.ts +3 -9
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +8 -41
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/util/sszBytes.d.ts +4 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +69 -12
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +36 -17
- package/src/api/impl/beacon/state/utils.ts +2 -2
- package/src/api/impl/validator/index.ts +8 -4
- package/src/chain/archiveStore/archiveStore.ts +0 -10
- package/src/chain/archiveStore/interface.ts +4 -4
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +8 -5
- package/src/chain/archiveStore/utils/archiveBlocks.ts +59 -1
- package/src/chain/blocks/blockInput/types.ts +4 -3
- package/src/chain/blocks/importBlock.ts +47 -8
- package/src/chain/blocks/importExecutionPayload.ts +241 -0
- package/src/chain/blocks/payloadEnvelopeInput/index.ts +2 -0
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +336 -0
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +33 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +61 -0
- package/src/chain/blocks/types.ts +8 -0
- package/src/chain/blocks/verifyBlocksSignatures.ts +1 -1
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +55 -0
- package/src/chain/chain.ts +60 -15
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -2
- package/src/chain/forkChoice/index.ts +0 -10
- package/src/chain/interface.ts +8 -5
- package/src/chain/opPools/utils.ts +1 -1
- package/src/chain/prepareNextSlot.ts +6 -2
- package/src/chain/produceBlock/computeNewStateRoot.ts +6 -1
- package/src/chain/produceBlock/produceBlockBody.ts +1 -1
- package/src/chain/regen/errors.ts +6 -1
- package/src/chain/regen/interface.ts +14 -6
- package/src/chain/regen/queued.ts +48 -12
- package/src/chain/regen/regen.ts +37 -7
- package/src/chain/seenCache/index.ts +1 -1
- package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +106 -0
- package/src/chain/stateCache/datastore/db.ts +33 -10
- package/src/chain/stateCache/datastore/file.ts +6 -5
- package/src/chain/stateCache/datastore/types.ts +3 -2
- package/src/chain/stateCache/fifoBlockStateCache.ts +10 -4
- package/src/chain/stateCache/persistentCheckpointsCache.ts +248 -139
- package/src/chain/stateCache/types.ts +18 -8
- package/src/chain/validation/executionPayloadEnvelope.ts +38 -25
- package/src/chain/validation/lightClientFinalityUpdate.ts +1 -1
- package/src/chain/validation/lightClientOptimisticUpdate.ts +1 -1
- package/src/chain/validation/syncCommittee.ts +15 -14
- package/src/chain/validation/voluntaryExit.ts +2 -1
- package/src/chain/validatorMonitor.ts +11 -1
- package/src/execution/engine/interface.ts +2 -2
- package/src/metrics/metrics/lodestar.ts +100 -19
- package/src/network/gossip/encoding.ts +16 -0
- package/src/network/interface.ts +1 -1
- package/src/network/network.ts +4 -4
- package/src/network/processor/extractSlotRootFns.ts +19 -6
- package/src/network/processor/gossipHandlers.ts +45 -8
- package/src/network/processor/index.ts +110 -89
- package/src/network/reqresp/ReqRespBeaconNode.ts +1 -1
- package/src/sync/backfill/backfill.ts +1 -1
- package/src/sync/constants.ts +1 -1
- package/src/sync/unknownBlock.ts +10 -50
- package/src/util/sszBytes.ts +90 -10
- package/lib/chain/archiveStore/utils/archivePayloads.d.ts +0 -7
- package/lib/chain/archiveStore/utils/archivePayloads.d.ts.map +0 -1
- package/lib/chain/archiveStore/utils/archivePayloads.js +0 -10
- package/lib/chain/archiveStore/utils/archivePayloads.js.map +0 -1
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts +0 -15
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.d.ts.map +0 -1
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js +0 -28
- package/lib/chain/seenCache/seenExecutionPayloadEnvelope.js.map +0 -1
- package/src/chain/archiveStore/utils/archivePayloads.ts +0 -15
- package/src/chain/seenCache/seenExecutionPayloadEnvelope.ts +0 -34
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {PayloadStatus} from "@lodestar/fork-choice";
|
|
2
2
|
import {
|
|
3
|
+
BeaconStateView,
|
|
3
4
|
CachedBeaconStateGloas,
|
|
4
5
|
computeStartSlotAtEpoch,
|
|
5
|
-
|
|
6
|
-
getExecutionPayloadEnvelopeSigningRoot,
|
|
6
|
+
getExecutionPayloadEnvelopeSignatureSet,
|
|
7
7
|
} from "@lodestar/state-transition";
|
|
8
8
|
import {gloas} from "@lodestar/types";
|
|
9
9
|
import {toRootHex} from "@lodestar/utils";
|
|
10
10
|
import {ExecutionPayloadEnvelopeError, ExecutionPayloadEnvelopeErrorCode, GossipAction} from "../errors/index.js";
|
|
11
11
|
import {IBeaconChain} from "../index.js";
|
|
12
|
+
import {RegenCaller} from "../regen/index.js";
|
|
12
13
|
|
|
13
14
|
export async function validateApiExecutionPayloadEnvelope(
|
|
14
15
|
chain: IBeaconChain,
|
|
@@ -47,7 +48,9 @@ async function validateExecutionPayloadEnvelope(
|
|
|
47
48
|
|
|
48
49
|
// [IGNORE] The node has not seen another valid
|
|
49
50
|
// `SignedExecutionPayloadEnvelope` for this block root from this builder.
|
|
50
|
-
|
|
51
|
+
const envelopeBlock = chain.forkChoice.getBlockHex(blockRootHex, PayloadStatus.FULL);
|
|
52
|
+
const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
|
|
53
|
+
if (envelopeBlock || payloadInput?.hasPayloadEnvelope()) {
|
|
51
54
|
throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
|
|
52
55
|
code: ExecutionPayloadEnvelopeErrorCode.ENVELOPE_ALREADY_KNOWN,
|
|
53
56
|
blockRoot: blockRootHex,
|
|
@@ -55,6 +58,14 @@ async function validateExecutionPayloadEnvelope(
|
|
|
55
58
|
});
|
|
56
59
|
}
|
|
57
60
|
|
|
61
|
+
if (!payloadInput) {
|
|
62
|
+
// PayloadEnvelopeInput should have been created during block import
|
|
63
|
+
throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
|
|
64
|
+
code: ExecutionPayloadEnvelopeErrorCode.PAYLOAD_ENVELOPE_INPUT_MISSING,
|
|
65
|
+
blockRoot: blockRootHex,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
58
69
|
// [IGNORE] The envelope is from a slot greater than or equal to the latest finalized slot -- i.e. validate that `envelope.slot >= compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)`
|
|
59
70
|
const finalizedCheckpoint = chain.forkChoice.getFinalizedCheckpoint();
|
|
60
71
|
const finalizedSlot = computeStartSlotAtEpoch(finalizedCheckpoint.epoch);
|
|
@@ -79,45 +90,47 @@ async function validateExecutionPayloadEnvelope(
|
|
|
79
90
|
});
|
|
80
91
|
}
|
|
81
92
|
|
|
82
|
-
if (block.builderIndex == null || block.blockHashFromBid == null) {
|
|
83
|
-
// This indicates this block is a pre-gloas block which is wrong
|
|
84
|
-
throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
|
|
85
|
-
code: ExecutionPayloadEnvelopeErrorCode.CACHE_FAIL,
|
|
86
|
-
blockRoot: blockRootHex,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
93
|
// [REJECT] `envelope.builder_index == bid.builder_index`
|
|
91
|
-
if (envelope.builderIndex !==
|
|
94
|
+
if (envelope.builderIndex !== payloadInput.getBuilderIndex()) {
|
|
92
95
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
93
96
|
code: ExecutionPayloadEnvelopeErrorCode.BUILDER_INDEX_MISMATCH,
|
|
94
97
|
envelopeBuilderIndex: envelope.builderIndex,
|
|
95
|
-
bidBuilderIndex:
|
|
98
|
+
bidBuilderIndex: payloadInput.getBuilderIndex(),
|
|
96
99
|
});
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
// [REJECT] `payload.block_hash == bid.block_hash`
|
|
100
|
-
if (toRootHex(payload.blockHash) !==
|
|
103
|
+
if (toRootHex(payload.blockHash) !== payloadInput.getBlockHashHex()) {
|
|
101
104
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
102
105
|
code: ExecutionPayloadEnvelopeErrorCode.BLOCK_HASH_MISMATCH,
|
|
103
106
|
envelopeBlockHash: toRootHex(payload.blockHash),
|
|
104
|
-
bidBlockHash:
|
|
107
|
+
bidBlockHash: payloadInput.getBlockHashHex(),
|
|
105
108
|
});
|
|
106
109
|
}
|
|
107
110
|
|
|
108
|
-
//
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
// Get the post block state which is the pre-payload state to verify the builder's signature.
|
|
112
|
+
const blockState = await chain.regen
|
|
113
|
+
.getState(block.stateRoot, RegenCaller.validateGossipPayloadEnvelope)
|
|
114
|
+
.catch(() => {
|
|
115
|
+
throw new ExecutionPayloadEnvelopeError(GossipAction.IGNORE, {
|
|
116
|
+
code: ExecutionPayloadEnvelopeErrorCode.UNKNOWN_BLOCK_STATE,
|
|
117
|
+
blockRoot: blockRootHex,
|
|
118
|
+
slot: envelope.slot,
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const state = blockState as CachedBeaconStateGloas;
|
|
123
|
+
const signatureSet = getExecutionPayloadEnvelopeSignatureSet(
|
|
124
|
+
chain.config,
|
|
125
|
+
chain.pubkeyCache,
|
|
126
|
+
new BeaconStateView(state),
|
|
127
|
+
executionPayloadEnvelope,
|
|
128
|
+
payloadInput.proposerIndex
|
|
114
129
|
);
|
|
115
130
|
|
|
116
|
-
if (!(await chain.bls.verifySignatureSets([signatureSet]))) {
|
|
131
|
+
if (!(await chain.bls.verifySignatureSets([signatureSet], {verifyOnMainThread: true}))) {
|
|
117
132
|
throw new ExecutionPayloadEnvelopeError(GossipAction.REJECT, {
|
|
118
133
|
code: ExecutionPayloadEnvelopeErrorCode.INVALID_SIGNATURE,
|
|
119
134
|
});
|
|
120
135
|
}
|
|
121
|
-
|
|
122
|
-
chain.seenExecutionPayloadEnvelopes.add(blockRootHex, envelope.slot);
|
|
123
136
|
}
|
|
@@ -6,7 +6,7 @@ import {LightClientError, LightClientErrorCode} from "../errors/lightClientError
|
|
|
6
6
|
import {IBeaconChain} from "../interface.js";
|
|
7
7
|
import {updateReceivedTooEarly} from "./lightClientOptimisticUpdate.js";
|
|
8
8
|
|
|
9
|
-
// https://github.com/ethereum/consensus-specs/blob/
|
|
9
|
+
// https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#light_client_finality_update
|
|
10
10
|
export function validateLightClientFinalityUpdate(
|
|
11
11
|
config: ChainForkConfig,
|
|
12
12
|
chain: IBeaconChain,
|
|
@@ -6,7 +6,7 @@ import {GossipAction} from "../errors/index.js";
|
|
|
6
6
|
import {LightClientError, LightClientErrorCode} from "../errors/lightClientError.js";
|
|
7
7
|
import {IBeaconChain} from "../interface.js";
|
|
8
8
|
|
|
9
|
-
// https://github.com/ethereum/consensus-specs/blob/
|
|
9
|
+
// https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update
|
|
10
10
|
export function validateLightClientOptimisticUpdate(
|
|
11
11
|
config: ChainForkConfig,
|
|
12
12
|
chain: IBeaconChain,
|
|
@@ -15,12 +15,12 @@ export async function validateGossipSyncCommittee(
|
|
|
15
15
|
chain: IBeaconChain,
|
|
16
16
|
syncCommittee: altair.SyncCommitteeMessage,
|
|
17
17
|
subnet: SubnetID
|
|
18
|
-
): Promise<{
|
|
18
|
+
): Promise<{indicesInSubcommittee: IndexInSubcommittee[]}> {
|
|
19
19
|
const {slot, validatorIndex, beaconBlockRoot} = syncCommittee;
|
|
20
20
|
const messageRoot = toRootHex(beaconBlockRoot);
|
|
21
21
|
|
|
22
22
|
const headState = chain.getHeadState();
|
|
23
|
-
const
|
|
23
|
+
const indicesInSubcommittee = validateGossipSyncCommitteeExceptSig(chain, headState, subnet, syncCommittee);
|
|
24
24
|
|
|
25
25
|
// [IGNORE] The signature's slot is for the current slot, i.e. sync_committee_signature.slot == current_slot.
|
|
26
26
|
// > Checked in validateGossipSyncCommitteeExceptSig()
|
|
@@ -68,7 +68,7 @@ export async function validateGossipSyncCommittee(
|
|
|
68
68
|
// Register this valid item as seen
|
|
69
69
|
chain.seenSyncCommitteeMessages.add(slot, subnet, validatorIndex, messageRoot);
|
|
70
70
|
|
|
71
|
-
return {
|
|
71
|
+
return {indicesInSubcommittee};
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export async function validateApiSyncCommittee(
|
|
@@ -105,7 +105,7 @@ export function validateGossipSyncCommitteeExceptSig(
|
|
|
105
105
|
headState: CachedBeaconStateAllForks,
|
|
106
106
|
subnet: SubnetID,
|
|
107
107
|
data: Pick<altair.SyncCommitteeMessage, "slot" | "validatorIndex">
|
|
108
|
-
): IndexInSubcommittee {
|
|
108
|
+
): IndexInSubcommittee[] {
|
|
109
109
|
const {slot, validatorIndex} = data;
|
|
110
110
|
// [IGNORE] The signature's slot is for the current slot, i.e. sync_committee_signature.slot == current_slot.
|
|
111
111
|
// (with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
|
|
@@ -127,26 +127,27 @@ export function validateGossipSyncCommitteeExceptSig(
|
|
|
127
127
|
|
|
128
128
|
// [REJECT] The subnet_id is valid for the given validator, i.e. subnet_id in compute_subnets_for_sync_committee(state, sync_committee_signature.validator_index).
|
|
129
129
|
// Note this validation implies the validator is part of the broader current sync committee along with the correct subcommittee.
|
|
130
|
-
const
|
|
131
|
-
if (
|
|
130
|
+
const indicesInSubcommittee = getIndicesInSubcommittee(headState, subnet, data);
|
|
131
|
+
if (indicesInSubcommittee === null) {
|
|
132
132
|
throw new SyncCommitteeError(GossipAction.REJECT, {
|
|
133
133
|
code: SyncCommitteeErrorCode.VALIDATOR_NOT_IN_SYNC_COMMITTEE,
|
|
134
134
|
validatorIndex,
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
return
|
|
138
|
+
return indicesInSubcommittee;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
/**
|
|
142
|
-
* Returns
|
|
143
|
-
* Returns `null` if not part of the sync committee or not part of the given `subnet
|
|
142
|
+
* Returns all IndexInSubcommittee positions of the given `subnet`.
|
|
143
|
+
* Returns `null` if not part of the sync committee or not part of the given `subnet`.
|
|
144
|
+
* A validator may appear multiple times in the same subcommittee.
|
|
144
145
|
*/
|
|
145
|
-
function
|
|
146
|
+
function getIndicesInSubcommittee(
|
|
146
147
|
headState: CachedBeaconStateAllForks,
|
|
147
148
|
subnet: SubnetID,
|
|
148
149
|
data: Pick<altair.SyncCommitteeMessage, "slot" | "validatorIndex">
|
|
149
|
-
): IndexInSubcommittee | null {
|
|
150
|
+
): IndexInSubcommittee[] | null {
|
|
150
151
|
const syncCommittee = headState.epochCtx.getIndexedSyncCommittee(data.slot);
|
|
151
152
|
const indexesInCommittee = syncCommittee.validatorIndexMap.get(data.validatorIndex);
|
|
152
153
|
if (indexesInCommittee === undefined) {
|
|
@@ -154,12 +155,12 @@ function getIndexInSubcommittee(
|
|
|
154
155
|
return null;
|
|
155
156
|
}
|
|
156
157
|
|
|
158
|
+
const indices: IndexInSubcommittee[] = [];
|
|
157
159
|
for (const indexInCommittee of indexesInCommittee) {
|
|
158
160
|
if (Math.floor(indexInCommittee / SYNC_COMMITTEE_SUBNET_SIZE) === subnet) {
|
|
159
|
-
|
|
161
|
+
indices.push(indexInCommittee % SYNC_COMMITTEE_SUBNET_SIZE);
|
|
160
162
|
}
|
|
161
163
|
}
|
|
162
164
|
|
|
163
|
-
|
|
164
|
-
return null;
|
|
165
|
+
return indices.length > 0 ? indices : null;
|
|
165
166
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BeaconStateView,
|
|
2
3
|
VoluntaryExitValidity,
|
|
3
4
|
getVoluntaryExitSignatureSet,
|
|
4
5
|
getVoluntaryExitValidity,
|
|
@@ -59,7 +60,7 @@ async function validateVoluntaryExit(
|
|
|
59
60
|
});
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
const signatureSet = getVoluntaryExitSignatureSet(chain.config, state
|
|
63
|
+
const signatureSet = getVoluntaryExitSignatureSet(chain.config, new BeaconStateView(state), voluntaryExit);
|
|
63
64
|
if (!(await chain.bls.verifySignatureSets([signatureSet], {batchable: true, priority: prioritizeBls}))) {
|
|
64
65
|
throw new VoluntaryExitError(GossipAction.REJECT, {
|
|
65
66
|
code: VoluntaryExitErrorCode.INVALID_SIGNATURE,
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
ValidatorIndex,
|
|
24
24
|
altair,
|
|
25
25
|
deneb,
|
|
26
|
+
gloas,
|
|
26
27
|
} from "@lodestar/types";
|
|
27
28
|
import {LogData, LogHandler, LogLevel, Logger, MapDef, MapDefMax, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
28
29
|
import {GENESIS_SLOT} from "../constants/constants.js";
|
|
@@ -61,6 +62,11 @@ export type ValidatorMonitor = {
|
|
|
61
62
|
): void;
|
|
62
63
|
registerBeaconBlock(src: OpSource, delaySec: Seconds, block: BeaconBlock): void;
|
|
63
64
|
registerBlobSidecar(src: OpSource, seenTimestampSec: Seconds, blob: deneb.BlobSidecar): void;
|
|
65
|
+
registerExecutionPayloadEnvelope(
|
|
66
|
+
src: OpSource,
|
|
67
|
+
delaySec: Seconds,
|
|
68
|
+
envelope: gloas.SignedExecutionPayloadEnvelope
|
|
69
|
+
): void;
|
|
64
70
|
registerImportedBlock(block: BeaconBlock, data: {proposerBalanceDelta: number}): void;
|
|
65
71
|
onPoolSubmitUnaggregatedAttestation(
|
|
66
72
|
seenTimestampSec: number,
|
|
@@ -450,6 +456,10 @@ export function createValidatorMonitor(
|
|
|
450
456
|
//TODO: freetheblobs
|
|
451
457
|
},
|
|
452
458
|
|
|
459
|
+
registerExecutionPayloadEnvelope(_src, _delaySec, _envelope) {
|
|
460
|
+
// TODO GLOAS: implement execution payload envelope monitoring
|
|
461
|
+
},
|
|
462
|
+
|
|
453
463
|
registerImportedBlock(block, {proposerBalanceDelta}) {
|
|
454
464
|
const validator = validators.get(block.proposerIndex);
|
|
455
465
|
if (validator) {
|
|
@@ -889,7 +899,7 @@ function renderAttestationSummary(
|
|
|
889
899
|
summary: AttestationSummary | undefined,
|
|
890
900
|
flags: ParticipationFlags
|
|
891
901
|
): string {
|
|
892
|
-
// Reference https://github.com/ethereum/consensus-specs/blob/
|
|
902
|
+
// Reference https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/beacon-chain.md#get_attestation_participation_flag_indices
|
|
893
903
|
//
|
|
894
904
|
// is_matching_source = data.source == justified_checkpoint
|
|
895
905
|
// is_matching_target = is_matching_source and data.target.root == get_block_root(state, data.target.epoch)
|
|
@@ -128,7 +128,7 @@ export interface IExecutionEngine {
|
|
|
128
128
|
* corresponding state, up to and including finalized_block_hash.
|
|
129
129
|
*
|
|
130
130
|
* The call of the notify_forkchoice_updated function maps on the POS_FORKCHOICE_UPDATED event defined in the EIP-3675.
|
|
131
|
-
* https://github.com/ethereum/consensus-specs/blob/
|
|
131
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/merge/fork-choice.md#notify_forkchoice_updated
|
|
132
132
|
*
|
|
133
133
|
* Should be called in response to fork-choice head and finalized events
|
|
134
134
|
*/
|
|
@@ -145,7 +145,7 @@ export interface IExecutionEngine {
|
|
|
145
145
|
* since the corresponding call to prepare_payload method.
|
|
146
146
|
*
|
|
147
147
|
* Required for block producing
|
|
148
|
-
* https://github.com/ethereum/consensus-specs/blob/
|
|
148
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/merge/validator.md#get_payload
|
|
149
149
|
*/
|
|
150
150
|
getPayload(
|
|
151
151
|
fork: ForkName,
|
|
@@ -3,6 +3,7 @@ import {NotReorgedReason} from "@lodestar/fork-choice";
|
|
|
3
3
|
import {ArchiveStoreTask} from "../../chain/archiveStore/archiveStore.js";
|
|
4
4
|
import {FrequencyStateArchiveStep} from "../../chain/archiveStore/strategies/frequencyStateArchiveStrategy.js";
|
|
5
5
|
import {BlockInputSource} from "../../chain/blocks/blockInput/index.js";
|
|
6
|
+
import {PayloadEnvelopeInputSource} from "../../chain/blocks/payloadEnvelopeInput/index.js";
|
|
6
7
|
import {JobQueueItemType} from "../../chain/bls/index.js";
|
|
7
8
|
import {AttestationErrorCode, BlockErrorCode} from "../../chain/errors/index.js";
|
|
8
9
|
import {
|
|
@@ -237,6 +238,56 @@ export function createLodestarMetrics(
|
|
|
237
238
|
}),
|
|
238
239
|
},
|
|
239
240
|
|
|
241
|
+
payloadEnvelopeProcessorQueue: {
|
|
242
|
+
length: register.gauge({
|
|
243
|
+
name: "lodestar_payload_envelope_processor_queue_length",
|
|
244
|
+
help: "Count of total payload envelope processor queue length",
|
|
245
|
+
}),
|
|
246
|
+
droppedJobs: register.gauge({
|
|
247
|
+
name: "lodestar_payload_envelope_processor_queue_dropped_jobs_total",
|
|
248
|
+
help: "Count of total payload envelope processor queue dropped jobs",
|
|
249
|
+
}),
|
|
250
|
+
jobTime: register.histogram({
|
|
251
|
+
name: "lodestar_payload_envelope_processor_queue_job_time_seconds",
|
|
252
|
+
help: "Time to process payload envelope processor queue job in seconds",
|
|
253
|
+
buckets: [0.01, 0.1, 1, 4, 12],
|
|
254
|
+
}),
|
|
255
|
+
jobWaitTime: register.histogram({
|
|
256
|
+
name: "lodestar_payload_envelope_processor_queue_job_wait_time_seconds",
|
|
257
|
+
help: "Time from job added to the payload envelope processor queue to starting in seconds",
|
|
258
|
+
buckets: [0.01, 0.1, 1, 4, 12],
|
|
259
|
+
}),
|
|
260
|
+
concurrency: register.gauge({
|
|
261
|
+
name: "lodestar_payload_envelope_processor_queue_concurrency",
|
|
262
|
+
help: "Current concurrency of payload envelope processor queue",
|
|
263
|
+
}),
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
unfinalizedPayloadEnvelopeWritesQueue: {
|
|
267
|
+
length: register.gauge({
|
|
268
|
+
name: "lodestar_unfinalized_payload_envelope_writes_queue_length",
|
|
269
|
+
help: "Count of total unfinalized payload envelope writes queue length",
|
|
270
|
+
}),
|
|
271
|
+
droppedJobs: register.gauge({
|
|
272
|
+
name: "lodestar_unfinalized_payload_envelope_writes_queue_dropped_jobs_total",
|
|
273
|
+
help: "Count of total unfinalized payload envelope writes queue dropped jobs",
|
|
274
|
+
}),
|
|
275
|
+
jobTime: register.histogram({
|
|
276
|
+
name: "lodestar_unfinalized_payload_envelope_writes_queue_job_time_seconds",
|
|
277
|
+
help: "Time to process unfinalized payload envelope writes queue job in seconds",
|
|
278
|
+
buckets: [0.01, 0.1, 1, 4, 12],
|
|
279
|
+
}),
|
|
280
|
+
jobWaitTime: register.histogram({
|
|
281
|
+
name: "lodestar_unfinalized_payload_envelope_writes_queue_job_wait_time_seconds",
|
|
282
|
+
help: "Time from job added to the unfinalized payload envelope writes queue to starting in seconds",
|
|
283
|
+
buckets: [0.01, 0.1, 1, 4, 12],
|
|
284
|
+
}),
|
|
285
|
+
concurrency: register.gauge({
|
|
286
|
+
name: "lodestar_unfinalized_payload_envelope_writes_queue_concurrency",
|
|
287
|
+
help: "Current concurrency of unfinalized payload envelope writes queue",
|
|
288
|
+
}),
|
|
289
|
+
},
|
|
290
|
+
|
|
240
291
|
engineHttpProcessorQueue: {
|
|
241
292
|
length: register.gauge({
|
|
242
293
|
name: "lodestar_engine_http_processor_queue_length",
|
|
@@ -925,6 +976,18 @@ export function createLodestarMetrics(
|
|
|
925
976
|
labelNames: ["reason"],
|
|
926
977
|
}),
|
|
927
978
|
},
|
|
979
|
+
importPayload: {
|
|
980
|
+
bySource: register.gauge<{source: PayloadEnvelopeInputSource}>({
|
|
981
|
+
name: "lodestar_import_payload_by_source_total",
|
|
982
|
+
help: "Total number of imported execution payload envelopes by source",
|
|
983
|
+
labelNames: ["source"],
|
|
984
|
+
}),
|
|
985
|
+
columnsBySource: register.gauge<{source: PayloadEnvelopeInputSource}>({
|
|
986
|
+
name: "lodestar_import_payload_columns_by_source_total",
|
|
987
|
+
help: "Total number of payload-attached columns (sampled columns for Gloas) by source",
|
|
988
|
+
labelNames: ["source"],
|
|
989
|
+
}),
|
|
990
|
+
},
|
|
928
991
|
engineNotifyNewPayloadResult: register.gauge<{result: ExecutionPayloadStatus}>({
|
|
929
992
|
name: "lodestar_execution_engine_notify_new_payload_result_total",
|
|
930
993
|
help: "The total result of calling notifyNewPayload execution engine api",
|
|
@@ -1495,6 +1558,20 @@ export function createLodestarMetrics(
|
|
|
1495
1558
|
help: "Number of BlockInputs created via a data column being seen first",
|
|
1496
1559
|
}),
|
|
1497
1560
|
},
|
|
1561
|
+
payloadEnvelopeInput: {
|
|
1562
|
+
count: register.gauge({
|
|
1563
|
+
name: "lodestar_seen_payload_envelope_input_cache_size",
|
|
1564
|
+
help: "Number of cached PayloadEnvelopeInputs",
|
|
1565
|
+
}),
|
|
1566
|
+
serializedObjectRefs: register.gauge({
|
|
1567
|
+
name: "lodestar_seen_payload_envelope_input_cache_serialized_object_refs",
|
|
1568
|
+
help: "Number of serialized-cache object refs retained by cached PayloadEnvelopeInputs",
|
|
1569
|
+
}),
|
|
1570
|
+
created: register.counter({
|
|
1571
|
+
name: "lodestar_seen_payload_envelope_input_cache_items_created_total",
|
|
1572
|
+
help: "Number of PayloadEnvelopeInputs created",
|
|
1573
|
+
}),
|
|
1574
|
+
},
|
|
1498
1575
|
},
|
|
1499
1576
|
|
|
1500
1577
|
processFinalizedCheckpoint: {
|
|
@@ -1635,33 +1712,37 @@ export function createLodestarMetrics(
|
|
|
1635
1712
|
}),
|
|
1636
1713
|
},
|
|
1637
1714
|
|
|
1638
|
-
//
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
name: "
|
|
1642
|
-
help: "Total number of gossip
|
|
1715
|
+
// some gossip messages need to wait for block to be processed before they can be processed
|
|
1716
|
+
awaitingBlockGossipMessages: {
|
|
1717
|
+
queue: register.gauge<{topic: GossipType}>({
|
|
1718
|
+
name: "lodestar_awaiting_block_gossip_messages_total",
|
|
1719
|
+
help: "Total number of gossip messages waiting for block to be processed",
|
|
1720
|
+
labelNames: ["topic"],
|
|
1643
1721
|
}),
|
|
1644
1722
|
countPerSlot: register.gauge({
|
|
1645
|
-
name: "
|
|
1646
|
-
help: "Total number of gossip
|
|
1723
|
+
name: "lodestar_awaiting_block_gossip_messages_per_slot_total",
|
|
1724
|
+
help: "Total number of gossip messages waiting for block to be processed per slot",
|
|
1647
1725
|
}),
|
|
1648
|
-
resolve: register.gauge({
|
|
1649
|
-
name: "
|
|
1650
|
-
help: "Total number of gossip
|
|
1726
|
+
resolve: register.gauge<{topic: GossipType}>({
|
|
1727
|
+
name: "lodestar_awaiting_block_gossip_messages_resolve_total",
|
|
1728
|
+
help: "Total number of gossip messages are reprocessed",
|
|
1729
|
+
labelNames: ["topic"],
|
|
1651
1730
|
}),
|
|
1652
|
-
waitSecBeforeResolve: register.gauge({
|
|
1653
|
-
name: "
|
|
1731
|
+
waitSecBeforeResolve: register.gauge<{topic: GossipType}>({
|
|
1732
|
+
name: "lodestar_awaiting_block_gossip_messages_wait_time_resolve_seconds",
|
|
1654
1733
|
help: "Time to wait for unknown block in seconds",
|
|
1734
|
+
labelNames: ["topic"],
|
|
1655
1735
|
}),
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1736
|
+
// having 2 labels here is not great for performance, however it's rarely happening and having the reason label is important for debugging
|
|
1737
|
+
reject: register.gauge<{reason: ReprocessRejectReason; topic: GossipType}>({
|
|
1738
|
+
name: "lodestar_awaiting_block_gossip_messages_reject_total",
|
|
1739
|
+
help: "Total number of gossip messages are rejected to reprocess",
|
|
1740
|
+
labelNames: ["reason", "topic"],
|
|
1660
1741
|
}),
|
|
1661
|
-
waitSecBeforeReject: register.gauge<{reason: ReprocessRejectReason}>({
|
|
1662
|
-
name: "
|
|
1742
|
+
waitSecBeforeReject: register.gauge<{reason: ReprocessRejectReason; topic: GossipType}>({
|
|
1743
|
+
name: "lodestar_awaiting_block_gossip_messages_wait_time_reject_seconds",
|
|
1663
1744
|
help: "Time to wait for unknown block before being rejected",
|
|
1664
|
-
labelNames: ["reason"],
|
|
1745
|
+
labelNames: ["reason", "topic"],
|
|
1665
1746
|
}),
|
|
1666
1747
|
},
|
|
1667
1748
|
|
|
@@ -24,12 +24,28 @@ const decoder = new snappyWasm.Decoder();
|
|
|
24
24
|
// Shared buffer to convert msgId to string
|
|
25
25
|
const sharedMsgIdBuf = Buffer.alloc(20);
|
|
26
26
|
|
|
27
|
+
// Cache topic -> seed to avoid per-message allocations on the hot path.
|
|
28
|
+
// Topics are a fixed set per fork (changes only at fork boundaries).
|
|
29
|
+
const topicSeedCache = new Map<string, bigint>();
|
|
30
|
+
|
|
27
31
|
/**
|
|
28
32
|
* The function used to generate a gossipsub message id
|
|
29
33
|
* We use the first 8 bytes of SHA256(data) for content addressing
|
|
30
34
|
*/
|
|
31
35
|
export function fastMsgIdFn(rpcMsg: RPC.Message): string {
|
|
32
36
|
if (rpcMsg.data) {
|
|
37
|
+
if (rpcMsg.topic) {
|
|
38
|
+
// Use topic-derived seed to prevent cross-topic deduplication of identical messages.
|
|
39
|
+
// SyncCommitteeMessages are published to multiple sync_committee_{subnet} topics with
|
|
40
|
+
// identical data, so hashing only the data incorrectly deduplicates across subnets.
|
|
41
|
+
// See https://github.com/ChainSafe/lodestar/issues/8294
|
|
42
|
+
let topicSeed = topicSeedCache.get(rpcMsg.topic);
|
|
43
|
+
if (topicSeed === undefined) {
|
|
44
|
+
topicSeed = xxhash.h64Raw(Buffer.from(rpcMsg.topic), h64Seed);
|
|
45
|
+
topicSeedCache.set(rpcMsg.topic, topicSeed);
|
|
46
|
+
}
|
|
47
|
+
return xxhash.h64Raw(rpcMsg.data, topicSeed).toString(16);
|
|
48
|
+
}
|
|
33
49
|
return xxhash.h64Raw(rpcMsg.data, h64Seed).toString(16);
|
|
34
50
|
}
|
|
35
51
|
return "0000000000000000";
|
package/src/network/interface.ts
CHANGED
|
@@ -68,7 +68,7 @@ export interface INetwork extends INetworkCorePublic {
|
|
|
68
68
|
reportPeer(peer: PeerIdStr, action: PeerAction, actionName: string): void;
|
|
69
69
|
shouldAggregate(subnet: SubnetID, slot: Slot): boolean;
|
|
70
70
|
reStatusPeers(peers: PeerIdStr[]): Promise<void>;
|
|
71
|
-
|
|
71
|
+
searchUnknownBlock(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void;
|
|
72
72
|
// ReqResp
|
|
73
73
|
sendBeaconBlocksByRange(peerId: PeerIdStr, request: phase0.BeaconBlocksByRangeRequest): Promise<SignedBeaconBlock[]>;
|
|
74
74
|
sendBeaconBlocksByRoot(peerId: PeerIdStr, request: BeaconBlocksByRootRequest): Promise<SignedBeaconBlock[]>;
|
package/src/network/network.ts
CHANGED
|
@@ -277,8 +277,8 @@ export class Network implements INetwork {
|
|
|
277
277
|
return this.core.reStatusPeers(peers);
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
|
|
281
|
-
this.networkProcessor.
|
|
280
|
+
searchUnknownBlock(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
|
|
281
|
+
this.networkProcessor.searchUnknownBlock(slotRoot, source, peer);
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
async reportPeer(peer: PeerIdStr, action: PeerAction, actionName: string): Promise<void> {
|
|
@@ -721,7 +721,7 @@ export class Network implements INetwork {
|
|
|
721
721
|
|
|
722
722
|
try {
|
|
723
723
|
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
724
|
-
// https://github.com/ethereum/consensus-specs/blob/
|
|
724
|
+
// https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
725
725
|
await this.waitForSyncMessageCutoff(finalityUpdate.signatureSlot);
|
|
726
726
|
await this.publishLightClientFinalityUpdate(finalityUpdate);
|
|
727
727
|
} catch (e) {
|
|
@@ -738,7 +738,7 @@ export class Network implements INetwork {
|
|
|
738
738
|
|
|
739
739
|
try {
|
|
740
740
|
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
741
|
-
// https://github.com/ethereum/consensus-specs/blob/
|
|
741
|
+
// https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
742
742
|
await this.waitForSyncMessageCutoff(optimisticUpdate.signatureSlot);
|
|
743
743
|
await this.publishLightClientOptimisticUpdate(optimisticUpdate);
|
|
744
744
|
} catch (e) {
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import {ForkName} from "@lodestar/params";
|
|
1
|
+
import {ForkName, isForkPostGloas} from "@lodestar/params";
|
|
2
2
|
import {SlotOptionalRoot, SlotRootHex} from "@lodestar/types";
|
|
3
3
|
import {
|
|
4
|
+
getBeaconBlockRootFromDataColumnSidecarSerialized,
|
|
5
|
+
getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized,
|
|
4
6
|
getBlockRootFromBeaconAttestationSerialized,
|
|
5
7
|
getBlockRootFromSignedAggregateAndProofSerialized,
|
|
6
8
|
getSlotFromBeaconAttestationSerialized,
|
|
7
9
|
getSlotFromBlobSidecarSerialized,
|
|
8
10
|
getSlotFromDataColumnSidecarSerialized,
|
|
11
|
+
getSlotFromExecutionPayloadEnvelopeSerialized,
|
|
9
12
|
getSlotFromSignedAggregateAndProofSerialized,
|
|
10
13
|
getSlotFromSignedBeaconBlockSerialized,
|
|
11
14
|
} from "../../util/sszBytes.js";
|
|
@@ -14,7 +17,7 @@ import {ExtractSlotRootFns} from "./types.js";
|
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* Extract the slot and block root of a gossip message form serialized data.
|
|
17
|
-
*
|
|
20
|
+
* Not applicable for all topics.
|
|
18
21
|
*/
|
|
19
22
|
export function createExtractBlockSlotRootFns(): ExtractSlotRootFns {
|
|
20
23
|
return {
|
|
@@ -52,13 +55,23 @@ export function createExtractBlockSlotRootFns(): ExtractSlotRootFns {
|
|
|
52
55
|
}
|
|
53
56
|
return {slot};
|
|
54
57
|
},
|
|
55
|
-
[GossipType.data_column_sidecar]: (data: Uint8Array): SlotOptionalRoot | null => {
|
|
56
|
-
const slot = getSlotFromDataColumnSidecarSerialized(data);
|
|
57
|
-
|
|
58
|
+
[GossipType.data_column_sidecar]: (data: Uint8Array, fork: ForkName): SlotOptionalRoot | null => {
|
|
59
|
+
const slot = getSlotFromDataColumnSidecarSerialized(data, fork);
|
|
58
60
|
if (slot === null) {
|
|
59
61
|
return null;
|
|
60
62
|
}
|
|
61
|
-
|
|
63
|
+
|
|
64
|
+
const root = isForkPostGloas(fork) ? getBeaconBlockRootFromDataColumnSidecarSerialized(data) : null;
|
|
65
|
+
return root !== null ? {slot, root} : {slot};
|
|
66
|
+
},
|
|
67
|
+
[GossipType.execution_payload]: (data: Uint8Array): SlotRootHex | null => {
|
|
68
|
+
const slot = getSlotFromExecutionPayloadEnvelopeSerialized(data);
|
|
69
|
+
const root = getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized(data);
|
|
70
|
+
|
|
71
|
+
if (slot === null || root === null) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
return {slot, root};
|
|
62
75
|
},
|
|
63
76
|
};
|
|
64
77
|
}
|