@lodestar/beacon-node 1.44.0-dev.552cdce8d0 → 1.44.0-dev.6a52e6a9f6
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 +30 -0
- 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 +1 -1
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +69 -12
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +101 -42
- 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 -4
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +5 -2
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +5 -3
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/chain.d.ts +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +2 -1
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +11 -1
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +2 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/payloadAttestation.d.ts +6 -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/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +14 -4
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.d.ts +4 -4
- package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.js +6 -4
- package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +2 -1
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +7 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +107 -18
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +2 -1
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +2 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +0 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +0 -4
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +0 -5
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +0 -5
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +1 -4
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +5 -2
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +0 -2
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts +7 -3
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +58 -15
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +24 -4
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +1 -0
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +16 -0
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/execution/builder/index.d.ts +1 -2
- package/lib/execution/builder/index.d.ts.map +1 -1
- package/lib/execution/builder/index.js +0 -1
- package/lib/execution/builder/index.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +1 -0
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/types.d.ts +2 -0
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +2 -0
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +1 -1
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +4 -3
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +1 -1
- package/lib/network/interface.d.ts +1 -0
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +1 -0
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +5 -0
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +12 -4
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +5 -0
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +3 -3
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts +2 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +15 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/index.js +2 -2
- package/lib/network/reqresp/handlers/index.js.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js +22 -3
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
- package/package.json +14 -16
- package/src/api/impl/beacon/blocks/index.ts +36 -0
- package/src/api/impl/beacon/pool/index.ts +3 -1
- package/src/api/impl/debug/index.ts +73 -12
- package/src/api/impl/validator/index.ts +112 -43
- package/src/chain/archiveStore/archiveStore.ts +0 -5
- package/src/chain/blocks/importBlock.ts +10 -2
- package/src/chain/blocks/importExecutionPayload.ts +8 -2
- package/src/chain/chain.ts +2 -0
- package/src/chain/errors/executionPayloadBid.ts +6 -1
- package/src/chain/errors/payloadAttestation.ts +2 -0
- package/src/chain/forkChoice/index.ts +14 -4
- package/src/chain/opPools/executionPayloadBidPool.ts +10 -9
- package/src/chain/prepareNextSlot.ts +2 -1
- package/src/chain/produceBlock/produceBlockBody.ts +158 -25
- package/src/chain/regen/interface.ts +2 -1
- package/src/chain/regen/queued.ts +0 -5
- package/src/chain/stateCache/fifoBlockStateCache.ts +0 -6
- package/src/chain/stateCache/persistentCheckpointsCache.ts +6 -2
- package/src/chain/stateCache/types.ts +0 -2
- package/src/chain/validation/executionPayloadBid.ts +66 -19
- package/src/chain/validation/payloadAttestationMessage.ts +26 -4
- package/src/chain/validatorMonitor.ts +18 -0
- package/src/execution/builder/index.ts +1 -4
- package/src/execution/engine/interface.ts +1 -0
- package/src/execution/engine/types.ts +4 -0
- package/src/metrics/metrics/lodestar.ts +4 -3
- package/src/network/interface.ts +1 -0
- package/src/network/network.ts +11 -0
- package/src/network/processor/gossipHandlers.ts +17 -4
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +6 -0
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +1 -1
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +3 -3
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +20 -1
- package/src/network/reqresp/handlers/index.ts +2 -2
- package/src/network/reqresp/utils/dataColumnResponseValidation.ts +21 -3
- package/lib/execution/builder/utils.d.ts +0 -5
- package/lib/execution/builder/utils.d.ts.map +0 -1
- package/lib/execution/builder/utils.js +0 -17
- package/lib/execution/builder/utils.js.map +0 -1
- package/src/execution/builder/utils.ts +0 -19
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ForkSeq } from "@lodestar/params";
|
|
1
2
|
import { RespStatus, ResponseError } from "@lodestar/reqresp";
|
|
2
3
|
import { prettyBytes, prettyPrintIndices, toRootHex } from "@lodestar/utils";
|
|
3
4
|
import { getBlobKzgCommitmentsCountFromSignedBeaconBlockSerialized } from "../../../util/sszBytes.js";
|
|
@@ -12,6 +13,13 @@ export async function handleColumnSidecarUnavailability({ chain, db, metrics, un
|
|
|
12
13
|
logData.blockRoot = prettyBytes(blockRoot);
|
|
13
14
|
}
|
|
14
15
|
chain.logger.debug("dataColumnSidecar requested unavailable", logData);
|
|
16
|
+
// Post-gloas, columns exist only for FULL blocks; a finalized block is FULL if its envelope was
|
|
17
|
+
// archived. Bid blobsCount is unreliable here since an EMPTY block's bid may still commit to blobs
|
|
18
|
+
if (blockRoot === undefined && chain.config.getForkSeq(slot) >= ForkSeq.gloas) {
|
|
19
|
+
const envelopeBytes = await db.executionPayloadEnvelopeArchive.getBinary(slot);
|
|
20
|
+
if (!envelopeBytes)
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
15
23
|
const blockBytes = blockRoot ? await db.block.getBinary(blockRoot) : await db.blockArchive.getBinary(slot);
|
|
16
24
|
if (!blockBytes) {
|
|
17
25
|
chain.logger.verbose(`Expected ${blockRoot ? "unfinalized" : "finalized"} block not found while handling unavailable dataColumnSidecar`, {
|
|
@@ -38,9 +46,20 @@ export function validateRequestedDataColumns(chain, requestedColumns) {
|
|
|
38
46
|
if (requestedColumns.length === 0) {
|
|
39
47
|
throw new ResponseError(RespStatus.INVALID_REQUEST, "dataColumnSidecar requested without column indices");
|
|
40
48
|
}
|
|
41
|
-
const custodyColumns = chain.custodyConfig
|
|
42
|
-
const availableColumns =
|
|
43
|
-
const missingColumns =
|
|
49
|
+
const { custodyColumns, custodyColumnsIndex } = chain.custodyConfig;
|
|
50
|
+
const availableColumns = [];
|
|
51
|
+
const missingColumns = [];
|
|
52
|
+
for (const c of requestedColumns) {
|
|
53
|
+
// `c` is peer-controlled and SSZ-deserialized as `uint64`, so it may exceed
|
|
54
|
+
// `NUMBER_OF_COLUMNS - 1`; `Uint8Array` returns `undefined` for OOB reads,
|
|
55
|
+
// and `undefined !== 0` would silently classify OOB indices as custodied.
|
|
56
|
+
if ((custodyColumnsIndex[c] ?? 0) !== 0) {
|
|
57
|
+
availableColumns.push(c);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
missingColumns.push(c);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
44
63
|
if (missingColumns.length > 0) {
|
|
45
64
|
chain.logger.verbose("Requested dataColumnSidecar for non-custody columns", {
|
|
46
65
|
requestedColumns: prettyPrintIndices(requestedColumns),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataColumnResponseValidation.js","sourceRoot":"","sources":["../../../../src/network/reqresp/utils/dataColumnResponseValidation.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,UAAU,EAAE,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EAAC,WAAW,EAAE,kBAAkB,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAI3E,OAAO,EAAC,yDAAyD,EAAC,MAAM,2BAA2B,CAAC;AAEpG,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,EACtD,KAAK,EACL,EAAE,EACF,OAAO,EACP,wBAAwB,EACxB,gBAAgB,EAChB,gBAAgB,EAChB,IAAI,EACJ,SAAS,GAUV,EAAiB;IAChB,MAAM,OAAO,GAAY;QACvB,IAAI;QACJ,wBAAwB,EAAE,kBAAkB,CAAC,wBAAwB,CAAC;QACtE,gBAAgB,EAAE,kBAAkB,CAAC,gBAAgB,CAAC;QACtD,gBAAgB,EAAE,kBAAkB,CAAC,gBAAgB,CAAC;KACvD,CAAC;IACF,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE,OAAO,CAAC,CAAC;IAEvE,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3G,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,KAAK,CAAC,MAAM,CAAC,OAAO,CAClB,YAAY,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,+DAA+D,EAClH;YACE,IAAI;YACJ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;YACvD,qBAAqB,EAAE,KAAK,CAAC,qBAAqB;SACnD,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,uCAAuC;IACvC,MAAM,UAAU,GAAG,yDAAyD,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAEvG,wFAAwF;IACxF,IAAI,UAAU,KAAK,CAAC;QAAE,OAAO;IAE7B,wEAAwE;IACxE,mEAAmE;IACnE,OAAO,EAAE,WAAW,CAAC,qBAAqB,CAAC,GAAG,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAChF,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,kEAAkE,EAAE;QACvF,wBAAwB,EAAE,kBAAkB,CAAC,wBAAwB,CAAC;QACtE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;KAC1D,CAAC,CAAC;AAAA,CACJ;AAED,MAAM,UAAU,4BAA4B,CAAC,KAAmB,EAAE,gBAA+B,EAAiB;IAChH,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,aAAa,CAAC,UAAU,CAAC,eAAe,EAAE,oDAAoD,CAAC,CAAC;IAC5G,CAAC;IAED,MAAM,cAAc,GAAG,KAAK,CAAC,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"dataColumnResponseValidation.js","sourceRoot":"","sources":["../../../../src/network/reqresp/utils/dataColumnResponseValidation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/ChainSafe/lodestar/issues"
|
|
13
13
|
},
|
|
14
|
-
"version": "1.44.0-dev.
|
|
14
|
+
"version": "1.44.0-dev.6a52e6a9f6",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -116,7 +116,6 @@
|
|
|
116
116
|
"@chainsafe/libp2p-quic": "^2.0.1",
|
|
117
117
|
"@chainsafe/persistent-merkle-tree": "^1.2.5",
|
|
118
118
|
"@chainsafe/prometheus-gc-stats": "^1.0.0",
|
|
119
|
-
"@chainsafe/pubkey-index-map": "^3.0.0",
|
|
120
119
|
"@chainsafe/snappy-wasm": "^0.5.0",
|
|
121
120
|
"@chainsafe/ssz": "^1.4.0",
|
|
122
121
|
"@chainsafe/threads": "^1.11.3",
|
|
@@ -135,17 +134,17 @@
|
|
|
135
134
|
"@libp2p/peer-id": "^6.0.4",
|
|
136
135
|
"@libp2p/prometheus-metrics": "^5.0.14",
|
|
137
136
|
"@libp2p/tcp": "^11.0.13",
|
|
138
|
-
"@lodestar/api": "^1.44.0-dev.
|
|
139
|
-
"@lodestar/config": "^1.44.0-dev.
|
|
140
|
-
"@lodestar/db": "^1.44.0-dev.
|
|
141
|
-
"@lodestar/fork-choice": "^1.44.0-dev.
|
|
142
|
-
"@lodestar/logger": "^1.44.0-dev.
|
|
143
|
-
"@lodestar/params": "^1.44.0-dev.
|
|
144
|
-
"@lodestar/reqresp": "^1.44.0-dev.
|
|
145
|
-
"@lodestar/state-transition": "^1.44.0-dev.
|
|
146
|
-
"@lodestar/types": "^1.44.0-dev.
|
|
147
|
-
"@lodestar/utils": "^1.44.0-dev.
|
|
148
|
-
"@lodestar/validator": "^1.44.0-dev.
|
|
137
|
+
"@lodestar/api": "^1.44.0-dev.6a52e6a9f6",
|
|
138
|
+
"@lodestar/config": "^1.44.0-dev.6a52e6a9f6",
|
|
139
|
+
"@lodestar/db": "^1.44.0-dev.6a52e6a9f6",
|
|
140
|
+
"@lodestar/fork-choice": "^1.44.0-dev.6a52e6a9f6",
|
|
141
|
+
"@lodestar/logger": "^1.44.0-dev.6a52e6a9f6",
|
|
142
|
+
"@lodestar/params": "^1.44.0-dev.6a52e6a9f6",
|
|
143
|
+
"@lodestar/reqresp": "^1.44.0-dev.6a52e6a9f6",
|
|
144
|
+
"@lodestar/state-transition": "^1.44.0-dev.6a52e6a9f6",
|
|
145
|
+
"@lodestar/types": "^1.44.0-dev.6a52e6a9f6",
|
|
146
|
+
"@lodestar/utils": "^1.44.0-dev.6a52e6a9f6",
|
|
147
|
+
"@lodestar/validator": "^1.44.0-dev.6a52e6a9f6",
|
|
149
148
|
"@multiformats/multiaddr": "^13.0.1",
|
|
150
149
|
"datastore-core": "^11.0.2",
|
|
151
150
|
"datastore-fs": "^11.0.2",
|
|
@@ -168,13 +167,12 @@
|
|
|
168
167
|
"@libp2p/interface-internal": "^3.0.13",
|
|
169
168
|
"@libp2p/logger": "^6.2.2",
|
|
170
169
|
"@libp2p/utils": "^7.0.13",
|
|
171
|
-
"@lodestar/spec-test-util": "^1.44.0-dev.
|
|
170
|
+
"@lodestar/spec-test-util": "^1.44.0-dev.6a52e6a9f6",
|
|
172
171
|
"@types/js-yaml": "^4.0.5",
|
|
173
172
|
"@types/qs": "^6.9.7",
|
|
174
173
|
"@types/tmp": "^0.2.3",
|
|
175
174
|
"dotenv": "^16.4.5",
|
|
176
175
|
"js-yaml": "^4.1.0",
|
|
177
|
-
"rewiremock": "^3.14.5",
|
|
178
176
|
"rimraf": "^4.4.1",
|
|
179
177
|
"snappy": "^7.2.2",
|
|
180
178
|
"snappyjs": "^0.7.0",
|
|
@@ -186,5 +184,5 @@
|
|
|
186
184
|
"beacon",
|
|
187
185
|
"blockchain"
|
|
188
186
|
],
|
|
189
|
-
"gitHead": "
|
|
187
|
+
"gitHead": "81de9c8ef90c65bd31cc81b2f90fc01981705073"
|
|
190
188
|
}
|
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
ProduceFullGloas,
|
|
51
51
|
} from "../../../../chain/produceBlock/index.js";
|
|
52
52
|
import {validateGossipBlock} from "../../../../chain/validation/block.js";
|
|
53
|
+
import {validateApiExecutionPayloadBid} from "../../../../chain/validation/executionPayloadBid.js";
|
|
53
54
|
import {validateApiExecutionPayloadEnvelope} from "../../../../chain/validation/executionPayloadEnvelope.js";
|
|
54
55
|
import {OpSource} from "../../../../chain/validatorMonitor.js";
|
|
55
56
|
import {
|
|
@@ -825,6 +826,41 @@ export function getBeaconBlockApi({
|
|
|
825
826
|
});
|
|
826
827
|
},
|
|
827
828
|
|
|
829
|
+
async publishExecutionPayloadBid({signedExecutionPayloadBid}) {
|
|
830
|
+
const bid = signedExecutionPayloadBid.message;
|
|
831
|
+
const slot = bid.slot;
|
|
832
|
+
const fork = config.getForkName(slot);
|
|
833
|
+
|
|
834
|
+
if (!isForkPostGloas(fork)) {
|
|
835
|
+
throw new ApiError(400, `publishExecutionPayloadBid not supported for pre-gloas fork=${fork}`);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
await validateApiExecutionPayloadBid(chain, signedExecutionPayloadBid);
|
|
839
|
+
|
|
840
|
+
try {
|
|
841
|
+
const insertOutcome = chain.executionPayloadBidPool.add(signedExecutionPayloadBid);
|
|
842
|
+
metrics?.opPool.executionPayloadBidPool.apiInsertOutcome.inc({insertOutcome});
|
|
843
|
+
} catch (e) {
|
|
844
|
+
chain.logger.error("Error adding to executionPayloadBid pool", {}, e as Error);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
const sentPeers = await network.publishSignedExecutionPayloadBid(signedExecutionPayloadBid);
|
|
848
|
+
|
|
849
|
+
chain.emitter.emit(routes.events.EventType.executionPayloadBid, {
|
|
850
|
+
version: fork,
|
|
851
|
+
data: signedExecutionPayloadBid,
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
chain.logger.info("Published execution payload bid", {
|
|
855
|
+
slot,
|
|
856
|
+
builderIndex: bid.builderIndex,
|
|
857
|
+
blockHash: toRootHex(bid.blockHash),
|
|
858
|
+
parentBlockHash: toRootHex(bid.parentBlockHash),
|
|
859
|
+
value: bid.value,
|
|
860
|
+
sentPeers,
|
|
861
|
+
});
|
|
862
|
+
},
|
|
863
|
+
|
|
828
864
|
async getSignedExecutionPayloadEnvelope({blockId}, context) {
|
|
829
865
|
const {block, executionOptimistic, finalized} = await getBlockResponse(chain, blockId);
|
|
830
866
|
const slot = block.message.slot;
|
|
@@ -328,8 +328,10 @@ export function getBeaconPoolApi({
|
|
|
328
328
|
|
|
329
329
|
chain.forkChoice.notifyPtcMessages(
|
|
330
330
|
toRootHex(payloadAttestationMessage.data.beaconBlockRoot),
|
|
331
|
+
payloadAttestationMessage.data.slot,
|
|
331
332
|
validatorCommitteeIndices,
|
|
332
|
-
payloadAttestationMessage.data.payloadPresent
|
|
333
|
+
payloadAttestationMessage.data.payloadPresent,
|
|
334
|
+
payloadAttestationMessage.data.blobDataAvailable
|
|
333
335
|
);
|
|
334
336
|
|
|
335
337
|
await network.publishPayloadAttestationMessage(payloadAttestationMessage);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ApplicationMethods} from "@lodestar/api/server";
|
|
3
|
-
import {ExecutionStatus} from "@lodestar/fork-choice";
|
|
3
|
+
import {ExecutionStatus, PayloadStatus} from "@lodestar/fork-choice";
|
|
4
4
|
import {ForkPostDeneb, ZERO_HASH_HEX, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
|
|
5
|
+
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
5
6
|
import {BeaconState, DataColumnSidecar, DataColumnSidecars, type SignedBeaconBlock, sszTypesFor} from "@lodestar/types";
|
|
6
7
|
import {toRootHex} from "@lodestar/utils";
|
|
7
8
|
import {getBlobKzgCommitments} from "../../../util/dataColumns.js";
|
|
@@ -12,6 +13,29 @@ import {getStateResponseWithRegen} from "../beacon/state/utils.js";
|
|
|
12
13
|
import {ApiModules} from "../types.js";
|
|
13
14
|
import {assertUniqueItems} from "../utils.js";
|
|
14
15
|
|
|
16
|
+
function toForkChoiceValidity(status: ExecutionStatus): "valid" | "invalid" | "optimistic" {
|
|
17
|
+
switch (status) {
|
|
18
|
+
case ExecutionStatus.Valid:
|
|
19
|
+
return "valid";
|
|
20
|
+
case ExecutionStatus.Invalid:
|
|
21
|
+
return "invalid";
|
|
22
|
+
case ExecutionStatus.Syncing:
|
|
23
|
+
case ExecutionStatus.PreMerge:
|
|
24
|
+
return "optimistic";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function toPayloadStatusName(status: PayloadStatus): "pending" | "empty" | "full" {
|
|
29
|
+
switch (status) {
|
|
30
|
+
case PayloadStatus.PENDING:
|
|
31
|
+
return "pending";
|
|
32
|
+
case PayloadStatus.EMPTY:
|
|
33
|
+
return "empty";
|
|
34
|
+
case PayloadStatus.FULL:
|
|
35
|
+
return "full";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
15
39
|
export function getDebugApi({
|
|
16
40
|
chain,
|
|
17
41
|
config,
|
|
@@ -40,23 +64,60 @@ export function getDebugApi({
|
|
|
40
64
|
justifiedEpoch: node.justifiedEpoch,
|
|
41
65
|
finalizedEpoch: node.finalizedEpoch,
|
|
42
66
|
weight: node.weight,
|
|
43
|
-
validity: (
|
|
44
|
-
switch (node.executionStatus) {
|
|
45
|
-
case ExecutionStatus.Valid:
|
|
46
|
-
return "valid";
|
|
47
|
-
case ExecutionStatus.Invalid:
|
|
48
|
-
return "invalid";
|
|
49
|
-
case ExecutionStatus.Syncing:
|
|
50
|
-
case ExecutionStatus.PreMerge:
|
|
51
|
-
return "optimistic";
|
|
52
|
-
}
|
|
53
|
-
})(),
|
|
67
|
+
validity: toForkChoiceValidity(node.executionStatus),
|
|
54
68
|
executionBlockHash: node.executionPayloadBlockHash ?? ZERO_HASH_HEX,
|
|
55
69
|
})),
|
|
56
70
|
},
|
|
57
71
|
};
|
|
58
72
|
},
|
|
59
73
|
|
|
74
|
+
async getDebugForkChoiceV2() {
|
|
75
|
+
const {forkChoice} = chain;
|
|
76
|
+
return {
|
|
77
|
+
data: {
|
|
78
|
+
justifiedCheckpoint: forkChoice.getJustifiedCheckpoint(),
|
|
79
|
+
finalizedCheckpoint: forkChoice.getFinalizedCheckpoint(),
|
|
80
|
+
forkChoiceNodes: forkChoice.getAllNodes().map((node) => {
|
|
81
|
+
// Payload-specific fields apply only to a revealed Gloas payload = the FULL variant of a
|
|
82
|
+
// Gloas block
|
|
83
|
+
const ptc = node.payloadStatus === PayloadStatus.FULL ? forkChoice.getPTCVoteCounts(node.blockRoot) : null;
|
|
84
|
+
return {
|
|
85
|
+
payloadStatus: toPayloadStatusName(node.payloadStatus),
|
|
86
|
+
slot: node.slot,
|
|
87
|
+
blockRoot: node.blockRoot,
|
|
88
|
+
parentRoot: node.parentRoot,
|
|
89
|
+
weight: node.weight,
|
|
90
|
+
validity: toForkChoiceValidity(node.executionStatus),
|
|
91
|
+
executionBlockHash: node.executionPayloadBlockHash ?? ZERO_HASH_HEX,
|
|
92
|
+
extraData: {
|
|
93
|
+
executionOptimistic: isOptimisticBlock(node),
|
|
94
|
+
timestamp: computeTimeAtSlot(config, node.slot, chain.genesisTime),
|
|
95
|
+
target: node.targetRoot,
|
|
96
|
+
justifiedEpoch: node.justifiedEpoch,
|
|
97
|
+
finalizedEpoch: node.finalizedEpoch,
|
|
98
|
+
unrealizedJustifiedEpoch: node.unrealizedJustifiedEpoch,
|
|
99
|
+
unrealizedFinalizedEpoch: node.unrealizedFinalizedEpoch,
|
|
100
|
+
payloadAttesterCount: ptc?.attesterCount ?? null,
|
|
101
|
+
payloadAvailabilityYesCount: ptc?.payloadPresentCount ?? null,
|
|
102
|
+
payloadDataAvailabilityYesCount: ptc?.dataAvailableCount ?? null,
|
|
103
|
+
gasLimit:
|
|
104
|
+
node.payloadStatus === PayloadStatus.FULL && "executionPayloadGasLimit" in node
|
|
105
|
+
? node.executionPayloadGasLimit
|
|
106
|
+
: null,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}),
|
|
110
|
+
extraData: {
|
|
111
|
+
unrealizedJustifiedCheckpoint: forkChoice.getUnrealizedJustifiedCheckpoint(),
|
|
112
|
+
unrealizedFinalizedCheckpoint: forkChoice.getUnrealizedFinalizedCheckpoint(),
|
|
113
|
+
proposerBoostRoot: forkChoice.getProposerBoostRoot(),
|
|
114
|
+
previousProposerBoostRoot: forkChoice.getPreviousProposerBoostRoot(),
|
|
115
|
+
headRoot: forkChoice.getHeadRoot(),
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
|
|
60
121
|
async getProtoArrayNodes() {
|
|
61
122
|
const nodes = chain.forkChoice.getAllNodes().map((node) => ({
|
|
62
123
|
// if node has executionPayloadNumber, it will overwrite the below default
|
|
@@ -914,20 +914,38 @@ export function getValidatorApi(
|
|
|
914
914
|
notWhileSyncing();
|
|
915
915
|
await waitForSlot(slot);
|
|
916
916
|
|
|
917
|
-
// TODO GLOAS: support producing blocks from builder bids
|
|
918
|
-
const source = ProducedBlockSource.engine;
|
|
919
|
-
|
|
920
|
-
// TODO GLOAS: needs to be updated after fork choice changes are merged
|
|
921
917
|
const parentBlock = chain.getProposerHead(slot);
|
|
922
918
|
const {blockRoot: parentBlockRootHex, slot: parentSlot} = parentBlock;
|
|
923
919
|
const parentBlockRoot = fromHex(parentBlockRootHex);
|
|
924
920
|
notOnOutOfRangeData(parentBlockRoot);
|
|
925
921
|
metrics?.blockProductionSlotDelta.set(slot - parentSlot);
|
|
926
|
-
metrics?.blockProductionRequests.inc({source});
|
|
927
922
|
|
|
928
923
|
const graffitiBytes = toGraffitiBytes(
|
|
929
924
|
graffiti ?? getDefaultGraffiti(getLodestarClientVersion(opts), chain.executionEngine.clientVersion, opts)
|
|
930
925
|
);
|
|
926
|
+
|
|
927
|
+
// TODO GLOAS: respect builderSelection (MaxProfit, BuilderAlways, ExecutionAlways, etc.) to let
|
|
928
|
+
// the user control bid source preferences and value comparison. Also add external builder api
|
|
929
|
+
// support when it is implemented.
|
|
930
|
+
const isBuildingOnFull = chain.forkChoice.shouldBuildOnFull(parentBlock, slot);
|
|
931
|
+
const bidParentBlockHash = isBuildingOnFull ? parentBlock.executionPayloadBlockHash : parentBlock.parentBlockHash;
|
|
932
|
+
const builderBid = chain.executionPayloadBidPool.getBestBid(slot, bidParentBlockHash, parentBlockRootHex);
|
|
933
|
+
|
|
934
|
+
const logCtx = {
|
|
935
|
+
slot,
|
|
936
|
+
parentSlot,
|
|
937
|
+
parentBlockRoot: parentBlockRootHex,
|
|
938
|
+
parentBlockHash: parentBlock.executionPayloadBlockHash,
|
|
939
|
+
fork,
|
|
940
|
+
...(builderBid !== null
|
|
941
|
+
? {
|
|
942
|
+
bidValue: builderBid.message.value,
|
|
943
|
+
builderIndex: builderBid.message.builderIndex,
|
|
944
|
+
bidBlockHash: toRootHex(builderBid.message.blockHash),
|
|
945
|
+
}
|
|
946
|
+
: {}),
|
|
947
|
+
};
|
|
948
|
+
|
|
931
949
|
const commonBlockBodyPromise = chain.produceCommonBlockBody({
|
|
932
950
|
slot,
|
|
933
951
|
parentBlock,
|
|
@@ -935,44 +953,76 @@ export function getValidatorApi(
|
|
|
935
953
|
graffiti: graffitiBytes,
|
|
936
954
|
});
|
|
937
955
|
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
feeRecipient,
|
|
947
|
-
commonBlockBodyPromise,
|
|
948
|
-
});
|
|
956
|
+
const baseAttrs = {
|
|
957
|
+
slot,
|
|
958
|
+
parentBlock,
|
|
959
|
+
randaoReveal,
|
|
960
|
+
graffiti: graffitiBytes,
|
|
961
|
+
feeRecipient,
|
|
962
|
+
commonBlockBodyPromise,
|
|
963
|
+
};
|
|
949
964
|
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
metrics?.
|
|
953
|
-
|
|
965
|
+
metrics?.blockProductionRequests.inc({source: ProducedBlockSource.engine});
|
|
966
|
+
if (builderBid !== null) {
|
|
967
|
+
metrics?.blockProductionRequests.inc({source: ProducedBlockSource.builder});
|
|
968
|
+
}
|
|
954
969
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
970
|
+
const timed = <T>(source: ProducedBlockSource, fn: () => Promise<T>): Promise<T> => {
|
|
971
|
+
const t = metrics?.blockProductionTime.startTimer();
|
|
972
|
+
return fn().finally(() => t?.({source}));
|
|
973
|
+
};
|
|
974
|
+
|
|
975
|
+
// Always build local block. If builder bid available, also build with it in parallel and prefer it.
|
|
976
|
+
const [engineResult, bidResult] = await Promise.allSettled([
|
|
977
|
+
timed(ProducedBlockSource.engine, () => chain.produceBlock(baseAttrs)),
|
|
978
|
+
builderBid !== null
|
|
979
|
+
? timed(ProducedBlockSource.builder, () => chain.produceBlock({...baseAttrs, builderBid}))
|
|
980
|
+
: Promise.reject(),
|
|
981
|
+
]);
|
|
982
|
+
|
|
983
|
+
let bestResult: typeof engineResult | null = null;
|
|
984
|
+
let source: ProducedBlockSource = ProducedBlockSource.engine;
|
|
985
|
+
if (builderBid !== null && bidResult.status === "fulfilled") {
|
|
986
|
+
source = ProducedBlockSource.builder;
|
|
987
|
+
bestResult = bidResult;
|
|
988
|
+
logger.info("Selected builder bid block", logCtx);
|
|
989
|
+
} else if (engineResult.status === "fulfilled") {
|
|
990
|
+
source = ProducedBlockSource.engine;
|
|
991
|
+
bestResult = engineResult;
|
|
992
|
+
if (builderBid !== null) {
|
|
993
|
+
logger.warn("Builder bid block production failed, using local block", logCtx);
|
|
964
994
|
}
|
|
995
|
+
}
|
|
965
996
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
}
|
|
974
|
-
|
|
997
|
+
if (bestResult === null || bestResult.status !== "fulfilled") {
|
|
998
|
+
const engineReason = engineResult.status === "rejected" ? engineResult.reason : undefined;
|
|
999
|
+
const bidReason = builderBid !== null && bidResult.status === "rejected" ? bidResult.reason : undefined;
|
|
1000
|
+
logger.error("Block production failed", {...logCtx, engineReason, bidReason});
|
|
1001
|
+
throw Error(`Block production failed: engine=${engineReason ?? "n/a"} builder=${bidReason ?? "n/a"}`);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
const {block, executionPayloadValue, consensusBlockValue} = bestResult.value;
|
|
1005
|
+
|
|
1006
|
+
metrics?.blockProductionSuccess.inc({source});
|
|
1007
|
+
metrics?.blockProductionNumAggregated.observe({source}, block.body.attestations.length);
|
|
1008
|
+
metrics?.blockProductionConsensusBlockValue.observe({source}, Number(formatWeiToEth(consensusBlockValue)));
|
|
1009
|
+
metrics?.blockProductionExecutionPayloadValue.observe({source}, Number(formatWeiToEth(executionPayloadValue)));
|
|
1010
|
+
|
|
1011
|
+
const blockRoot = toRootHex(config.getForkTypes(slot).BeaconBlock.hashTreeRoot(block));
|
|
1012
|
+
logger.verbose("Produced block", {
|
|
1013
|
+
...logCtx,
|
|
1014
|
+
executionPayloadValue,
|
|
1015
|
+
consensusBlockValue,
|
|
1016
|
+
root: blockRoot,
|
|
1017
|
+
});
|
|
1018
|
+
if (chain.opts.persistProducedBlocks) {
|
|
1019
|
+
void chain.persistBlock(block, "produced_engine_block");
|
|
975
1020
|
}
|
|
1021
|
+
|
|
1022
|
+
return {
|
|
1023
|
+
data: block as gloas.BeaconBlock,
|
|
1024
|
+
meta: {version: fork, consensusBlockValue},
|
|
1025
|
+
};
|
|
976
1026
|
},
|
|
977
1027
|
|
|
978
1028
|
async produceAttestationData({committeeIndex, slot}) {
|
|
@@ -1060,15 +1110,34 @@ export function getValidatorApi(
|
|
|
1060
1110
|
notWhileSyncing();
|
|
1061
1111
|
await waitForSlot(slot);
|
|
1062
1112
|
|
|
1063
|
-
const block = chain.forkChoice.
|
|
1113
|
+
const block = chain.forkChoice.getCanonicalBlockAtSlot(slot);
|
|
1064
1114
|
if (!block) {
|
|
1065
|
-
|
|
1115
|
+
// No block is seen at slot. Return 404 so vc can skip casting payload attestation.
|
|
1116
|
+
throw new ApiError(404, `No canonical block found at slot=${slot}`);
|
|
1066
1117
|
}
|
|
1067
1118
|
|
|
1068
|
-
const blockIsForSlot = block.slot === slot;
|
|
1069
1119
|
const payloadInput = chain.seenPayloadEnvelopeInputCache.get(block.blockRoot);
|
|
1070
|
-
|
|
1071
|
-
|
|
1120
|
+
// Spec: set payload_present only if the envelope was seen before get_payload_due_ms()
|
|
1121
|
+
// into the slot. Use the envelope's own arrival time (getPayloadEnvelopeSource), not
|
|
1122
|
+
// the input's creation time.
|
|
1123
|
+
const payloadDueSec = config.getPayloadDueMs() / 1000;
|
|
1124
|
+
const payloadSeenSec =
|
|
1125
|
+
payloadInput?.hasPayloadEnvelope() === true
|
|
1126
|
+
? chain.clock.secFromSlot(slot, payloadInput.getPayloadEnvelopeSource().seenTimestampSec)
|
|
1127
|
+
: null;
|
|
1128
|
+
const payloadPresent = payloadSeenSec !== null && payloadSeenSec < payloadDueSec;
|
|
1129
|
+
const blobDataAvailable = payloadInput?.hasAllData() === true;
|
|
1130
|
+
|
|
1131
|
+
logger.debug("Produced payload attestation data", {
|
|
1132
|
+
slot,
|
|
1133
|
+
blockRoot: block.blockRoot,
|
|
1134
|
+
blockSlot: block.slot,
|
|
1135
|
+
payloadPresent,
|
|
1136
|
+
blobDataAvailable,
|
|
1137
|
+
hasPayloadInput: payloadInput !== undefined,
|
|
1138
|
+
payloadSeenSec,
|
|
1139
|
+
payloadDueSec,
|
|
1140
|
+
});
|
|
1072
1141
|
|
|
1073
1142
|
return {
|
|
1074
1143
|
data: {
|
|
@@ -30,7 +30,6 @@ export enum ArchiveStoreTask {
|
|
|
30
30
|
PruneHistory = "prune_history",
|
|
31
31
|
OnFinalizedCheckpoint = "on_finalized_checkpoint",
|
|
32
32
|
MaybeArchiveState = "maybe_archive_state",
|
|
33
|
-
RegenPruneOnFinalized = "regen_prune_on_finalized",
|
|
34
33
|
ForkchoicePrune = "forkchoice_prune",
|
|
35
34
|
UpdateBackfillRange = "update_backfill_range",
|
|
36
35
|
}
|
|
@@ -229,10 +228,6 @@ export class ArchiveStore {
|
|
|
229
228
|
await this.statesArchiverStrategy.maybeArchiveState(finalized, this.metrics);
|
|
230
229
|
timer?.({source: ArchiveStoreTask.MaybeArchiveState});
|
|
231
230
|
|
|
232
|
-
timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
233
|
-
this.chain.regen.pruneOnFinalized(finalizedEpoch);
|
|
234
|
-
timer?.({source: ArchiveStoreTask.RegenPruneOnFinalized});
|
|
235
|
-
|
|
236
231
|
// tasks rely on extended fork choice
|
|
237
232
|
timer = this.metrics?.processFinalizedCheckpoint.durationByTask.startTimer();
|
|
238
233
|
const prunedBlocks = this.chain.forkChoice.prune(finalized.rootHex);
|
|
@@ -116,13 +116,19 @@ export async function importBlock(
|
|
|
116
116
|
}
|
|
117
117
|
executionStatus = parentBlock.executionStatus;
|
|
118
118
|
}
|
|
119
|
+
|
|
120
|
+
// getBeaconProposerOrNull will return null if head state is more than one epoch away
|
|
121
|
+
// from block slot. We skip proposer boost canonical check as we cannot determine the canonical proposer
|
|
122
|
+
const expectedProposerIndex: number | null = this.getHeadState().getBeaconProposerOrNull(blockSlot);
|
|
123
|
+
|
|
119
124
|
const blockSummary = this.forkChoice.onBlock(
|
|
120
125
|
block.message,
|
|
121
126
|
postState,
|
|
122
127
|
blockDelaySec,
|
|
123
128
|
currentSlot,
|
|
124
129
|
executionStatus,
|
|
125
|
-
dataAvailabilityStatus
|
|
130
|
+
dataAvailabilityStatus,
|
|
131
|
+
expectedProposerIndex
|
|
126
132
|
);
|
|
127
133
|
|
|
128
134
|
// This adds the state necessary to process the next block
|
|
@@ -257,8 +263,10 @@ export async function importBlock(
|
|
|
257
263
|
if (ptcIndices.length > 0) {
|
|
258
264
|
this.forkChoice.notifyPtcMessages(
|
|
259
265
|
toRootHex(payloadAttestation.data.beaconBlockRoot),
|
|
266
|
+
payloadAttestation.data.slot,
|
|
260
267
|
ptcIndices,
|
|
261
|
-
payloadAttestation.data.payloadPresent
|
|
268
|
+
payloadAttestation.data.payloadPresent,
|
|
269
|
+
payloadAttestation.data.blobDataAvailable
|
|
262
270
|
);
|
|
263
271
|
}
|
|
264
272
|
} catch (e) {
|
|
@@ -129,7 +129,7 @@ export async function importExecutionPayload(
|
|
|
129
129
|
|
|
130
130
|
// 3. Regenerate state for envelope verification
|
|
131
131
|
const blockState = await this.regen
|
|
132
|
-
.getBlockSlotState(protoBlock, protoBlock.slot, {dontTransferCache: true}, RegenCaller.
|
|
132
|
+
.getBlockSlotState(protoBlock, protoBlock.slot, {dontTransferCache: true}, RegenCaller.importExecutionPayload)
|
|
133
133
|
.catch(() =>
|
|
134
134
|
// only happen at the 1st batch of skipped slot checkpoint sync
|
|
135
135
|
this.regen.getClosestHeadState(protoBlock)
|
|
@@ -237,6 +237,7 @@ export async function importExecutionPayload(
|
|
|
237
237
|
blockRootHex,
|
|
238
238
|
blockHashHex,
|
|
239
239
|
envelope.payload.blockNumber,
|
|
240
|
+
envelope.payload.gasLimit,
|
|
240
241
|
execStatus,
|
|
241
242
|
dataAvailabilityStatus
|
|
242
243
|
);
|
|
@@ -254,7 +255,11 @@ export async function importExecutionPayload(
|
|
|
254
255
|
}
|
|
255
256
|
|
|
256
257
|
// 8. Record metrics for payload envelope and column sources
|
|
257
|
-
this.
|
|
258
|
+
const delaySec = this.clock.secFromSlot(slot);
|
|
259
|
+
this.metrics?.importPayload.elapsedTimeTillImported.observe(
|
|
260
|
+
{source: payloadInput.getPayloadEnvelopeSource().source},
|
|
261
|
+
delaySec
|
|
262
|
+
);
|
|
258
263
|
for (const {source} of payloadInput.getSampledColumnsWithSource()) {
|
|
259
264
|
this.metrics?.importPayload.columnsBySource.inc({source});
|
|
260
265
|
}
|
|
@@ -275,6 +280,7 @@ export async function importExecutionPayload(
|
|
|
275
280
|
builderIndex: envelope.builderIndex,
|
|
276
281
|
blockRoot: blockRootHex,
|
|
277
282
|
blockHash: blockHashHex,
|
|
283
|
+
delaySec,
|
|
278
284
|
});
|
|
279
285
|
}
|
|
280
286
|
|
package/src/chain/chain.ts
CHANGED
|
@@ -1049,6 +1049,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1049
1049
|
feeRecipient,
|
|
1050
1050
|
commonBlockBodyPromise,
|
|
1051
1051
|
parentBlock,
|
|
1052
|
+
builderBid,
|
|
1052
1053
|
}: BlockAttributes & {commonBlockBodyPromise: Promise<CommonBlockBody>}
|
|
1053
1054
|
): Promise<{
|
|
1054
1055
|
block: AssembledBlockType<T>;
|
|
@@ -1078,6 +1079,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1078
1079
|
proposerIndex,
|
|
1079
1080
|
proposerPubKey,
|
|
1080
1081
|
commonBlockBodyPromise,
|
|
1082
|
+
builderBid,
|
|
1081
1083
|
}
|
|
1082
1084
|
);
|
|
1083
1085
|
|
|
@@ -9,7 +9,9 @@ export enum ExecutionPayloadBidErrorCode {
|
|
|
9
9
|
BID_TOO_HIGH = "EXECUTION_PAYLOAD_BID_ERROR_BID_TOO_HIGH",
|
|
10
10
|
TOO_MANY_KZG_COMMITMENTS = "EXECUTION_PAYLOAD_BID_ERROR_TOO_MANY_KZG_COMMITMENTS",
|
|
11
11
|
UNKNOWN_BLOCK_ROOT = "EXECUTION_PAYLOAD_BID_ERROR_UNKNOWN_BLOCK_ROOT",
|
|
12
|
+
UNKNOWN_PARENT_BLOCK_HASH = "EXECUTION_PAYLOAD_BID_ERROR_UNKNOWN_PARENT_BLOCK_HASH",
|
|
12
13
|
INVALID_SLOT = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SLOT",
|
|
14
|
+
NOT_LATER_THAN_PARENT = "EXECUTION_PAYLOAD_BID_ERROR_NOT_LATER_THAN_PARENT",
|
|
13
15
|
INVALID_SIGNATURE = "EXECUTION_PAYLOAD_BID_ERROR_INVALID_SIGNATURE",
|
|
14
16
|
NO_MATCHING_PROPOSER_PREFERENCES = "EXECUTION_PAYLOAD_BID_ERROR_NO_MATCHING_PROPOSER_PREFERENCES",
|
|
15
17
|
PROPOSER_PREFERENCES_FEE_RECIPIENT_MISMATCH = "EXECUTION_PAYLOAD_BID_ERROR_PROPOSER_PREFERENCES_FEE_RECIPIENT_MISMATCH",
|
|
@@ -38,7 +40,9 @@ export type ExecutionPayloadBidErrorType =
|
|
|
38
40
|
commitmentLimit: number;
|
|
39
41
|
}
|
|
40
42
|
| {code: ExecutionPayloadBidErrorCode.UNKNOWN_BLOCK_ROOT; parentBlockRoot: RootHex}
|
|
43
|
+
| {code: ExecutionPayloadBidErrorCode.UNKNOWN_PARENT_BLOCK_HASH; parentBlockHash: RootHex}
|
|
41
44
|
| {code: ExecutionPayloadBidErrorCode.INVALID_SLOT; builderIndex: BuilderIndex; slot: Slot}
|
|
45
|
+
| {code: ExecutionPayloadBidErrorCode.NOT_LATER_THAN_PARENT; parentSlot: Slot; slot: Slot}
|
|
42
46
|
| {code: ExecutionPayloadBidErrorCode.INVALID_SIGNATURE; builderIndex: BuilderIndex; slot: Slot}
|
|
43
47
|
| {
|
|
44
48
|
code: ExecutionPayloadBidErrorCode.NO_MATCHING_PROPOSER_PREFERENCES;
|
|
@@ -56,7 +60,8 @@ export type ExecutionPayloadBidErrorType =
|
|
|
56
60
|
code: ExecutionPayloadBidErrorCode.PROPOSER_PREFERENCES_GAS_LIMIT_MISMATCH;
|
|
57
61
|
builderIndex: BuilderIndex;
|
|
58
62
|
bidGasLimit: number;
|
|
59
|
-
|
|
63
|
+
parentGasLimit: number;
|
|
64
|
+
targetGasLimit: number;
|
|
60
65
|
};
|
|
61
66
|
|
|
62
67
|
export class ExecutionPayloadBidError extends GossipActionError<ExecutionPayloadBidErrorType> {}
|
|
@@ -5,6 +5,7 @@ export enum PayloadAttestationErrorCode {
|
|
|
5
5
|
NOT_CURRENT_SLOT = "PAYLOAD_ATTESTATION_ERROR_NOT_CURRENT_SLOT",
|
|
6
6
|
PAYLOAD_ATTESTATION_ALREADY_KNOWN = "PAYLOAD_ATTESTATION_ERROR_PAYLOAD_ATTESTATION_ALREADY_KNOWN",
|
|
7
7
|
UNKNOWN_BLOCK_ROOT = "PAYLOAD_ATTESTATION_ERROR_UNKNOWN_BLOCK_ROOT",
|
|
8
|
+
INVALID_BLOCK_SLOT = "PAYLOAD_ATTESTATION_ERROR_INVALID_BLOCK_SLOT",
|
|
8
9
|
INVALID_BLOCK = "PAYLOAD_ATTESTATION_ERROR_INVALID_BLOCK",
|
|
9
10
|
INVALID_ATTESTER = "PAYLOAD_ATTESTATION_ERROR_INVALID_ATTESTER",
|
|
10
11
|
INVALID_SIGNATURE = "PAYLOAD_ATTESTATION_ERROR_INVALID_SIGNATURE",
|
|
@@ -18,6 +19,7 @@ export type PayloadAttestationErrorType =
|
|
|
18
19
|
blockRoot: RootHex;
|
|
19
20
|
}
|
|
20
21
|
| {code: PayloadAttestationErrorCode.UNKNOWN_BLOCK_ROOT; blockRoot: RootHex}
|
|
22
|
+
| {code: PayloadAttestationErrorCode.INVALID_BLOCK_SLOT; blockRoot: RootHex; blockSlot: Slot; slot: Slot}
|
|
21
23
|
| {code: PayloadAttestationErrorCode.INVALID_BLOCK; blockRoot: RootHex}
|
|
22
24
|
| {code: PayloadAttestationErrorCode.INVALID_ATTESTER; attesterIndex: ValidatorIndex}
|
|
23
25
|
| {code: PayloadAttestationErrorCode.INVALID_SIGNATURE};
|