@lodestar/builder 1.49.0-dev.a261342520 → 1.49.0-dev.ae6cc426f1
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.
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ForkPostGloas } from "@lodestar/params";
|
|
2
|
+
import type { BlobsBundle, ColumnIndex, ExecutionPayload, ExecutionRequests, RootHex, SSEPayloadAttributes } from "@lodestar/types";
|
|
3
|
+
import { LodestarError } from "@lodestar/utils";
|
|
4
|
+
export type PayloadId = string;
|
|
5
|
+
export type ForkchoiceState = {
|
|
6
|
+
headBlockHash: RootHex;
|
|
7
|
+
safeBlockHash: RootHex;
|
|
8
|
+
finalizedBlockHash: RootHex;
|
|
9
|
+
};
|
|
10
|
+
export type PayloadAttributes = SSEPayloadAttributes<ForkPostGloas>["payloadAttributes"];
|
|
11
|
+
export type BuildRequest = {
|
|
12
|
+
fork: ForkPostGloas;
|
|
13
|
+
forkchoiceState: ForkchoiceState;
|
|
14
|
+
payloadAttributes: PayloadAttributes;
|
|
15
|
+
};
|
|
16
|
+
export type BuildHandle = {
|
|
17
|
+
sourceId: string;
|
|
18
|
+
fork: ForkPostGloas;
|
|
19
|
+
payloadId: PayloadId;
|
|
20
|
+
};
|
|
21
|
+
export type BuiltPayload = {
|
|
22
|
+
sourceId: string;
|
|
23
|
+
fork: ForkPostGloas;
|
|
24
|
+
executionPayload: ExecutionPayload<ForkPostGloas>;
|
|
25
|
+
executionRequests: ExecutionRequests<ForkPostGloas>;
|
|
26
|
+
blobsBundle: BlobsBundle<ForkPostGloas>;
|
|
27
|
+
executionPayloadValue: bigint;
|
|
28
|
+
};
|
|
29
|
+
export type EnginePayloadResult = {
|
|
30
|
+
executionPayload: ExecutionPayload<ForkPostGloas>;
|
|
31
|
+
executionPayloadValue: bigint;
|
|
32
|
+
blobsBundle?: BlobsBundle<ForkPostGloas>;
|
|
33
|
+
executionRequests?: ExecutionRequests<ForkPostGloas>;
|
|
34
|
+
};
|
|
35
|
+
/** Narrow Engine boundary whose transport owns serialization, retries, and request execution. */
|
|
36
|
+
export interface PayloadSourceEngine {
|
|
37
|
+
notifyForkchoiceUpdate(fork: ForkPostGloas, headBlockHash: RootHex, safeBlockHash: RootHex, finalizedBlockHash: RootHex, payloadAttributes: PayloadAttributes, custodyColumns: ColumnIndex[] | null, signal: AbortSignal): Promise<PayloadId | null>;
|
|
38
|
+
getPayload(fork: ForkPostGloas, payloadId: PayloadId, signal: AbortSignal): Promise<EnginePayloadResult>;
|
|
39
|
+
}
|
|
40
|
+
/** Source that prepares and retrieves complete execution payloads without owning build scheduling policy. */
|
|
41
|
+
export interface PayloadSource {
|
|
42
|
+
readonly id: string;
|
|
43
|
+
prepare(request: BuildRequest, signal: AbortSignal): Promise<BuildHandle>;
|
|
44
|
+
getPayload(handle: BuildHandle, signal: AbortSignal): Promise<BuiltPayload>;
|
|
45
|
+
}
|
|
46
|
+
export declare enum PayloadSourceErrorCode {
|
|
47
|
+
NO_PAYLOAD_ID = "PAYLOAD_SOURCE_ERROR_NO_PAYLOAD_ID",
|
|
48
|
+
MISSING_BLOBS_BUNDLE = "PAYLOAD_SOURCE_ERROR_MISSING_BLOBS_BUNDLE",
|
|
49
|
+
MISSING_EXECUTION_REQUESTS = "PAYLOAD_SOURCE_ERROR_MISSING_EXECUTION_REQUESTS"
|
|
50
|
+
}
|
|
51
|
+
export type PayloadSourceErrorType = {
|
|
52
|
+
code: PayloadSourceErrorCode.NO_PAYLOAD_ID;
|
|
53
|
+
sourceId: string;
|
|
54
|
+
} | {
|
|
55
|
+
code: PayloadSourceErrorCode.MISSING_BLOBS_BUNDLE | PayloadSourceErrorCode.MISSING_EXECUTION_REQUESTS;
|
|
56
|
+
sourceId: string;
|
|
57
|
+
payloadId: PayloadId;
|
|
58
|
+
};
|
|
59
|
+
export declare class PayloadSourceError extends LodestarError<PayloadSourceErrorType> {
|
|
60
|
+
}
|
|
61
|
+
/** Payload source backed by an injected Engine boundary. Engine ownership and lifecycle remain caller policy. */
|
|
62
|
+
export declare class EnginePayloadSource implements PayloadSource {
|
|
63
|
+
readonly id: string;
|
|
64
|
+
private readonly engine;
|
|
65
|
+
constructor(id: string, engine: PayloadSourceEngine);
|
|
66
|
+
prepare(request: BuildRequest, signal: AbortSignal): Promise<BuildHandle>;
|
|
67
|
+
getPayload(handle: BuildHandle, signal: AbortSignal): Promise<BuiltPayload>;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=payloadSource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payloadSource.d.ts","sourceRoot":"","sources":["../../src/services/payloadSource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { LodestarError } from "@lodestar/utils";
|
|
2
|
+
export var PayloadSourceErrorCode;
|
|
3
|
+
(function (PayloadSourceErrorCode) {
|
|
4
|
+
PayloadSourceErrorCode["NO_PAYLOAD_ID"] = "PAYLOAD_SOURCE_ERROR_NO_PAYLOAD_ID";
|
|
5
|
+
PayloadSourceErrorCode["MISSING_BLOBS_BUNDLE"] = "PAYLOAD_SOURCE_ERROR_MISSING_BLOBS_BUNDLE";
|
|
6
|
+
PayloadSourceErrorCode["MISSING_EXECUTION_REQUESTS"] = "PAYLOAD_SOURCE_ERROR_MISSING_EXECUTION_REQUESTS";
|
|
7
|
+
})(PayloadSourceErrorCode || (PayloadSourceErrorCode = {}));
|
|
8
|
+
export class PayloadSourceError extends LodestarError {
|
|
9
|
+
}
|
|
10
|
+
/** Payload source backed by an injected Engine boundary. Engine ownership and lifecycle remain caller policy. */
|
|
11
|
+
export class EnginePayloadSource {
|
|
12
|
+
id;
|
|
13
|
+
engine;
|
|
14
|
+
constructor(id, engine) {
|
|
15
|
+
this.id = id;
|
|
16
|
+
this.engine = engine;
|
|
17
|
+
}
|
|
18
|
+
async prepare(request, signal) {
|
|
19
|
+
const { headBlockHash, safeBlockHash, finalizedBlockHash } = request.forkchoiceState;
|
|
20
|
+
const payloadId = await this.engine.notifyForkchoiceUpdate(request.fork, headBlockHash, safeBlockHash, finalizedBlockHash, request.payloadAttributes,
|
|
21
|
+
// The builder does not custody or sample data columns, so it never provides a custody set.
|
|
22
|
+
// A null custody set leaves the execution client's blobpool sampling set untouched, which is
|
|
23
|
+
// also what the spec's own build call does (`prepare_execution_payload` passes `custody_columns=None`).
|
|
24
|
+
null, signal);
|
|
25
|
+
if (payloadId === null) {
|
|
26
|
+
throw new PayloadSourceError({ code: PayloadSourceErrorCode.NO_PAYLOAD_ID, sourceId: this.id }, `Execution client did not return a payload ID sourceId=${this.id}`);
|
|
27
|
+
}
|
|
28
|
+
return { sourceId: this.id, fork: request.fork, payloadId };
|
|
29
|
+
}
|
|
30
|
+
async getPayload(handle, signal) {
|
|
31
|
+
const { executionPayload, executionPayloadValue, blobsBundle, executionRequests } = await this.engine.getPayload(handle.fork, handle.payloadId, signal);
|
|
32
|
+
if (blobsBundle === undefined) {
|
|
33
|
+
throw new PayloadSourceError({
|
|
34
|
+
code: PayloadSourceErrorCode.MISSING_BLOBS_BUNDLE,
|
|
35
|
+
sourceId: this.id,
|
|
36
|
+
payloadId: handle.payloadId,
|
|
37
|
+
}, `Execution client did not return a blobs bundle sourceId=${this.id} payloadId=${handle.payloadId}`);
|
|
38
|
+
}
|
|
39
|
+
if (executionRequests === undefined) {
|
|
40
|
+
throw new PayloadSourceError({
|
|
41
|
+
code: PayloadSourceErrorCode.MISSING_EXECUTION_REQUESTS,
|
|
42
|
+
sourceId: this.id,
|
|
43
|
+
payloadId: handle.payloadId,
|
|
44
|
+
}, `Execution client did not return execution requests sourceId=${this.id} payloadId=${handle.payloadId}`);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
sourceId: this.id,
|
|
48
|
+
fork: handle.fork,
|
|
49
|
+
executionPayload,
|
|
50
|
+
executionRequests,
|
|
51
|
+
blobsBundle,
|
|
52
|
+
executionPayloadValue,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=payloadSource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payloadSource.js","sourceRoot":"","sources":["../../src/services/payloadSource.ts"],"names":[],"mappings":"AASA,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AA6D9C,MAAM,CAAN,IAAY,sBAIX;AAJD,WAAY,sBAAsB;IAChC,8EAAoD,CAAA;IACpD,4FAAkE,CAAA;IAClE,wGAA8E,CAAA;AAChF,CAAC,EAJW,sBAAsB,KAAtB,sBAAsB,QAIjC;AAUD,MAAM,OAAO,kBAAmB,SAAQ,aAAqC;CAAG;AAEhF,iHAAiH;AACjH,MAAM,OAAO,mBAAmB;IAEnB,EAAE;IACM,MAAM;IAFzB,YACW,EAAU,EACF,MAA2B;kBADnC,EAAE;sBACM,MAAM;IACtB,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,OAAqB,EAAE,MAAmB;QACtD,MAAM,EAAC,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAC,GAAG,OAAO,CAAC,eAAe,CAAC;QACnF,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,CACxD,OAAO,CAAC,IAAI,EACZ,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,OAAO,CAAC,iBAAiB;QACzB,2FAA2F;QAC3F,6FAA6F;QAC7F,wGAAwG;QACxG,IAAI,EACJ,MAAM,CACP,CAAC;QAEF,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,kBAAkB,CAC1B,EAAC,IAAI,EAAE,sBAAsB,CAAC,aAAa,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAC,EAC/D,yDAAyD,IAAI,CAAC,EAAE,EAAE,CACnE,CAAC;QACJ,CAAC;QAED,OAAO,EAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,SAAS,EAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAmB,EAAE,MAAmB;QACvD,MAAM,EAAC,gBAAgB,EAAE,qBAAqB,EAAE,WAAW,EAAE,iBAAiB,EAAC,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAC5G,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,SAAS,EAChB,MAAM,CACP,CAAC;QAEF,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,kBAAkB,CAC1B;gBACE,IAAI,EAAE,sBAAsB,CAAC,oBAAoB;gBACjD,QAAQ,EAAE,IAAI,CAAC,EAAE;gBACjB,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,EACD,2DAA2D,IAAI,CAAC,EAAE,cAAc,MAAM,CAAC,SAAS,EAAE,CACnG,CAAC;QACJ,CAAC;QAED,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;YACpC,MAAM,IAAI,kBAAkB,CAC1B;gBACE,IAAI,EAAE,sBAAsB,CAAC,0BAA0B;gBACvD,QAAQ,EAAE,IAAI,CAAC,EAAE;gBACjB,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,EACD,+DAA+D,IAAI,CAAC,EAAE,cAAc,MAAM,CAAC,SAAS,EAAE,CACvG,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,EAAE;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,gBAAgB;YAChB,iBAAiB;YACjB,WAAW;YACX,qBAAqB;SACtB,CAAC;IACJ,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lodestar/builder",
|
|
3
|
-
"version": "1.49.0-dev.
|
|
3
|
+
"version": "1.49.0-dev.ae6cc426f1",
|
|
4
4
|
"description": "A Typescript implementation of the builder client",
|
|
5
5
|
"author": "ChainSafe Systems",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -48,16 +48,16 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@chainsafe/lodestar-z": "catalog:",
|
|
50
50
|
"@chainsafe/ssz": "^1.8.0",
|
|
51
|
-
"@lodestar/api": "^1.49.0-dev.
|
|
52
|
-
"@lodestar/config": "^1.49.0-dev.
|
|
53
|
-
"@lodestar/params": "^1.49.0-dev.
|
|
54
|
-
"@lodestar/state-transition": "^1.49.0-dev.
|
|
55
|
-
"@lodestar/types": "^1.49.0-dev.
|
|
56
|
-
"@lodestar/utils": "^1.49.0-dev.
|
|
51
|
+
"@lodestar/api": "^1.49.0-dev.ae6cc426f1",
|
|
52
|
+
"@lodestar/config": "^1.49.0-dev.ae6cc426f1",
|
|
53
|
+
"@lodestar/params": "^1.49.0-dev.ae6cc426f1",
|
|
54
|
+
"@lodestar/state-transition": "^1.49.0-dev.ae6cc426f1",
|
|
55
|
+
"@lodestar/types": "^1.49.0-dev.ae6cc426f1",
|
|
56
|
+
"@lodestar/utils": "^1.49.0-dev.ae6cc426f1"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@lodestar/logger": "^1.49.0-dev.
|
|
60
|
-
"@lodestar/test-utils": "^1.49.0-dev.
|
|
59
|
+
"@lodestar/logger": "^1.49.0-dev.ae6cc426f1",
|
|
60
|
+
"@lodestar/test-utils": "^1.49.0-dev.ae6cc426f1"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "4f45c6954eb81b7e86e86508c23df807b0bbfc81"
|
|
63
63
|
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import type {ForkPostGloas} from "@lodestar/params";
|
|
2
|
+
import type {
|
|
3
|
+
BlobsBundle,
|
|
4
|
+
ColumnIndex,
|
|
5
|
+
ExecutionPayload,
|
|
6
|
+
ExecutionRequests,
|
|
7
|
+
RootHex,
|
|
8
|
+
SSEPayloadAttributes,
|
|
9
|
+
} from "@lodestar/types";
|
|
10
|
+
import {LodestarError} from "@lodestar/utils";
|
|
11
|
+
|
|
12
|
+
export type PayloadId = string;
|
|
13
|
+
|
|
14
|
+
export type ForkchoiceState = {
|
|
15
|
+
headBlockHash: RootHex;
|
|
16
|
+
safeBlockHash: RootHex;
|
|
17
|
+
finalizedBlockHash: RootHex;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type PayloadAttributes = SSEPayloadAttributes<ForkPostGloas>["payloadAttributes"];
|
|
21
|
+
|
|
22
|
+
export type BuildRequest = {
|
|
23
|
+
fork: ForkPostGloas;
|
|
24
|
+
forkchoiceState: ForkchoiceState;
|
|
25
|
+
payloadAttributes: PayloadAttributes;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type BuildHandle = {
|
|
29
|
+
sourceId: string;
|
|
30
|
+
fork: ForkPostGloas;
|
|
31
|
+
payloadId: PayloadId;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type BuiltPayload = {
|
|
35
|
+
sourceId: string;
|
|
36
|
+
fork: ForkPostGloas;
|
|
37
|
+
executionPayload: ExecutionPayload<ForkPostGloas>;
|
|
38
|
+
executionRequests: ExecutionRequests<ForkPostGloas>;
|
|
39
|
+
blobsBundle: BlobsBundle<ForkPostGloas>;
|
|
40
|
+
executionPayloadValue: bigint;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type EnginePayloadResult = {
|
|
44
|
+
executionPayload: ExecutionPayload<ForkPostGloas>;
|
|
45
|
+
executionPayloadValue: bigint;
|
|
46
|
+
blobsBundle?: BlobsBundle<ForkPostGloas>;
|
|
47
|
+
executionRequests?: ExecutionRequests<ForkPostGloas>;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Narrow Engine boundary whose transport owns serialization, retries, and request execution. */
|
|
51
|
+
export interface PayloadSourceEngine {
|
|
52
|
+
notifyForkchoiceUpdate(
|
|
53
|
+
fork: ForkPostGloas,
|
|
54
|
+
headBlockHash: RootHex,
|
|
55
|
+
safeBlockHash: RootHex,
|
|
56
|
+
finalizedBlockHash: RootHex,
|
|
57
|
+
payloadAttributes: PayloadAttributes,
|
|
58
|
+
custodyColumns: ColumnIndex[] | null,
|
|
59
|
+
signal: AbortSignal
|
|
60
|
+
): Promise<PayloadId | null>;
|
|
61
|
+
getPayload(fork: ForkPostGloas, payloadId: PayloadId, signal: AbortSignal): Promise<EnginePayloadResult>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Source that prepares and retrieves complete execution payloads without owning build scheduling policy. */
|
|
65
|
+
export interface PayloadSource {
|
|
66
|
+
readonly id: string;
|
|
67
|
+
prepare(request: BuildRequest, signal: AbortSignal): Promise<BuildHandle>;
|
|
68
|
+
getPayload(handle: BuildHandle, signal: AbortSignal): Promise<BuiltPayload>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export enum PayloadSourceErrorCode {
|
|
72
|
+
NO_PAYLOAD_ID = "PAYLOAD_SOURCE_ERROR_NO_PAYLOAD_ID",
|
|
73
|
+
MISSING_BLOBS_BUNDLE = "PAYLOAD_SOURCE_ERROR_MISSING_BLOBS_BUNDLE",
|
|
74
|
+
MISSING_EXECUTION_REQUESTS = "PAYLOAD_SOURCE_ERROR_MISSING_EXECUTION_REQUESTS",
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export type PayloadSourceErrorType =
|
|
78
|
+
| {code: PayloadSourceErrorCode.NO_PAYLOAD_ID; sourceId: string}
|
|
79
|
+
| {
|
|
80
|
+
code: PayloadSourceErrorCode.MISSING_BLOBS_BUNDLE | PayloadSourceErrorCode.MISSING_EXECUTION_REQUESTS;
|
|
81
|
+
sourceId: string;
|
|
82
|
+
payloadId: PayloadId;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export class PayloadSourceError extends LodestarError<PayloadSourceErrorType> {}
|
|
86
|
+
|
|
87
|
+
/** Payload source backed by an injected Engine boundary. Engine ownership and lifecycle remain caller policy. */
|
|
88
|
+
export class EnginePayloadSource implements PayloadSource {
|
|
89
|
+
constructor(
|
|
90
|
+
readonly id: string,
|
|
91
|
+
private readonly engine: PayloadSourceEngine
|
|
92
|
+
) {}
|
|
93
|
+
|
|
94
|
+
async prepare(request: BuildRequest, signal: AbortSignal): Promise<BuildHandle> {
|
|
95
|
+
const {headBlockHash, safeBlockHash, finalizedBlockHash} = request.forkchoiceState;
|
|
96
|
+
const payloadId = await this.engine.notifyForkchoiceUpdate(
|
|
97
|
+
request.fork,
|
|
98
|
+
headBlockHash,
|
|
99
|
+
safeBlockHash,
|
|
100
|
+
finalizedBlockHash,
|
|
101
|
+
request.payloadAttributes,
|
|
102
|
+
// The builder does not custody or sample data columns, so it never provides a custody set.
|
|
103
|
+
// A null custody set leaves the execution client's blobpool sampling set untouched, which is
|
|
104
|
+
// also what the spec's own build call does (`prepare_execution_payload` passes `custody_columns=None`).
|
|
105
|
+
null,
|
|
106
|
+
signal
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
if (payloadId === null) {
|
|
110
|
+
throw new PayloadSourceError(
|
|
111
|
+
{code: PayloadSourceErrorCode.NO_PAYLOAD_ID, sourceId: this.id},
|
|
112
|
+
`Execution client did not return a payload ID sourceId=${this.id}`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return {sourceId: this.id, fork: request.fork, payloadId};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async getPayload(handle: BuildHandle, signal: AbortSignal): Promise<BuiltPayload> {
|
|
120
|
+
const {executionPayload, executionPayloadValue, blobsBundle, executionRequests} = await this.engine.getPayload(
|
|
121
|
+
handle.fork,
|
|
122
|
+
handle.payloadId,
|
|
123
|
+
signal
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
if (blobsBundle === undefined) {
|
|
127
|
+
throw new PayloadSourceError(
|
|
128
|
+
{
|
|
129
|
+
code: PayloadSourceErrorCode.MISSING_BLOBS_BUNDLE,
|
|
130
|
+
sourceId: this.id,
|
|
131
|
+
payloadId: handle.payloadId,
|
|
132
|
+
},
|
|
133
|
+
`Execution client did not return a blobs bundle sourceId=${this.id} payloadId=${handle.payloadId}`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (executionRequests === undefined) {
|
|
138
|
+
throw new PayloadSourceError(
|
|
139
|
+
{
|
|
140
|
+
code: PayloadSourceErrorCode.MISSING_EXECUTION_REQUESTS,
|
|
141
|
+
sourceId: this.id,
|
|
142
|
+
payloadId: handle.payloadId,
|
|
143
|
+
},
|
|
144
|
+
`Execution client did not return execution requests sourceId=${this.id} payloadId=${handle.payloadId}`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
sourceId: this.id,
|
|
150
|
+
fork: handle.fork,
|
|
151
|
+
executionPayload,
|
|
152
|
+
executionRequests,
|
|
153
|
+
blobsBundle,
|
|
154
|
+
executionPayloadValue,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|