@lodestar/beacon-node 1.49.0-dev.9d1b583d24 → 1.49.0-dev.9ec766d7e0
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.js +2 -2
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +4 -2
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +9 -7
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +1 -2
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +0 -5
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.js +4 -6
- package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.js +14 -3
- package/lib/chain/archiveStore/utils/pruneHistory.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +13 -0
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.js +2 -2
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/emitter.d.ts +10 -0
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +4 -0
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/attesterSlashingError.d.ts +4 -1
- package/lib/chain/errors/attesterSlashingError.d.ts.map +1 -1
- package/lib/chain/errors/attesterSlashingError.js +1 -0
- package/lib/chain/errors/attesterSlashingError.js.map +1 -1
- package/lib/chain/errors/payloadAttestation.d.ts +4 -0
- package/lib/chain/errors/payloadAttestation.d.ts.map +1 -1
- package/lib/chain/errors/payloadAttestation.js +1 -0
- package/lib/chain/errors/payloadAttestation.js.map +1 -1
- package/lib/chain/errors/proposerSlashingError.d.ts +4 -1
- package/lib/chain/errors/proposerSlashingError.d.ts.map +1 -1
- package/lib/chain/errors/proposerSlashingError.js +1 -0
- package/lib/chain/errors/proposerSlashingError.js.map +1 -1
- package/lib/chain/options.d.ts +0 -4
- 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/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +4 -2
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +6 -6
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +2 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +3 -2
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +1 -2
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +8 -1
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -2
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +2 -2
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/db/beacon.d.ts +1 -2
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +1 -3
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/buckets.d.ts +0 -1
- package/lib/db/buckets.d.ts.map +1 -1
- package/lib/db/buckets.js +1 -1
- package/lib/db/buckets.js.map +1 -1
- package/lib/db/interface.d.ts +1 -2
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.d.ts +5 -0
- package/lib/db/repositories/blockArchive.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.js +36 -1
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/index.d.ts +0 -1
- package/lib/db/repositories/index.d.ts.map +1 -1
- package/lib/db/repositories/index.js +0 -1
- package/lib/db/repositories/index.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +26 -14
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +53 -24
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts +1 -2
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +5 -10
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/gossipsub.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.js +16 -1
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +9 -6
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +23 -8
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +16 -5
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipValidatorFn.d.ts +2 -0
- package/lib/network/processor/gossipValidatorFn.d.ts.map +1 -1
- package/lib/network/processor/gossipValidatorFn.js +88 -7
- package/lib/network/processor/gossipValidatorFn.js.map +1 -1
- package/lib/network/processor/index.d.ts +6 -2
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +62 -24
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/protocols.d.ts.map +1 -1
- package/lib/network/reqresp/protocols.js +19 -5
- package/lib/network/reqresp/protocols.js.map +1 -1
- package/lib/node/nodejs.d.ts +2 -7
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +2 -22
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/interface.d.ts +1 -2
- package/lib/sync/interface.d.ts.map +1 -1
- package/lib/sync/options.d.ts +0 -6
- package/lib/sync/options.d.ts.map +1 -1
- package/lib/sync/options.js +0 -2
- package/lib/sync/options.js.map +1 -1
- package/lib/sync/types.d.ts +39 -0
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +42 -0
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +20 -0
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +190 -13
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/util/shuffle.d.ts +0 -4
- package/lib/util/shuffle.d.ts.map +1 -1
- package/lib/util/shuffle.js +0 -8
- package/lib/util/shuffle.js.map +1 -1
- package/lib/util/sszBytes.d.ts +5 -0
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +13 -1
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +15 -16
- package/src/api/impl/beacon/blocks/index.ts +2 -2
- package/src/api/impl/beacon/pool/index.ts +6 -2
- package/src/api/impl/validator/index.ts +9 -7
- package/src/chain/archiveStore/archiveStore.ts +0 -6
- package/src/chain/archiveStore/historicalState/metrics.ts +4 -7
- package/src/chain/archiveStore/utils/pruneHistory.ts +14 -4
- package/src/chain/blocks/importExecutionPayload.ts +14 -0
- package/src/chain/blocks/index.ts +2 -2
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +1 -1
- package/src/chain/emitter.ts +7 -2
- package/src/chain/errors/attesterSlashingError.ts +3 -1
- package/src/chain/errors/payloadAttestation.ts +2 -0
- package/src/chain/errors/proposerSlashingError.ts +3 -1
- package/src/chain/options.ts +0 -5
- package/src/chain/produceBlock/computeNewStateRoot.ts +9 -2
- package/src/chain/produceBlock/produceBlockBody.ts +17 -6
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +3 -2
- package/src/chain/validation/attesterSlashing.ts +1 -2
- package/src/chain/validation/payloadAttestationMessage.ts +9 -0
- package/src/chain/validation/proposerSlashing.ts +1 -2
- package/src/chain/validatorMonitor.ts +12 -2
- package/src/db/beacon.ts +0 -5
- package/src/db/buckets.ts +1 -1
- package/src/db/interface.ts +0 -3
- package/src/db/repositories/blockArchive.ts +38 -1
- package/src/db/repositories/index.ts +0 -1
- package/src/metrics/metrics/lodestar.ts +63 -28
- package/src/network/gossip/encoding.ts +5 -8
- package/src/network/gossip/gossipsub.ts +19 -2
- package/src/network/gossip/topic.ts +25 -7
- package/src/network/processor/gossipHandlers.ts +18 -5
- package/src/network/processor/gossipValidatorFn.ts +111 -7
- package/src/network/processor/index.ts +81 -24
- package/src/network/reqresp/protocols.ts +31 -6
- package/src/node/nodejs.ts +0 -27
- package/src/sync/interface.ts +1 -2
- package/src/sync/options.ts +0 -8
- package/src/sync/types.ts +44 -3
- package/src/sync/unknownBlock.ts +213 -13
- package/src/util/shuffle.ts +0 -9
- package/src/util/sszBytes.ts +18 -0
- package/lib/chain/archiveStore/utils/updateBackfillRange.d.ts +0 -20
- package/lib/chain/archiveStore/utils/updateBackfillRange.d.ts.map +0 -1
- package/lib/chain/archiveStore/utils/updateBackfillRange.js +0 -40
- package/lib/chain/archiveStore/utils/updateBackfillRange.js.map +0 -1
- package/lib/db/repositories/backfilledRanges.d.ts +0 -18
- package/lib/db/repositories/backfilledRanges.d.ts.map +0 -1
- package/lib/db/repositories/backfilledRanges.js +0 -26
- package/lib/db/repositories/backfilledRanges.js.map +0 -1
- package/lib/sync/backfill/backfill.d.ts +0 -169
- package/lib/sync/backfill/backfill.d.ts.map +0 -1
- package/lib/sync/backfill/backfill.js +0 -686
- package/lib/sync/backfill/backfill.js.map +0 -1
- package/lib/sync/backfill/errors.d.ts +0 -30
- package/lib/sync/backfill/errors.d.ts.map +0 -1
- package/lib/sync/backfill/errors.js +0 -15
- package/lib/sync/backfill/errors.js.map +0 -1
- package/lib/sync/backfill/index.d.ts +0 -2
- package/lib/sync/backfill/index.d.ts.map +0 -1
- package/lib/sync/backfill/index.js +0 -2
- package/lib/sync/backfill/index.js.map +0 -1
- package/lib/sync/backfill/verify.d.ts +0 -18
- package/lib/sync/backfill/verify.d.ts.map +0 -1
- package/lib/sync/backfill/verify.js +0 -36
- package/lib/sync/backfill/verify.js.map +0 -1
- package/src/chain/archiveStore/utils/updateBackfillRange.ts +0 -50
- package/src/db/repositories/backfilledRanges.ts +0 -29
- package/src/sync/backfill/backfill.ts +0 -916
- package/src/sync/backfill/errors.ts +0 -23
- package/src/sync/backfill/index.ts +0 -1
- package/src/sync/backfill/verify.ts +0 -58
package/lib/sync/options.d.ts
CHANGED
|
@@ -13,12 +13,6 @@ export type SyncOptions = {
|
|
|
13
13
|
disableRangeSync?: boolean;
|
|
14
14
|
/** USE FOR TESTING ONLY. Disable unknown block sync completely */
|
|
15
15
|
disableBlockInputSync?: boolean;
|
|
16
|
-
/**
|
|
17
|
-
* The batch size of slots for backfill sync can attempt to sync/process before yielding
|
|
18
|
-
* to sync loop. This number can be increased or decreased to make a suitable resource
|
|
19
|
-
* allocation to backfill sync. The default of 0 would mean backfill sync will be skipped
|
|
20
|
-
*/
|
|
21
|
-
backfillBatchSize: number;
|
|
22
16
|
/** For testing only, MAX_PENDING_BLOCKS by default */
|
|
23
17
|
maxPendingBlocks?: number;
|
|
24
18
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/sync/options.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IAEvC,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kEAAkE;IAClE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/sync/options.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IAEvC,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kEAAkE;IAClE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,WAIhC,CAAC"}
|
package/lib/sync/options.js
CHANGED
|
@@ -2,8 +2,6 @@ import { SLOTS_PER_EPOCH } from "@lodestar/params";
|
|
|
2
2
|
export const defaultSyncOptions = {
|
|
3
3
|
isSingleNode: false,
|
|
4
4
|
disableProcessAsChainSegment: false,
|
|
5
|
-
/** By default skip the backfill sync */
|
|
6
|
-
backfillBatchSize: 0,
|
|
7
5
|
slotImportTolerance: SLOTS_PER_EPOCH,
|
|
8
6
|
};
|
|
9
7
|
//# sourceMappingURL=options.js.map
|
package/lib/sync/options.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/sync/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/sync/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAgCjD,MAAM,CAAC,MAAM,kBAAkB,GAAgB;IAC7C,YAAY,EAAE,KAAK;IACnB,4BAA4B,EAAE,KAAK;IACnC,mBAAmB,EAAE,eAAe;CACrC,CAAC"}
|
package/lib/sync/types.d.ts
CHANGED
|
@@ -20,11 +20,50 @@ export declare enum PendingBlockType {
|
|
|
20
20
|
* Payload analog of UNKNOWN_BLOCK_ROOT: we have a beacon block root but not its execution payload envelope.
|
|
21
21
|
*/
|
|
22
22
|
UNKNOWN_PAYLOAD_BLOCK_ROOT = "unknown_payload_block_root",
|
|
23
|
+
/**
|
|
24
|
+
* Same as UNKNOWN_PAYLOAD_BLOCK_ROOT, but the trigger also carries the payload's slot
|
|
25
|
+
*/
|
|
26
|
+
UNKNOWN_PAYLOAD_BLOCK_ROOT_SLOT = "unknown_payload_block_root_slot",
|
|
27
|
+
/**
|
|
28
|
+
* Same as UNKNOWN_PAYLOAD_BLOCK_ROOT_SLOT for the current slot
|
|
29
|
+
*/
|
|
30
|
+
DEFERRED_PAYLOAD_BLOCK_ROOT = "deferred_payload_block_root",
|
|
23
31
|
/**
|
|
24
32
|
* Payload analog of INCOMPLETE_BLOCK_INPUT: we have a partial payload input that did not complete in time.
|
|
25
33
|
*/
|
|
26
34
|
INCOMPLETE_PAYLOAD_ENVELOPE = "incomplete_payload_envelope"
|
|
27
35
|
}
|
|
36
|
+
export declare enum DownloadResult {
|
|
37
|
+
/** payload fully downloaded, ready to process */
|
|
38
|
+
Resolved = "resolved",
|
|
39
|
+
/** payload fully downloaded, but it was already imported (via gossip) while we were downloading */
|
|
40
|
+
Late = "late",
|
|
41
|
+
/** envelope downloaded, held until the block lands in fork choice */
|
|
42
|
+
WaitingForBlock = "waiting_for_block",
|
|
43
|
+
/** fetch failed, the pending entry is retained for retry */
|
|
44
|
+
Failed = "failed"
|
|
45
|
+
}
|
|
46
|
+
export declare enum FetchResult {
|
|
47
|
+
SuccessResolved = "success_resolved",
|
|
48
|
+
SuccessMissingParent = "success_missing_parent",
|
|
49
|
+
SuccessLate = "success_late",
|
|
50
|
+
SuccessWaitingForBlock = "success_waiting_for_block",
|
|
51
|
+
FailureTriedAllPeers = "failure_tried_all_peers",
|
|
52
|
+
FailureMaxAttempts = "failure_max_attempts"
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Outcome of a slot's deferred optimistic payload searches, recorded once when its poll loop ends.
|
|
56
|
+
*/
|
|
57
|
+
export declare enum DeferredPayloadResult {
|
|
58
|
+
/** gossip delivered every watched payload before PAYLOAD_DUE, no search was needed */
|
|
59
|
+
ImportedBeforeSearch = "imported_before_search",
|
|
60
|
+
/** at least one was missing at PAYLOAD_DUE, we searched, and all were imported afterwards */
|
|
61
|
+
ImportedAfterSearch = "imported_after_search",
|
|
62
|
+
/** something was still not in fork choice when the slot ended */
|
|
63
|
+
Unresolved = "unresolved",
|
|
64
|
+
/** the slot had no optimistic search and no payload import at all, eg a skipped slot */
|
|
65
|
+
ResolvedNoRoot = "resolved_no_root"
|
|
66
|
+
}
|
|
28
67
|
export declare enum PendingBlockInputStatus {
|
|
29
68
|
pending = "pending",
|
|
30
69
|
fetching = "fetching",
|
package/lib/sync/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAC,8BAA8B,EAAC,MAAM,uBAAuB,CAAC;AAErE,OAAO,EAAC,WAAW,EAAC,MAAM,qCAAqC,CAAC;AAChE,OAAO,EAAC,oBAAoB,EAAC,MAAM,8DAA8D,CAAC;AAElG,oBAAY,gBAAgB;IAC1B;;OAEG;IACH,kBAAkB,qBAAqB;IACvC;;OAEG;IACH,cAAc,mBAAmB;IACjC;;;OAGG;IACH,sBAAsB,yBAAyB;IAE/C;;OAEG;IACH,0BAA0B,+BAA+B;IACzD;;OAEG;IACH,2BAA2B,gCAAgC;CAC5D;AAED,oBAAY,uBAAuB;IACjC,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,UAAU,eAAe;IACzB,UAAU,eAAe;CAC1B;AAED;;;;;GAKG;AACH,oBAAY,iBAAiB;IAC3B,2HAA2H;IAC3H,cAAc,oBAAoB;IAClC,wFAAwF;IACxF,OAAO,aAAa;IACpB,4FAA4F;IAC5F,QAAQ,aAAa;IACrB,iEAAiE;IACjE,aAAa,mBAAmB;IAChC,wEAAwE;IACxE,OAAO,aAAa;IACpB,gFAAgF;IAChF,SAAS,eAAe;IACxB,mEAAmE;IACnE,YAAY,kBAAkB;IAC9B,qGAAqG;IACrG,oBAAoB,2BAA2B;IAC/C,kFAAkF;IAClF,eAAe,qBAAqB;IACpC,6DAA6D;IAC7D,gBAAgB,sBAAsB;IACtC,kGAAkG;IAClG,WAAW,gBAAgB;IAC3B,0DAA0D;IAC1D,OAAO,YAAY;CACpB;AAED,oBAAY,yBAAyB;IACnC,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,eAAe,sBAAsB;IACrC,UAAU,eAAe;IACzB,UAAU,eAAe;CAC1B;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,uBAAuB,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,uBAAuB,CAAC,OAAO,GAAG,uBAAuB,CAAC,QAAQ,CAAC;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG,cAAc,CAAC;AAEzE,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EACF,yBAAyB,CAAC,OAAO,GACjC,yBAAyB,CAAC,QAAQ,GAClC,yBAAyB,CAAC,UAAU,GACpC,yBAAyB,CAAC,UAAU,CAAC;IACzC,YAAY,EAAE,oBAAoB,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,yBAAyB,CAAC,OAAO,GAAG,yBAAyB,CAAC,QAAQ,CAAC;IAC/E,OAAO,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"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"}
|
package/lib/sync/types.js
CHANGED
|
@@ -18,11 +18,53 @@ export var PendingBlockType;
|
|
|
18
18
|
* Payload analog of UNKNOWN_BLOCK_ROOT: we have a beacon block root but not its execution payload envelope.
|
|
19
19
|
*/
|
|
20
20
|
PendingBlockType["UNKNOWN_PAYLOAD_BLOCK_ROOT"] = "unknown_payload_block_root";
|
|
21
|
+
/**
|
|
22
|
+
* Same as UNKNOWN_PAYLOAD_BLOCK_ROOT, but the trigger also carries the payload's slot
|
|
23
|
+
*/
|
|
24
|
+
PendingBlockType["UNKNOWN_PAYLOAD_BLOCK_ROOT_SLOT"] = "unknown_payload_block_root_slot";
|
|
25
|
+
/**
|
|
26
|
+
* Same as UNKNOWN_PAYLOAD_BLOCK_ROOT_SLOT for the current slot
|
|
27
|
+
*/
|
|
28
|
+
PendingBlockType["DEFERRED_PAYLOAD_BLOCK_ROOT"] = "deferred_payload_block_root";
|
|
21
29
|
/**
|
|
22
30
|
* Payload analog of INCOMPLETE_BLOCK_INPUT: we have a partial payload input that did not complete in time.
|
|
23
31
|
*/
|
|
24
32
|
PendingBlockType["INCOMPLETE_PAYLOAD_ENVELOPE"] = "incomplete_payload_envelope";
|
|
25
33
|
})(PendingBlockType || (PendingBlockType = {}));
|
|
34
|
+
export var DownloadResult;
|
|
35
|
+
(function (DownloadResult) {
|
|
36
|
+
/** payload fully downloaded, ready to process */
|
|
37
|
+
DownloadResult["Resolved"] = "resolved";
|
|
38
|
+
/** payload fully downloaded, but it was already imported (via gossip) while we were downloading */
|
|
39
|
+
DownloadResult["Late"] = "late";
|
|
40
|
+
/** envelope downloaded, held until the block lands in fork choice */
|
|
41
|
+
DownloadResult["WaitingForBlock"] = "waiting_for_block";
|
|
42
|
+
/** fetch failed, the pending entry is retained for retry */
|
|
43
|
+
DownloadResult["Failed"] = "failed";
|
|
44
|
+
})(DownloadResult || (DownloadResult = {}));
|
|
45
|
+
export var FetchResult;
|
|
46
|
+
(function (FetchResult) {
|
|
47
|
+
FetchResult["SuccessResolved"] = "success_resolved";
|
|
48
|
+
FetchResult["SuccessMissingParent"] = "success_missing_parent";
|
|
49
|
+
FetchResult["SuccessLate"] = "success_late";
|
|
50
|
+
FetchResult["SuccessWaitingForBlock"] = "success_waiting_for_block";
|
|
51
|
+
FetchResult["FailureTriedAllPeers"] = "failure_tried_all_peers";
|
|
52
|
+
FetchResult["FailureMaxAttempts"] = "failure_max_attempts";
|
|
53
|
+
})(FetchResult || (FetchResult = {}));
|
|
54
|
+
/**
|
|
55
|
+
* Outcome of a slot's deferred optimistic payload searches, recorded once when its poll loop ends.
|
|
56
|
+
*/
|
|
57
|
+
export var DeferredPayloadResult;
|
|
58
|
+
(function (DeferredPayloadResult) {
|
|
59
|
+
/** gossip delivered every watched payload before PAYLOAD_DUE, no search was needed */
|
|
60
|
+
DeferredPayloadResult["ImportedBeforeSearch"] = "imported_before_search";
|
|
61
|
+
/** at least one was missing at PAYLOAD_DUE, we searched, and all were imported afterwards */
|
|
62
|
+
DeferredPayloadResult["ImportedAfterSearch"] = "imported_after_search";
|
|
63
|
+
/** something was still not in fork choice when the slot ended */
|
|
64
|
+
DeferredPayloadResult["Unresolved"] = "unresolved";
|
|
65
|
+
/** the slot had no optimistic search and no payload import at all, eg a skipped slot */
|
|
66
|
+
DeferredPayloadResult["ResolvedNoRoot"] = "resolved_no_root";
|
|
67
|
+
})(DeferredPayloadResult || (DeferredPayloadResult = {}));
|
|
26
68
|
export var PendingBlockInputStatus;
|
|
27
69
|
(function (PendingBlockInputStatus) {
|
|
28
70
|
PendingBlockInputStatus["pending"] = "pending";
|
package/lib/sync/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAI1C,MAAM,CAAN,IAAY,
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,10 @@ import { INetwork } from "../network/index.js";
|
|
|
6
6
|
import { PeerSyncMeta } from "../network/peers/peersData.js";
|
|
7
7
|
import { PeerIdStr } from "../util/peerId.js";
|
|
8
8
|
import { SyncOptions } from "./options.js";
|
|
9
|
+
/**
|
|
10
|
+
* Poll pending payloads of the current slot this often, between PAYLOAD_DUE and the end of the slot.
|
|
11
|
+
*/
|
|
12
|
+
export declare const PAYLOAD_POLL_INTERVAL_MS = 1000;
|
|
9
13
|
/**
|
|
10
14
|
* BlockInputSync is a class that handles ReqResp to find blocks and data related to a specific blockRoot. The
|
|
11
15
|
* blockRoot may have been found via object gossip, or the API. Gossip objects that can trigger a search are block,
|
|
@@ -55,6 +59,11 @@ export declare class BlockInputSync {
|
|
|
55
59
|
private subscribedToNetworkEvents;
|
|
56
60
|
private peerBalancer;
|
|
57
61
|
private rateLimitBackoffTimeout;
|
|
62
|
+
/**
|
|
63
|
+
* Search unknown payload starting at PAYLOAD_DUE_BPS.
|
|
64
|
+
*/
|
|
65
|
+
private readonly deferredPayloadRoots;
|
|
66
|
+
private payloadPollAbortController;
|
|
58
67
|
constructor(config: ChainForkConfig, network: INetwork, chain: IBeaconChain, logger: Logger, metrics: Metrics | null, opts?: SyncOptions | undefined);
|
|
59
68
|
subscribeToNetwork(): void;
|
|
60
69
|
unsubscribeFromNetwork(): void;
|
|
@@ -69,6 +78,7 @@ export declare class BlockInputSync {
|
|
|
69
78
|
*/
|
|
70
79
|
private onIncompleteBlockInput;
|
|
71
80
|
private onUnknownEnvelopeBlockRoot;
|
|
81
|
+
private onUnknownEnvelopeBlockRootSlot;
|
|
72
82
|
private onIncompletePayloadEnvelope;
|
|
73
83
|
/**
|
|
74
84
|
* Process an unknownBlockParent event and register the block in `pendingBlocks` Map.
|
|
@@ -104,6 +114,16 @@ export declare class BlockInputSync {
|
|
|
104
114
|
private triggerUnknownBlockSearch;
|
|
105
115
|
private scheduleRateLimitBackoffRetry;
|
|
106
116
|
private clearRateLimitBackoffTimer;
|
|
117
|
+
/**
|
|
118
|
+
* Start this slot's payload poll: end the previous slot's loop, move roots it never got to
|
|
119
|
+
* into pendingPayloads, then poll from PAYLOAD_DUE to the end of the slot.
|
|
120
|
+
*/
|
|
121
|
+
private startPayloadPollAtSlot;
|
|
122
|
+
/**
|
|
123
|
+
* Poll unknown payloads of the current slot.
|
|
124
|
+
*/
|
|
125
|
+
private pollPayloadsAtSlot;
|
|
126
|
+
private addDeferredPayloadRoot;
|
|
107
127
|
private downloadBlock;
|
|
108
128
|
/**
|
|
109
129
|
* Import a block that has already passed the local dependency checks in BlockInputSync.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unknownBlock.d.ts","sourceRoot":"","sources":["../../src/sync/unknownBlock.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAMjD,OAAO,EAAC,MAAM,EAA+
|
|
1
|
+
{"version":3,"file":"unknownBlock.d.ts","sourceRoot":"","sources":["../../src/sync/unknownBlock.ts"],"names":[],"mappings":"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"}
|
package/lib/sync/unknownBlock.js
CHANGED
|
@@ -2,7 +2,7 @@ import { routes } from "@lodestar/api";
|
|
|
2
2
|
import { ForkSeq, SLOTS_PER_EPOCH, isForkPostGloas } from "@lodestar/params";
|
|
3
3
|
import { RequestError, RequestErrorCode } from "@lodestar/reqresp";
|
|
4
4
|
import { computeTimeAtSlot } from "@lodestar/state-transition";
|
|
5
|
-
import { fromHex, prettyPrintIndices, pruneSetToMax, sleep, toRootHex } from "@lodestar/utils";
|
|
5
|
+
import { fromHex, isErrorAborted, prettyPrintIndices, pruneSetToMax, sleep, toRootHex } from "@lodestar/utils";
|
|
6
6
|
import { isBlockInputBlobs, isBlockInputColumns } from "../chain/blocks/blockInput/blockInput.js";
|
|
7
7
|
import { BlockInputSource } from "../chain/blocks/blockInput/types.js";
|
|
8
8
|
import { PayloadError, PayloadErrorCode } from "../chain/blocks/importExecutionPayload.js";
|
|
@@ -13,11 +13,12 @@ import { validateGloasBlockDataColumnSidecars } from "../chain/validation/dataCo
|
|
|
13
13
|
import { validateGossipExecutionPayloadEnvelope } from "../chain/validation/executionPayloadEnvelope.js";
|
|
14
14
|
import { NetworkEvent, prettyPrintPeerIdStr } from "../network/index.js";
|
|
15
15
|
import { MAX_PEERS_PER_ROOT } from "../network/processor/constants.js";
|
|
16
|
+
import { ClockEvent } from "../util/clock.js";
|
|
16
17
|
import { shuffle } from "../util/shuffle.js";
|
|
17
18
|
import { sortBy } from "../util/sortBy.js";
|
|
18
19
|
import { wrapError } from "../util/wrapError.js";
|
|
19
20
|
import { MAX_CONCURRENT_REQUESTS } from "./constants.js";
|
|
20
|
-
import { DroppedItemReason, PendingBlockInputStatus, PendingBlockType, PendingPayloadInputStatus, getBlockInputSyncCacheItemRootHex, getBlockInputSyncCacheItemSlot, getPayloadSyncCacheItemRootHex, getPayloadSyncCacheItemSlot, isPendingBlockInput, isPendingPayloadEnvelope, isPendingPayloadInput, } from "./types.js";
|
|
21
|
+
import { DeferredPayloadResult, DownloadResult, DroppedItemReason, FetchResult, PendingBlockInputStatus, PendingBlockType, PendingPayloadInputStatus, getBlockInputSyncCacheItemRootHex, getBlockInputSyncCacheItemSlot, getPayloadSyncCacheItemRootHex, getPayloadSyncCacheItemSlot, isPendingBlockInput, isPendingPayloadEnvelope, isPendingPayloadInput, } from "./types.js";
|
|
21
22
|
import { DownloadByRootError, downloadByRoot } from "./utils/downloadByRoot.js";
|
|
22
23
|
import { getAllDescendantBlocks, getUnknownAndAncestorBlocks } from "./utils/pendingBlocksTree.js";
|
|
23
24
|
import { getRateLimitedUntilMs } from "./utils/rateLimit.js";
|
|
@@ -28,14 +29,10 @@ const MAX_PENDING_BLOCKS = 100;
|
|
|
28
29
|
* A pending payload without slot can only stay at most 2 epochs.
|
|
29
30
|
*/
|
|
30
31
|
const PRUNE_UNRESOLVED_SLOT_EPOCHS = 2;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
FetchResult["SuccessLate"] = "success_late";
|
|
36
|
-
FetchResult["FailureTriedAllPeers"] = "failure_tried_all_peers";
|
|
37
|
-
FetchResult["FailureMaxAttempts"] = "failure_max_attempts";
|
|
38
|
-
})(FetchResult || (FetchResult = {}));
|
|
32
|
+
/**
|
|
33
|
+
* Poll pending payloads of the current slot this often, between PAYLOAD_DUE and the end of the slot.
|
|
34
|
+
*/
|
|
35
|
+
export const PAYLOAD_POLL_INTERVAL_MS = 1_000;
|
|
39
36
|
class UnknownBlockRateLimitedError extends Error {
|
|
40
37
|
constructor(message) {
|
|
41
38
|
super(message);
|
|
@@ -92,6 +89,11 @@ export class BlockInputSync {
|
|
|
92
89
|
subscribedToNetworkEvents = false;
|
|
93
90
|
peerBalancer;
|
|
94
91
|
rateLimitBackoffTimeout;
|
|
92
|
+
/**
|
|
93
|
+
* Search unknown payload starting at PAYLOAD_DUE_BPS.
|
|
94
|
+
*/
|
|
95
|
+
deferredPayloadRoots = new Map();
|
|
96
|
+
payloadPollAbortController;
|
|
95
97
|
constructor(config, network, chain, logger, metrics, opts) {
|
|
96
98
|
this.config = config;
|
|
97
99
|
this.network = network;
|
|
@@ -117,6 +119,7 @@ export class BlockInputSync {
|
|
|
117
119
|
this.logger.verbose("BlockInputSync enabled.");
|
|
118
120
|
this.chain.emitter.on(ChainEvent.unknownBlockRoot, this.onUnknownBlockRoot);
|
|
119
121
|
this.chain.emitter.on(ChainEvent.unknownEnvelopeBlockRoot, this.onUnknownEnvelopeBlockRoot);
|
|
122
|
+
this.chain.emitter.on(ChainEvent.unknownEnvelopeBlockRootSlot, this.onUnknownEnvelopeBlockRootSlot);
|
|
120
123
|
this.chain.emitter.on(ChainEvent.incompleteBlockInput, this.onIncompleteBlockInput);
|
|
121
124
|
this.chain.emitter.on(ChainEvent.incompletePayloadEnvelope, this.onIncompletePayloadEnvelope);
|
|
122
125
|
this.chain.emitter.on(ChainEvent.blockUnknownParent, this.onUnknownParent);
|
|
@@ -125,6 +128,7 @@ export class BlockInputSync {
|
|
|
125
128
|
this.chain.emitter.on(routes.events.EventType.executionPayload, this.onPayloadImported);
|
|
126
129
|
this.network.events.on(NetworkEvent.peerConnected, this.onPeerConnected);
|
|
127
130
|
this.network.events.on(NetworkEvent.peerDisconnected, this.onPeerDisconnected);
|
|
131
|
+
this.chain.clock.on(ClockEvent.slot, this.startPayloadPollAtSlot);
|
|
128
132
|
// Seed the balancer with peers that connected before we subscribed
|
|
129
133
|
for (const peerId of this.network.getConnectedPeers()) {
|
|
130
134
|
try {
|
|
@@ -135,13 +139,21 @@ export class BlockInputSync {
|
|
|
135
139
|
}
|
|
136
140
|
}
|
|
137
141
|
this.subscribedToNetworkEvents = true;
|
|
142
|
+
// we subscribe mid-slot, and a root can be deferred at any point in the slot, so start this
|
|
143
|
+
// slot's loop now instead of waiting for the next ClockEvent.slot
|
|
144
|
+
this.startPayloadPollAtSlot(this.chain.clock.currentSlot);
|
|
138
145
|
}
|
|
139
146
|
}
|
|
140
147
|
unsubscribeFromNetwork() {
|
|
141
148
|
this.logger.verbose("BlockInputSync disabled.");
|
|
142
149
|
this.clearRateLimitBackoffTimer();
|
|
150
|
+
this.chain.clock.off(ClockEvent.slot, this.startPayloadPollAtSlot);
|
|
151
|
+
this.payloadPollAbortController?.abort();
|
|
152
|
+
this.payloadPollAbortController = undefined;
|
|
153
|
+
this.deferredPayloadRoots.clear();
|
|
143
154
|
this.chain.emitter.off(ChainEvent.unknownBlockRoot, this.onUnknownBlockRoot);
|
|
144
155
|
this.chain.emitter.off(ChainEvent.unknownEnvelopeBlockRoot, this.onUnknownEnvelopeBlockRoot);
|
|
156
|
+
this.chain.emitter.off(ChainEvent.unknownEnvelopeBlockRootSlot, this.onUnknownEnvelopeBlockRootSlot);
|
|
145
157
|
this.chain.emitter.off(ChainEvent.incompleteBlockInput, this.onIncompleteBlockInput);
|
|
146
158
|
this.chain.emitter.off(ChainEvent.incompletePayloadEnvelope, this.onIncompletePayloadEnvelope);
|
|
147
159
|
this.chain.emitter.off(ChainEvent.blockUnknownParent, this.onUnknownParent);
|
|
@@ -202,6 +214,33 @@ export class BlockInputSync {
|
|
|
202
214
|
this.logger.debug("Error handling unknownEnvelopeBlockRoot event", {}, e);
|
|
203
215
|
}
|
|
204
216
|
};
|
|
217
|
+
onUnknownEnvelopeBlockRootSlot = (data) => {
|
|
218
|
+
try {
|
|
219
|
+
if (data.slot === this.chain.clock.currentSlot) {
|
|
220
|
+
// we receive the optimistic search, the poll loop searches it at PAYLOAD_DUE or on its next
|
|
221
|
+
// tick. If that loop already returned - every root it watched was imported - this root waits
|
|
222
|
+
// for the next slot, where startPayloadPollAtSlot moves it to pendingPayloads. That is not the normal
|
|
223
|
+
// scenario, and in a forking condition it only delays the search of the extra root
|
|
224
|
+
const deferred = this.deferredPayloadRoots.get(data.rootHex);
|
|
225
|
+
if (deferred === undefined) {
|
|
226
|
+
this.deferredPayloadRoots.set(data.rootHex, { slot: data.slot, source: data.source, peer: data.peer });
|
|
227
|
+
}
|
|
228
|
+
else if (deferred.peer === undefined) {
|
|
229
|
+
deferred.peer = data.peer;
|
|
230
|
+
}
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const isNewRoot = this.addByPayloadRootHex(data.rootHex, data.peer, data.slot);
|
|
234
|
+
if (isNewRoot) {
|
|
235
|
+
this.triggerUnknownBlockSearch();
|
|
236
|
+
this.metrics?.blockInputSync.requests.inc({ type: PendingBlockType.UNKNOWN_PAYLOAD_BLOCK_ROOT_SLOT });
|
|
237
|
+
this.metrics?.blockInputSync.payloadSource.inc({ source: data.source });
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch (e) {
|
|
241
|
+
this.logger.debug("Error handling unknownEnvelopeBlockRootSlot event", {}, e);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
205
244
|
onIncompletePayloadEnvelope = (data) => {
|
|
206
245
|
try {
|
|
207
246
|
this.addByPayloadInput(data.payloadInput, data.peer);
|
|
@@ -660,6 +699,115 @@ export class BlockInputSync {
|
|
|
660
699
|
this.rateLimitBackoffTimeout = undefined;
|
|
661
700
|
}
|
|
662
701
|
}
|
|
702
|
+
/**
|
|
703
|
+
* Start this slot's payload poll: end the previous slot's loop, move roots it never got to
|
|
704
|
+
* into pendingPayloads, then poll from PAYLOAD_DUE to the end of the slot.
|
|
705
|
+
*/
|
|
706
|
+
startPayloadPollAtSlot = (slot) => {
|
|
707
|
+
if (!isForkPostGloas(this.config.getForkName(slot))) {
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
// end the previous slot's loop, wherever it is: its sleep is bound to this same controller
|
|
711
|
+
this.payloadPollAbortController?.abort();
|
|
712
|
+
this.payloadPollAbortController = new AbortController();
|
|
713
|
+
// entries from an earlier slot is not polled
|
|
714
|
+
for (const [rootHex, { slot: deferredSlot, source, peer }] of this.deferredPayloadRoots) {
|
|
715
|
+
if (deferredSlot < slot) {
|
|
716
|
+
if (!this.chain.forkChoice.hasPayloadHexUnsafe(rootHex)) {
|
|
717
|
+
this.addDeferredPayloadRoot(rootHex, deferredSlot, source, peer);
|
|
718
|
+
}
|
|
719
|
+
this.deferredPayloadRoots.delete(rootHex);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
this.pollPayloadsAtSlot(slot, this.payloadPollAbortController.signal).catch((e) => {
|
|
723
|
+
if (!isErrorAborted(e)) {
|
|
724
|
+
this.logger.debug("Error polling payloads", { slot }, e);
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
};
|
|
728
|
+
/**
|
|
729
|
+
* Poll unknown payloads of the current slot.
|
|
730
|
+
*/
|
|
731
|
+
async pollPayloadsAtSlot(slot, signal) {
|
|
732
|
+
// fixed tick count so the loop cannot outlive its slot: for mainnet, it's 6 ticks
|
|
733
|
+
const tickCount = Math.floor((this.config.SLOT_DURATION_MS - this.config.getPayloadDueMs()) / PAYLOAD_POLL_INTERVAL_MS);
|
|
734
|
+
// a root still missing on several ticks is searched on each of them, recorded once
|
|
735
|
+
const searchedRoots = new Set();
|
|
736
|
+
let polls = 0;
|
|
737
|
+
try {
|
|
738
|
+
await sleep(Math.max(0, this.config.getPayloadDueMs() - this.chain.clock.msFromSlot(slot)), signal);
|
|
739
|
+
for (polls = 0; polls < tickCount; polls++) {
|
|
740
|
+
let importedCount = 0;
|
|
741
|
+
for (const [rootHex, { slot: deferredSlot, source, peer }] of this.deferredPayloadRoots) {
|
|
742
|
+
if (this.chain.forkChoice.hasPayloadHexUnsafe(rootHex)) {
|
|
743
|
+
importedCount++;
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
// copy to the regular pendingPayloads so that we can search
|
|
747
|
+
this.addDeferredPayloadRoot(rootHex, deferredSlot, source, peer);
|
|
748
|
+
searchedRoots.add(rootHex);
|
|
749
|
+
}
|
|
750
|
+
// an empty deferredPayloadRoots means there is no optimistic search comes before PAYLOAD_DUE
|
|
751
|
+
// we have to poll until the payload of current slot is imported or slot end
|
|
752
|
+
if (this.deferredPayloadRoots.size > 0 && importedCount === this.deferredPayloadRoots.size) {
|
|
753
|
+
if (searchedRoots.size > 0) {
|
|
754
|
+
// the backup search was needed
|
|
755
|
+
this.metrics?.blockInputSync.deferredPayloadResult.inc({
|
|
756
|
+
result: DeferredPayloadResult.ImportedAfterSearch,
|
|
757
|
+
});
|
|
758
|
+
this.metrics?.blockInputSync.deferredPayloadPolls.observe(polls);
|
|
759
|
+
this.logger.verbose("Payload imported after unknown sync search", {
|
|
760
|
+
slot,
|
|
761
|
+
roots: Array.from(searchedRoots).join(","),
|
|
762
|
+
polls,
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
else {
|
|
766
|
+
// this happens most of the time on devnet
|
|
767
|
+
// gossip delivered everything before PAYLOAD_DUE
|
|
768
|
+
this.metrics?.blockInputSync.deferredPayloadResult.inc({
|
|
769
|
+
result: DeferredPayloadResult.ImportedBeforeSearch,
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
this.triggerUnknownBlockSearch();
|
|
775
|
+
if (polls < tickCount - 1) {
|
|
776
|
+
// no sleep after the last tick: the loop would otherwise end right at the slot boundary,
|
|
777
|
+
// where startPayloadPollAtSlot aborts it
|
|
778
|
+
await sleep(PAYLOAD_POLL_INTERVAL_MS, signal);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
// reaching here means the early return never fired
|
|
782
|
+
if (this.deferredPayloadRoots.size > 0) {
|
|
783
|
+
this.metrics?.blockInputSync.deferredPayloadResult.inc({ result: DeferredPayloadResult.Unresolved });
|
|
784
|
+
this.logger.debug("Deferred payloads still missing at end of slot", {
|
|
785
|
+
slot,
|
|
786
|
+
roots: Array.from(this.deferredPayloadRoots.keys()).join(","),
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
// no optimistic search and no payload import ended the loop, eg a skipped slot
|
|
791
|
+
this.metrics?.blockInputSync.deferredPayloadResult.inc({ result: DeferredPayloadResult.ResolvedNoRoot });
|
|
792
|
+
this.logger.debug("No deferred payloads at slot", {
|
|
793
|
+
slot,
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
catch (e) {
|
|
798
|
+
if (!isErrorAborted(e)) {
|
|
799
|
+
throw e;
|
|
800
|
+
}
|
|
801
|
+
this.logger.verbose("Payload poll aborted", { slot, polls, msIntoSlot: this.chain.clock.msFromSlot(slot) });
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
addDeferredPayloadRoot(rootHex, slot, source, peer) {
|
|
805
|
+
const isNewRoot = this.addByPayloadRootHex(rootHex, peer, slot);
|
|
806
|
+
if (isNewRoot) {
|
|
807
|
+
this.metrics?.blockInputSync.requests.inc({ type: PendingBlockType.DEFERRED_PAYLOAD_BLOCK_ROOT });
|
|
808
|
+
this.metrics?.blockInputSync.payloadSource.inc({ source });
|
|
809
|
+
}
|
|
810
|
+
}
|
|
663
811
|
async downloadBlock(block) {
|
|
664
812
|
if (block.status !== PendingBlockInputStatus.pending) {
|
|
665
813
|
return;
|
|
@@ -946,14 +1094,22 @@ export class BlockInputSync {
|
|
|
946
1094
|
return;
|
|
947
1095
|
}
|
|
948
1096
|
this.pendingPayloads.set(resultRootHex, pendingPayload);
|
|
1097
|
+
const result = isPendingPayloadEnvelope(pendingPayload)
|
|
1098
|
+
? DownloadResult.WaitingForBlock
|
|
1099
|
+
: this.chain.forkChoice.hasPayloadHexUnsafe(resultRootHex)
|
|
1100
|
+
? DownloadResult.Late
|
|
1101
|
+
: DownloadResult.Resolved;
|
|
1102
|
+
this.metrics?.blockInputSync.downloadedPayloadsResult.inc({ result });
|
|
949
1103
|
if (isPendingPayloadEnvelope(pendingPayload)) {
|
|
950
1104
|
await this.reconcilePayloadEnvelope(pendingPayload);
|
|
951
1105
|
}
|
|
952
1106
|
else if (pendingPayload.status === PendingPayloadInputStatus.downloaded) {
|
|
1107
|
+
this.metrics?.blockInputSync.elapsedTimeTillPayloadReceived.observe(Date.now() / 1000 - computeTimeAtSlot(this.config, pendingPayload.payloadInput.slot, this.chain.genesisTime));
|
|
953
1108
|
await this.processPayload(pendingPayload);
|
|
954
1109
|
}
|
|
955
1110
|
return;
|
|
956
1111
|
}
|
|
1112
|
+
this.metrics?.blockInputSync.downloadedPayloadsResult.inc({ result: DownloadResult.Failed });
|
|
957
1113
|
this.logger.debug("Ignoring unknown payload root after failed download", logCtx, res.err);
|
|
958
1114
|
if (!isPendingPayloadEnvelope(payload)) {
|
|
959
1115
|
payload.status = PendingPayloadInputStatus.pending;
|
|
@@ -1050,6 +1206,10 @@ export class BlockInputSync {
|
|
|
1050
1206
|
? cacheItem.payloadInput
|
|
1051
1207
|
: await this.chain.seenPayloadEnvelopeInputCache.getOrReload(rootHex);
|
|
1052
1208
|
let envelope = payloadInput?.hasPayloadEnvelope() ? payloadInput.getPayloadEnvelope() : undefined;
|
|
1209
|
+
const fetchStartSec = Date.now() / 1000;
|
|
1210
|
+
if (typeof slot === "number") {
|
|
1211
|
+
this.metrics?.blockInputSync.payloadFetchBegin.observe(this.chain.clock.secFromSlot(slot, fetchStartSec));
|
|
1212
|
+
}
|
|
1053
1213
|
let i = 0;
|
|
1054
1214
|
let deferredByRateLimit = false;
|
|
1055
1215
|
while (i++ < this.getMaxDownloadAttempts()) {
|
|
@@ -1065,6 +1225,8 @@ export class BlockInputSync {
|
|
|
1065
1225
|
const reason = pendingColumns.size > 0
|
|
1066
1226
|
? `cannot find peer with needed columns=${prettyPrintIndices(Array.from(pendingColumns))}`
|
|
1067
1227
|
: "no peer available to download pending payload";
|
|
1228
|
+
this.metrics?.blockInputSync.payloadFetchTime.observe({ result: FetchResult.FailureTriedAllPeers }, Date.now() / 1000 - fetchStartSec);
|
|
1229
|
+
this.metrics?.blockInputSync.payloadFetchPeers.set({ result: FetchResult.FailureTriedAllPeers }, i);
|
|
1068
1230
|
throw Error(`Error fetching payload by root slot=${slot} root=${rootHex} after ${i}: ${reason}`);
|
|
1069
1231
|
}
|
|
1070
1232
|
const { peerId, client: peerClient } = peerMeta;
|
|
@@ -1072,7 +1234,12 @@ export class BlockInputSync {
|
|
|
1072
1234
|
try {
|
|
1073
1235
|
if (!envelope) {
|
|
1074
1236
|
envelope = await this.fetchExecutionPayloadEnvelope(peerId, blockRoot, rootHex);
|
|
1237
|
+
const slotWasUnknown = typeof slot !== "number";
|
|
1075
1238
|
slot = envelope.message.payload.slotNumber;
|
|
1239
|
+
if (slotWasUnknown) {
|
|
1240
|
+
// we were not able to observe the time into slot when starting the fetch, do it now
|
|
1241
|
+
this.metrics?.blockInputSync.payloadFetchBegin.observe(this.chain.clock.secFromSlot(slot, fetchStartSec));
|
|
1242
|
+
}
|
|
1076
1243
|
}
|
|
1077
1244
|
payloadInput ??= await this.chain.seenPayloadEnvelopeInputCache.getOrReload(rootHex);
|
|
1078
1245
|
if (!this.chain.forkChoice.hasBlockHex(rootHex)) {
|
|
@@ -1080,6 +1247,8 @@ export class BlockInputSync {
|
|
|
1080
1247
|
// envelope and wait for the block body; reconcilePayloadEnvelope validates once the block lands.
|
|
1081
1248
|
// payloadInput may be seeded from the block body during download, so a non-null payloadInput does not
|
|
1082
1249
|
// imply the block is imported.
|
|
1250
|
+
this.metrics?.blockInputSync.payloadFetchTime.observe({ result: FetchResult.SuccessWaitingForBlock }, Date.now() / 1000 - fetchStartSec);
|
|
1251
|
+
this.metrics?.blockInputSync.payloadFetchPeers.set({ result: FetchResult.SuccessWaitingForBlock }, i);
|
|
1083
1252
|
return {
|
|
1084
1253
|
status: PendingPayloadInputStatus.waitingForBlock,
|
|
1085
1254
|
envelope,
|
|
@@ -1124,6 +1293,12 @@ export class BlockInputSync {
|
|
|
1124
1293
|
hasAllData: pendingPayload.payloadInput.hasAllData(),
|
|
1125
1294
|
});
|
|
1126
1295
|
if (pendingPayload.status === PendingPayloadInputStatus.downloaded) {
|
|
1296
|
+
// late = the payload got imported (via gossip) while we were downloading, same as the block path
|
|
1297
|
+
const result = this.chain.forkChoice.hasPayloadHexUnsafe(rootHex)
|
|
1298
|
+
? FetchResult.SuccessLate
|
|
1299
|
+
: FetchResult.SuccessResolved;
|
|
1300
|
+
this.metrics?.blockInputSync.payloadFetchTime.observe({ result }, Date.now() / 1000 - fetchStartSec);
|
|
1301
|
+
this.metrics?.blockInputSync.payloadFetchPeers.set({ result }, i);
|
|
1127
1302
|
return pendingPayload;
|
|
1128
1303
|
}
|
|
1129
1304
|
cacheItem = pendingPayload;
|
|
@@ -1155,6 +1330,8 @@ export class BlockInputSync {
|
|
|
1155
1330
|
this.peerBalancer.onRequestCompleted(peerId);
|
|
1156
1331
|
}
|
|
1157
1332
|
}
|
|
1333
|
+
this.metrics?.blockInputSync.payloadFetchTime.observe({ result: FetchResult.FailureMaxAttempts }, Date.now() / 1000 - fetchStartSec);
|
|
1334
|
+
this.metrics?.blockInputSync.payloadFetchPeers.set({ result: FetchResult.FailureMaxAttempts }, i - 1);
|
|
1158
1335
|
if (deferredByRateLimit && this.peerBalancer.getNextRateLimitRetryAt() !== null) {
|
|
1159
1336
|
throw new UnknownBlockRateLimitedError(`Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts: peers are rate-limited`);
|
|
1160
1337
|
}
|
|
@@ -1227,7 +1404,7 @@ export class BlockInputSync {
|
|
|
1227
1404
|
}
|
|
1228
1405
|
// no more peer with needed columns to try, throw error
|
|
1229
1406
|
const message = `Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: cannot find peer with needed columns=${prettyPrintIndices(Array.from(pendingColumns))}`;
|
|
1230
|
-
this.metrics?.blockInputSync.
|
|
1407
|
+
this.metrics?.blockInputSync.fetchTime.observe({ result: FetchResult.FailureTriedAllPeers }, Date.now() / 1000 - fetchStartSec);
|
|
1231
1408
|
this.metrics?.blockInputSync.fetchPeers.set({ result: FetchResult.FailureTriedAllPeers }, i);
|
|
1232
1409
|
throw Error(message);
|
|
1233
1410
|
}
|
|
@@ -1309,7 +1486,7 @@ export class BlockInputSync {
|
|
|
1309
1486
|
: this.chain.forkChoice.hasBlockHex(cacheItem.blockInput.parentRootHex)
|
|
1310
1487
|
? FetchResult.SuccessResolved
|
|
1311
1488
|
: FetchResult.SuccessMissingParent;
|
|
1312
|
-
this.metrics?.blockInputSync.
|
|
1489
|
+
this.metrics?.blockInputSync.fetchTime.observe({ result }, Date.now() / 1000 - fetchStartSec);
|
|
1313
1490
|
this.metrics?.blockInputSync.fetchPeers.set({ result }, i);
|
|
1314
1491
|
return cacheItem;
|
|
1315
1492
|
}
|
|
@@ -1336,7 +1513,7 @@ export class BlockInputSync {
|
|
|
1336
1513
|
throw new Error(`${message} Missing column indices=${prettyPrintIndices(missing)}.`);
|
|
1337
1514
|
}
|
|
1338
1515
|
}
|
|
1339
|
-
this.metrics?.blockInputSync.
|
|
1516
|
+
this.metrics?.blockInputSync.fetchTime.observe({ result: FetchResult.FailureMaxAttempts }, Date.now() / 1000 - fetchStartSec);
|
|
1340
1517
|
this.metrics?.blockInputSync.fetchPeers.set({ result: FetchResult.FailureMaxAttempts }, i - 1);
|
|
1341
1518
|
throw Error(message);
|
|
1342
1519
|
}
|