@chainsafe/lodestar 1.47.0-dev.ec596194e2 → 1.47.0-dev.f0f26cd2b6
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/.git-data.json +1 -1
- package/lib/cmds/beacon/handler.d.ts.map +1 -1
- package/lib/cmds/beacon/handler.js +10 -4
- package/lib/cmds/beacon/handler.js.map +1 -1
- package/lib/cmds/builder/handler.d.ts.map +1 -1
- package/lib/cmds/builder/handler.js +19 -3
- package/lib/cmds/builder/handler.js.map +1 -1
- package/lib/cmds/builder/loadKeypair.d.ts +2 -1
- package/lib/cmds/builder/loadKeypair.d.ts.map +1 -1
- package/lib/cmds/builder/loadKeypair.js +3 -2
- package/lib/cmds/builder/loadKeypair.js.map +1 -1
- package/lib/cmds/builder/options.d.ts +8 -0
- package/lib/cmds/builder/options.d.ts.map +1 -1
- package/lib/cmds/builder/options.js +24 -0
- package/lib/cmds/builder/options.js.map +1 -1
- package/lib/cmds/dev/options.d.ts +4 -0
- package/lib/cmds/dev/options.d.ts.map +1 -1
- package/lib/cmds/validator/blsToExecutionChange.js +1 -1
- package/lib/cmds/validator/blsToExecutionChange.js.map +1 -1
- package/lib/cmds/validator/handler.d.ts.map +1 -1
- package/lib/cmds/validator/handler.js +15 -2
- package/lib/cmds/validator/handler.js.map +1 -1
- package/lib/cmds/validator/keymanager/decryptKeystoreDefinitions.js +1 -1
- package/lib/cmds/validator/keymanager/decryptKeystoreDefinitions.js.map +1 -1
- package/lib/cmds/validator/keymanager/impl.d.ts +13 -2
- package/lib/cmds/validator/keymanager/impl.d.ts.map +1 -1
- package/lib/cmds/validator/keymanager/impl.js +41 -4
- package/lib/cmds/validator/keymanager/impl.js.map +1 -1
- package/lib/cmds/validator/keymanager/keystoreCache.js +1 -1
- package/lib/cmds/validator/keymanager/keystoreCache.js.map +1 -1
- package/lib/cmds/validator/keymanager/persistedKeys.d.ts.map +1 -1
- package/lib/cmds/validator/keymanager/persistedKeys.js +3 -1
- package/lib/cmds/validator/keymanager/persistedKeys.js.map +1 -1
- package/lib/cmds/validator/options.d.ts +4 -0
- package/lib/cmds/validator/options.d.ts.map +1 -1
- package/lib/cmds/validator/options.js +24 -0
- package/lib/cmds/validator/options.js.map +1 -1
- package/lib/cmds/validator/signers/index.js +1 -1
- package/lib/cmds/validator/signers/index.js.map +1 -1
- package/lib/cmds/validator/voluntaryExit.js +1 -1
- package/lib/cmds/validator/voluntaryExit.js.map +1 -1
- package/lib/networks/chiado.d.ts.map +1 -1
- package/lib/networks/chiado.js +4 -10
- package/lib/networks/chiado.js.map +1 -1
- package/lib/options/beaconNodeOptions/builder.d.ts.map +1 -1
- package/lib/options/beaconNodeOptions/builder.js +2 -2
- package/lib/options/beaconNodeOptions/builder.js.map +1 -1
- package/lib/options/beaconNodeOptions/chain.d.ts.map +1 -1
- package/lib/options/beaconNodeOptions/chain.js +1 -1
- package/lib/options/beaconNodeOptions/chain.js.map +1 -1
- package/lib/util/format.js +1 -1
- package/lib/util/format.js.map +1 -1
- package/lib/util/proposerConfig.d.ts +16 -11
- package/lib/util/proposerConfig.d.ts.map +1 -1
- package/lib/util/proposerConfig.js +128 -11
- package/lib/util/proposerConfig.js.map +1 -1
- package/package.json +21 -21
- package/src/cmds/beacon/handler.ts +10 -4
- package/src/cmds/builder/handler.ts +24 -4
- package/src/cmds/builder/loadKeypair.ts +5 -1
- package/src/cmds/builder/options.ts +33 -0
- package/src/cmds/validator/blsToExecutionChange.ts +1 -1
- package/src/cmds/validator/handler.ts +29 -2
- package/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts +1 -1
- package/src/cmds/validator/keymanager/impl.ts +56 -4
- package/src/cmds/validator/keymanager/keystoreCache.ts +1 -1
- package/src/cmds/validator/keymanager/persistedKeys.ts +5 -1
- package/src/cmds/validator/options.ts +36 -0
- package/src/cmds/validator/signers/index.ts +1 -1
- package/src/cmds/validator/voluntaryExit.ts +1 -1
- package/src/networks/chiado.ts +4 -10
- package/src/options/beaconNodeOptions/builder.ts +4 -2
- package/src/options/beaconNodeOptions/chain.ts +2 -1
- package/src/util/format.ts +1 -1
- package/src/util/proposerConfig.ts +152 -13
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { builderConfigDataFromJson } from "@lodestar/api/keymanager";
|
|
4
|
+
import { MAX_BUILDER_AUTH_DATA_SIZE, MAX_BUILDER_ENTRIES, MAX_BUILDER_URL_SIZE } from "@lodestar/params";
|
|
5
|
+
import { fromHex, isValidAsciiHttpUrl, toHex } from "@lodestar/utils";
|
|
3
6
|
import { parseFeeRecipient } from "./feeRecipient.js";
|
|
4
7
|
import { readFile } from "./file.js";
|
|
8
|
+
const UINT64_MAX = 2n ** 64n - 1n;
|
|
9
|
+
const BUILDER_AUTH_DATA_PATTERN = new RegExp(`^0x(?:[a-fA-F0-9]{2}){1,${MAX_BUILDER_AUTH_DATA_SIZE}}$`);
|
|
5
10
|
export function parseProposerConfig(configFilePath, defaultArgsConfig) {
|
|
6
11
|
const configFile = readFile(configFilePath, ["yml", "yaml"]);
|
|
7
12
|
const defaultConfigParsed = parseProposerConfigSection(configFile.default_config || {}, defaultArgsConfig);
|
|
@@ -21,7 +26,7 @@ function stringtoBool(input) {
|
|
|
21
26
|
}
|
|
22
27
|
function parseProposerConfigSection(proposerFileSection, overrideConfig) {
|
|
23
28
|
const { graffiti, strict_fee_recipient_check, fee_recipient, builder } = proposerFileSection;
|
|
24
|
-
const { gas_limit, selection: builderSelection, boost_factor } = builder || {};
|
|
29
|
+
const { gas_limit, selection: builderSelection, boost_factor, min_bid, max_execution_payment, builders, } = builder || {};
|
|
25
30
|
if (graffiti !== undefined && typeof graffiti !== "string") {
|
|
26
31
|
throw Error("graffiti is not 'string");
|
|
27
32
|
}
|
|
@@ -43,24 +48,50 @@ function parseProposerConfigSection(proposerFileSection, overrideConfig) {
|
|
|
43
48
|
if (boost_factor !== undefined && typeof boost_factor !== "string") {
|
|
44
49
|
throw Error("boost_factor is not 'string");
|
|
45
50
|
}
|
|
51
|
+
if (min_bid !== undefined && typeof min_bid !== "string") {
|
|
52
|
+
throw Error("min_bid is not 'string");
|
|
53
|
+
}
|
|
54
|
+
if (max_execution_payment !== undefined && typeof max_execution_payment !== "string") {
|
|
55
|
+
throw Error("max_execution_payment is not 'string");
|
|
56
|
+
}
|
|
57
|
+
const parsedBuilder = overrideConfig?.builder || builder
|
|
58
|
+
? {
|
|
59
|
+
gasLimit: overrideConfig?.builder?.gasLimit ?? (gas_limit !== undefined ? Number(gas_limit) : undefined),
|
|
60
|
+
selection: overrideConfig?.builder?.selection ?? parseBuilderSelection(builderSelection),
|
|
61
|
+
boostFactor: overrideConfig?.builder?.boostFactor ?? parseBuilderBoostFactor(boost_factor),
|
|
62
|
+
minBid: overrideConfig?.builder?.minBid ?? parseBuilderMinBid(min_bid),
|
|
63
|
+
maxExecutionPayment: overrideConfig?.builder?.maxExecutionPayment ?? parseBuilderGweiAmount(max_execution_payment),
|
|
64
|
+
builders: overrideConfig?.builder?.builders ?? parseBuilderEntries(builders),
|
|
65
|
+
}
|
|
66
|
+
: undefined;
|
|
67
|
+
if (overrideConfig?.builder?.builders !== undefined && builders !== undefined) {
|
|
68
|
+
throw Error("Cannot configure both --builder.urls and builders in the proposer settings file");
|
|
69
|
+
}
|
|
46
70
|
return {
|
|
47
71
|
graffiti: overrideConfig?.graffiti ?? graffiti,
|
|
48
72
|
strictFeeRecipientCheck: overrideConfig?.strictFeeRecipientCheck ??
|
|
49
73
|
(strict_fee_recipient_check ? stringtoBool(strict_fee_recipient_check) : undefined),
|
|
50
74
|
feeRecipient: overrideConfig?.feeRecipient ?? (fee_recipient ? parseFeeRecipient(fee_recipient) : undefined),
|
|
51
|
-
builder:
|
|
52
|
-
? {
|
|
53
|
-
gasLimit: overrideConfig?.builder?.gasLimit ?? (gas_limit !== undefined ? Number(gas_limit) : undefined),
|
|
54
|
-
selection: overrideConfig?.builder?.selection ?? parseBuilderSelection(builderSelection),
|
|
55
|
-
boostFactor: overrideConfig?.builder?.boostFactor ?? parseBuilderBoostFactor(boost_factor),
|
|
56
|
-
}
|
|
57
|
-
: undefined,
|
|
75
|
+
builder: parsedBuilder,
|
|
58
76
|
};
|
|
59
77
|
}
|
|
60
78
|
export function readProposerConfigDir(filepath, filename) {
|
|
61
79
|
const proposerConfigStr = fs.readFileSync(path.join(filepath, filename), "utf8");
|
|
62
|
-
|
|
63
|
-
|
|
80
|
+
// Persisted via `writeProposerConfig` with BigInt values serialized as strings
|
|
81
|
+
const persisted = JSON.parse(proposerConfigStr);
|
|
82
|
+
if (persisted.builder) {
|
|
83
|
+
const { boostFactor, minBid, maxExecutionPayment, builders } = persisted.builder;
|
|
84
|
+
persisted.builder.boostFactor = boostFactor !== undefined ? BigInt(boostFactor) : undefined;
|
|
85
|
+
persisted.builder.minBid = minBid !== undefined ? BigInt(minBid) : undefined;
|
|
86
|
+
persisted.builder.maxExecutionPayment = maxExecutionPayment !== undefined ? BigInt(maxExecutionPayment) : undefined;
|
|
87
|
+
persisted.builder.builders = builders?.map((entry) => ({
|
|
88
|
+
...entry,
|
|
89
|
+
maxExecutionPayment: entry.maxExecutionPayment !== undefined ? BigInt(entry.maxExecutionPayment) : undefined,
|
|
90
|
+
minBid: entry.minBid !== undefined ? BigInt(entry.minBid) : undefined,
|
|
91
|
+
builderBoostFactor: entry.builderBoostFactor !== undefined ? BigInt(entry.builderBoostFactor) : undefined,
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
return persisted;
|
|
64
95
|
}
|
|
65
96
|
export function parseBuilderSelection(builderSelection) {
|
|
66
97
|
if (builderSelection) {
|
|
@@ -89,6 +120,92 @@ export function parseBuilderBoostFactor(boostFactor) {
|
|
|
89
120
|
if (!/^\d+$/.test(boostFactor)) {
|
|
90
121
|
throw Error("Invalid input for builder boost factor, must be a valid number without decimals");
|
|
91
122
|
}
|
|
92
|
-
|
|
123
|
+
const parsed = BigInt(boostFactor);
|
|
124
|
+
if (parsed > UINT64_MAX) {
|
|
125
|
+
throw Error("Invalid input for builder boost factor, must not exceed 2**64 - 1");
|
|
126
|
+
}
|
|
127
|
+
return parsed;
|
|
128
|
+
}
|
|
129
|
+
export function parseBuilderMinBid(minBid) {
|
|
130
|
+
if (minBid === undefined)
|
|
131
|
+
return;
|
|
132
|
+
if (!/^\d+$/.test(minBid.toString())) {
|
|
133
|
+
throw Error("Invalid input for builder min bid, must be a valid number without decimals");
|
|
134
|
+
}
|
|
135
|
+
const parsed = BigInt(minBid);
|
|
136
|
+
if (parsed > UINT64_MAX) {
|
|
137
|
+
throw Error("Invalid input for builder min bid, must not exceed 2**64 - 1");
|
|
138
|
+
}
|
|
139
|
+
return parsed;
|
|
140
|
+
}
|
|
141
|
+
export function parseBuilderGweiAmount(amount) {
|
|
142
|
+
if (amount === undefined)
|
|
143
|
+
return;
|
|
144
|
+
if (!/^\d+$/.test(amount.toString())) {
|
|
145
|
+
throw Error("Invalid input for builder Gwei amount, must be a valid number without decimals");
|
|
146
|
+
}
|
|
147
|
+
const parsed = BigInt(amount);
|
|
148
|
+
if (parsed > UINT64_MAX) {
|
|
149
|
+
throw Error("Invalid input for builder Gwei amount, must not exceed 2**64 - 1");
|
|
150
|
+
}
|
|
151
|
+
return parsed;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Parse per-builder entries from the proposer settings file, same shape and validation as the
|
|
155
|
+
* keymanager builders api. No two entries may share both their url and their auth data, an
|
|
156
|
+
* omitted auth data is compared as the value derived from the entry url.
|
|
157
|
+
*/
|
|
158
|
+
export function parseBuilderEntries(builders) {
|
|
159
|
+
if (builders === undefined)
|
|
160
|
+
return undefined;
|
|
161
|
+
const { builders: entries } = builderConfigDataFromJson({ builders });
|
|
162
|
+
const seenEntries = new Set();
|
|
163
|
+
for (const entry of entries ?? []) {
|
|
164
|
+
if (!isValidAsciiHttpUrl(entry.url)) {
|
|
165
|
+
throw Error(`Invalid builder url: ${entry.url}`);
|
|
166
|
+
}
|
|
167
|
+
const authData = entry.authData !== undefined ? toHex(fromHex(entry.authData)) : toHex(Buffer.from(entry.url));
|
|
168
|
+
const entryKey = `${entry.url}|${authData}`;
|
|
169
|
+
if (seenEntries.has(entryKey)) {
|
|
170
|
+
throw Error(`Duplicate builder entry url=${entry.url}`);
|
|
171
|
+
}
|
|
172
|
+
seenEntries.add(entryKey);
|
|
173
|
+
}
|
|
174
|
+
return entries;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Parse builder urls into builder entries. Auth data agreed with a builder out of band may be
|
|
178
|
+
* appended as a hex fragment (`https://builder.example.com#0x0123`), it is stripped from the url
|
|
179
|
+
* and never sent on the wire. Without a fragment the auth data derives from the url.
|
|
180
|
+
*/
|
|
181
|
+
export function parseBuilderUrls(urls) {
|
|
182
|
+
if (urls === undefined)
|
|
183
|
+
return undefined;
|
|
184
|
+
const entries = [];
|
|
185
|
+
const seenEntries = new Set();
|
|
186
|
+
for (const value of urls) {
|
|
187
|
+
const fragmentIndex = value.indexOf("#");
|
|
188
|
+
const url = fragmentIndex === -1 ? value : value.slice(0, fragmentIndex);
|
|
189
|
+
const authData = fragmentIndex === -1 ? undefined : value.slice(fragmentIndex + 1);
|
|
190
|
+
if (!isValidAsciiHttpUrl(url)) {
|
|
191
|
+
throw Error(`Invalid builder url: ${url}`);
|
|
192
|
+
}
|
|
193
|
+
if (Buffer.byteLength(url, "utf8") > MAX_BUILDER_URL_SIZE) {
|
|
194
|
+
throw Error(`Invalid builder url, must not exceed ${MAX_BUILDER_URL_SIZE} bytes: ${url}`);
|
|
195
|
+
}
|
|
196
|
+
if (authData !== undefined && !BUILDER_AUTH_DATA_PATTERN.test(authData)) {
|
|
197
|
+
throw Error(`Invalid builder url auth data, must be a 0x-prefixed hex string of 1 to ${MAX_BUILDER_AUTH_DATA_SIZE} bytes: ${url}`);
|
|
198
|
+
}
|
|
199
|
+
const entryKey = `${url}|${authData !== undefined ? toHex(fromHex(authData)) : toHex(Buffer.from(url))}`;
|
|
200
|
+
if (seenEntries.has(entryKey)) {
|
|
201
|
+
throw Error(`Duplicate builder url: ${url}`);
|
|
202
|
+
}
|
|
203
|
+
seenEntries.add(entryKey);
|
|
204
|
+
entries.push({ url, authData });
|
|
205
|
+
}
|
|
206
|
+
if (entries.length > MAX_BUILDER_ENTRIES) {
|
|
207
|
+
throw Error(`Number of builder urls must not exceed ${MAX_BUILDER_ENTRIES}, got ${entries.length}`);
|
|
208
|
+
}
|
|
209
|
+
return entries;
|
|
93
210
|
}
|
|
94
211
|
//# sourceMappingURL=proposerConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposerConfig.js","sourceRoot":"","sources":["../../src/util/proposerConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"proposerConfig.js","sourceRoot":"","sources":["../../src/util/proposerConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAqB,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AACvF,OAAO,EAAC,0BAA0B,EAAE,mBAAmB,EAAE,oBAAoB,EAAC,MAAM,kBAAkB,CAAC;AACvG,OAAO,EAAC,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAC;AAEnC,MAAM,UAAU,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,CAAC;AAClC,MAAM,yBAAyB,GAAG,IAAI,MAAM,CAAC,2BAA2B,0BAA0B,IAAI,CAAC,CAAC;AAyBxG,MAAM,UAAU,mBAAmB,CACjC,cAAsB,EACtB,iBAAkC;IAElC,MAAM,UAAU,GAAG,QAAQ,CAAqB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACjF,MAAM,mBAAmB,GAAG,0BAA0B,CAAC,UAAU,CAAC,cAAc,IAAI,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAE3G,MAAM,kBAAkB,GAAG,UAAU,CAAC,eAAe,IAAI,EAAE,CAAC;IAC5D,MAAM,oBAAoB,GAA8C,EAAE,CAAC;IAC3E,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACxD,oBAAoB,CAAC,SAAS,CAAC,GAAG,0BAA0B,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9F,CAAC;IAED,OAAO;QACL,cAAc,EAAE,oBAAoB;QACpC,aAAa,EAAE,mBAAmB;KACnC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IACvE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,0BAA0B,CACjC,mBAA8C,EAC9C,cAA+B;IAE/B,MAAM,EAAC,QAAQ,EAAE,0BAA0B,EAAE,aAAa,EAAE,OAAO,EAAC,GAAG,mBAAmB,CAAC;IAC3F,MAAM,EACJ,SAAS,EACT,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EACZ,OAAO,EACP,qBAAqB,EACrB,QAAQ,GACT,GAAG,OAAO,IAAI,EAAE,CAAC;IAElB,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC3D,MAAM,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACzC,CAAC;IACD,IACE,0BAA0B,KAAK,SAAS;QACxC,CAAC,CAAC,0BAA0B,KAAK,MAAM,IAAI,0BAA0B,KAAK,OAAO,CAAC,EAClF,CAAC;QACD,MAAM,KAAK,CAAC,kDAAkD,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,aAAa,KAAK,SAAS,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QACrE,MAAM,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YACpC,MAAM,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IACD,IAAI,YAAY,KAAK,SAAS,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACnE,MAAM,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzD,MAAM,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,qBAAqB,KAAK,SAAS,IAAI,OAAO,qBAAqB,KAAK,QAAQ,EAAE,CAAC;QACrF,MAAM,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,aAAa,GACjB,cAAc,EAAE,OAAO,IAAI,OAAO;QAChC,CAAC,CAAC;YACE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACxG,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,IAAI,qBAAqB,CAAC,gBAAgB,CAAC;YACxF,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,IAAI,uBAAuB,CAAC,YAAY,CAAC;YAC1F,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,IAAI,kBAAkB,CAAC,OAAO,CAAC;YACtE,mBAAmB,EACjB,cAAc,EAAE,OAAO,EAAE,mBAAmB,IAAI,sBAAsB,CAAC,qBAAqB,CAAC;YAC/F,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,IAAI,mBAAmB,CAAC,QAAQ,CAAC;SAC7E;QACH,CAAC,CAAC,SAAS,CAAC;IAEhB,IAAI,cAAc,EAAE,OAAO,EAAE,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC9E,MAAM,KAAK,CAAC,iFAAiF,CAAC,CAAC;IACjG,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,cAAc,EAAE,QAAQ,IAAI,QAAQ;QAC9C,uBAAuB,EACrB,cAAc,EAAE,uBAAuB;YACvC,CAAC,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrF,YAAY,EAAE,cAAc,EAAE,YAAY,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5G,OAAO,EAAE,aAAa;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAAgB,EAAE,QAAgB;IACtE,MAAM,iBAAiB,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;IACjF,+EAA+E;IAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAmB,CAAC;IAClE,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;QACtB,MAAM,EAAC,WAAW,EAAE,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAC,GAAG,SAAS,CAAC,OAAO,CAAC;QAC/E,SAAS,CAAC,OAAO,CAAC,WAAW,GAAG,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5F,SAAS,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7E,SAAS,CAAC,OAAO,CAAC,mBAAmB,GAAG,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpH,SAAS,CAAC,OAAO,CAAC,QAAQ,GAAG,QAAQ,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACrD,GAAG,KAAK;YACR,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,SAAS;YAC5G,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;YACrE,kBAAkB,EAAE,KAAK,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,SAAS;SAC1G,CAAC,CAAC,CAAC;IACN,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,gBAAyB;IAC7D,IAAI,gBAAgB,EAAE,CAAC;QACrB,QAAQ,gBAAgB,EAAE,CAAC;YACzB,KAAK,SAAS;gBACZ,MAAM;YACR,KAAK,WAAW;gBACd,MAAM;YACR,KAAK,eAAe;gBAClB,MAAM;YACR,KAAK,aAAa;gBAChB,MAAM,KAAK,CAAC,iFAAiF,CAAC,CAAC;YACjG,KAAK,iBAAiB;gBACpB,MAAM;YACR,KAAK,eAAe;gBAClB,MAAM;YACR;gBACE,MAAM,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IACD,OAAO,gBAAqD,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,WAAoB;IAC1D,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO;IAEtC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,MAAM,KAAK,CAAC,iFAAiF,CAAC,CAAC;IACjG,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACnC,IAAI,MAAM,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAwB;IACzD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO;IAEjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;QACrC,MAAM,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,IAAI,MAAM,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC7D,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO;IAEjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;QACrC,MAAM,KAAK,CAAC,gFAAgF,CAAC,CAAC;IAChG,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,IAAI,MAAM,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,kEAAkE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAkB;IACpD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE7C,MAAM,EAAC,QAAQ,EAAE,OAAO,EAAC,GAAG,yBAAyB,CAAC,EAAC,QAAQ,EAAC,CAAC,CAAC;IAClE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,KAAK,CAAC,wBAAwB,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/G,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5C,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,MAAM,KAAK,CAAC,+BAA+B,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAe;IAC9C,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAEzC,MAAM,OAAO,GAAyB,EAAE,CAAC;IACzC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;QACnF,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,KAAK,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,oBAAoB,EAAE,CAAC;YAC1D,MAAM,KAAK,CAAC,wCAAwC,oBAAoB,WAAW,GAAG,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxE,MAAM,KAAK,CACT,2EAA2E,0BAA0B,WAAW,GAAG,EAAE,CACtH,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,GAAG,GAAG,IAAI,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACzG,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9B,MAAM,KAAK,CAAC,0BAA0B,GAAG,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,EAAC,GAAG,EAAE,QAAQ,EAAC,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACzC,MAAM,KAAK,CAAC,0CAA0C,mBAAmB,SAAS,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainsafe/lodestar",
|
|
3
|
-
"version": "1.47.0-dev.
|
|
3
|
+
"version": "1.47.0-dev.f0f26cd2b6",
|
|
4
4
|
"description": "Command line interface for lodestar",
|
|
5
5
|
"author": "ChainSafe Systems",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -59,26 +59,26 @@
|
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@chainsafe/bls-keygen": "^0.4.0",
|
|
61
61
|
"@chainsafe/bls-keystore": "^3.1.0",
|
|
62
|
-
"@chainsafe/blst": "^2.2.0",
|
|
63
62
|
"@chainsafe/discv5": "^12.0.2",
|
|
64
63
|
"@chainsafe/enr": "^6.0.2",
|
|
65
|
-
"@chainsafe/
|
|
66
|
-
"@chainsafe/
|
|
64
|
+
"@chainsafe/lodestar-z": "catalog:",
|
|
65
|
+
"@chainsafe/persistent-merkle-tree": "^1.3.1",
|
|
66
|
+
"@chainsafe/ssz": "^1.6.3",
|
|
67
67
|
"@chainsafe/threads": "^1.11.3",
|
|
68
|
-
"@libp2p/crypto": "^5.1.
|
|
69
|
-
"@libp2p/interface": "^3.
|
|
70
|
-
"@libp2p/peer-id": "^6.0.
|
|
71
|
-
"@lodestar/api": "^1.47.0-dev.
|
|
72
|
-
"@lodestar/beacon-node": "^1.47.0-dev.
|
|
73
|
-
"@lodestar/builder": "^1.47.0-dev.
|
|
74
|
-
"@lodestar/config": "^1.47.0-dev.
|
|
75
|
-
"@lodestar/db": "^1.47.0-dev.
|
|
76
|
-
"@lodestar/logger": "^1.47.0-dev.
|
|
77
|
-
"@lodestar/params": "^1.47.0-dev.
|
|
78
|
-
"@lodestar/state-transition": "^1.47.0-dev.
|
|
79
|
-
"@lodestar/types": "^1.47.0-dev.
|
|
80
|
-
"@lodestar/utils": "^1.47.0-dev.
|
|
81
|
-
"@lodestar/validator": "^1.47.0-dev.
|
|
68
|
+
"@libp2p/crypto": "^5.1.23",
|
|
69
|
+
"@libp2p/interface": "^3.3.0",
|
|
70
|
+
"@libp2p/peer-id": "^6.0.15",
|
|
71
|
+
"@lodestar/api": "^1.47.0-dev.f0f26cd2b6",
|
|
72
|
+
"@lodestar/beacon-node": "^1.47.0-dev.f0f26cd2b6",
|
|
73
|
+
"@lodestar/builder": "^1.47.0-dev.f0f26cd2b6",
|
|
74
|
+
"@lodestar/config": "^1.47.0-dev.f0f26cd2b6",
|
|
75
|
+
"@lodestar/db": "^1.47.0-dev.f0f26cd2b6",
|
|
76
|
+
"@lodestar/logger": "^1.47.0-dev.f0f26cd2b6",
|
|
77
|
+
"@lodestar/params": "^1.47.0-dev.f0f26cd2b6",
|
|
78
|
+
"@lodestar/state-transition": "^1.47.0-dev.f0f26cd2b6",
|
|
79
|
+
"@lodestar/types": "^1.47.0-dev.f0f26cd2b6",
|
|
80
|
+
"@lodestar/utils": "^1.47.0-dev.f0f26cd2b6",
|
|
81
|
+
"@lodestar/validator": "^1.47.0-dev.f0f26cd2b6",
|
|
82
82
|
"@multiformats/multiaddr": "^13.0.1",
|
|
83
83
|
"deepmerge": "^4.3.1",
|
|
84
84
|
"ethers": "^6.7.0",
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
"yargs": "^17.7.1"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
|
-
"@chainsafe/as-sha256": "^1.2.
|
|
95
|
+
"@chainsafe/as-sha256": "^1.2.5",
|
|
96
96
|
"@ethereumjs/rlp": "^4.0.1",
|
|
97
|
-
"@lodestar/test-utils": "^1.47.0-dev.
|
|
97
|
+
"@lodestar/test-utils": "^1.47.0-dev.f0f26cd2b6",
|
|
98
98
|
"@types/debug": "^4.1.7",
|
|
99
99
|
"@types/inquirer": "^9.0.3",
|
|
100
100
|
"@types/js-yaml": "^4.0.5",
|
|
@@ -108,5 +108,5 @@
|
|
|
108
108
|
"web3": "^4.0.3",
|
|
109
109
|
"web3-eth-accounts": "^4.0.3"
|
|
110
110
|
},
|
|
111
|
-
"gitHead": "
|
|
111
|
+
"gitHead": "f2cb518d19fecb98b13ff35caa3c0c421e02ad39"
|
|
112
112
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import {getHeapStatistics} from "node:v8";
|
|
3
3
|
import {SignableENR} from "@chainsafe/enr";
|
|
4
|
+
import {pubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
|
|
4
5
|
import {hasher} from "@chainsafe/persistent-merkle-tree";
|
|
5
6
|
import {BeaconDb, BeaconNode} from "@lodestar/beacon-node";
|
|
6
7
|
import {ChainForkConfig, createBeaconConfig} from "@lodestar/config";
|
|
7
8
|
import {LevelDbController} from "@lodestar/db/controller/level";
|
|
8
9
|
import {LoggerNode, getNodeLogger} from "@lodestar/logger/node";
|
|
9
|
-
import {ACTIVE_PRESET, PresetName} from "@lodestar/params";
|
|
10
|
-
import {createBeaconStateView
|
|
10
|
+
import {ACTIVE_PRESET, MAX_PENDING_DEPOSITS_PER_EPOCH, PresetName, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
11
|
+
import {createBeaconStateView} from "@lodestar/state-transition";
|
|
11
12
|
import {ErrorAborted, bytesToInt, formatBytes} from "@lodestar/utils";
|
|
12
13
|
import {ProcessShutdownCallback} from "@lodestar/validator";
|
|
13
14
|
import {BeaconNodeOptions, getBeaconConfigFromArgs} from "../../config/index.js";
|
|
@@ -78,8 +79,13 @@ export async function beaconHandler(args: BeaconArgs & GlobalArgs): Promise<void
|
|
|
78
79
|
wsCheckpoint,
|
|
79
80
|
} = await initBeaconState(args, beaconPaths.dataDir, config, db, logger);
|
|
80
81
|
const beaconConfig = createBeaconConfig(config, anchorState.genesisValidatorsRoot);
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
// Reserve 3 months of worst-case registry growth (MAX_PENDING_DEPOSITS_PER_EPOCH per epoch),
|
|
83
|
+
// over a year at organic rates, to avoid routine cache reallocations. Cache growth is protected
|
|
84
|
+
// by its native lock; if this headroom is exceeded, it grows by the same fixed step.
|
|
85
|
+
const headroomEpochs = (90 * 24 * 60 * 60) / (config.SECONDS_PER_SLOT * SLOTS_PER_EPOCH);
|
|
86
|
+
const pubkeyCacheHeadroom = MAX_PENDING_DEPOSITS_PER_EPOCH * Math.ceil(headroomEpochs);
|
|
87
|
+
pubkeyCache.ensureCapacity(anchorState.validators.length + pubkeyCacheHeadroom);
|
|
88
|
+
pubkeyCache.syncPubkeys(anchorState.validators.getAllReadonlyValues());
|
|
83
89
|
const anchorStateView = args["chain.nativeStateView"]
|
|
84
90
|
? createBeaconStateView({useNative: true, stateBytes: anchorStateBytes})
|
|
85
91
|
: createBeaconStateView({useNative: false, anchorState, config: beaconConfig, pubkeyCache});
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import {getClient} from "@lodestar/api";
|
|
3
|
-
import {
|
|
3
|
+
import {RegistryMetricCreator, collectNodeJSMetrics, getHttpMetricsServer} from "@lodestar/beacon-node";
|
|
4
|
+
import {Builder, getMetrics} from "@lodestar/builder";
|
|
4
5
|
import {getNodeLogger} from "@lodestar/logger/node";
|
|
5
6
|
import {fromHex, toPrintableUrl} from "@lodestar/utils";
|
|
6
7
|
import {getBeaconConfigFromArgs} from "../../config/beaconParams.js";
|
|
7
8
|
import {GlobalArgs} from "../../options/index.js";
|
|
8
9
|
import {getGlobalPaths} from "../../paths/global.js";
|
|
9
10
|
import {cleanOldLogFiles, onGracefulShutdown, parseFeeRecipient, parseLoggerArgs} from "../../util/index.js";
|
|
11
|
+
import {getVersionData} from "../../util/version.js";
|
|
10
12
|
import {loadBuilderKeypair} from "./loadKeypair.js";
|
|
11
|
-
import {IBuilderCliArgs} from "./options.js";
|
|
13
|
+
import {IBuilderCliArgs, builderMetricsDefaultOptions} from "./options.js";
|
|
12
14
|
|
|
13
15
|
const ZERO_ADDRESS = "0x" + "0".repeat(40);
|
|
14
16
|
|
|
@@ -29,13 +31,16 @@ export async function builderHandler(args: IBuilderCliArgs & GlobalArgs): Promis
|
|
|
29
31
|
logger.debug("Not able to delete log files", {}, e as Error);
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
const {version, commit} = getVersionData();
|
|
35
|
+
logger.info("Lodestar", {network, version, commit});
|
|
36
|
+
|
|
32
37
|
const executionFeeRecipient = parseFeeRecipient(args.executionFeeRecipient);
|
|
33
38
|
|
|
34
39
|
if (executionFeeRecipient === ZERO_ADDRESS) {
|
|
35
40
|
throw Error("Cannot put zero address as an executionFeeRecipient");
|
|
36
41
|
}
|
|
37
42
|
|
|
38
|
-
const keypair = await loadBuilderKeypair(args.keystore, args.keystorePassword, args.builderPubkey);
|
|
43
|
+
const keypair = await loadBuilderKeypair(logger, args.keystore, args.keystorePassword, args.builderPubkey);
|
|
39
44
|
|
|
40
45
|
const onGracefulShutdownCbs: (() => Promise<void> | void)[] = [];
|
|
41
46
|
onGracefulShutdown(async () => {
|
|
@@ -45,9 +50,23 @@ export async function builderHandler(args: IBuilderCliArgs & GlobalArgs): Promis
|
|
|
45
50
|
const abortController = new AbortController();
|
|
46
51
|
onGracefulShutdownCbs.push(async () => abortController.abort());
|
|
47
52
|
|
|
53
|
+
const register = args.metrics ? new RegistryMetricCreator() : null;
|
|
54
|
+
const metrics = register && getMetrics(register, {version, commit, network});
|
|
55
|
+
|
|
56
|
+
if (metrics) {
|
|
57
|
+
const closeMetrics = collectNodeJSMetrics(register);
|
|
58
|
+
onGracefulShutdownCbs.push(() => closeMetrics());
|
|
59
|
+
|
|
60
|
+
const port = args["metrics.port"] ?? builderMetricsDefaultOptions.port;
|
|
61
|
+
const address = args["metrics.address"] ?? builderMetricsDefaultOptions.address;
|
|
62
|
+
const metricsServer = await getHttpMetricsServer({port, address}, {register, logger});
|
|
63
|
+
|
|
64
|
+
onGracefulShutdownCbs.push(() => metricsServer.close());
|
|
65
|
+
}
|
|
66
|
+
|
|
48
67
|
const api = getClient(
|
|
49
68
|
{urls: [args.beaconNodeUrl], globalInit: {signal: abortController.signal, timeoutMs: args.requestTimeout}},
|
|
50
|
-
{config, logger}
|
|
69
|
+
{config, logger, metrics: metrics?.restApiClient}
|
|
51
70
|
);
|
|
52
71
|
|
|
53
72
|
logger.info("Beacon node", {beaconNode: toPrintableUrl(args.beaconNodeUrl), timeoutMs: args.requestTimeout});
|
|
@@ -59,6 +78,7 @@ export async function builderHandler(args: IBuilderCliArgs & GlobalArgs): Promis
|
|
|
59
78
|
abortController,
|
|
60
79
|
api,
|
|
61
80
|
executionFeeRecipient: fromHex(executionFeeRecipient),
|
|
81
|
+
metrics,
|
|
62
82
|
});
|
|
63
83
|
|
|
64
84
|
onGracefulShutdownCbs.push(() => builder.close());
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import {Keystore} from "@chainsafe/bls-keystore";
|
|
3
|
-
import {SecretKey} from "@chainsafe/blst";
|
|
3
|
+
import {SecretKey} from "@chainsafe/lodestar-z/blst";
|
|
4
4
|
import {Keypair} from "@lodestar/builder";
|
|
5
|
+
import {Logger} from "@lodestar/utils";
|
|
5
6
|
import {ensure0xPrefix} from "../../util/format.js";
|
|
6
7
|
import {readPassphraseFile} from "../../util/passphrase.js";
|
|
7
8
|
|
|
8
9
|
export async function loadBuilderKeypair(
|
|
10
|
+
logger: Logger,
|
|
9
11
|
keystorePath: string,
|
|
10
12
|
passwordPath: string,
|
|
11
13
|
expectedPubkey?: string
|
|
@@ -28,5 +30,7 @@ export async function loadBuilderKeypair(
|
|
|
28
30
|
throw Error(`Pubkey mismatch: keystore ${publicKeyHex}, expected ${expectedPubkey}`);
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
logger.info("Loaded builder keystore", {pubkey: publicKeyHex});
|
|
34
|
+
|
|
31
35
|
return {secretKey, publicKey};
|
|
32
36
|
}
|
|
@@ -2,6 +2,12 @@ import {defaultOptions} from "@lodestar/builder";
|
|
|
2
2
|
import {CliCommandOptions} from "@lodestar/utils";
|
|
3
3
|
import {LogArgs, logOptions} from "../../options/logOptions.js";
|
|
4
4
|
|
|
5
|
+
export const builderMetricsDefaultOptions = {
|
|
6
|
+
enabled: false,
|
|
7
|
+
port: 5065,
|
|
8
|
+
address: "127.0.0.1",
|
|
9
|
+
};
|
|
10
|
+
|
|
5
11
|
export type IBuilderCliArgs = LogArgs & {
|
|
6
12
|
beaconNodeUrl: string;
|
|
7
13
|
keystore: string;
|
|
@@ -9,6 +15,10 @@ export type IBuilderCliArgs = LogArgs & {
|
|
|
9
15
|
builderPubkey?: string;
|
|
10
16
|
executionFeeRecipient: string;
|
|
11
17
|
requestTimeout: number;
|
|
18
|
+
|
|
19
|
+
metrics?: boolean;
|
|
20
|
+
"metrics.port"?: number;
|
|
21
|
+
"metrics.address"?: string;
|
|
12
22
|
};
|
|
13
23
|
|
|
14
24
|
export const builderOptions: CliCommandOptions<IBuilderCliArgs> = {
|
|
@@ -48,4 +58,27 @@ export const builderOptions: CliCommandOptions<IBuilderCliArgs> = {
|
|
|
48
58
|
type: "number",
|
|
49
59
|
default: defaultOptions.requestTimeout,
|
|
50
60
|
},
|
|
61
|
+
|
|
62
|
+
// Metrics
|
|
63
|
+
|
|
64
|
+
metrics: {
|
|
65
|
+
description: "Enable the Prometheus metrics HTTP server",
|
|
66
|
+
type: "boolean",
|
|
67
|
+
defaultDescription: String(builderMetricsDefaultOptions.enabled),
|
|
68
|
+
group: "metrics",
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
"metrics.port": {
|
|
72
|
+
description: "Listen TCP port for the Prometheus metrics HTTP server",
|
|
73
|
+
type: "number",
|
|
74
|
+
defaultDescription: String(builderMetricsDefaultOptions.port),
|
|
75
|
+
group: "metrics",
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
"metrics.address": {
|
|
79
|
+
description: "Listen address for the Prometheus metrics HTTP server",
|
|
80
|
+
type: "string",
|
|
81
|
+
defaultDescription: String(builderMetricsDefaultOptions.address),
|
|
82
|
+
group: "metrics",
|
|
83
|
+
},
|
|
51
84
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {SecretKey} from "@chainsafe/blst";
|
|
1
|
+
import {SecretKey} from "@chainsafe/lodestar-z/blst";
|
|
2
2
|
import {getClient} from "@lodestar/api";
|
|
3
3
|
import {createBeaconConfig} from "@lodestar/config";
|
|
4
4
|
import {DOMAIN_BLS_TO_EXECUTION_CHANGE, ForkName} from "@lodestar/params";
|
|
@@ -28,7 +28,13 @@ import {
|
|
|
28
28
|
parseLoggerArgs,
|
|
29
29
|
parseProposerConfig,
|
|
30
30
|
} from "../../util/index.js";
|
|
31
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
parseBuilderBoostFactor,
|
|
33
|
+
parseBuilderGweiAmount,
|
|
34
|
+
parseBuilderMinBid,
|
|
35
|
+
parseBuilderSelection,
|
|
36
|
+
parseBuilderUrls,
|
|
37
|
+
} from "../../util/proposerConfig.js";
|
|
32
38
|
import {getVersionData} from "../../util/version.js";
|
|
33
39
|
import {KeymanagerApi} from "./keymanager/impl.js";
|
|
34
40
|
import {IPersistedKeysBackend} from "./keymanager/interface.js";
|
|
@@ -212,7 +218,8 @@ export async function validatorHandler(args: IValidatorCliArgs & GlobalArgs): Pr
|
|
|
212
218
|
validator,
|
|
213
219
|
persistedKeysBackend,
|
|
214
220
|
abortController.signal,
|
|
215
|
-
proposerConfigWriteDisabled
|
|
221
|
+
proposerConfigWriteDisabled,
|
|
222
|
+
args.allowDangerousTrustedPayments
|
|
216
223
|
);
|
|
217
224
|
const keymanagerServer = new KeymanagerRestApiServer(
|
|
218
225
|
{
|
|
@@ -250,6 +257,9 @@ function getProposerConfigFromArgs(
|
|
|
250
257
|
args["builder.selection"] ?? (args.builder ? defaultOptions.builderAliasSelection : undefined)
|
|
251
258
|
),
|
|
252
259
|
boostFactor: parseBuilderBoostFactor(args["builder.boostFactor"]),
|
|
260
|
+
minBid: parseBuilderMinBid(args["builder.minBid"]),
|
|
261
|
+
maxExecutionPayment: parseBuilderGweiAmount(args["builder.maxExecutionPayment"]),
|
|
262
|
+
builders: parseBuilderUrls(args["builder.urls"]),
|
|
253
263
|
},
|
|
254
264
|
};
|
|
255
265
|
|
|
@@ -273,6 +283,23 @@ function getProposerConfigFromArgs(
|
|
|
273
283
|
valProposerConfig = {defaultConfig} as ValidatorProposerConfig;
|
|
274
284
|
}
|
|
275
285
|
}
|
|
286
|
+
|
|
287
|
+
// Trusted execution payments are only backed by the builder's promise to pay, require an
|
|
288
|
+
// explicit opt-in before any configuration source can set a max execution payment above 0
|
|
289
|
+
if (args.allowDangerousTrustedPayments !== true) {
|
|
290
|
+
const configs = [valProposerConfig.defaultConfig, ...Object.values(valProposerConfig.proposerConfig ?? {})];
|
|
291
|
+
const hasTrustedPayment = configs.some(
|
|
292
|
+
(config) =>
|
|
293
|
+
(config.builder?.maxExecutionPayment ?? 0n) > 0n ||
|
|
294
|
+
(config.builder?.builders ?? []).some((entry) => (entry.maxExecutionPayment ?? 0n) > 0n)
|
|
295
|
+
);
|
|
296
|
+
if (hasTrustedPayment) {
|
|
297
|
+
throw new YargsError(
|
|
298
|
+
"Configuring a builder max execution payment above 0 requires --allowDangerousTrustedPayments"
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
276
303
|
return valProposerConfig;
|
|
277
304
|
}
|
|
278
305
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import {Keystore} from "@chainsafe/bls-keystore";
|
|
4
|
-
import {SecretKey} from "@chainsafe/blst";
|
|
4
|
+
import {SecretKey} from "@chainsafe/lodestar-z/blst";
|
|
5
5
|
import {LogLevel, Logger} from "@lodestar/utils";
|
|
6
6
|
import {SignerLocal, SignerType} from "@lodestar/validator";
|
|
7
7
|
import {lockFilepath, unlockFilepath} from "../../../util/lockfile.js";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {Keystore} from "@chainsafe/bls-keystore";
|
|
2
|
-
import {SecretKey} from "@chainsafe/blst";
|
|
2
|
+
import {SecretKey} from "@chainsafe/lodestar-z/blst";
|
|
3
3
|
import {
|
|
4
4
|
BuilderBoostFactorData,
|
|
5
|
+
BuilderConfigData,
|
|
5
6
|
DeleteRemoteKeyStatus,
|
|
6
7
|
DeletionStatus,
|
|
7
8
|
FeeRecipientData,
|
|
@@ -32,12 +33,13 @@ export class KeymanagerApi implements Api {
|
|
|
32
33
|
private readonly validator: Validator,
|
|
33
34
|
private readonly persistedKeysBackend: IPersistedKeysBackend,
|
|
34
35
|
private readonly signal: AbortSignal,
|
|
35
|
-
private readonly proposerConfigWriteDisabled?: boolean
|
|
36
|
+
private readonly proposerConfigWriteDisabled?: boolean,
|
|
37
|
+
private readonly allowDangerousTrustedPayments?: boolean
|
|
36
38
|
) {}
|
|
37
39
|
|
|
38
40
|
private checkIfProposerWriteEnabled(): void {
|
|
39
41
|
if (this.proposerConfigWriteDisabled === true) {
|
|
40
|
-
throw
|
|
42
|
+
throw new ApiError(403, "proposerSettingsFile option activated");
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -379,6 +381,48 @@ export class KeymanagerApi implements Api {
|
|
|
379
381
|
return {status: 204};
|
|
380
382
|
}
|
|
381
383
|
|
|
384
|
+
async getBuilderConfig({pubkey}: {pubkey: PubkeyHex}): ReturnType<Api["getBuilderConfig"]> {
|
|
385
|
+
this.assertValidKnownPubkey(pubkey);
|
|
386
|
+
return {data: this.validator.validatorStore.getBuilderConfig(pubkey)};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async setBuilderConfig({
|
|
390
|
+
pubkey,
|
|
391
|
+
builderConfig,
|
|
392
|
+
}: {
|
|
393
|
+
pubkey: PubkeyHex;
|
|
394
|
+
builderConfig: BuilderConfigData;
|
|
395
|
+
}): ReturnType<Api["setBuilderConfig"]> {
|
|
396
|
+
this.checkIfProposerWriteEnabled();
|
|
397
|
+
this.assertValidKnownPubkey(pubkey);
|
|
398
|
+
|
|
399
|
+
if (
|
|
400
|
+
this.allowDangerousTrustedPayments !== true &&
|
|
401
|
+
builderConfig.builders?.some((entry) => (entry.maxExecutionPayment ?? 0n) > 0n)
|
|
402
|
+
) {
|
|
403
|
+
throw new ApiError(
|
|
404
|
+
400,
|
|
405
|
+
"Configuring a builder max execution payment above 0 requires --allowDangerousTrustedPayments"
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
try {
|
|
410
|
+
this.validator.validatorStore.setBuilderConfig(pubkey, builderConfig);
|
|
411
|
+
} catch (e) {
|
|
412
|
+
throw new ApiError(400, (e as Error).message);
|
|
413
|
+
}
|
|
414
|
+
this.persistedKeysBackend.writeProposerConfig(pubkey, this.validator.validatorStore.getProposerConfig(pubkey));
|
|
415
|
+
return {status: 202};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
async deleteBuilderConfig({pubkey}: {pubkey: PubkeyHex}): ReturnType<Api["deleteBuilderConfig"]> {
|
|
419
|
+
this.checkIfProposerWriteEnabled();
|
|
420
|
+
this.assertValidKnownPubkey(pubkey);
|
|
421
|
+
this.validator.validatorStore.deleteBuilderConfig(pubkey);
|
|
422
|
+
this.persistedKeysBackend.writeProposerConfig(pubkey, this.validator.validatorStore.getProposerConfig(pubkey));
|
|
423
|
+
return {status: 204};
|
|
424
|
+
}
|
|
425
|
+
|
|
382
426
|
async getProposerConfig({pubkey}: {pubkey: PubkeyHex}): ReturnType<Api["getProposerConfig"]> {
|
|
383
427
|
this.assertValidKnownPubkey(pubkey);
|
|
384
428
|
|
|
@@ -390,7 +434,15 @@ export class KeymanagerApi implements Api {
|
|
|
390
434
|
? {
|
|
391
435
|
...config.builder,
|
|
392
436
|
// Default JSON serialization can't handle BigInt
|
|
393
|
-
boostFactor: config.builder.boostFactor
|
|
437
|
+
boostFactor: config.builder.boostFactor?.toString(),
|
|
438
|
+
minBid: config.builder.minBid?.toString(),
|
|
439
|
+
maxExecutionPayment: config.builder.maxExecutionPayment?.toString(),
|
|
440
|
+
builders: config.builder.builders?.map((entry) => ({
|
|
441
|
+
...entry,
|
|
442
|
+
maxExecutionPayment: entry.maxExecutionPayment?.toString(),
|
|
443
|
+
minBid: entry.minBid?.toString(),
|
|
444
|
+
builderBoostFactor: entry.builderBoostFactor?.toString(),
|
|
445
|
+
})),
|
|
394
446
|
}
|
|
395
447
|
: undefined,
|
|
396
448
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import {Keystore} from "@chainsafe/bls-keystore";
|
|
4
|
-
import {SecretKey} from "@chainsafe/blst";
|
|
4
|
+
import {SecretKey} from "@chainsafe/lodestar-z/blst";
|
|
5
5
|
import {fromHex, toHex, toPubkeyHex} from "@lodestar/utils";
|
|
6
6
|
import {SignerLocal, SignerType} from "@lodestar/validator";
|
|
7
7
|
import {writeFile600Perm} from "../../../util/file.js";
|
|
@@ -53,7 +53,11 @@ export class PersistedKeysBackend implements IPersistedKeysBackend {
|
|
|
53
53
|
if (proposerConfig !== null) {
|
|
54
54
|
// if proposerConfig is not empty write or update the json to file
|
|
55
55
|
const {proposerDirPath} = this.getValidatorPaths(pubkeyHex);
|
|
56
|
-
writeFile600Perm(
|
|
56
|
+
writeFile600Perm(
|
|
57
|
+
proposerDirPath,
|
|
58
|
+
// Default JSON serialization can't handle BigInt
|
|
59
|
+
JSON.stringify(proposerConfig, (_key, value) => (typeof value === "bigint" ? value.toString() : value))
|
|
60
|
+
);
|
|
57
61
|
} else {
|
|
58
62
|
this.deleteProposerConfig(pubkeyHex);
|
|
59
63
|
}
|