@lodestar/beacon-node 1.50.0-dev.67e8d54549 → 1.50.0-dev.6a7dbb4d5d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +7 -2
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +19 -1
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/beaconProposerCache.d.ts +5 -2
- package/lib/chain/beaconProposerCache.d.ts.map +1 -1
- package/lib/chain/beaconProposerCache.js +12 -4
- package/lib/chain/beaconProposerCache.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +5 -4
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +16 -18
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +8 -2
- package/src/api/impl/validator/index.ts +27 -1
- package/src/chain/beaconProposerCache.ts +12 -4
- package/src/chain/chain.ts +5 -6
- package/src/chain/produceBlock/produceBlockBody.ts +33 -20
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/ChainSafe/lodestar/issues"
|
|
13
13
|
},
|
|
14
|
-
"version": "1.50.0-dev.
|
|
14
|
+
"version": "1.50.0-dev.6a7dbb4d5d",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -127,17 +127,17 @@
|
|
|
127
127
|
"@libp2p/prometheus-metrics": "^5.0.28",
|
|
128
128
|
"@libp2p/tcp": "^11.0.27",
|
|
129
129
|
"@libp2p/utils": "^7.4.0",
|
|
130
|
-
"@lodestar/api": "^1.50.0-dev.
|
|
131
|
-
"@lodestar/config": "^1.50.0-dev.
|
|
132
|
-
"@lodestar/db": "^1.50.0-dev.
|
|
133
|
-
"@lodestar/fork-choice": "^1.50.0-dev.
|
|
134
|
-
"@lodestar/logger": "^1.50.0-dev.
|
|
135
|
-
"@lodestar/params": "^1.50.0-dev.
|
|
136
|
-
"@lodestar/reqresp": "^1.50.0-dev.
|
|
137
|
-
"@lodestar/state-transition": "^1.50.0-dev.
|
|
138
|
-
"@lodestar/types": "^1.50.0-dev.
|
|
139
|
-
"@lodestar/utils": "^1.50.0-dev.
|
|
140
|
-
"@lodestar/validator": "^1.50.0-dev.
|
|
130
|
+
"@lodestar/api": "^1.50.0-dev.6a7dbb4d5d",
|
|
131
|
+
"@lodestar/config": "^1.50.0-dev.6a7dbb4d5d",
|
|
132
|
+
"@lodestar/db": "^1.50.0-dev.6a7dbb4d5d",
|
|
133
|
+
"@lodestar/fork-choice": "^1.50.0-dev.6a7dbb4d5d",
|
|
134
|
+
"@lodestar/logger": "^1.50.0-dev.6a7dbb4d5d",
|
|
135
|
+
"@lodestar/params": "^1.50.0-dev.6a7dbb4d5d",
|
|
136
|
+
"@lodestar/reqresp": "^1.50.0-dev.6a7dbb4d5d",
|
|
137
|
+
"@lodestar/state-transition": "^1.50.0-dev.6a7dbb4d5d",
|
|
138
|
+
"@lodestar/types": "^1.50.0-dev.6a7dbb4d5d",
|
|
139
|
+
"@lodestar/utils": "^1.50.0-dev.6a7dbb4d5d",
|
|
140
|
+
"@lodestar/validator": "^1.50.0-dev.6a7dbb4d5d",
|
|
141
141
|
"@multiformats/multiaddr": "^13.0.1",
|
|
142
142
|
"datastore-core": "^12.0.1",
|
|
143
143
|
"datastore-level": "^13.0.1",
|
|
@@ -159,8 +159,8 @@
|
|
|
159
159
|
"@ethereumjs/rlp": "^4.0.1",
|
|
160
160
|
"@libp2p/interface-internal": "^3.1.12",
|
|
161
161
|
"@libp2p/logger": "^6.2.13",
|
|
162
|
-
"@lodestar/spec-test-util": "^1.50.0-dev.
|
|
163
|
-
"@lodestar/test-utils": "^1.50.0-dev.
|
|
162
|
+
"@lodestar/spec-test-util": "^1.50.0-dev.6a7dbb4d5d",
|
|
163
|
+
"@lodestar/test-utils": "^1.50.0-dev.6a7dbb4d5d",
|
|
164
164
|
"@types/js-yaml": "^4.0.5",
|
|
165
165
|
"@types/qs": "^6.9.7",
|
|
166
166
|
"@types/tmp": "^0.2.3",
|
|
@@ -175,5 +175,5 @@
|
|
|
175
175
|
"beacon",
|
|
176
176
|
"blockchain"
|
|
177
177
|
],
|
|
178
|
-
"gitHead": "
|
|
178
|
+
"gitHead": "e059d098420f9b8dc5fa7b16de95db114ff4ac62"
|
|
179
179
|
}
|
|
@@ -692,8 +692,14 @@ export function getBeaconBlockApi({
|
|
|
692
692
|
},
|
|
693
693
|
|
|
694
694
|
async getBlockRoot({blockId}) {
|
|
695
|
-
// Fast path: From head state already available in memory get historical blockRoot
|
|
696
|
-
|
|
695
|
+
// Fast path: From head state already available in memory get historical blockRoot.
|
|
696
|
+
// A 0x id is a root. parseInt() accepts that prefix as hex and can return a slot.
|
|
697
|
+
const slot =
|
|
698
|
+
typeof blockId === "number"
|
|
699
|
+
? blockId
|
|
700
|
+
: blockId.toLowerCase().startsWith("0x")
|
|
701
|
+
? Number.NaN
|
|
702
|
+
: parseInt(blockId, 10);
|
|
697
703
|
if (!Number.isNaN(slot)) {
|
|
698
704
|
const head = chain.forkChoice.getHead();
|
|
699
705
|
|
|
@@ -1940,7 +1940,7 @@ export function getValidatorApi(
|
|
|
1940
1940
|
Array.from(new Set(subscriptions.map(({validatorIndex}) => validatorIndex)))
|
|
1941
1941
|
);
|
|
1942
1942
|
} catch (e) {
|
|
1943
|
-
logger.
|
|
1943
|
+
logger.warn("Error tracking attached validators", {count: subscriptions.length}, e as Error);
|
|
1944
1944
|
}
|
|
1945
1945
|
|
|
1946
1946
|
notWhileSyncing(chain, sync.state);
|
|
@@ -2006,6 +2006,13 @@ export function getValidatorApi(
|
|
|
2006
2006
|
},
|
|
2007
2007
|
|
|
2008
2008
|
async prepareBeaconProposer({proposers}) {
|
|
2009
|
+
if (isForkPostGloas(config.getForkName(chain.clock.currentSlot))) {
|
|
2010
|
+
throw new ApiError(
|
|
2011
|
+
410,
|
|
2012
|
+
"prepareBeaconProposer is no longer supported from gloas, submit signed proposer preferences via POST /eth/v1/validator/proposer_preferences instead"
|
|
2013
|
+
);
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2009
2016
|
await chain.updateBeaconProposerData(chain.clock.currentEpoch, proposers);
|
|
2010
2017
|
},
|
|
2011
2018
|
|
|
@@ -2040,6 +2047,13 @@ export function getValidatorApi(
|
|
|
2040
2047
|
},
|
|
2041
2048
|
|
|
2042
2049
|
async registerValidator({registrations}) {
|
|
2050
|
+
if (isForkPostGloas(config.getForkName(chain.clock.currentSlot))) {
|
|
2051
|
+
throw new ApiError(
|
|
2052
|
+
410,
|
|
2053
|
+
"registerValidator is no longer supported from gloas, submit builder preferences via POST /eth/v1/validator/builder_preferences instead"
|
|
2054
|
+
);
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2043
2057
|
if (!chain.executionBuilder) {
|
|
2044
2058
|
throw Error("External builder not configured");
|
|
2045
2059
|
}
|
|
@@ -2075,11 +2089,14 @@ export function getValidatorApi(
|
|
|
2075
2089
|
|
|
2076
2090
|
async submitProposerPreferences({signedProposerPreferences}) {
|
|
2077
2091
|
const failures: FailureList = [];
|
|
2092
|
+
// Preferences submitted here are signed by validators using this node, gossiped ones are not
|
|
2093
|
+
const attachedValidatorIndices: ValidatorIndex[] = [];
|
|
2078
2094
|
|
|
2079
2095
|
await Promise.all(
|
|
2080
2096
|
signedProposerPreferences.map(async (signed, i) => {
|
|
2081
2097
|
try {
|
|
2082
2098
|
await validateGossipProposerPreferences(chain, signed);
|
|
2099
|
+
attachedValidatorIndices.push(signed.message.validatorIndex);
|
|
2083
2100
|
|
|
2084
2101
|
chain.proposerPreferencesPool.add(signed);
|
|
2085
2102
|
await network.publishProposerPreferences(signed);
|
|
@@ -2095,6 +2112,7 @@ export function getValidatorApi(
|
|
|
2095
2112
|
};
|
|
2096
2113
|
|
|
2097
2114
|
if (e instanceof ProposerPreferencesError && e.type.code === ProposerPreferencesErrorCode.ALREADY_KNOWN) {
|
|
2115
|
+
attachedValidatorIndices.push(signed.message.validatorIndex);
|
|
2098
2116
|
logger.debug("Ignoring known signed proposer preferences", logCtx);
|
|
2099
2117
|
return;
|
|
2100
2118
|
}
|
|
@@ -2108,6 +2126,14 @@ export function getValidatorApi(
|
|
|
2108
2126
|
})
|
|
2109
2127
|
);
|
|
2110
2128
|
|
|
2129
|
+
if (attachedValidatorIndices.length > 0) {
|
|
2130
|
+
try {
|
|
2131
|
+
await chain.updateAttachedValidators(chain.clock.currentEpoch, attachedValidatorIndices);
|
|
2132
|
+
} catch (e) {
|
|
2133
|
+
logger.warn("Error tracking attached validators", {count: attachedValidatorIndices.length}, e as Error);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2111
2137
|
if (failures.length > 0) {
|
|
2112
2138
|
throw new IndexedError("Error processing signed proposer preferences", failures);
|
|
2113
2139
|
}
|
|
@@ -15,10 +15,18 @@ export class BeaconProposerCache {
|
|
|
15
15
|
this.feeRecipientByValidatorIndex.set(validatorIndex, {epoch, feeRecipient});
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Track a validator that uses this node for duties, keeping the fee recipient it may have
|
|
20
|
+
* registered. Returns true if the validator was not tracked before.
|
|
21
|
+
*/
|
|
22
|
+
track(epoch: Epoch, validatorIndex: number): boolean {
|
|
23
|
+
const entry = this.feeRecipientByValidatorIndex.get(validatorIndex);
|
|
24
|
+
if (entry !== undefined) {
|
|
25
|
+
entry.epoch = epoch;
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
this.feeRecipientByValidatorIndex.set(validatorIndex, {epoch});
|
|
29
|
+
return true;
|
|
22
30
|
}
|
|
23
31
|
|
|
24
32
|
has(validatorIndex: number): boolean {
|
package/src/chain/chain.ts
CHANGED
|
@@ -1937,16 +1937,15 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1937
1937
|
}
|
|
1938
1938
|
|
|
1939
1939
|
async updateAttachedValidators(epoch: Epoch, validatorIndices: ValidatorIndex[]): Promise<void> {
|
|
1940
|
-
|
|
1941
|
-
|
|
1940
|
+
let hasNewValidators = false;
|
|
1942
1941
|
for (const validatorIndex of validatorIndices) {
|
|
1943
|
-
this.beaconProposerCache.
|
|
1942
|
+
if (this.beaconProposerCache.track(epoch, validatorIndex)) {
|
|
1943
|
+
hasNewValidators = true;
|
|
1944
|
+
}
|
|
1944
1945
|
}
|
|
1945
1946
|
|
|
1946
|
-
const newValidatorCount = this.beaconProposerCache.getValidatorIndices().length;
|
|
1947
|
-
|
|
1948
1947
|
// Only update validator custody if we discovered new validators
|
|
1949
|
-
if (
|
|
1948
|
+
if (hasNewValidators) {
|
|
1950
1949
|
const finalizedCheckpoint = this.forkChoice.getFinalizedCheckpoint();
|
|
1951
1950
|
await this.updateValidatorsCustodyRequirement(finalizedCheckpoint);
|
|
1952
1951
|
}
|
|
@@ -77,6 +77,7 @@ import {IExecutionBuilder, IExecutionEngine, PayloadAttributes, PayloadId} from
|
|
|
77
77
|
import {getShufflingDependentRoot} from "../../util/dependentRoot.js";
|
|
78
78
|
import {fromGraffitiBytes} from "../../util/graffiti.js";
|
|
79
79
|
import {kzg} from "../../util/kzg.js";
|
|
80
|
+
import {BeaconProposerCache} from "../beaconProposerCache.js";
|
|
80
81
|
import type {BeaconChain} from "../chain.js";
|
|
81
82
|
import {CommonBlockBody} from "../interface.js";
|
|
82
83
|
import {ProposerPreferencesPool} from "../opPools/index.js";
|
|
@@ -286,19 +287,12 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
286
287
|
// this into a completely separate function and have pre/post gloas more separated
|
|
287
288
|
const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice, this.logger);
|
|
288
289
|
const finalizedBlockHash = getFinalizedExecutionBlockHash(this.forkChoice);
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const feeRecipientType = requestedFeeRecipient
|
|
296
|
-
? "requested"
|
|
297
|
-
: pooledPreferences !== null
|
|
298
|
-
? "preferences"
|
|
299
|
-
: this.beaconProposerCache.get(proposerIndex)
|
|
300
|
-
? "cached"
|
|
301
|
-
: "default";
|
|
290
|
+
const {feeRecipient, feeRecipientType} = getProposerFeeRecipient(
|
|
291
|
+
requestedFeeRecipient,
|
|
292
|
+
getPooledProposerPreferences(this, blockSlot, parentBlock.blockRoot),
|
|
293
|
+
this.beaconProposerCache,
|
|
294
|
+
proposerIndex
|
|
295
|
+
);
|
|
302
296
|
Object.assign(logMeta, {feeRecipientType, feeRecipient});
|
|
303
297
|
|
|
304
298
|
const endExecutionPayload = this.metrics?.executionBlockProductionTimeSteps.startTimer();
|
|
@@ -452,13 +446,12 @@ export async function produceBlockBody<T extends BlockType>(
|
|
|
452
446
|
|
|
453
447
|
const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice, this.logger);
|
|
454
448
|
const finalizedBlockHash = getFinalizedExecutionBlockHash(this.forkChoice);
|
|
455
|
-
const feeRecipient =
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
449
|
+
const {feeRecipient, feeRecipientType} = getProposerFeeRecipient(
|
|
450
|
+
requestedFeeRecipient,
|
|
451
|
+
null,
|
|
452
|
+
this.beaconProposerCache,
|
|
453
|
+
proposerIndex
|
|
454
|
+
);
|
|
462
455
|
Object.assign(logMeta, {feeRecipientType, feeRecipient});
|
|
463
456
|
|
|
464
457
|
if (blockType === BlockType.Blinded) {
|
|
@@ -1014,6 +1007,26 @@ function getProposerTargetGasLimit(
|
|
|
1014
1007
|
return BigInt(parentPayloadVariant.executionPayloadGasLimit);
|
|
1015
1008
|
}
|
|
1016
1009
|
|
|
1010
|
+
/** The proposer's request wins over its signed preferences, which win over its registered proposer data */
|
|
1011
|
+
function getProposerFeeRecipient(
|
|
1012
|
+
requestedFeeRecipient: string | undefined,
|
|
1013
|
+
pooledPreferences: gloas.ProposerPreferences | null,
|
|
1014
|
+
beaconProposerCache: BeaconProposerCache,
|
|
1015
|
+
proposerIndex: ValidatorIndex
|
|
1016
|
+
): {feeRecipient: string; feeRecipientType: "requested" | "preferences" | "cached" | "default"} {
|
|
1017
|
+
if (requestedFeeRecipient !== undefined) {
|
|
1018
|
+
return {feeRecipient: requestedFeeRecipient, feeRecipientType: "requested"};
|
|
1019
|
+
}
|
|
1020
|
+
if (pooledPreferences !== null) {
|
|
1021
|
+
return {feeRecipient: toHex(pooledPreferences.feeRecipient), feeRecipientType: "preferences"};
|
|
1022
|
+
}
|
|
1023
|
+
const cachedFeeRecipient = beaconProposerCache.get(proposerIndex);
|
|
1024
|
+
if (cachedFeeRecipient !== undefined) {
|
|
1025
|
+
return {feeRecipient: cachedFeeRecipient, feeRecipientType: "cached"};
|
|
1026
|
+
}
|
|
1027
|
+
return {feeRecipient: beaconProposerCache.getOrDefault(proposerIndex), feeRecipientType: "default"};
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1017
1030
|
/**
|
|
1018
1031
|
* The preferences the proposer of `slot` signed for the branch of `parentBlockRoot`, the same
|
|
1019
1032
|
* `(slot, dependent_root)` lookup as gossip bid validation. Null if none are pooled.
|