@lodestar/state-transition 1.44.0-dev.6ef8199cfa → 1.44.0-dev.762dd5f186

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 (90) hide show
  1. package/lib/block/index.d.ts +2 -0
  2. package/lib/block/index.d.ts.map +1 -1
  3. package/lib/block/index.js +3 -1
  4. package/lib/block/index.js.map +1 -1
  5. package/lib/block/processBuilderDepositRequest.d.ts +10 -0
  6. package/lib/block/processBuilderDepositRequest.d.ts.map +1 -0
  7. package/lib/block/processBuilderDepositRequest.js +27 -0
  8. package/lib/block/processBuilderDepositRequest.js.map +1 -0
  9. package/lib/block/processBuilderExitRequest.d.ts +13 -0
  10. package/lib/block/processBuilderExitRequest.d.ts.map +1 -0
  11. package/lib/block/processBuilderExitRequest.js +29 -0
  12. package/lib/block/processBuilderExitRequest.js.map +1 -0
  13. package/lib/block/processDepositRequest.d.ts +2 -8
  14. package/lib/block/processDepositRequest.d.ts.map +1 -1
  15. package/lib/block/processDepositRequest.js +3 -98
  16. package/lib/block/processDepositRequest.js.map +1 -1
  17. package/lib/block/processExecutionPayloadBid.d.ts +2 -3
  18. package/lib/block/processExecutionPayloadBid.d.ts.map +1 -1
  19. package/lib/block/processExecutionPayloadBid.js +16 -8
  20. package/lib/block/processExecutionPayloadBid.js.map +1 -1
  21. package/lib/block/processOperations.d.ts.map +1 -1
  22. package/lib/block/processOperations.js +3 -2
  23. package/lib/block/processOperations.js.map +1 -1
  24. package/lib/block/processParentExecutionPayload.d.ts +2 -2
  25. package/lib/block/processParentExecutionPayload.d.ts.map +1 -1
  26. package/lib/block/processParentExecutionPayload.js +16 -8
  27. package/lib/block/processParentExecutionPayload.js.map +1 -1
  28. package/lib/block/processProposerSlashing.d.ts.map +1 -1
  29. package/lib/block/processProposerSlashing.js +9 -1
  30. package/lib/block/processProposerSlashing.js.map +1 -1
  31. package/lib/block/processVoluntaryExit.d.ts +1 -1
  32. package/lib/block/processVoluntaryExit.d.ts.map +1 -1
  33. package/lib/block/processVoluntaryExit.js +1 -35
  34. package/lib/block/processVoluntaryExit.js.map +1 -1
  35. package/lib/cache/epochCache.d.ts.map +1 -1
  36. package/lib/cache/epochCache.js +10 -7
  37. package/lib/cache/epochCache.js.map +1 -1
  38. package/lib/epoch/processPendingDeposits.d.ts.map +1 -1
  39. package/lib/epoch/processPendingDeposits.js +4 -3
  40. package/lib/epoch/processPendingDeposits.js.map +1 -1
  41. package/lib/epoch/processProposerLookahead.d.ts.map +1 -1
  42. package/lib/epoch/processProposerLookahead.js +7 -2
  43. package/lib/epoch/processProposerLookahead.js.map +1 -1
  44. package/lib/slot/upgradeStateToGloas.js +35 -29
  45. package/lib/slot/upgradeStateToGloas.js.map +1 -1
  46. package/lib/stateView/beaconStateView.d.ts +5 -2
  47. package/lib/stateView/beaconStateView.d.ts.map +1 -1
  48. package/lib/stateView/beaconStateView.js +14 -0
  49. package/lib/stateView/beaconStateView.js.map +1 -1
  50. package/lib/stateView/interface.d.ts +30 -2
  51. package/lib/stateView/interface.d.ts.map +1 -1
  52. package/lib/stateView/interface.js.map +1 -1
  53. package/lib/stateView/nativeBeaconStateView.d.ts +230 -0
  54. package/lib/stateView/nativeBeaconStateView.d.ts.map +1 -0
  55. package/lib/stateView/nativeBeaconStateView.js +717 -0
  56. package/lib/stateView/nativeBeaconStateView.js.map +1 -0
  57. package/lib/stateView/stateViewFactory.d.ts.map +1 -1
  58. package/lib/stateView/stateViewFactory.js +2 -0
  59. package/lib/stateView/stateViewFactory.js.map +1 -1
  60. package/lib/util/epochShuffling.js +1 -1
  61. package/lib/util/epochShuffling.js.map +1 -1
  62. package/lib/util/gloas.d.ts +31 -0
  63. package/lib/util/gloas.d.ts.map +1 -1
  64. package/lib/util/gloas.js +83 -1
  65. package/lib/util/gloas.js.map +1 -1
  66. package/lib/util/shuffling.d.ts +2 -2
  67. package/lib/util/shuffling.d.ts.map +1 -1
  68. package/lib/util/shuffling.js +4 -3
  69. package/lib/util/shuffling.js.map +1 -1
  70. package/package.json +7 -8
  71. package/src/block/index.ts +6 -1
  72. package/src/block/processBuilderDepositRequest.ts +43 -0
  73. package/src/block/processBuilderExitRequest.ts +39 -0
  74. package/src/block/processDepositRequest.ts +4 -124
  75. package/src/block/processExecutionPayloadBid.ts +24 -9
  76. package/src/block/processOperations.ts +3 -2
  77. package/src/block/processParentExecutionPayload.ts +23 -11
  78. package/src/block/processProposerSlashing.ts +9 -4
  79. package/src/block/processVoluntaryExit.ts +2 -61
  80. package/src/cache/epochCache.ts +10 -7
  81. package/src/epoch/processPendingDeposits.ts +2 -0
  82. package/src/epoch/processProposerLookahead.ts +8 -1
  83. package/src/slot/upgradeStateToGloas.ts +49 -33
  84. package/src/stateView/beaconStateView.ts +18 -1
  85. package/src/stateView/interface.ts +34 -1
  86. package/src/stateView/nativeBeaconStateView.ts +915 -0
  87. package/src/stateView/stateViewFactory.ts +2 -0
  88. package/src/util/epochShuffling.ts +1 -1
  89. package/src/util/gloas.ts +104 -1
  90. package/src/util/shuffling.ts +4 -3
@@ -31,6 +31,7 @@ type NativeOpts = {
31
31
  export function createBeaconStateView(opts: NodeJSOpts | NativeOpts): IBeaconStateView {
32
32
  if (opts.useNative) {
33
33
  throw new Error("Native (Zig) BeaconStateView not yet implemented");
34
+ // TODO: return a new instance of NativeBeaconStateView
34
35
  }
35
36
  const {anchorState, config, pubkeyCache} = opts;
36
37
  const cachedState = createCachedBeaconState(anchorState, {config, pubkeyCache}, {skipSyncPubkeys: true});
@@ -69,6 +70,7 @@ type RegenNativeOpts = {
69
70
  export function createBeaconStateViewForHistoricalRegen(opts: RegenNodeJSOpts | RegenNativeOpts): IBeaconStateView {
70
71
  if (opts.useNative) {
71
72
  throw new Error("Native (Zig) BeaconStateView not yet implemented");
73
+ // TODO: return a new instance of NativeBeaconStateView
72
74
  }
73
75
  const {config, stateBytes} = opts;
74
76
  const state = getStateTypeFromBytes(config, stateBytes).deserializeToViewDU(stateBytes);
@@ -124,7 +124,7 @@ export async function computeEpochShufflingAsync(
124
124
  }
125
125
 
126
126
  export function calculateDecisionRoot(state: BeaconStateAllForks, epoch: Epoch): RootHex {
127
- const pivotSlot = computeStartSlotAtEpoch(epoch - 1) - 1;
127
+ const pivotSlot = Math.max(GENESIS_SLOT, computeStartSlotAtEpoch(epoch - 1) - 1);
128
128
  return toRootHex(getBlockRootAtSlot(state, pivotSlot));
129
129
  }
130
130
 
package/src/util/gloas.ts CHANGED
@@ -1,8 +1,11 @@
1
+ import {PublicKey, Signature, verify} from "@chainsafe/blst";
2
+ import {BeaconConfig} from "@lodestar/config";
1
3
  import {
2
4
  BUILDER_INDEX_FLAG,
3
5
  BUILDER_PAYMENT_THRESHOLD_DENOMINATOR,
4
6
  BUILDER_PAYMENT_THRESHOLD_NUMERATOR,
5
7
  BUILDER_WITHDRAWAL_PREFIX,
8
+ DOMAIN_BUILDER_DEPOSIT,
6
9
  EFFECTIVE_BALANCE_INCREMENT,
7
10
  FAR_FUTURE_EPOCH,
8
11
  MIN_DEPOSIT_AMOUNT,
@@ -10,15 +13,18 @@ import {
10
13
  PTC_SIZE,
11
14
  SLOTS_PER_EPOCH,
12
15
  } from "@lodestar/params";
13
- import {BuilderIndex, Epoch, ValidatorIndex, gloas} from "@lodestar/types";
16
+ import {BuilderIndex, Epoch, ValidatorIndex, gloas, ssz} from "@lodestar/types";
14
17
  import {AttestationData} from "@lodestar/types/phase0";
15
18
  import {byteArrayEquals} from "@lodestar/utils";
19
+ import {ZERO_HASH} from "../constants/index.js";
16
20
  import {CachedBeaconStateFulu, CachedBeaconStateGloas} from "../types.js";
17
21
  import {getBlockRootAtSlot} from "./blockRoot.js";
22
+ import {computeDomain} from "./domain.js";
18
23
  import {computeEpochAtSlot} from "./epoch.js";
19
24
  import {computeEpochShuffling} from "./epochShuffling.js";
20
25
  import {RootCache} from "./rootCache.js";
21
26
  import {computePayloadTimelinessCommitteesForEpoch} from "./seed.js";
27
+ import {computeSigningRoot} from "./signingRoot.js";
22
28
  import {getActiveValidatorIndices} from "./validator.js";
23
29
 
24
30
  export function isBuilderWithdrawalCredential(withdrawalCredentials: Uint8Array): boolean {
@@ -73,6 +79,34 @@ export function isActiveBuilder(builder: gloas.Builder, finalizedEpoch: Epoch):
73
79
  return builder.depositEpoch < finalizedEpoch && builder.withdrawableEpoch === FAR_FUTURE_EPOCH;
74
80
  }
75
81
 
82
+ /**
83
+ * Compute the gas limit that satisfies the EIP-1559 adjustment rule from `parentGasLimit`,
84
+ * clamping `targetGasLimit` into the allowed window of `±max(parentGasLimit / 1024, 1) - 1`.
85
+ *
86
+ * From https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
87
+ */
88
+ export function getExpectedGasLimit(parentGasLimit: number, targetGasLimit: number): number {
89
+ const maxGasLimitDifference = Math.max(Math.floor(parentGasLimit / 1024), 1) - 1;
90
+
91
+ if (targetGasLimit > parentGasLimit) {
92
+ const gasDiff = targetGasLimit - parentGasLimit;
93
+ return parentGasLimit + Math.min(gasDiff, maxGasLimitDifference);
94
+ }
95
+
96
+ const gasDiff = parentGasLimit - targetGasLimit;
97
+ return parentGasLimit - Math.min(gasDiff, maxGasLimitDifference);
98
+ }
99
+
100
+ /**
101
+ * Check if `gasLimit` is compatible with `targetGasLimit` under the EIP-1559 transition rule
102
+ * from `parentGasLimit`. The bid must hit `targetGasLimit` when the target is within one
103
+ * adjustment step of the parent, otherwise it must hit the clamped boundary.
104
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.8/specs/gloas/builder.md#new-is_gas_limit_target_compatible
105
+ */
106
+ export function isGasLimitTargetCompatible(parentGasLimit: number, gasLimit: number, targetGasLimit: number): boolean {
107
+ return gasLimit === getExpectedGasLimit(parentGasLimit, targetGasLimit);
108
+ }
109
+
76
110
  /**
77
111
  * Get the total pending balance to withdraw for a builder (from withdrawals + payments).
78
112
  * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-get_pending_balance_to_withdraw_for_builder
@@ -213,3 +247,72 @@ export function getPtcWindowEpochCacheData(state: CachedBeaconStateGloas): {
213
247
  nextPayloadTimelinessCommittees: toUint32Arrays(nextPtcWindow),
214
248
  };
215
249
  }
250
+
251
+ /**
252
+ * Add a new builder to the builders registry. Reuses slots from exited and fully withdrawn
253
+ * builders when available, otherwise appends.
254
+ *
255
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md#new-add_builder_to_registry
256
+ */
257
+ export function addBuilderToRegistry(
258
+ state: CachedBeaconStateGloas,
259
+ pubkey: Uint8Array,
260
+ version: number,
261
+ executionAddress: Uint8Array,
262
+ amount: number,
263
+ slot: number
264
+ ): void {
265
+ const currentEpoch = computeEpochAtSlot(state.slot);
266
+ const depositEpoch = computeEpochAtSlot(slot);
267
+
268
+ let builderIndex = state.builders.length;
269
+ for (let i = 0; i < state.builders.length; i++) {
270
+ const builder = state.builders.getReadonly(i);
271
+ if (builder.withdrawableEpoch <= currentEpoch && builder.balance === 0) {
272
+ builderIndex = i;
273
+ break;
274
+ }
275
+ }
276
+
277
+ const newBuilder = ssz.gloas.Builder.toViewDU({
278
+ pubkey,
279
+ version,
280
+ executionAddress,
281
+ balance: amount,
282
+ depositEpoch,
283
+ withdrawableEpoch: FAR_FUTURE_EPOCH,
284
+ });
285
+
286
+ if (builderIndex < state.builders.length) {
287
+ state.builders.set(builderIndex, newBuilder);
288
+ } else {
289
+ state.builders.push(newBuilder);
290
+ }
291
+ }
292
+
293
+ /**
294
+ * Verify the proof of possession on a builder deposit request.
295
+ *
296
+ * The dedicated `DOMAIN_BUILDER_DEPOSIT` (vs the validator `DOMAIN_DEPOSIT`) prevents replay
297
+ * of validator deposit signatures against the builder deposit contract and vice versa.
298
+ *
299
+ * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md#new-is_valid_builder_deposit_signature
300
+ */
301
+ export function isValidBuilderDepositSignature(
302
+ config: BeaconConfig,
303
+ pubkey: Uint8Array,
304
+ withdrawalCredentials: Uint8Array,
305
+ amount: number,
306
+ signature: Uint8Array
307
+ ): boolean {
308
+ const depositMessage = {pubkey, withdrawalCredentials, amount};
309
+ const domain = computeDomain(DOMAIN_BUILDER_DEPOSIT, config.GENESIS_FORK_VERSION, ZERO_HASH);
310
+ const signingRoot = computeSigningRoot(ssz.phase0.DepositMessage, depositMessage, domain);
311
+ try {
312
+ const publicKey = PublicKey.fromBytes(pubkey, true);
313
+ const sig = Signature.fromBytes(signature, true);
314
+ return verify(signingRoot, publicKey, sig);
315
+ } catch (_e) {
316
+ return false;
317
+ }
318
+ }
@@ -21,8 +21,8 @@ import {EpochShuffling} from "./epochShuffling.js";
21
21
  * Computed for the requested epoch, not `state.epoch`, so it is correct when `state` is one
22
22
  * epoch off the requested epoch (e.g. serving next-epoch duties from the current state).
23
23
  *
24
- * Returns `null` when the genesis block decides its own shuffling (caller falls back to the
25
- * genesis block root).
24
+ * Returns `null` when the decision block is not in the state's past (the genesis block decides
25
+ * its own shuffling, or it has not been produced yet); caller supplies the fallback.
26
26
  */
27
27
  export function proposerShufflingDecisionRoot(
28
28
  fork: ForkName,
@@ -30,7 +30,8 @@ export function proposerShufflingDecisionRoot(
30
30
  proposalEpoch: Epoch
31
31
  ): Root | null {
32
32
  const decisionSlot = proposerShufflingDecisionSlot(fork, proposalEpoch);
33
- if (state.slot === decisionSlot) {
33
+ // Return null when the decision block is not in the state's past or the getBlockRootAtSlot() api will throw
34
+ if (decisionSlot >= state.slot) {
34
35
  return null;
35
36
  }
36
37
  return state.getBlockRootAtSlot(decisionSlot);