@lodestar/beacon-node 1.45.0-dev.905415417a → 1.45.0-dev.9333ecfccb
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/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +0 -1
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/index.js +46 -3
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +11 -2
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js +39 -3
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/validator/index.js +2 -2
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/opPools/proposerPreferencesPool.d.ts +2 -1
- package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
- package/lib/chain/opPools/proposerPreferencesPool.js +3 -0
- package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +4 -12
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts.map +1 -1
- package/lib/chain/validation/proposerPreferences.js +11 -1
- package/lib/chain/validation/proposerPreferences.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +0 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/package.json +14 -14
- package/src/api/impl/beacon/pool/index.ts +0 -1
- package/src/api/impl/beacon/state/index.ts +52 -1
- package/src/api/impl/beacon/state/utils.ts +57 -4
- package/src/api/impl/validator/index.ts +2 -2
- package/src/chain/opPools/proposerPreferencesPool.ts +5 -1
- package/src/chain/produceBlock/produceBlockBody.ts +9 -17
- package/src/chain/validation/proposerPreferences.ts +13 -1
- package/src/network/processor/gossipHandlers.ts +0 -1
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {CheckpointWithHex, IForkChoice} from "@lodestar/fork-choice";
|
|
3
3
|
import {GENESIS_SLOT} from "@lodestar/params";
|
|
4
|
-
import {IBeaconStateView, PubkeyCache} from "@lodestar/state-transition";
|
|
5
|
-
import {
|
|
6
|
-
|
|
4
|
+
import {IBeaconStateView, IBeaconStateViewGloas, PubkeyCache} from "@lodestar/state-transition";
|
|
5
|
+
import {
|
|
6
|
+
BLSPubkey,
|
|
7
|
+
BuilderIndex,
|
|
8
|
+
Epoch,
|
|
9
|
+
RootHex,
|
|
10
|
+
Slot,
|
|
11
|
+
ValidatorIndex,
|
|
12
|
+
getValidatorStatus,
|
|
13
|
+
phase0,
|
|
14
|
+
} from "@lodestar/types";
|
|
15
|
+
import {byteArrayEquals, fromHex} from "@lodestar/utils";
|
|
7
16
|
import {IBeaconChain} from "../../../../chain/index.js";
|
|
8
17
|
import {ApiError, ValidationError} from "../../errors.js";
|
|
9
18
|
|
|
@@ -78,6 +87,50 @@ export function toValidatorResponse(
|
|
|
78
87
|
};
|
|
79
88
|
}
|
|
80
89
|
|
|
90
|
+
type StateBuilderIndexResponse =
|
|
91
|
+
| {valid: true; builderIndex: BuilderIndex}
|
|
92
|
+
| {valid: false; code: number; reason: string};
|
|
93
|
+
|
|
94
|
+
export function getStateBuilderIndex(
|
|
95
|
+
id: routes.beacon.BuilderId | BLSPubkey,
|
|
96
|
+
state: IBeaconStateViewGloas
|
|
97
|
+
): StateBuilderIndexResponse {
|
|
98
|
+
if (typeof id === "string") {
|
|
99
|
+
// mutate `id` and fallthrough to below
|
|
100
|
+
if (id.startsWith("0x")) {
|
|
101
|
+
try {
|
|
102
|
+
id = fromHex(id);
|
|
103
|
+
} catch (_e) {
|
|
104
|
+
return {valid: false, code: 400, reason: "Invalid pubkey hex encoding"};
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
id = Number(id);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (typeof id === "number") {
|
|
112
|
+
const builderIndex = id;
|
|
113
|
+
// builder is invalid or added later than given stateId
|
|
114
|
+
if (!Number.isSafeInteger(builderIndex) || builderIndex < 0) {
|
|
115
|
+
return {valid: false, code: 400, reason: "Invalid builder index"};
|
|
116
|
+
}
|
|
117
|
+
if (builderIndex >= state.getBuildersLength()) {
|
|
118
|
+
return {valid: false, code: 404, reason: "Builder index from future state"};
|
|
119
|
+
}
|
|
120
|
+
return {valid: true, builderIndex};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// typeof id === Uint8Array
|
|
124
|
+
// There is no builder pubkey cache, linear scan over the registry
|
|
125
|
+
const buildersLength = state.getBuildersLength();
|
|
126
|
+
for (let builderIndex = 0; builderIndex < buildersLength; builderIndex++) {
|
|
127
|
+
if (byteArrayEquals(state.getBuilder(builderIndex).pubkey, id)) {
|
|
128
|
+
return {valid: true, builderIndex};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return {valid: false, code: 404, reason: "Builder pubkey not found in state"};
|
|
132
|
+
}
|
|
133
|
+
|
|
81
134
|
export function filterStateValidatorsByStatus(
|
|
82
135
|
statuses: string[],
|
|
83
136
|
state: IBeaconStateView,
|
|
@@ -122,7 +175,7 @@ export function getStateValidatorIndex(
|
|
|
122
175
|
if (typeof id === "number") {
|
|
123
176
|
const validatorIndex = id;
|
|
124
177
|
// validator is invalid or added later than given stateId
|
|
125
|
-
if (!Number.isSafeInteger(validatorIndex)) {
|
|
178
|
+
if (!Number.isSafeInteger(validatorIndex) || validatorIndex < 0) {
|
|
126
179
|
return {valid: false, code: 400, reason: "Invalid validator index"};
|
|
127
180
|
}
|
|
128
181
|
if (validatorIndex >= state.validatorCount) {
|
|
@@ -1118,8 +1118,8 @@ export function getValidatorApi(
|
|
|
1118
1118
|
|
|
1119
1119
|
const block = chain.forkChoice.getCanonicalBlockAtSlot(slot);
|
|
1120
1120
|
if (!block) {
|
|
1121
|
-
// No block is seen at slot. Return
|
|
1122
|
-
|
|
1121
|
+
// No canonical block is seen at slot. Return 204 so vc can skip casting payload attestation.
|
|
1122
|
+
return {data: undefined, meta: {version: fork}, status: 204};
|
|
1123
1123
|
}
|
|
1124
1124
|
|
|
1125
1125
|
const payloadInput = chain.seenPayloadEnvelopeInputCache.get(block.blockRoot);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {RootHex, Slot, gloas} from "@lodestar/types";
|
|
1
|
+
import {RootHex, Slot, ValidatorIndex, gloas} from "@lodestar/types";
|
|
2
2
|
import {toRootHex} from "@lodestar/utils";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -22,6 +22,10 @@ export class ProposerPreferencesPool {
|
|
|
22
22
|
return this.bySlot.get(slot)?.get(dependentRootHex) ?? null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
isKnown(proposalSlot: Slot, dependentRoot: RootHex, validatorIndex: ValidatorIndex): boolean {
|
|
26
|
+
return this.get(proposalSlot, dependentRoot)?.message.validatorIndex === validatorIndex;
|
|
27
|
+
}
|
|
28
|
+
|
|
25
29
|
add(signed: gloas.SignedProposerPreferences): void {
|
|
26
30
|
const {proposalSlot, dependentRoot} = signed.message;
|
|
27
31
|
const rootHex = toRootHex(dependentRoot);
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
ValidatorIndex,
|
|
44
44
|
Wei,
|
|
45
45
|
altair,
|
|
46
|
+
bellatrix,
|
|
46
47
|
capella,
|
|
47
48
|
deneb,
|
|
48
49
|
electra,
|
|
@@ -830,28 +831,19 @@ export function getPayloadAttributesForSSE(
|
|
|
830
831
|
feeRecipient,
|
|
831
832
|
});
|
|
832
833
|
|
|
833
|
-
|
|
834
|
-
if (isForkPostGloas(fork)) {
|
|
835
|
-
const parentBlock = chain.forkChoice.getBlockHexAndBlockHash(
|
|
836
|
-
toRootHex(parentBlockRoot),
|
|
837
|
-
toRootHex(parentBlockHash)
|
|
838
|
-
);
|
|
839
|
-
if (parentBlock?.executionPayloadBlockHash == null) {
|
|
840
|
-
throw Error(`Parent block not found in fork choice root=${toRootHex(parentBlockRoot)}`);
|
|
841
|
-
}
|
|
842
|
-
parentBlockNumber = parentBlock.executionPayloadNumber;
|
|
843
|
-
} else {
|
|
844
|
-
parentBlockNumber = prepareState.payloadBlockNumber;
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
const ssePayloadAttributes: SSEPayloadAttributes = {
|
|
834
|
+
const ssePayloadAttributes = {
|
|
848
835
|
proposerIndex: prepareState.getBeaconProposer(prepareSlot),
|
|
849
836
|
proposalSlot: prepareSlot,
|
|
850
|
-
parentBlockNumber,
|
|
851
837
|
parentBlockRoot,
|
|
852
838
|
parentBlockHash,
|
|
853
839
|
payloadAttributes,
|
|
854
|
-
};
|
|
840
|
+
} as SSEPayloadAttributes;
|
|
841
|
+
|
|
842
|
+
if (!isForkPostGloas(fork)) {
|
|
843
|
+
// Removed in Gloas, builders can get the block number from the EL via the block hash if required
|
|
844
|
+
(ssePayloadAttributes as bellatrix.SSEPayloadAttributes).parentBlockNumber = prepareState.payloadBlockNumber;
|
|
845
|
+
}
|
|
846
|
+
|
|
855
847
|
return ssePayloadAttributes;
|
|
856
848
|
}
|
|
857
849
|
|
|
@@ -81,7 +81,7 @@ export async function validateGossipProposerPreferences(
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// [IGNORE] First valid message for (dependent_root, proposal_slot, validator_index).
|
|
84
|
-
if (chain.proposerPreferencesPool.
|
|
84
|
+
if (chain.proposerPreferencesPool.isKnown(proposalSlot, dependentRootHex, validatorIndex)) {
|
|
85
85
|
throw new ProposerPreferencesError(GossipAction.IGNORE, {
|
|
86
86
|
code: ProposerPreferencesErrorCode.ALREADY_KNOWN,
|
|
87
87
|
proposalSlot,
|
|
@@ -104,4 +104,16 @@ export async function validateGossipProposerPreferences(
|
|
|
104
104
|
validatorIndex,
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
|
+
|
|
108
|
+
// Repeated check - deals with race-condition between preferences submissions
|
|
109
|
+
if (chain.proposerPreferencesPool.isKnown(proposalSlot, dependentRootHex, validatorIndex)) {
|
|
110
|
+
throw new ProposerPreferencesError(GossipAction.IGNORE, {
|
|
111
|
+
code: ProposerPreferencesErrorCode.ALREADY_KNOWN,
|
|
112
|
+
proposalSlot,
|
|
113
|
+
validatorIndex,
|
|
114
|
+
dependentRoot: dependentRootHex,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
chain.proposerPreferencesPool.add(signedProposerPreferences);
|
|
107
119
|
}
|
|
@@ -1273,7 +1273,6 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1273
1273
|
const signedProposerPreferences = sszDeserialize(topic, serializedData);
|
|
1274
1274
|
await validateGossipProposerPreferences(chain, signedProposerPreferences);
|
|
1275
1275
|
|
|
1276
|
-
chain.proposerPreferencesPool.add(signedProposerPreferences);
|
|
1277
1276
|
chain.emitter.emit(routes.events.EventType.proposerPreferences, {
|
|
1278
1277
|
version: ForkName.gloas,
|
|
1279
1278
|
data: signedProposerPreferences,
|