@lodestar/beacon-node 1.48.0-dev.3211c1bdd4 → 1.48.0-dev.386c085495
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/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +39 -39
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +0 -13
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/index.d.ts +8 -4
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +16 -18
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +8 -0
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/types.js.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.js +10 -1
- package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
- package/lib/chain/chain.d.ts +7 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +69 -40
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +1 -1
- package/lib/chain/emitter.js +1 -1
- package/lib/chain/errors/blockError.d.ts +3 -5
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +2 -2
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +0 -11
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +0 -2
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/errors/gossipValidation.d.ts +2 -1
- package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
- package/lib/chain/errors/gossipValidation.js +1 -0
- package/lib/chain/errors/gossipValidation.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.js +13 -13
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +46 -64
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +9 -50
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +0 -29
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +7 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +22 -5
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +4 -1
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +11 -0
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/rateLimit.js +2 -1
- package/lib/network/reqresp/rateLimit.js.map +1 -1
- package/lib/sync/range/range.d.ts.map +1 -1
- package/lib/sync/range/range.js +24 -1
- package/lib/sync/range/range.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/validator/index.ts +44 -43
- package/src/chain/blocks/importBlock.ts +0 -13
- package/src/chain/blocks/index.ts +31 -25
- package/src/chain/blocks/types.ts +9 -0
- package/src/chain/blocks/utils/chainSegment.ts +10 -1
- package/src/chain/chain.ts +78 -50
- package/src/chain/emitter.ts +1 -1
- package/src/chain/errors/blockError.ts +3 -3
- package/src/chain/errors/executionPayloadEnvelope.ts +0 -9
- package/src/chain/errors/gossipValidation.ts +1 -0
- package/src/chain/interface.ts +2 -2
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/prepareNextSlot.ts +16 -16
- package/src/chain/produceBlock/produceBlockBody.ts +50 -71
- package/src/chain/validation/block.ts +9 -66
- package/src/chain/validation/executionPayloadEnvelope.ts +0 -37
- package/src/chain/validatorMonitor.ts +24 -7
- package/src/execution/engine/mock.ts +4 -1
- package/src/network/processor/index.ts +13 -0
- package/src/network/reqresp/rateLimit.ts +2 -1
- package/src/sync/range/range.ts +23 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {MIN_ATTESTATION_INCLUSION_DELAY, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
2
|
+
import {MIN_ATTESTATION_INCLUSION_DELAY, SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
|
|
3
3
|
import {
|
|
4
4
|
IBeaconStateView,
|
|
5
5
|
ParticipationFlags,
|
|
@@ -1117,7 +1117,11 @@ function isCanonical(rootCache: RootHexCache, block: AttestationBlockInclusion):
|
|
|
1117
1117
|
|
|
1118
1118
|
/** Returns true if root at slot is the same at slot - 1 == there was no new block at slot */
|
|
1119
1119
|
function isMissedSlot(rootCache: RootHexCache, slot: Slot): boolean {
|
|
1120
|
-
|
|
1120
|
+
if (slot <= 0) {
|
|
1121
|
+
return false;
|
|
1122
|
+
}
|
|
1123
|
+
const root = rootCache.getBlockRootAtSlot(slot);
|
|
1124
|
+
return root !== null && root === rootCache.getBlockRootAtSlot(slot - 1);
|
|
1121
1125
|
}
|
|
1122
1126
|
|
|
1123
1127
|
function renderBlockProposalSummary(
|
|
@@ -1131,7 +1135,11 @@ function renderBlockProposalSummary(
|
|
|
1131
1135
|
return "not_submitted";
|
|
1132
1136
|
}
|
|
1133
1137
|
|
|
1134
|
-
|
|
1138
|
+
const canonicalRoot = rootCache.getBlockRootAtSlot(proposalSlot);
|
|
1139
|
+
if (canonicalRoot === null) {
|
|
1140
|
+
return "unknown";
|
|
1141
|
+
}
|
|
1142
|
+
if (canonicalRoot === proposal.blockRoot) {
|
|
1135
1143
|
// Canonical state includes our block
|
|
1136
1144
|
return "canonical";
|
|
1137
1145
|
}
|
|
@@ -1157,14 +1165,23 @@ function renderBlockProposalSummary(
|
|
|
1157
1165
|
* In normal network conditions the same root is read multiple times, specially the target.
|
|
1158
1166
|
*/
|
|
1159
1167
|
export class RootHexCache {
|
|
1160
|
-
private readonly blockRootSlotCache = new Map<Slot, RootHex>();
|
|
1168
|
+
private readonly blockRootSlotCache = new Map<Slot, RootHex | null>();
|
|
1161
1169
|
|
|
1162
1170
|
constructor(private readonly state: IBeaconStateView) {}
|
|
1163
1171
|
|
|
1164
|
-
|
|
1172
|
+
/**
|
|
1173
|
+
* Block root at `slot`, null if the state does not cover it: slots at or after the state's own slot (an inclusion
|
|
1174
|
+
* in a block the head state does not know yet, e.g. an orphaned block, or the slot after the last attestation of
|
|
1175
|
+
* the epoch) or slots older than `SLOTS_PER_HISTORICAL_ROOT`. Callers treat null as unknown instead of throwing
|
|
1176
|
+
* and aborting the summaries of all remaining validators.
|
|
1177
|
+
*/
|
|
1178
|
+
getBlockRootAtSlot(slot: Slot): RootHex | null {
|
|
1165
1179
|
let root = this.blockRootSlotCache.get(slot);
|
|
1166
|
-
if (
|
|
1167
|
-
root =
|
|
1180
|
+
if (root === undefined) {
|
|
1181
|
+
root =
|
|
1182
|
+
slot < this.state.slot && slot >= this.state.slot - SLOTS_PER_HISTORICAL_ROOT
|
|
1183
|
+
? toRootHex(this.state.getBlockRootAtSlot(slot))
|
|
1184
|
+
: null;
|
|
1168
1185
|
this.blockRootSlotCache.set(slot, root);
|
|
1169
1186
|
}
|
|
1170
1187
|
return root;
|
|
@@ -296,7 +296,10 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend {
|
|
|
296
296
|
|
|
297
297
|
// 5. Client software MUST update its forkchoice state if payloads referenced by forkchoiceState.headBlockHash and
|
|
298
298
|
// forkchoiceState.finalizedBlockHash are VALID.
|
|
299
|
-
|
|
299
|
+
//
|
|
300
|
+
// A zero finalizedBlockHash means "no finalized execution block" (e.g. the finalized checkpoint has no execution
|
|
301
|
+
// payload, pre-merge/pre-TTD). Real EL clients accept this, so the mock must not treat it as an unknown block.
|
|
302
|
+
if (finalizedBlockHash !== ZERO_HASH_HEX && !this.validBlocks.has(finalizedBlockHash)) {
|
|
300
303
|
throw Error(`Unknown finalizedBlockHash ${finalizedBlockHash}`);
|
|
301
304
|
}
|
|
302
305
|
this.headBlockHash = headBlockHash;
|
|
@@ -360,6 +360,19 @@ export class NetworkProcessor {
|
|
|
360
360
|
return;
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
+
// DOS protection: drop far-future messages before allocating any unknown-root tracking entry.
|
|
364
|
+
// Bound each topic to what its gossip validator accepts; only execution_payload_bid accepts the next slot.
|
|
365
|
+
const latestPermissableSlot =
|
|
366
|
+
this.chain.clock.currentSlotWithGossipDisparity + (topicType === GossipType.execution_payload_bid ? 1 : 0);
|
|
367
|
+
if (slot > latestPermissableSlot) {
|
|
368
|
+
// No need to report the dropped job to gossip. It will be eventually pruned from the mcache
|
|
369
|
+
this.metrics?.networkProcessor.gossipValidationError.inc({
|
|
370
|
+
topic: topicType,
|
|
371
|
+
error: GossipErrorCode.FUTURE_SLOT,
|
|
372
|
+
});
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
363
376
|
message.msgSlot = slot;
|
|
364
377
|
|
|
365
378
|
// this determines whether this message needs to wait for a Block or Envelope
|
|
@@ -126,7 +126,8 @@ function getRequestCountFn<T extends ReqRespMethod>(
|
|
|
126
126
|
const type = requestSszTypeByMethod(fork, config)[method];
|
|
127
127
|
return (reqData: Uint8Array) => {
|
|
128
128
|
try {
|
|
129
|
-
|
|
129
|
+
// A schema-valid request can cost 0 tokens; floor to 1 so it stays charged and bannable, not free.
|
|
130
|
+
return Math.max(1, (type && fn(type.deserialize(reqData))) ?? 1);
|
|
130
131
|
} catch (_e) {
|
|
131
132
|
return 1;
|
|
132
133
|
}
|
package/src/sync/range/range.ts
CHANGED
|
@@ -217,7 +217,29 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
} else {
|
|
220
|
-
await this.chain.processChainSegment(blocks, payloadEnvelopes, flags);
|
|
220
|
+
const {orphaned, skipped} = await this.chain.processChainSegment(blocks, payloadEnvelopes, flags);
|
|
221
|
+
// We log orphaned payloads to work with different clients
|
|
222
|
+
// in the future, consider applying penalties in certain conditions
|
|
223
|
+
// make sure the payload source was from range sync in that case
|
|
224
|
+
for (const {slot, payloadEnvelopeInput} of orphaned) {
|
|
225
|
+
const {peerIdStr, source} = payloadEnvelopeInput.getPayloadEnvelopeSource();
|
|
226
|
+
let client = "unknown";
|
|
227
|
+
if (peerIdStr !== undefined) {
|
|
228
|
+
try {
|
|
229
|
+
client = this.getConnectedPeerSyncMeta(peerIdStr).client;
|
|
230
|
+
} catch {
|
|
231
|
+
// peer disconnected since serving the envelope, keep "unknown"
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
this.logger.debug("Orphaned payload envelope in range sync batch", {
|
|
235
|
+
slot,
|
|
236
|
+
root: payloadEnvelopeInput.blockRootHex,
|
|
237
|
+
peer: peerIdStr ?? "unknown",
|
|
238
|
+
source,
|
|
239
|
+
client,
|
|
240
|
+
skipped,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
221
243
|
}
|
|
222
244
|
};
|
|
223
245
|
|