@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.
Files changed (34) hide show
  1. package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/pool/index.js +0 -1
  3. package/lib/api/impl/beacon/pool/index.js.map +1 -1
  4. package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
  5. package/lib/api/impl/beacon/state/index.js +46 -3
  6. package/lib/api/impl/beacon/state/index.js.map +1 -1
  7. package/lib/api/impl/beacon/state/utils.d.ts +11 -2
  8. package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
  9. package/lib/api/impl/beacon/state/utils.js +39 -3
  10. package/lib/api/impl/beacon/state/utils.js.map +1 -1
  11. package/lib/api/impl/validator/index.js +2 -2
  12. package/lib/api/impl/validator/index.js.map +1 -1
  13. package/lib/chain/opPools/proposerPreferencesPool.d.ts +2 -1
  14. package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
  15. package/lib/chain/opPools/proposerPreferencesPool.js +3 -0
  16. package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
  17. package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
  18. package/lib/chain/produceBlock/produceBlockBody.js +4 -12
  19. package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
  20. package/lib/chain/validation/proposerPreferences.d.ts.map +1 -1
  21. package/lib/chain/validation/proposerPreferences.js +11 -1
  22. package/lib/chain/validation/proposerPreferences.js.map +1 -1
  23. package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
  24. package/lib/network/processor/gossipHandlers.js +0 -1
  25. package/lib/network/processor/gossipHandlers.js.map +1 -1
  26. package/package.json +14 -14
  27. package/src/api/impl/beacon/pool/index.ts +0 -1
  28. package/src/api/impl/beacon/state/index.ts +52 -1
  29. package/src/api/impl/beacon/state/utils.ts +57 -4
  30. package/src/api/impl/validator/index.ts +2 -2
  31. package/src/chain/opPools/proposerPreferencesPool.ts +5 -1
  32. package/src/chain/produceBlock/produceBlockBody.ts +9 -17
  33. package/src/chain/validation/proposerPreferences.ts +13 -1
  34. 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 {BLSPubkey, Epoch, RootHex, Slot, ValidatorIndex, getValidatorStatus, phase0} from "@lodestar/types";
6
- import {fromHex} from "@lodestar/utils";
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 404 so vc can skip casting payload attestation.
1122
- throw new ApiError(404, `No canonical block found at slot=${slot}`);
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
- let parentBlockNumber: number;
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.get(proposalSlot, dependentRootHex)?.message.validatorIndex === validatorIndex) {
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,