@lodestar/builder 1.47.0-dev.ec596194e2 → 1.47.0-dev.f15d061b32
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/README.md +1 -1
- package/lib/builder.d.ts +2 -0
- package/lib/builder.d.ts.map +1 -1
- package/lib/builder.js +2 -2
- package/lib/builder.js.map +1 -1
- package/lib/identity.d.ts +2 -1
- package/lib/identity.d.ts.map +1 -1
- package/lib/identity.js +61 -22
- package/lib/identity.js.map +1 -1
- package/lib/metrics.d.ts +34 -1
- package/lib/metrics.d.ts.map +1 -1
- package/lib/metrics.js +51 -2
- package/lib/metrics.js.map +1 -1
- package/lib/services/builderSigner.d.ts +1 -1
- package/lib/services/builderSigner.d.ts.map +1 -1
- package/lib/services/builderStatusTracker.d.ts +3 -1
- package/lib/services/builderStatusTracker.d.ts.map +1 -1
- package/lib/services/builderStatusTracker.js +6 -1
- package/lib/services/builderStatusTracker.js.map +1 -1
- package/package.json +12 -12
- package/src/builder.ts +5 -2
- package/src/identity.ts +65 -23
- package/src/metrics.ts +70 -2
- package/src/services/builderSigner.ts +1 -1
- package/src/services/builderStatusTracker.ts +6 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Lodestar Builder
|
|
2
2
|
|
|
3
3
|
[](https://discord.gg/aMxzVcr)
|
|
4
|
-
[](https://github.com/ethereum/consensus-specs/releases/tag/v1.7.0-alpha.14)
|
|
5
5
|

|
|
6
6
|

|
|
7
7
|
|
package/lib/builder.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ChainForkConfig } from "@lodestar/config";
|
|
|
3
3
|
import { ClockOptions, IClock } from "@lodestar/state-transition";
|
|
4
4
|
import { BuilderIndex, ExecutionAddress } from "@lodestar/types";
|
|
5
5
|
import { Logger } from "@lodestar/utils";
|
|
6
|
+
import { Metrics } from "./metrics.js";
|
|
6
7
|
import { BuilderSigner, Keypair } from "./services/builderSigner.js";
|
|
7
8
|
import { BuilderStatusTracker } from "./services/builderStatusTracker.js";
|
|
8
9
|
export type BuilderModules = {
|
|
@@ -20,6 +21,7 @@ export type BuilderOptions = {
|
|
|
20
21
|
api: ApiClient;
|
|
21
22
|
clock?: ClockOptions;
|
|
22
23
|
executionFeeRecipient: ExecutionAddress;
|
|
24
|
+
metrics: Metrics | null;
|
|
23
25
|
};
|
|
24
26
|
/**
|
|
25
27
|
* Main class for the Builder client.
|
package/lib/builder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,eAAe,CAAC;AACxC,OAAO,EAAC,eAAe,EAAwC,MAAM,kBAAkB,CAAC;AACxF,OAAO,EAAQ,YAAY,EAAE,MAAM,EAAC,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAC,YAAY,EAAE,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAC,MAAM,EAAmB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,eAAe,CAAC;AACxC,OAAO,EAAC,eAAe,EAAwC,MAAM,kBAAkB,CAAC;AACxF,OAAO,EAAQ,YAAY,EAAE,MAAM,EAAC,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAC,YAAY,EAAE,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAC,MAAM,EAAmB,MAAM,iBAAiB,CAAC;AAGzD,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAErC,OAAO,EAAC,aAAa,EAAE,OAAO,EAAC,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAC,oBAAoB,EAAC,MAAM,oCAAoC,CAAC;AAExE,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,cAAc,CAAC;IACrB,aAAa,EAAE,aAAa,CAAC;IAC7B,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,eAAe,CAAC;IACjC,GAAG,EAAE,SAAS,CAAC;IACf,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,qBAAqB,EAAE,gBAAgB,CAAC;IACxC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,qBAAa,OAAO;IAClB,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAuB;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkB;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAmB;IAEzD,YAAY,EAAC,IAAI,EAAE,aAAa,EAAE,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAC,EAAE,cAAc,EAiBpF;IAED,OAAa,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CA+BxD;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3B;CACF"}
|
package/lib/builder.js
CHANGED
|
@@ -46,8 +46,8 @@ export class Builder {
|
|
|
46
46
|
await waitForNodeReady(api, logger, opts.abortController.signal);
|
|
47
47
|
await logNodeVersion(api, logger);
|
|
48
48
|
const clock = new Clock(config, logger, { genesisTime: Number(genesis.genesisTime), ...opts.clock });
|
|
49
|
-
const index = await resolveBuilderIdentity(api, logger, builderSigner.getPubkeyHex(), opts.abortController.signal, clock);
|
|
50
|
-
const builderStatusTracker = new BuilderStatusTracker(api, logger, index);
|
|
49
|
+
const index = await resolveBuilderIdentity(api, logger, builderSigner.getPubkeyHex(), opts.abortController.signal, clock, config);
|
|
50
|
+
const builderStatusTracker = new BuilderStatusTracker(api, logger, index, opts.metrics);
|
|
51
51
|
return new Builder({ opts, builderSigner, builderStatusTracker, clock, index });
|
|
52
52
|
}
|
|
53
53
|
async close() {
|
package/lib/builder.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,iBAAiB,EAAE,kBAAkB,EAAC,MAAM,kBAAkB,CAAC;AACxF,OAAO,EAAC,KAAK,EAAuB,MAAM,4BAA4B,CAAC;AAEvE,OAAO,EAAS,KAAK,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAC,sBAAsB,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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"}
|
package/lib/identity.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ApiClient, routes } from "@lodestar/api";
|
|
2
|
+
import { ChainForkConfig } from "@lodestar/config";
|
|
2
3
|
import { IClock } from "@lodestar/state-transition";
|
|
3
4
|
import { BuilderIndex, BuilderStatus } from "@lodestar/types";
|
|
4
5
|
import { Logger } from "@lodestar/utils";
|
|
5
6
|
export declare const WAITING_FOR_BUILDER_POLL_MS: number;
|
|
6
|
-
export declare function resolveBuilderIdentity(api: ApiClient, logger: Logger, id: routes.beacon.BuilderId, signal: AbortSignal, clock: IClock): Promise<BuilderIndex>;
|
|
7
|
+
export declare function resolveBuilderIdentity(api: ApiClient, logger: Logger, id: routes.beacon.BuilderId, signal: AbortSignal, clock: IClock, config: ChainForkConfig): Promise<BuilderIndex>;
|
|
7
8
|
export declare function getBuilderStatus(api: ApiClient, logger: Logger, id: routes.beacon.BuilderId): Promise<{
|
|
8
9
|
status: BuilderStatus;
|
|
9
10
|
balance: number;
|
package/lib/identity.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAA4B,MAAM,EAAC,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAC,MAAM,EAAC,MAAM,4BAA4B,CAAC;AAClD,OAAO,EAAC,YAAY,EAAE,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAe,MAAM,EAA2C,MAAM,iBAAiB,CAAC;AAE/F,eAAO,MAAM,2BAA2B,QAAY,CAAC;AAErD,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,EAC3B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,YAAY,CAAC,CAgBvB;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,GAC1B,OAAO,CAAC;IAAC,MAAM,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GAAG,IAAI,CAAC,CAe1D"}
|
package/lib/identity.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { ApiError, HttpStatusCode } from "@lodestar/api";
|
|
1
2
|
import { PAYLOAD_BUILDER_VERSION } from "@lodestar/params";
|
|
2
|
-
import { ErrorAborted, sleep, toHex } from "@lodestar/utils";
|
|
3
|
+
import { ErrorAborted, TimeoutError, isFetchError, sleep, toHex } from "@lodestar/utils";
|
|
3
4
|
export const WAITING_FOR_BUILDER_POLL_MS = 10 * 1000;
|
|
4
|
-
export async function resolveBuilderIdentity(api, logger, id, signal, clock) {
|
|
5
|
-
const builderEntry = await waitForBuilder(api, logger, id, signal, clock);
|
|
5
|
+
export async function resolveBuilderIdentity(api, logger, id, signal, clock, config) {
|
|
6
|
+
const builderEntry = await waitForBuilder(api, logger, id, signal, clock, config);
|
|
6
7
|
if (builderEntry.builder.version !== PAYLOAD_BUILDER_VERSION) {
|
|
7
8
|
throw Error(`Builder version mismatch: got ${builderEntry.builder.version}, expected ${PAYLOAD_BUILDER_VERSION}`);
|
|
8
9
|
}
|
|
@@ -17,7 +18,7 @@ export async function resolveBuilderIdentity(api, logger, id, signal, clock) {
|
|
|
17
18
|
}
|
|
18
19
|
export async function getBuilderStatus(api, logger, id) {
|
|
19
20
|
try {
|
|
20
|
-
const builderEntry = await fetchBuilder(api, id);
|
|
21
|
+
const builderEntry = await fetchBuilder(api, logger, id);
|
|
21
22
|
if (builderEntry) {
|
|
22
23
|
return {
|
|
23
24
|
status: builderEntry.status,
|
|
@@ -32,9 +33,38 @@ export async function getBuilderStatus(api, logger, id) {
|
|
|
32
33
|
return null;
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
|
-
async function waitForBuilder(api, logger, id, signal, clock) {
|
|
36
|
+
async function waitForBuilder(api, logger, id, signal, clock, config) {
|
|
37
|
+
const gloasForkEpoch = config.GLOAS_FORK_EPOCH;
|
|
36
38
|
while (!signal.aborted) {
|
|
37
|
-
const
|
|
39
|
+
const currentEpoch = clock.getCurrentEpoch();
|
|
40
|
+
if (currentEpoch < gloasForkEpoch) {
|
|
41
|
+
// Builders only exist post-gloas, the beacon node returns an error for pre-gloas state
|
|
42
|
+
logger.info("Waiting for Gloas fork before resolving builder identity", {
|
|
43
|
+
gloasForkEpoch,
|
|
44
|
+
currentEpoch,
|
|
45
|
+
slot: clock.getCurrentSlot(),
|
|
46
|
+
});
|
|
47
|
+
await sleep(WAITING_FOR_BUILDER_POLL_MS, signal);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
let builder = null;
|
|
51
|
+
try {
|
|
52
|
+
builder = await fetchBuilder(api, logger, id);
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
// At the fork boundary getStateBuilders("head") can still 400: it serves the head block's
|
|
56
|
+
// post-state, which stays pre-gloas until a gloas-epoch block is head. Keep polling on the transient.
|
|
57
|
+
if (e instanceof ApiError && e.status === HttpStatusCode.BAD_REQUEST) {
|
|
58
|
+
logger.info("Waiting for Gloas state to be available at head", {
|
|
59
|
+
gloasForkEpoch,
|
|
60
|
+
currentEpoch,
|
|
61
|
+
slot: clock.getCurrentSlot(),
|
|
62
|
+
});
|
|
63
|
+
await sleep(WAITING_FOR_BUILDER_POLL_MS, signal);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
throw e;
|
|
67
|
+
}
|
|
38
68
|
if (builder?.status === "active") {
|
|
39
69
|
return builder;
|
|
40
70
|
}
|
|
@@ -51,24 +81,33 @@ async function waitForBuilder(api, logger, id, signal, clock) {
|
|
|
51
81
|
}
|
|
52
82
|
throw new ErrorAborted("waitForBuilder");
|
|
53
83
|
}
|
|
54
|
-
async function fetchBuilder(api, id) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (id
|
|
66
|
-
|
|
84
|
+
async function fetchBuilder(api, logger, id) {
|
|
85
|
+
try {
|
|
86
|
+
const builderRes = await api.beacon.getStateBuilders({
|
|
87
|
+
stateId: "head",
|
|
88
|
+
builderIds: [id],
|
|
89
|
+
});
|
|
90
|
+
const builders = builderRes.value();
|
|
91
|
+
if (builders.length === 0) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const builder = builders[0];
|
|
95
|
+
if (typeof id === "number") {
|
|
96
|
+
if (id !== builder.index) {
|
|
97
|
+
throw Error(`Index mismatch: got=${builder.index} expected=${id}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else if (id !== toHex(builder.builder.pubkey)) {
|
|
101
|
+
throw Error(`Pubkey mismatch: got=${toHex(builder.builder.pubkey)} expected=${id}`);
|
|
67
102
|
}
|
|
103
|
+
return builder;
|
|
68
104
|
}
|
|
69
|
-
|
|
70
|
-
|
|
105
|
+
catch (e) {
|
|
106
|
+
if (e instanceof TimeoutError || (isFetchError(e) && e.type !== "input")) {
|
|
107
|
+
logger.warn("Failed to fetch builder", { message: e.message });
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
throw e;
|
|
71
111
|
}
|
|
72
|
-
return builder;
|
|
73
112
|
}
|
|
74
113
|
//# sourceMappingURL=identity.js.map
|
package/lib/identity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"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"}
|
package/lib/metrics.d.ts
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
|
+
import { BuilderStatus } from "@lodestar/types";
|
|
1
2
|
import { MetricsRegisterExtra } from "@lodestar/utils";
|
|
2
3
|
export type Metrics = ReturnType<typeof getMetrics>;
|
|
3
|
-
export
|
|
4
|
+
export type LodestarGitData = {
|
|
5
|
+
/** "0.16.0 developer/feature-1 4f816b16" */
|
|
6
|
+
version: string;
|
|
7
|
+
/** "4f816b16dfde718e2d74f95f2c8292596138c248" */
|
|
8
|
+
commit: string;
|
|
9
|
+
/** "hoodi" */
|
|
10
|
+
network: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const builderStatusValue: Record<BuilderStatus, number>;
|
|
13
|
+
export declare function getMetrics(register: MetricsRegisterExtra, gitData: LodestarGitData): {
|
|
14
|
+
builderStatus: import("@lodestar/utils").GaugeExtra<import("@lodestar/utils").NoLabels>;
|
|
15
|
+
builderBalance: import("@lodestar/utils").GaugeExtra<import("@lodestar/utils").NoLabels>;
|
|
16
|
+
restApiClient: {
|
|
17
|
+
requestTime: import("@lodestar/utils").Histogram<{
|
|
18
|
+
routeId: string;
|
|
19
|
+
}>;
|
|
20
|
+
streamTime: import("@lodestar/utils").Histogram<{
|
|
21
|
+
routeId: string;
|
|
22
|
+
}>;
|
|
23
|
+
requestErrors: import("@lodestar/utils").GaugeExtra<{
|
|
24
|
+
routeId: string;
|
|
25
|
+
baseUrl: string;
|
|
26
|
+
}>;
|
|
27
|
+
requestToFallbacks: import("@lodestar/utils").GaugeExtra<{
|
|
28
|
+
routeId: string;
|
|
29
|
+
baseUrl: string;
|
|
30
|
+
}>;
|
|
31
|
+
urlsScore: import("@lodestar/utils").GaugeExtra<{
|
|
32
|
+
urlIndex: number;
|
|
33
|
+
baseUrl: string;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
4
37
|
//# sourceMappingURL=metrics.d.ts.map
|
package/lib/metrics.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,iBAAiB,CAAC;AAErD,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD,wBAAgB,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAC,oBAAoB,EAAC,MAAM,iBAAiB,CAAC;AAErD,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG;IAC5B,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,cAAc;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAsC,CAAC;AAEpG,wBAAgB,UAAU,CAAC,QAAQ,EAAE,oBAAoB,EAAE,OAAO,EAAE,eAAe;IAU/E,aAAa;IAKb,cAAc;IAOd,aAAa;QACX,WAAW;qBAA+B,MAAM;;QAQhD,UAAU;qBAA+B,MAAM;;QAQ/C,aAAa;qBAA2B,MAAM;qBAAW,MAAM;;QAM/D,kBAAkB;qBAA2B,MAAM;qBAAW,MAAM;;QAMpE,SAAS;sBAA4B,MAAM;qBAAW,MAAM;;;EAOjE"}
|
package/lib/metrics.js
CHANGED
|
@@ -1,4 +1,53 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
1
|
+
export const builderStatusValue = { pending: 0, active: 1, exited: 2 };
|
|
2
|
+
export function getMetrics(register, gitData) {
|
|
3
|
+
register
|
|
4
|
+
.gauge({
|
|
5
|
+
name: "lodestar_version",
|
|
6
|
+
help: "Lodestar version",
|
|
7
|
+
labelNames: Object.keys(gitData),
|
|
8
|
+
})
|
|
9
|
+
.set(gitData, 1);
|
|
10
|
+
return {
|
|
11
|
+
builderStatus: register.gauge({
|
|
12
|
+
name: "bc_builder_status",
|
|
13
|
+
help: "Current builder status: pending=0, active=1, exited=2",
|
|
14
|
+
}),
|
|
15
|
+
builderBalance: register.gauge({
|
|
16
|
+
name: "bc_builder_balance_gwei",
|
|
17
|
+
help: "Current builder balance in gwei",
|
|
18
|
+
}),
|
|
19
|
+
// REST API client
|
|
20
|
+
restApiClient: {
|
|
21
|
+
requestTime: register.histogram({
|
|
22
|
+
name: "bc_rest_api_client_request_time_seconds",
|
|
23
|
+
help: "Histogram of REST API client request time by routeId",
|
|
24
|
+
labelNames: ["routeId"],
|
|
25
|
+
// Expected times are ~ 50-500ms, but in an overload NodeJS they can be greater
|
|
26
|
+
buckets: [0.01, 0.1, 1, 2, 5],
|
|
27
|
+
}),
|
|
28
|
+
streamTime: register.histogram({
|
|
29
|
+
name: "bc_rest_api_client_stream_time_seconds",
|
|
30
|
+
help: "Histogram of REST API client streaming time by routeId",
|
|
31
|
+
labelNames: ["routeId"],
|
|
32
|
+
// Expected times are ~ 50-500ms, but in an overload NodeJS they can be greater
|
|
33
|
+
buckets: [0.01, 0.1, 1, 2, 5],
|
|
34
|
+
}),
|
|
35
|
+
requestErrors: register.gauge({
|
|
36
|
+
name: "bc_rest_api_client_request_errors_total",
|
|
37
|
+
help: "Total count of errors on REST API client requests by routeId",
|
|
38
|
+
labelNames: ["routeId", "baseUrl"],
|
|
39
|
+
}),
|
|
40
|
+
requestToFallbacks: register.gauge({
|
|
41
|
+
name: "bc_rest_api_client_request_to_fallbacks_total",
|
|
42
|
+
help: "Total count of requests to fallback URLs on REST API by routeId",
|
|
43
|
+
labelNames: ["routeId", "baseUrl"],
|
|
44
|
+
}),
|
|
45
|
+
urlsScore: register.gauge({
|
|
46
|
+
name: "bc_rest_api_client_urls_score",
|
|
47
|
+
help: "Current score of REST API URLs by url index",
|
|
48
|
+
labelNames: ["urlIndex", "baseUrl"],
|
|
49
|
+
}),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
3
52
|
}
|
|
4
53
|
//# sourceMappingURL=metrics.js.map
|
package/lib/metrics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,kBAAkB,GAAkC,EAAC,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAC,CAAC;AAEpG,MAAM,UAAU,UAAU,CAAC,QAA8B,EAAE,OAAwB;IACjF,QAAQ;SACL,KAAK,CAAkB;QACtB,IAAI,EAAE,kBAAkB;QACxB,IAAI,EAAE,kBAAkB;QACxB,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAA4B;KAC5D,CAAC;SACD,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAEnB,OAAO;QACL,aAAa,EAAE,QAAQ,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,mBAAmB;YACzB,IAAI,EAAE,uDAAuD;SAC9D,CAAC;QAEF,cAAc,EAAE,QAAQ,CAAC,KAAK,CAAC;YAC7B,IAAI,EAAE,yBAAyB;YAC/B,IAAI,EAAE,iCAAiC;SACxC,CAAC;QAEF,kBAAkB;QAElB,aAAa,EAAE;YACb,WAAW,EAAE,QAAQ,CAAC,SAAS,CAAoB;gBACjD,IAAI,EAAE,yCAAyC;gBAC/C,IAAI,EAAE,sDAAsD;gBAC5D,UAAU,EAAE,CAAC,SAAS,CAAC;gBACvB,+EAA+E;gBAC/E,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;aAC9B,CAAC;YAEF,UAAU,EAAE,QAAQ,CAAC,SAAS,CAAoB;gBAChD,IAAI,EAAE,wCAAwC;gBAC9C,IAAI,EAAE,wDAAwD;gBAC9D,UAAU,EAAE,CAAC,SAAS,CAAC;gBACvB,+EAA+E;gBAC/E,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;aAC9B,CAAC;YAEF,aAAa,EAAE,QAAQ,CAAC,KAAK,CAAqC;gBAChE,IAAI,EAAE,yCAAyC;gBAC/C,IAAI,EAAE,8DAA8D;gBACpE,UAAU,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;aACnC,CAAC;YAEF,kBAAkB,EAAE,QAAQ,CAAC,KAAK,CAAqC;gBACrE,IAAI,EAAE,+CAA+C;gBACrD,IAAI,EAAE,iEAAiE;gBACvE,UAAU,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;aACnC,CAAC;YAEF,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAsC;gBAC7D,IAAI,EAAE,+BAA+B;gBACrC,IAAI,EAAE,6CAA6C;gBACnD,UAAU,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;aACpC,CAAC;SACH;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builderSigner.d.ts","sourceRoot":"","sources":["../../src/services/builderSigner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"builderSigner.d.ts","sourceRoot":"","sources":["../../src/services/builderSigner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAC,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAEtC,MAAM,MAAM,OAAO,GAAG;IAAC,SAAS,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAC,CAAC;AAEnE,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,YAAY,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAGjD;IAED,4BAA4B,CAAC,QAAQ,EAAE,KAAK,CAAC,wBAAwB,GAAG,KAAK,CAAC,8BAA8B,CAO3G;IAED,uBAAuB,CAAC,GAAG,EAAE,KAAK,CAAC,mBAAmB,GAAG,KAAK,CAAC,yBAAyB,CAOvF;IAED,YAAY,IAAI,MAAM,CAErB;CACF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ApiClient } from "@lodestar/api";
|
|
2
2
|
import { BuilderIndex, BuilderStatus, Epoch } from "@lodestar/types";
|
|
3
3
|
import { Logger } from "@lodestar/utils";
|
|
4
|
+
import { Metrics } from "../metrics.js";
|
|
4
5
|
/**
|
|
5
6
|
* Service for tracking builder status.
|
|
6
7
|
* Provides regular builder status and balance updates for operator diagnostics.
|
|
@@ -9,9 +10,10 @@ export declare class BuilderStatusTracker {
|
|
|
9
10
|
private readonly api;
|
|
10
11
|
private readonly logger;
|
|
11
12
|
private readonly index;
|
|
13
|
+
private readonly metrics;
|
|
12
14
|
private status?;
|
|
13
15
|
private balanceGwei?;
|
|
14
|
-
constructor(api: ApiClient, logger: Logger, index: BuilderIndex);
|
|
16
|
+
constructor(api: ApiClient, logger: Logger, index: BuilderIndex, metrics: Metrics | null);
|
|
15
17
|
poll(currentEpoch: Epoch): Promise<void>;
|
|
16
18
|
getStatus(): {
|
|
17
19
|
status: BuilderStatus | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builderStatusTracker.d.ts","sourceRoot":"","sources":["../../src/services/builderStatusTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,eAAe,CAAC;AACxC,OAAO,EAAC,YAAY,EAAE,aAAa,EAAE,KAAK,EAAC,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"builderStatusTracker.d.ts","sourceRoot":"","sources":["../../src/services/builderStatusTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,eAAe,CAAC;AACxC,OAAO,EAAC,YAAY,EAAE,aAAa,EAAE,KAAK,EAAC,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEvC,OAAO,EAAC,OAAO,EAAqB,MAAM,eAAe,CAAC;AAE1D;;;GAGG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IAEzC,OAAO,CAAC,MAAM,CAAC,CAAgB;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAS;IAE7B,YAAY,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,EAKvF;IAEK,IAAI,CAAC,YAAY,EAAE,KAAK,iBAgB7B;IAED,SAAS,IAAI;QAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;KAAC,CAK5E;CACF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getBuilderStatus } from "../identity.js";
|
|
2
|
+
import { builderStatusValue } from "../metrics.js";
|
|
2
3
|
/**
|
|
3
4
|
* Service for tracking builder status.
|
|
4
5
|
* Provides regular builder status and balance updates for operator diagnostics.
|
|
@@ -7,12 +8,14 @@ export class BuilderStatusTracker {
|
|
|
7
8
|
api;
|
|
8
9
|
logger;
|
|
9
10
|
index;
|
|
11
|
+
metrics;
|
|
10
12
|
status;
|
|
11
13
|
balanceGwei;
|
|
12
|
-
constructor(api, logger, index) {
|
|
14
|
+
constructor(api, logger, index, metrics) {
|
|
13
15
|
this.api = api;
|
|
14
16
|
this.logger = logger;
|
|
15
17
|
this.index = index;
|
|
18
|
+
this.metrics = metrics;
|
|
16
19
|
}
|
|
17
20
|
async poll(currentEpoch) {
|
|
18
21
|
const builderStatus = await getBuilderStatus(this.api, this.logger, this.index);
|
|
@@ -27,6 +30,8 @@ export class BuilderStatusTracker {
|
|
|
27
30
|
balance: builderStatus.balance,
|
|
28
31
|
epoch: currentEpoch,
|
|
29
32
|
});
|
|
33
|
+
this.metrics?.builderStatus.set(builderStatusValue[builderStatus.status]);
|
|
34
|
+
this.metrics?.builderBalance.set(builderStatus.balance);
|
|
30
35
|
}
|
|
31
36
|
}
|
|
32
37
|
getStatus() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builderStatusTracker.js","sourceRoot":"","sources":["../../src/services/builderStatusTracker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,gBAAgB,EAAC,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"builderStatusTracker.js","sourceRoot":"","sources":["../../src/services/builderStatusTracker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,gBAAgB,EAAC,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAU,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAE1D;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IACd,GAAG,CAAY;IACf,MAAM,CAAS;IACf,KAAK,CAAe;IACpB,OAAO,CAAiB;IAEjC,MAAM,CAAiB;IACvB,WAAW,CAAU;IAE7B,YAAY,GAAc,EAAE,MAAc,EAAE,KAAmB,EAAE,OAAuB;QACtF,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,YAAmB;QAC5B,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAChF,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,CAAC,MAAM,EAAE,CAAC;gBACtE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,EAAC,CAAC,CAAC;YACjH,CAAC;YACD,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;YACnC,IAAI,CAAC,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE;gBACjC,MAAM,EAAE,aAAa,CAAC,MAAM;gBAC5B,OAAO,EAAE,aAAa,CAAC,OAAO;gBAC9B,KAAK,EAAE,YAAY;aACpB,CAAC,CAAC;YACH,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;YAC1E,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,WAAW;SAC1B,CAAC;IACJ,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lodestar/builder",
|
|
3
|
-
"version": "1.47.0-dev.
|
|
3
|
+
"version": "1.47.0-dev.f15d061b32",
|
|
4
4
|
"description": "A Typescript implementation of the builder client",
|
|
5
5
|
"author": "ChainSafe Systems",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -46,18 +46,18 @@
|
|
|
46
46
|
"blockchain"
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@chainsafe/
|
|
50
|
-
"@chainsafe/ssz": "^1.6.
|
|
51
|
-
"@lodestar/api": "^1.47.0-dev.
|
|
52
|
-
"@lodestar/config": "^1.47.0-dev.
|
|
53
|
-
"@lodestar/params": "^1.47.0-dev.
|
|
54
|
-
"@lodestar/state-transition": "^1.47.0-dev.
|
|
55
|
-
"@lodestar/types": "^1.47.0-dev.
|
|
56
|
-
"@lodestar/utils": "^1.47.0-dev.
|
|
49
|
+
"@chainsafe/lodestar-z": "catalog:",
|
|
50
|
+
"@chainsafe/ssz": "^1.6.3",
|
|
51
|
+
"@lodestar/api": "^1.47.0-dev.f15d061b32",
|
|
52
|
+
"@lodestar/config": "^1.47.0-dev.f15d061b32",
|
|
53
|
+
"@lodestar/params": "^1.47.0-dev.f15d061b32",
|
|
54
|
+
"@lodestar/state-transition": "^1.47.0-dev.f15d061b32",
|
|
55
|
+
"@lodestar/types": "^1.47.0-dev.f15d061b32",
|
|
56
|
+
"@lodestar/utils": "^1.47.0-dev.f15d061b32"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@lodestar/logger": "^1.47.0-dev.
|
|
60
|
-
"@lodestar/test-utils": "^1.47.0-dev.
|
|
59
|
+
"@lodestar/logger": "^1.47.0-dev.f15d061b32",
|
|
60
|
+
"@lodestar/test-utils": "^1.47.0-dev.f15d061b32"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "7545ada86d5e25707adb069fd1a6d2482a41e210"
|
|
63
63
|
}
|
package/src/builder.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {BuilderIndex, ExecutionAddress} from "@lodestar/types";
|
|
|
5
5
|
import {Logger, toHex, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {waitForGenesis} from "./genesis.js";
|
|
7
7
|
import {resolveBuilderIdentity} from "./identity.js";
|
|
8
|
+
import {Metrics} from "./metrics.js";
|
|
8
9
|
import {logNodeVersion, waitForNodeReady} from "./readiness.js";
|
|
9
10
|
import {BuilderSigner, Keypair} from "./services/builderSigner.js";
|
|
10
11
|
import {BuilderStatusTracker} from "./services/builderStatusTracker.js";
|
|
@@ -25,6 +26,7 @@ export type BuilderOptions = {
|
|
|
25
26
|
api: ApiClient;
|
|
26
27
|
clock?: ClockOptions;
|
|
27
28
|
executionFeeRecipient: ExecutionAddress;
|
|
29
|
+
metrics: Metrics | null;
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
/**
|
|
@@ -82,10 +84,11 @@ export class Builder {
|
|
|
82
84
|
logger,
|
|
83
85
|
builderSigner.getPubkeyHex(),
|
|
84
86
|
opts.abortController.signal,
|
|
85
|
-
clock
|
|
87
|
+
clock,
|
|
88
|
+
config
|
|
86
89
|
);
|
|
87
90
|
|
|
88
|
-
const builderStatusTracker = new BuilderStatusTracker(api, logger, index);
|
|
91
|
+
const builderStatusTracker = new BuilderStatusTracker(api, logger, index, opts.metrics);
|
|
89
92
|
|
|
90
93
|
return new Builder({opts, builderSigner, builderStatusTracker, clock, index});
|
|
91
94
|
}
|
package/src/identity.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {ApiClient, routes} from "@lodestar/api";
|
|
1
|
+
import {ApiClient, ApiError, HttpStatusCode, routes} from "@lodestar/api";
|
|
2
|
+
import {ChainForkConfig} from "@lodestar/config";
|
|
2
3
|
import {PAYLOAD_BUILDER_VERSION} from "@lodestar/params";
|
|
3
4
|
import {IClock} from "@lodestar/state-transition";
|
|
4
5
|
import {BuilderIndex, BuilderStatus} from "@lodestar/types";
|
|
5
|
-
import {ErrorAborted, Logger, sleep, toHex} from "@lodestar/utils";
|
|
6
|
+
import {ErrorAborted, Logger, TimeoutError, isFetchError, sleep, toHex} from "@lodestar/utils";
|
|
6
7
|
|
|
7
8
|
export const WAITING_FOR_BUILDER_POLL_MS = 10 * 1000;
|
|
8
9
|
|
|
@@ -11,9 +12,10 @@ export async function resolveBuilderIdentity(
|
|
|
11
12
|
logger: Logger,
|
|
12
13
|
id: routes.beacon.BuilderId,
|
|
13
14
|
signal: AbortSignal,
|
|
14
|
-
clock: IClock
|
|
15
|
+
clock: IClock,
|
|
16
|
+
config: ChainForkConfig
|
|
15
17
|
): Promise<BuilderIndex> {
|
|
16
|
-
const builderEntry = await waitForBuilder(api, logger, id, signal, clock);
|
|
18
|
+
const builderEntry = await waitForBuilder(api, logger, id, signal, clock, config);
|
|
17
19
|
|
|
18
20
|
if (builderEntry.builder.version !== PAYLOAD_BUILDER_VERSION) {
|
|
19
21
|
throw Error(`Builder version mismatch: got ${builderEntry.builder.version}, expected ${PAYLOAD_BUILDER_VERSION}`);
|
|
@@ -36,7 +38,7 @@ export async function getBuilderStatus(
|
|
|
36
38
|
id: routes.beacon.BuilderId
|
|
37
39
|
): Promise<{status: BuilderStatus; balance: number} | null> {
|
|
38
40
|
try {
|
|
39
|
-
const builderEntry = await fetchBuilder(api, id);
|
|
41
|
+
const builderEntry = await fetchBuilder(api, logger, id);
|
|
40
42
|
if (builderEntry) {
|
|
41
43
|
return {
|
|
42
44
|
status: builderEntry.status,
|
|
@@ -56,10 +58,41 @@ async function waitForBuilder(
|
|
|
56
58
|
logger: Logger,
|
|
57
59
|
id: routes.beacon.BuilderId,
|
|
58
60
|
signal: AbortSignal,
|
|
59
|
-
clock: IClock
|
|
61
|
+
clock: IClock,
|
|
62
|
+
config: ChainForkConfig
|
|
60
63
|
): Promise<routes.beacon.BuilderResponse> {
|
|
64
|
+
const gloasForkEpoch = config.GLOAS_FORK_EPOCH;
|
|
61
65
|
while (!signal.aborted) {
|
|
62
|
-
const
|
|
66
|
+
const currentEpoch = clock.getCurrentEpoch();
|
|
67
|
+
if (currentEpoch < gloasForkEpoch) {
|
|
68
|
+
// Builders only exist post-gloas, the beacon node returns an error for pre-gloas state
|
|
69
|
+
logger.info("Waiting for Gloas fork before resolving builder identity", {
|
|
70
|
+
gloasForkEpoch,
|
|
71
|
+
currentEpoch,
|
|
72
|
+
slot: clock.getCurrentSlot(),
|
|
73
|
+
});
|
|
74
|
+
await sleep(WAITING_FOR_BUILDER_POLL_MS, signal);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let builder: routes.beacon.BuilderResponse | null = null;
|
|
79
|
+
try {
|
|
80
|
+
builder = await fetchBuilder(api, logger, id);
|
|
81
|
+
} catch (e) {
|
|
82
|
+
// At the fork boundary getStateBuilders("head") can still 400: it serves the head block's
|
|
83
|
+
// post-state, which stays pre-gloas until a gloas-epoch block is head. Keep polling on the transient.
|
|
84
|
+
if (e instanceof ApiError && e.status === HttpStatusCode.BAD_REQUEST) {
|
|
85
|
+
logger.info("Waiting for Gloas state to be available at head", {
|
|
86
|
+
gloasForkEpoch,
|
|
87
|
+
currentEpoch,
|
|
88
|
+
slot: clock.getCurrentSlot(),
|
|
89
|
+
});
|
|
90
|
+
await sleep(WAITING_FOR_BUILDER_POLL_MS, signal);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
throw e;
|
|
94
|
+
}
|
|
95
|
+
|
|
63
96
|
if (builder?.status === "active") {
|
|
64
97
|
return builder;
|
|
65
98
|
}
|
|
@@ -78,28 +111,37 @@ async function waitForBuilder(
|
|
|
78
111
|
|
|
79
112
|
async function fetchBuilder(
|
|
80
113
|
api: ApiClient,
|
|
114
|
+
logger: Logger,
|
|
81
115
|
id: routes.beacon.BuilderId
|
|
82
116
|
): Promise<routes.beacon.BuilderResponse | null> {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
117
|
+
try {
|
|
118
|
+
const builderRes = await api.beacon.getStateBuilders({
|
|
119
|
+
stateId: "head",
|
|
120
|
+
builderIds: [id],
|
|
121
|
+
});
|
|
87
122
|
|
|
88
|
-
|
|
123
|
+
const builders = builderRes.value();
|
|
89
124
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
125
|
+
if (builders.length === 0) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
93
128
|
|
|
94
|
-
|
|
129
|
+
const builder = builders[0];
|
|
95
130
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
131
|
+
if (typeof id === "number") {
|
|
132
|
+
if (id !== builder.index) {
|
|
133
|
+
throw Error(`Index mismatch: got=${builder.index} expected=${id}`);
|
|
134
|
+
}
|
|
135
|
+
} else if (id !== toHex(builder.builder.pubkey)) {
|
|
136
|
+
throw Error(`Pubkey mismatch: got=${toHex(builder.builder.pubkey)} expected=${id}`);
|
|
99
137
|
}
|
|
100
|
-
} else if (id !== toHex(builder.builder.pubkey)) {
|
|
101
|
-
throw Error(`Pubkey mismatch: got=${toHex(builder.builder.pubkey)} expected=${id}`);
|
|
102
|
-
}
|
|
103
138
|
|
|
104
|
-
|
|
139
|
+
return builder;
|
|
140
|
+
} catch (e) {
|
|
141
|
+
if (e instanceof TimeoutError || (isFetchError(e) && e.type !== "input")) {
|
|
142
|
+
logger.warn("Failed to fetch builder", {message: e.message});
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
throw e;
|
|
146
|
+
}
|
|
105
147
|
}
|
package/src/metrics.ts
CHANGED
|
@@ -1,7 +1,75 @@
|
|
|
1
|
+
import {BuilderStatus} from "@lodestar/types";
|
|
1
2
|
import {MetricsRegisterExtra} from "@lodestar/utils";
|
|
2
3
|
|
|
3
4
|
export type Metrics = ReturnType<typeof getMetrics>;
|
|
4
5
|
|
|
5
|
-
export
|
|
6
|
-
|
|
6
|
+
export type LodestarGitData = {
|
|
7
|
+
/** "0.16.0 developer/feature-1 4f816b16" */
|
|
8
|
+
version: string;
|
|
9
|
+
/** "4f816b16dfde718e2d74f95f2c8292596138c248" */
|
|
10
|
+
commit: string;
|
|
11
|
+
/** "hoodi" */
|
|
12
|
+
network: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const builderStatusValue: Record<BuilderStatus, number> = {pending: 0, active: 1, exited: 2};
|
|
16
|
+
|
|
17
|
+
export function getMetrics(register: MetricsRegisterExtra, gitData: LodestarGitData) {
|
|
18
|
+
register
|
|
19
|
+
.gauge<LodestarGitData>({
|
|
20
|
+
name: "lodestar_version",
|
|
21
|
+
help: "Lodestar version",
|
|
22
|
+
labelNames: Object.keys(gitData) as [keyof LodestarGitData],
|
|
23
|
+
})
|
|
24
|
+
.set(gitData, 1);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
builderStatus: register.gauge({
|
|
28
|
+
name: "bc_builder_status",
|
|
29
|
+
help: "Current builder status: pending=0, active=1, exited=2",
|
|
30
|
+
}),
|
|
31
|
+
|
|
32
|
+
builderBalance: register.gauge({
|
|
33
|
+
name: "bc_builder_balance_gwei",
|
|
34
|
+
help: "Current builder balance in gwei",
|
|
35
|
+
}),
|
|
36
|
+
|
|
37
|
+
// REST API client
|
|
38
|
+
|
|
39
|
+
restApiClient: {
|
|
40
|
+
requestTime: register.histogram<{routeId: string}>({
|
|
41
|
+
name: "bc_rest_api_client_request_time_seconds",
|
|
42
|
+
help: "Histogram of REST API client request time by routeId",
|
|
43
|
+
labelNames: ["routeId"],
|
|
44
|
+
// Expected times are ~ 50-500ms, but in an overload NodeJS they can be greater
|
|
45
|
+
buckets: [0.01, 0.1, 1, 2, 5],
|
|
46
|
+
}),
|
|
47
|
+
|
|
48
|
+
streamTime: register.histogram<{routeId: string}>({
|
|
49
|
+
name: "bc_rest_api_client_stream_time_seconds",
|
|
50
|
+
help: "Histogram of REST API client streaming time by routeId",
|
|
51
|
+
labelNames: ["routeId"],
|
|
52
|
+
// Expected times are ~ 50-500ms, but in an overload NodeJS they can be greater
|
|
53
|
+
buckets: [0.01, 0.1, 1, 2, 5],
|
|
54
|
+
}),
|
|
55
|
+
|
|
56
|
+
requestErrors: register.gauge<{routeId: string; baseUrl: string}>({
|
|
57
|
+
name: "bc_rest_api_client_request_errors_total",
|
|
58
|
+
help: "Total count of errors on REST API client requests by routeId",
|
|
59
|
+
labelNames: ["routeId", "baseUrl"],
|
|
60
|
+
}),
|
|
61
|
+
|
|
62
|
+
requestToFallbacks: register.gauge<{routeId: string; baseUrl: string}>({
|
|
63
|
+
name: "bc_rest_api_client_request_to_fallbacks_total",
|
|
64
|
+
help: "Total count of requests to fallback URLs on REST API by routeId",
|
|
65
|
+
labelNames: ["routeId", "baseUrl"],
|
|
66
|
+
}),
|
|
67
|
+
|
|
68
|
+
urlsScore: register.gauge<{urlIndex: number; baseUrl: string}>({
|
|
69
|
+
name: "bc_rest_api_client_urls_score",
|
|
70
|
+
help: "Current score of REST API URLs by url index",
|
|
71
|
+
labelNames: ["urlIndex", "baseUrl"],
|
|
72
|
+
}),
|
|
73
|
+
},
|
|
74
|
+
};
|
|
7
75
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {PublicKey, SecretKey} from "@chainsafe/blst";
|
|
1
|
+
import {PublicKey, SecretKey} from "@chainsafe/lodestar-z/blst";
|
|
2
2
|
import {BeaconConfig} from "@lodestar/config";
|
|
3
3
|
import {getExecutionPayloadBidSigningRoot, getExecutionPayloadEnvelopeSigningRoot} from "@lodestar/state-transition";
|
|
4
4
|
import {gloas} from "@lodestar/types";
|
|
@@ -2,6 +2,7 @@ import {ApiClient} from "@lodestar/api";
|
|
|
2
2
|
import {BuilderIndex, BuilderStatus, Epoch} from "@lodestar/types";
|
|
3
3
|
import {Logger} from "@lodestar/utils";
|
|
4
4
|
import {getBuilderStatus} from "../identity.js";
|
|
5
|
+
import {Metrics, builderStatusValue} from "../metrics.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Service for tracking builder status.
|
|
@@ -11,14 +12,16 @@ export class BuilderStatusTracker {
|
|
|
11
12
|
private readonly api: ApiClient;
|
|
12
13
|
private readonly logger: Logger;
|
|
13
14
|
private readonly index: BuilderIndex;
|
|
15
|
+
private readonly metrics: Metrics | null;
|
|
14
16
|
|
|
15
17
|
private status?: BuilderStatus;
|
|
16
18
|
private balanceGwei?: number;
|
|
17
19
|
|
|
18
|
-
constructor(api: ApiClient, logger: Logger, index: BuilderIndex) {
|
|
20
|
+
constructor(api: ApiClient, logger: Logger, index: BuilderIndex, metrics: Metrics | null) {
|
|
19
21
|
this.api = api;
|
|
20
22
|
this.logger = logger;
|
|
21
23
|
this.index = index;
|
|
24
|
+
this.metrics = metrics;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
async poll(currentEpoch: Epoch) {
|
|
@@ -34,6 +37,8 @@ export class BuilderStatusTracker {
|
|
|
34
37
|
balance: builderStatus.balance,
|
|
35
38
|
epoch: currentEpoch,
|
|
36
39
|
});
|
|
40
|
+
this.metrics?.builderStatus.set(builderStatusValue[builderStatus.status]);
|
|
41
|
+
this.metrics?.builderBalance.set(builderStatus.balance);
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
44
|
|