@lodestar/state-transition 1.48.0-dev.f22c5ce63e → 1.48.0-rc.0

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 (94) hide show
  1. package/lib/block/index.d.ts.map +1 -1
  2. package/lib/block/index.js +44 -13
  3. package/lib/block/index.js.map +1 -1
  4. package/lib/block/processExecutionPayloadBid.d.ts +2 -2
  5. package/lib/block/processExecutionPayloadBid.d.ts.map +1 -1
  6. package/lib/block/processExecutionPayloadBid.js +3 -2
  7. package/lib/block/processExecutionPayloadBid.js.map +1 -1
  8. package/lib/block/processOperations.d.ts.map +1 -1
  9. package/lib/block/processOperations.js +62 -33
  10. package/lib/block/processOperations.js.map +1 -1
  11. package/lib/block/processParentExecutionPayload.d.ts.map +1 -1
  12. package/lib/block/processParentExecutionPayload.js +2 -16
  13. package/lib/block/processParentExecutionPayload.js.map +1 -1
  14. package/lib/block/processPayloadAttestation.d.ts +1 -1
  15. package/lib/block/processPayloadAttestation.d.ts.map +1 -1
  16. package/lib/block/processPayloadAttestation.js +2 -2
  17. package/lib/block/processPayloadAttestation.js.map +1 -1
  18. package/lib/block/processWithdrawals.d.ts.map +1 -1
  19. package/lib/block/processWithdrawals.js +8 -2
  20. package/lib/block/processWithdrawals.js.map +1 -1
  21. package/lib/block/types.d.ts +30 -0
  22. package/lib/block/types.d.ts.map +1 -1
  23. package/lib/block/types.js +32 -0
  24. package/lib/block/types.js.map +1 -1
  25. package/lib/epoch/processInactivityUpdates.d.ts.map +1 -1
  26. package/lib/epoch/processInactivityUpdates.js +7 -1
  27. package/lib/epoch/processInactivityUpdates.js.map +1 -1
  28. package/lib/epoch/processPtcWindow.d.ts.map +1 -1
  29. package/lib/epoch/processPtcWindow.js +12 -9
  30. package/lib/epoch/processPtcWindow.js.map +1 -1
  31. package/lib/index.d.ts +1 -1
  32. package/lib/index.d.ts.map +1 -1
  33. package/lib/index.js +1 -1
  34. package/lib/index.js.map +1 -1
  35. package/lib/lightClient/spec/index.d.ts +1 -1
  36. package/lib/lightClient/spec/index.d.ts.map +1 -1
  37. package/lib/lightClient/spec/index.js +1 -1
  38. package/lib/lightClient/spec/index.js.map +1 -1
  39. package/lib/lightClient/spec/utils.d.ts +13 -3
  40. package/lib/lightClient/spec/utils.d.ts.map +1 -1
  41. package/lib/lightClient/spec/utils.js +108 -34
  42. package/lib/lightClient/spec/utils.js.map +1 -1
  43. package/lib/metrics.d.ts +7 -1
  44. package/lib/metrics.d.ts.map +1 -1
  45. package/lib/metrics.js +12 -1
  46. package/lib/metrics.js.map +1 -1
  47. package/lib/rewards/blockRewards.d.ts.map +1 -1
  48. package/lib/rewards/blockRewards.js +1 -3
  49. package/lib/rewards/blockRewards.js.map +1 -1
  50. package/lib/signatureSets/index.d.ts.map +1 -1
  51. package/lib/signatureSets/index.js +8 -0
  52. package/lib/signatureSets/index.js.map +1 -1
  53. package/lib/slot/upgradeStateToGloas.js +1 -1
  54. package/lib/slot/upgradeStateToGloas.js.map +1 -1
  55. package/lib/stateView/beaconStateView.d.ts +6 -1
  56. package/lib/stateView/beaconStateView.d.ts.map +1 -1
  57. package/lib/stateView/beaconStateView.js +12 -0
  58. package/lib/stateView/beaconStateView.js.map +1 -1
  59. package/lib/stateView/interface.d.ts +3 -1
  60. package/lib/stateView/interface.d.ts.map +1 -1
  61. package/lib/stateView/interface.js.map +1 -1
  62. package/lib/stateView/nativeBeaconStateView.d.ts +4 -1
  63. package/lib/stateView/nativeBeaconStateView.d.ts.map +1 -1
  64. package/lib/stateView/nativeBeaconStateView.js +10 -0
  65. package/lib/stateView/nativeBeaconStateView.js.map +1 -1
  66. package/lib/util/gloas.d.ts.map +1 -1
  67. package/lib/util/gloas.js +1 -1
  68. package/lib/util/gloas.js.map +1 -1
  69. package/lib/util/seed.d.ts +1 -1
  70. package/lib/util/seed.d.ts.map +1 -1
  71. package/lib/util/seed.js +14 -11
  72. package/lib/util/seed.js.map +1 -1
  73. package/package.json +8 -8
  74. package/src/block/index.ts +53 -17
  75. package/src/block/processExecutionPayloadBid.ts +6 -5
  76. package/src/block/processOperations.ts +63 -45
  77. package/src/block/processParentExecutionPayload.ts +2 -27
  78. package/src/block/processPayloadAttestation.ts +3 -2
  79. package/src/block/processWithdrawals.ts +12 -2
  80. package/src/block/types.ts +32 -0
  81. package/src/epoch/processInactivityUpdates.ts +8 -1
  82. package/src/epoch/processPtcWindow.ts +15 -8
  83. package/src/index.ts +1 -1
  84. package/src/lightClient/spec/index.ts +2 -0
  85. package/src/lightClient/spec/utils.ts +142 -48
  86. package/src/metrics.ts +13 -2
  87. package/src/rewards/blockRewards.ts +1 -3
  88. package/src/signatureSets/index.ts +17 -3
  89. package/src/slot/upgradeStateToGloas.ts +1 -1
  90. package/src/stateView/beaconStateView.ts +16 -0
  91. package/src/stateView/interface.ts +3 -0
  92. package/src/stateView/nativeBeaconStateView.ts +13 -1
  93. package/src/util/gloas.ts +1 -0
  94. package/src/util/seed.ts +25 -13
package/src/metrics.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import {ForkName} from "@lodestar/params";
2
2
  import {MetricsRegister} from "@lodestar/utils";
3
- import {ProposerRewardType} from "./block/types.js";
3
+ import {BlockProcessStep, ProcessOperationsStep, ProposerRewardType} from "./block/types.js";
4
4
  import {EpochTransitionStep} from "./epoch/index.js";
5
5
  import {StateCloneSource, StateHashTreeRootSource} from "./stateTransition.js";
6
6
  import {CachedBeaconStateAllForks} from "./types.js";
@@ -57,10 +57,21 @@ export function getMetrics(register: MetricsRegister) {
57
57
  processBlockTime: register.histogram({
58
58
  name: "lodestar_stfn_process_block_seconds",
59
59
  help: "Time to process a single block in seconds",
60
- // TODO: Add metrics for each step
61
60
  // Block processing can take 5-40ms, 100ms max
62
61
  buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 1],
63
62
  }),
63
+ processBlockStepTime: register.histogram<{step: BlockProcessStep}>({
64
+ name: "lodestar_stfn_process_block_step_seconds",
65
+ help: "Time to call each step of process block in seconds",
66
+ labelNames: ["step"],
67
+ buckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1],
68
+ }),
69
+ processOperationsStepTime: register.histogram<{step: ProcessOperationsStep}>({
70
+ name: "lodestar_stfn_process_operations_step_seconds",
71
+ help: "Time to call each step of process operations in seconds",
72
+ labelNames: ["step"],
73
+ buckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1],
74
+ }),
64
75
  processBlockCommitTime: register.histogram({
65
76
  name: "lodestar_stfn_process_block_commit_seconds",
66
77
  help: "Time to call commit after process a single block in seconds",
@@ -42,9 +42,7 @@ export async function computeBlockRewards(
42
42
  let syncAggregateReward = cachedSyncAggregateReward;
43
43
 
44
44
  if (blockAttestationReward === 0) {
45
- const parentSlot = isForkPostGloas(fork)
46
- ? (preState as CachedBeaconStateGloas).latestExecutionPayloadBid.slot
47
- : null;
45
+ const parentSlot = isForkPostGloas(fork) ? (preState as CachedBeaconStateGloas).latestBlockHeader.slot : null;
48
46
  blockAttestationReward =
49
47
  fork === ForkName.phase0
50
48
  ? computeBlockAttestationRewardPhase0(block as phase0.BeaconBlock, preState as CachedBeaconStatePhase0)
@@ -1,13 +1,14 @@
1
1
  import {BeaconConfig} from "@lodestar/config";
2
2
  import {ForkSeq} from "@lodestar/params";
3
- import {IndexedAttestation, SignedBeaconBlock, altair, capella} from "@lodestar/types";
3
+ import {IndexedAttestation, SignedBeaconBlock, altair, capella, gloas} from "@lodestar/types";
4
4
  import {getSyncCommitteeSignatureSet} from "../block/processSyncCommittee.js";
5
5
  import {SyncCommitteeCache} from "../cache/syncCommitteeCache.js";
6
- import {IBeaconStateView} from "../stateView/interface.js";
7
- import {ISignatureSet} from "../util/index.js";
6
+ import {IBeaconStateView, IBeaconStateViewGloas} from "../stateView/interface.js";
7
+ import {ISignatureSet, createAggregateSignatureSetFromComponents} from "../util/index.js";
8
8
  import {getAttesterSlashingsSignatureSets} from "./attesterSlashings.js";
9
9
  import {getBlsToExecutionChangeSignatureSets} from "./blsToExecutionChange.js";
10
10
  import {getAttestationsSignatureSets} from "./indexedAttestation.js";
11
+ import {getPayloadAttestationDataSigningRoot} from "./indexedPayloadAttestation.js";
11
12
  import {getBlockProposerSignatureSet} from "./proposer.js";
12
13
  import {getProposerSlashingsSignatureSets} from "./proposerSlashings.js";
13
14
  import {getRandaoRevealSignatureSet} from "./randao.js";
@@ -79,5 +80,18 @@ export function getBlockSignatureSets(
79
80
  }
80
81
  }
81
82
 
83
+ if (fork >= ForkSeq.gloas) {
84
+ for (const payloadAttestation of (signedBlock as gloas.SignedBeaconBlock).message.body.payloadAttestations) {
85
+ const ptc = (state as IBeaconStateViewGloas).getPayloadTimelinessCommittee(payloadAttestation.data.slot);
86
+ signatureSets.push(
87
+ createAggregateSignatureSetFromComponents(
88
+ payloadAttestation.aggregationBits.intersectValues(ptc),
89
+ getPayloadAttestationDataSigningRoot(config, payloadAttestation.data),
90
+ payloadAttestation.signature
91
+ )
92
+ );
93
+ }
94
+ }
95
+
82
96
  return signatureSets;
83
97
  }
@@ -110,7 +110,7 @@ export function upgradeStateToGloas(
110
110
  ssz.gloas.PendingConsolidations
111
111
  );
112
112
  stateGloasView.proposerLookahead = stateGloasCloned.proposerLookahead;
113
- stateGloasView.ptcWindow = ssz.gloas.PtcWindow.toViewDU(initializePtcWindow(stateFulu));
113
+ stateGloasView.ptcWindow = ssz.gloas.PayloadTimelinessCommitteeWindow.toViewDU(initializePtcWindow(stateFulu));
114
114
 
115
115
  for (let i = 0; i < SLOTS_PER_HISTORICAL_ROOT; i++) {
116
116
  stateGloasView.executionPayloadAvailability.set(i, true);
@@ -116,6 +116,10 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
116
116
  return this.config.getForkName(this.cachedState.slot);
117
117
  }
118
118
 
119
+ get forkSeq(): ForkSeq {
120
+ return this.config.getForkSeq(this.cachedState.slot);
121
+ }
122
+
119
123
  get slot(): number {
120
124
  return this.cachedState.slot;
121
125
  }
@@ -452,6 +456,18 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
452
456
  }
453
457
  throw new Error(`PTC committees are not available for epoch=${epoch}`);
454
458
  }
459
+
460
+ /**
461
+ * Return the PTC for a slot in the previous, current or next epoch
462
+ */
463
+ getPayloadTimelinessCommittee(slot: Slot): Uint32Array {
464
+ if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
465
+ throw new Error("PTC committees are not supported before Gloas");
466
+ }
467
+
468
+ return (this.cachedState as CachedBeaconStateGloas).epochCtx.getPayloadTimelinessCommittee(slot);
469
+ }
470
+
455
471
  /**
456
472
  * Return all positions of the validator in the PTC committee for the given slot.
457
473
  *
@@ -10,6 +10,7 @@ import {
10
10
  ForkPostFulu,
11
11
  ForkPostGloas,
12
12
  ForkPostHeze,
13
+ ForkSeq,
13
14
  isForkPostAltair,
14
15
  isForkPostBellatrix,
15
16
  isForkPostCapella,
@@ -77,6 +78,7 @@ export interface IBeaconStateView {
77
78
 
78
79
  // phase0
79
80
  forkName: ForkName;
81
+ forkSeq: ForkSeq;
80
82
  slot: Slot;
81
83
  fork: Fork;
82
84
  epoch: Epoch;
@@ -283,6 +285,7 @@ export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
283
285
  getBuildersLength(): number;
284
286
  canBuilderCoverBid(builderIndex: BuilderIndex, bidAmount: number): boolean;
285
287
  getEpochPTCs(epoch: Epoch): Uint32Array[];
288
+ getPayloadTimelinessCommittee(slot: Slot): Uint32Array;
286
289
  getIndicesInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number[];
287
290
  /**
288
291
  * Clone the state and apply parent execution payload effects.
@@ -1,6 +1,6 @@
1
1
  import {CompactMultiProof} from "@chainsafe/persistent-merkle-tree";
2
2
  import {BitArray, ByteViews} from "@chainsafe/ssz";
3
- import {ForkName} from "@lodestar/params";
3
+ import {ForkName, ForkSeq} from "@lodestar/params";
4
4
  import {
5
5
  BeaconBlock,
6
6
  BeaconState,
@@ -66,6 +66,7 @@ import {
66
66
  export class NativeBeaconStateView implements IBeaconStateViewLatestFork {
67
67
  // phase0
68
68
  private _forkName: ForkName | null = null;
69
+ private _forkSeq: ForkSeq | null = null;
69
70
  private _slot: Slot | null = null;
70
71
  private _fork: Fork | null = null;
71
72
  private _epoch: Epoch | null = null;
@@ -194,6 +195,13 @@ export class NativeBeaconStateView implements IBeaconStateViewLatestFork {
194
195
  return this._forkName;
195
196
  }
196
197
 
198
+ get forkSeq(): ForkSeq {
199
+ if (this._forkSeq === null) {
200
+ this._forkSeq = this.binding.forkSeq;
201
+ }
202
+ return this._forkSeq;
203
+ }
204
+
197
205
  get slot(): Slot {
198
206
  if (this._slot === null) {
199
207
  this._slot = this.binding.slot;
@@ -918,6 +926,10 @@ export class NativeBeaconStateView implements IBeaconStateViewLatestFork {
918
926
  return cached;
919
927
  }
920
928
 
929
+ getPayloadTimelinessCommittee(slot: Slot): Uint32Array {
930
+ return this.binding.getPayloadTimelinessCommittee(slot);
931
+ }
932
+
921
933
  getIndicesInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number[] {
922
934
  return this.binding.getIndicesInPayloadTimelinessCommittee(validatorIndex, slot);
923
935
  }
package/src/util/gloas.ts CHANGED
@@ -220,6 +220,7 @@ export function initializePtcWindow(state: CachedBeaconStateFulu): Uint32Array[]
220
220
  state,
221
221
  epoch,
222
222
  shuffling.committees,
223
+ shuffling.shuffling,
223
224
  state.epochCtx.effectiveBalanceIncrements
224
225
  )
225
226
  );
package/src/util/seed.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import {digest} from "@chainsafe/as-sha256";
2
+ import {computePtcIndicesForEpoch} from "@chainsafe/lodestar-z/shuffle";
2
3
  import {
3
4
  computeProposerIndex as nativeComputeProposerIndex,
4
5
  computeSyncCommitteeIndices as nativeComputeSyncCommitteeIndices,
@@ -275,25 +276,36 @@ export function computePayloadTimelinessCommitteesForEpoch(
275
276
  state: BeaconStateAllForks,
276
277
  epoch: number,
277
278
  committees: Uint32Array[][],
279
+ shuffling: Uint32Array,
278
280
  effectiveBalanceIncrements: EffectiveBalanceIncrements
279
281
  ): Uint32Array[] {
280
282
  const epochSeed = getSeed(state, epoch, DOMAIN_PTC_ATTESTER);
281
283
  const startSlot = epoch * SLOTS_PER_EPOCH;
284
+ const slotOffsets = new Uint32Array(SLOTS_PER_EPOCH + 1);
285
+ let shufflingLength = 0;
286
+ for (let i = 0; i < SLOTS_PER_EPOCH; i++) {
287
+ slotOffsets[i] = shufflingLength;
288
+ for (const committee of committees[i]) {
289
+ shufflingLength += committee.length;
290
+ }
291
+ }
292
+ slotOffsets[SLOTS_PER_EPOCH] = shufflingLength;
293
+
294
+ // Native sampling returns all committees concatenated in slot order, with PTC_SIZE indices per slot.
295
+ const flatPtcIndices = computePtcIndicesForEpoch(
296
+ epochSeed,
297
+ startSlot,
298
+ SLOTS_PER_EPOCH,
299
+ shuffling,
300
+ slotOffsets,
301
+ effectiveBalanceIncrements,
302
+ PTC_SIZE,
303
+ MAX_EFFECTIVE_BALANCE_ELECTRA,
304
+ EFFECTIVE_BALANCE_INCREMENT
305
+ );
282
306
  const result: Uint32Array[] = new Array(SLOTS_PER_EPOCH);
283
-
284
- // Pre-allocate slot seed buffer once, reuse across all slots
285
- const slotSeedInput = new Uint8Array(epochSeed.length + 8);
286
- slotSeedInput.set(epochSeed, 0);
287
- const slotSeedView = new DataView(slotSeedInput.buffer, slotSeedInput.byteOffset, slotSeedInput.byteLength);
288
-
289
307
  for (let i = 0; i < SLOTS_PER_EPOCH; i++) {
290
- const slot = startSlot + i;
291
- // Write slot as little-endian uint64 (fits in uint32 range)
292
- slotSeedView.setUint32(epochSeed.length, slot, true);
293
- slotSeedView.setUint32(epochSeed.length + 4, 0, true);
294
- const slotSeed = digest(slotSeedInput);
295
-
296
- result[i] = computePayloadTimelinessCommitteeForSlot(slotSeed, committees[i], effectiveBalanceIncrements);
308
+ result[i] = flatPtcIndices.subarray(i * PTC_SIZE, (i + 1) * PTC_SIZE);
297
309
  }
298
310
  return result;
299
311
  }