@lodestar/state-transition 1.49.0 → 1.50.0-dev.023ad6c012

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 (68) hide show
  1. package/lib/block/indexedBuilderState.d.ts +19 -0
  2. package/lib/block/indexedBuilderState.d.ts.map +1 -0
  3. package/lib/block/indexedBuilderState.js +60 -0
  4. package/lib/block/indexedBuilderState.js.map +1 -0
  5. package/lib/block/processBuilderDepositRequest.d.ts +2 -2
  6. package/lib/block/processBuilderDepositRequest.d.ts.map +1 -1
  7. package/lib/block/processBuilderDepositRequest.js +5 -4
  8. package/lib/block/processBuilderDepositRequest.js.map +1 -1
  9. package/lib/block/processBuilderExitRequest.d.ts +2 -2
  10. package/lib/block/processBuilderExitRequest.d.ts.map +1 -1
  11. package/lib/block/processBuilderExitRequest.js +4 -3
  12. package/lib/block/processBuilderExitRequest.js.map +1 -1
  13. package/lib/block/processParentExecutionPayload.d.ts.map +1 -1
  14. package/lib/block/processParentExecutionPayload.js +9 -5
  15. package/lib/block/processParentExecutionPayload.js.map +1 -1
  16. package/lib/index.d.ts +1 -0
  17. package/lib/index.d.ts.map +1 -1
  18. package/lib/index.js +1 -0
  19. package/lib/index.js.map +1 -1
  20. package/lib/rewards/attestationsRewards.d.ts.map +1 -1
  21. package/lib/rewards/attestationsRewards.js +15 -6
  22. package/lib/rewards/attestationsRewards.js.map +1 -1
  23. package/lib/stateView/beaconStateView.d.ts +4 -0
  24. package/lib/stateView/beaconStateView.d.ts.map +1 -1
  25. package/lib/stateView/beaconStateView.js +20 -0
  26. package/lib/stateView/beaconStateView.js.map +1 -1
  27. package/lib/stateView/interface.d.ts +2 -0
  28. package/lib/stateView/interface.d.ts.map +1 -1
  29. package/lib/stateView/interface.js.map +1 -1
  30. package/lib/stateView/nativeBeaconStateView.d.ts +4 -0
  31. package/lib/stateView/nativeBeaconStateView.d.ts.map +1 -1
  32. package/lib/stateView/nativeBeaconStateView.js +14 -0
  33. package/lib/stateView/nativeBeaconStateView.js.map +1 -1
  34. package/lib/stateView/stateViewFactory.d.ts +5 -13
  35. package/lib/stateView/stateViewFactory.d.ts.map +1 -1
  36. package/lib/stateView/stateViewFactory.js +5 -5
  37. package/lib/stateView/stateViewFactory.js.map +1 -1
  38. package/lib/util/gloas.d.ts +11 -14
  39. package/lib/util/gloas.d.ts.map +1 -1
  40. package/lib/util/gloas.js +2 -42
  41. package/lib/util/gloas.js.map +1 -1
  42. package/lib/util/index.d.ts +1 -0
  43. package/lib/util/index.d.ts.map +1 -1
  44. package/lib/util/index.js +1 -0
  45. package/lib/util/index.js.map +1 -1
  46. package/lib/util/sszBytes.d.ts +16 -17
  47. package/lib/util/sszBytes.d.ts.map +1 -1
  48. package/lib/util/sszBytes.js +93 -20
  49. package/lib/util/sszBytes.js.map +1 -1
  50. package/lib/util/weakSubjectivity.d.ts +11 -6
  51. package/lib/util/weakSubjectivity.d.ts.map +1 -1
  52. package/lib/util/weakSubjectivity.js +22 -28
  53. package/lib/util/weakSubjectivity.js.map +1 -1
  54. package/package.json +7 -7
  55. package/src/block/indexedBuilderState.ts +65 -0
  56. package/src/block/processBuilderDepositRequest.ts +6 -17
  57. package/src/block/processBuilderExitRequest.ts +5 -9
  58. package/src/block/processParentExecutionPayload.ts +9 -6
  59. package/src/index.ts +1 -0
  60. package/src/rewards/attestationsRewards.ts +17 -5
  61. package/src/stateView/beaconStateView.ts +26 -0
  62. package/src/stateView/interface.ts +2 -0
  63. package/src/stateView/nativeBeaconStateView.ts +16 -0
  64. package/src/stateView/stateViewFactory.ts +9 -16
  65. package/src/util/gloas.ts +2 -53
  66. package/src/util/index.ts +6 -0
  67. package/src/util/sszBytes.ts +129 -22
  68. package/src/util/weakSubjectivity.ts +43 -40
@@ -1,26 +1,27 @@
1
+ import { EFFECTIVE_BALANCE_INCREMENT } from "@lodestar/params";
2
+ import { ssz } from "@lodestar/types";
1
3
  import { bytesToInt } from "@lodestar/utils";
4
+ const UINT64_SIZE = 8;
5
+ const ROOT_SIZE = 32;
2
6
  /**
3
- * Slot uint64
4
- */
5
- const SLOT_BYTE_COUNT = 8;
6
- /**
7
- * 48 + 32 + 8 + 1 + 8 + 8 + 8 + 8 = 121
8
7
  * ```
9
8
  * class Validator(Container):
10
- pubkey: BLSPubkey [fixed - 48 bytes]
11
- withdrawal_credentials: Bytes32 [fixed - 32 bytes]
12
- effective_balance: Gwei [fixed - 8 bytes]
13
- slashed: boolean [fixed - 1 byte]
14
- # Status epochs
15
- activation_eligibility_epoch: Epoch [fixed - 8 bytes]
16
- activation_epoch: Epoch [fixed - 8 bytes]
17
- exit_epoch: Epoch [fixed - 8 bytes]
18
- withdrawable_epoch: Epoch [fixed - 8 bytes]
19
- ```
9
+ * pubkey: BLSPubkey [fixed - 48 bytes]
10
+ * withdrawal_credentials: Bytes32 [fixed - 32 bytes]
11
+ * effective_balance: Gwei [fixed - 8 bytes]
12
+ * slashed: boolean [fixed - 1 byte]
13
+ * activation_eligibility_epoch: Epoch [fixed - 8 bytes]
14
+ * activation_epoch: Epoch [fixed - 8 bytes]
15
+ * exit_epoch: Epoch [fixed - 8 bytes]
16
+ * withdrawable_epoch: Epoch [fixed - 8 bytes]
17
+ * ```
20
18
  */
21
- export const VALIDATOR_BYTES_SIZE = 121;
19
+ const PUBKEY_SIZE = 48;
20
+ const VALIDATOR_EFFECTIVE_BALANCE_OFFSET = PUBKEY_SIZE + ROOT_SIZE;
21
+ const VALIDATOR_ACTIVATION_EPOCH_OFFSET = VALIDATOR_EFFECTIVE_BALANCE_OFFSET + UINT64_SIZE + 1 + UINT64_SIZE;
22
+ const VALIDATOR_EXIT_EPOCH_OFFSET = VALIDATOR_ACTIVATION_EPOCH_OFFSET + UINT64_SIZE;
23
+ export const VALIDATOR_BYTES_SIZE = VALIDATOR_EXIT_EPOCH_OFFSET + UINT64_SIZE + UINT64_SIZE;
22
24
  /**
23
- * 8 + 32 = 40
24
25
  * ```
25
26
  * class BeaconState(Container):
26
27
  * genesis_time: uint64 [fixed - 8 bytes]
@@ -29,9 +30,11 @@ export const VALIDATOR_BYTES_SIZE = 121;
29
30
  * ...
30
31
  * ```
31
32
  */
32
- const SLOT_BYTES_POSITION_IN_STATE = 40;
33
+ const STATE_GENESIS_TIME_OFFSET = 0;
34
+ const STATE_GENESIS_VALIDATORS_ROOT_OFFSET = STATE_GENESIS_TIME_OFFSET + UINT64_SIZE;
35
+ const STATE_SLOT_OFFSET = STATE_GENESIS_VALIDATORS_ROOT_OFFSET + ROOT_SIZE;
33
36
  export function getForkFromStateBytes(config, bytes) {
34
- const slot = bytesToInt(bytes.subarray(SLOT_BYTES_POSITION_IN_STATE, SLOT_BYTES_POSITION_IN_STATE + SLOT_BYTE_COUNT));
37
+ const slot = bytesToInt(bytes.subarray(STATE_SLOT_OFFSET, STATE_SLOT_OFFSET + UINT64_SIZE));
35
38
  return config.getForkSeq(slot);
36
39
  }
37
40
  export function getStateTypeFromBytes(config, bytes) {
@@ -39,6 +42,76 @@ export function getStateTypeFromBytes(config, bytes) {
39
42
  return config.getForkTypes(slot).BeaconState;
40
43
  }
41
44
  export function getStateSlotFromBytes(bytes) {
42
- return bytesToInt(bytes.subarray(SLOT_BYTES_POSITION_IN_STATE, SLOT_BYTES_POSITION_IN_STATE + SLOT_BYTE_COUNT));
45
+ return bytesToInt(bytes.subarray(STATE_SLOT_OFFSET, STATE_SLOT_OFFSET + UINT64_SIZE));
46
+ }
47
+ export function readBeaconStateBytesMetadata(bytes) {
48
+ if (bytes.length < STATE_SLOT_OFFSET + UINT64_SIZE) {
49
+ return null;
50
+ }
51
+ const data = { uint8Array: bytes, dataView: new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength) };
52
+ return {
53
+ genesisTime: ssz.UintNum64.value_deserializeFromBytes(data, STATE_GENESIS_TIME_OFFSET, STATE_GENESIS_TIME_OFFSET + UINT64_SIZE),
54
+ genesisValidatorsRoot: Uint8Array.from(bytes.subarray(STATE_GENESIS_VALIDATORS_ROOT_OFFSET, STATE_GENESIS_VALIDATORS_ROOT_OFFSET + ROOT_SIZE)),
55
+ slot: ssz.Slot.value_deserializeFromBytes(data, STATE_SLOT_OFFSET, STATE_SLOT_OFFSET + UINT64_SIZE),
56
+ };
57
+ }
58
+ /** Read only the validator fields needed for weak subjectivity, without allocating validator objects. */
59
+ export function scanActiveValidatorsFromStateBytes(stateBytes, stateType, epoch) {
60
+ const range = getValidatorsRangeFromStateBytes(stateBytes, stateType);
61
+ if (range === null) {
62
+ return null;
63
+ }
64
+ const data = {
65
+ uint8Array: stateBytes,
66
+ dataView: new DataView(stateBytes.buffer, stateBytes.byteOffset, stateBytes.byteLength),
67
+ };
68
+ let activeValidatorCount = 0;
69
+ let totalActiveBalanceIncrements = 0;
70
+ for (let offset = range.start; offset < range.end; offset += VALIDATOR_BYTES_SIZE) {
71
+ const activationEpoch = ssz.EpochInf.value_deserializeFromBytes(data, offset + VALIDATOR_ACTIVATION_EPOCH_OFFSET, offset + VALIDATOR_ACTIVATION_EPOCH_OFFSET + UINT64_SIZE);
72
+ const exitEpoch = ssz.EpochInf.value_deserializeFromBytes(data, offset + VALIDATOR_EXIT_EPOCH_OFFSET, offset + VALIDATOR_EXIT_EPOCH_OFFSET + UINT64_SIZE);
73
+ if (activationEpoch <= epoch && epoch < exitEpoch) {
74
+ activeValidatorCount++;
75
+ const effectiveBalance = ssz.UintNum64.value_deserializeFromBytes(data, offset + VALIDATOR_EFFECTIVE_BALANCE_OFFSET, offset + VALIDATOR_EFFECTIVE_BALANCE_OFFSET + UINT64_SIZE);
76
+ totalActiveBalanceIncrements += Math.floor(effectiveBalance / EFFECTIVE_BALANCE_INCREMENT);
77
+ }
78
+ }
79
+ return { activeValidatorCount, totalActiveBalanceIncrements: Math.max(1, totalActiveBalanceIncrements) };
80
+ }
81
+ export function getValidatorCountFromStateBytes(config, stateBytes) {
82
+ const range = getValidatorsRangeFromStateBytes(stateBytes, getStateTypeFromBytes(config, stateBytes));
83
+ // A non-null range always holds a whole number of validator records, so the division is exact
84
+ return range === null ? null : (range.end - range.start) / VALIDATOR_BYTES_SIZE;
85
+ }
86
+ /** Returns a view into `stateBytes`, or null if the index is not in the registry. */
87
+ export function getValidatorPubkeyFromStateBytes(config, stateBytes, index) {
88
+ const range = getValidatorsRangeFromStateBytes(stateBytes, getStateTypeFromBytes(config, stateBytes));
89
+ if (range === null) {
90
+ return null;
91
+ }
92
+ const start = range.start + index * VALIDATOR_BYTES_SIZE;
93
+ if (index < 0 || start >= range.end) {
94
+ return null;
95
+ }
96
+ return stateBytes.subarray(start, start + PUBKEY_SIZE);
97
+ }
98
+ function getValidatorsRangeFromStateBytes(stateBytes, stateType) {
99
+ let range;
100
+ try {
101
+ const containerType = stateType;
102
+ const dataView = new DataView(stateBytes.buffer, stateBytes.byteOffset, stateBytes.byteLength);
103
+ const ranges = containerType.getFieldRanges(dataView, 0, stateBytes.length);
104
+ range = ranges[Object.keys(containerType.fields).indexOf("validators")];
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ if (!range || range.start < 0 || range.end > stateBytes.length || range.end < range.start) {
110
+ return null;
111
+ }
112
+ if ((range.end - range.start) % VALIDATOR_BYTES_SIZE !== 0) {
113
+ return null;
114
+ }
115
+ return range;
43
116
  }
44
117
  //# sourceMappingURL=sszBytes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sszBytes.js","sourceRoot":"","sources":["../../src/util/sszBytes.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAE3C;;GAEG;AACH,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAExC;;;;;;;;;GASG;AACH,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAExC,MAAM,UAAU,qBAAqB,CAAC,MAAuB,EAAE,KAAiB;IAC9E,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,4BAA4B,EAAE,4BAA4B,GAAG,eAAe,CAAC,CAAC,CAAC;IACtH,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAuB,EAAE,KAAiB;IAC9E,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAiB;IACrD,OAAO,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,4BAA4B,EAAE,4BAA4B,GAAG,eAAe,CAAC,CAAC,CAAC;AAClH,CAAC"}
1
+ {"version":3,"file":"sszBytes.js","sourceRoot":"","sources":["../../src/util/sszBytes.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { BeaconConfig, ChainForkConfig } from "@lodestar/config";
2
- import { Epoch, Root } from "@lodestar/types";
3
- import { Checkpoint } from "@lodestar/types/phase0";
1
+ import { ChainForkConfig } from "@lodestar/config";
2
+ import { Epoch, Root, TimeSeconds } from "@lodestar/types";
4
3
  import { BeaconStateAllForks, CachedBeaconStateAllForks } from "../types.js";
4
+ import { StateBytesMetadata } from "./sszBytes.js";
5
5
  export declare const ETH_TO_GWEI: number;
6
6
  /**
7
7
  * Returns the epoch of the latest weak subjectivity checkpoint for the given
@@ -19,13 +19,18 @@ export declare function getLatestWeakSubjectivityCheckpointEpoch(config: ChainFo
19
19
  export declare function computeWeakSubjectivityPeriodCachedState(config: ChainForkConfig, state: CachedBeaconStateAllForks): number;
20
20
  /**
21
21
  * Same to computeWeakSubjectivityPeriodCachedState but for normal state
22
- * This is called only 1 time at app startup so it's ok to calculate totalActiveBalanceIncrements manually
23
22
  */
24
23
  export declare function computeWeakSubjectivityPeriod(config: ChainForkConfig, state: BeaconStateAllForks): number;
25
24
  export declare function computeWeakSubjectivityPeriodFromConstituentsPhase0(activeValidatorCount: number, totalBalanceByIncrement: number, churnLimit: number, minWithdrawabilityDelay: number): number;
26
25
  export declare function computeWeakSubjectivityPeriodFromConstituentsElectra(totalBalanceByIncrement: number, balanceChurnLimit: number, minWithdrawabilityDelay: number): number;
27
26
  export declare function computeWeakSubjectivityPeriodFromConstituentsGloas(totalBalanceByIncrement: number, exitChurnLimit: number, activationChurnLimit: number, consolidationChurnLimit: number, minWithdrawabilityDelay: number): number;
28
27
  export declare function getLatestBlockRoot(state: BeaconStateAllForks): Root;
29
- export declare function isWithinWeakSubjectivityPeriod(config: BeaconConfig, wsState: BeaconStateAllForks, wsCheckpoint: Checkpoint): boolean;
30
- export declare function ensureWithinWeakSubjectivityPeriod(config: BeaconConfig, wsState: BeaconStateAllForks, wsCheckpoint: Checkpoint): void;
28
+ export type WeakSubjectivitySummary = {
29
+ checkpointEpoch: Epoch;
30
+ genesisTime: number;
31
+ period: number;
32
+ };
33
+ /** The metadata must describe the supplied state bytes. */
34
+ export declare function computeWeakSubjectivitySummaryFromStateBytes(config: ChainForkConfig, bytes: Uint8Array, metadata: StateBytesMetadata): WeakSubjectivitySummary | null;
35
+ export declare function isWithinWeakSubjectivityPeriodFromSummary(config: ChainForkConfig, summary: WeakSubjectivitySummary, now?: TimeSeconds): boolean;
31
36
  //# sourceMappingURL=weakSubjectivity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"weakSubjectivity.d.ts","sourceRoot":"","sources":["../../src/util/weakSubjectivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAU/D,OAAO,EAAC,KAAK,EAAE,IAAI,EAAM,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAC,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAGlD,OAAO,EAAC,mBAAmB,EAAE,yBAAyB,EAAC,MAAM,aAAa,CAAC;AAc3E,eAAO,MAAM,WAAW,QAAU,CAAC;AAGnC;;;GAGG;AACH,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,yBAAyB,GAC/B,KAAK,CAEP;AAED;;;;;;;GAOG;AACH,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,yBAAyB,GAC/B,MAAM,CAwBR;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAuCzG;AAED,wBAAgB,mDAAmD,CACjE,oBAAoB,EAAE,MAAM,EAC5B,uBAAuB,EAAE,MAAM,EAC/B,UAAU,EAAE,MAAM,EAClB,uBAAuB,EAAE,MAAM,GAC9B,MAAM,CAuBR;AAED,wBAAgB,oDAAoD,CAClE,uBAAuB,EAAE,MAAM,EAE/B,iBAAiB,EAAE,MAAM,EACzB,uBAAuB,EAAE,MAAM,GAC9B,MAAM,CAOR;AAED,wBAAgB,kDAAkD,CAChE,uBAAuB,EAAE,MAAM,EAC/B,cAAc,EAAE,MAAM,EACtB,oBAAoB,EAAE,MAAM,EAC5B,uBAAuB,EAAE,MAAM,EAC/B,uBAAuB,EAAE,MAAM,GAC9B,MAAM,CAOR;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAMnE;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,mBAAmB,EAC5B,YAAY,EAAE,UAAU,GACvB,OAAO,CAOT;AAED,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,mBAAmB,EAC5B,YAAY,EAAE,UAAU,GACvB,IAAI,CAgBN"}
1
+ {"version":3,"file":"weakSubjectivity.d.ts","sourceRoot":"","sources":["../../src/util/weakSubjectivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAWjD,OAAO,EAAC,KAAK,EAAE,IAAI,EAAQ,WAAW,EAAM,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAAC,mBAAmB,EAAE,yBAAyB,EAAC,MAAM,aAAa,CAAC;AAE3E,OAAO,EAAC,kBAAkB,EAA4D,MAAM,eAAe,CAAC;AAY5G,eAAO,MAAM,WAAW,QAAU,CAAC;AAGnC;;;GAGG;AACH,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,yBAAyB,GAC/B,KAAK,CAEP;AAED;;;;;;;GAOG;AACH,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,yBAAyB,GAC/B,MAAM,CAwBR;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAgBzG;AAwCD,wBAAgB,mDAAmD,CACjE,oBAAoB,EAAE,MAAM,EAC5B,uBAAuB,EAAE,MAAM,EAC/B,UAAU,EAAE,MAAM,EAClB,uBAAuB,EAAE,MAAM,GAC9B,MAAM,CAuBR;AAED,wBAAgB,oDAAoD,CAClE,uBAAuB,EAAE,MAAM,EAE/B,iBAAiB,EAAE,MAAM,EACzB,uBAAuB,EAAE,MAAM,GAC9B,MAAM,CAOR;AAED,wBAAgB,kDAAkD,CAChE,uBAAuB,EAAE,MAAM,EAC/B,cAAc,EAAE,MAAM,EACtB,oBAAoB,EAAE,MAAM,EAC5B,uBAAuB,EAAE,MAAM,EAC/B,uBAAuB,EAAE,MAAM,GAC9B,MAAM,CAOR;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAMnE;AAED,MAAM,MAAM,uBAAuB,GAAG;IAAC,eAAe,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC;AAEpG,2DAA2D;AAC3D,wBAAgB,4CAA4C,CAC1D,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,kBAAkB,GAC3B,uBAAuB,GAAG,IAAI,CAOhC;AAED,wBAAgB,yCAAyC,CACvD,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,uBAAuB,EAChC,GAAG,GAAE,WAA+B,GACnC,OAAO,CAGT"}
@@ -1,9 +1,8 @@
1
- import { EFFECTIVE_BALANCE_INCREMENT, ForkSeq, MAX_DEPOSITS, MAX_EFFECTIVE_BALANCE, SLOTS_PER_EPOCH, isForkPostElectra, isForkPostGloas, } from "@lodestar/params";
1
+ import { EFFECTIVE_BALANCE_INCREMENT, ForkSeq, GENESIS_SLOT, MAX_DEPOSITS, MAX_EFFECTIVE_BALANCE, SLOTS_PER_EPOCH, isForkPostElectra, isForkPostGloas, } from "@lodestar/params";
2
2
  import { ssz } from "@lodestar/types";
3
- import { toRootHex } from "@lodestar/utils";
4
3
  import { ZERO_HASH } from "../constants/constants.js";
5
4
  import { computeCheckpointEpochAtStateSlot, computeEpochAtSlot, getCurrentEpoch } from "./epoch.js";
6
- import { getCurrentSlot } from "./slot.js";
5
+ import { getStateTypeFromBytes, scanActiveValidatorsFromStateBytes } from "./sszBytes.js";
7
6
  import { getActivationChurnLimit, getActiveValidatorIndices, getBalanceChurnLimit, getBalanceChurnLimitFromCache, getChurnLimit, getConsolidationChurnLimit, getExitChurnLimit, getGloasChurnLimits, } from "./validator.js";
8
7
  export const ETH_TO_GWEI = 10 ** 9;
9
8
  const SAFETY_DECAY = 10;
@@ -33,12 +32,10 @@ export function computeWeakSubjectivityPeriodCachedState(config, state) {
33
32
  }
34
33
  /**
35
34
  * Same to computeWeakSubjectivityPeriodCachedState but for normal state
36
- * This is called only 1 time at app startup so it's ok to calculate totalActiveBalanceIncrements manually
37
35
  */
38
36
  export function computeWeakSubjectivityPeriod(config, state) {
39
37
  const activeIndices = getActiveValidatorIndices(state, getCurrentEpoch(state));
40
38
  const validators = state.validators.getAllReadonlyValues();
41
- const fork = config.getForkName(state.slot);
42
39
  let totalActiveBalanceIncrements = 0;
43
40
  for (const index of activeIndices) {
44
41
  totalActiveBalanceIncrements += Math.floor(validators[index].effectiveBalance / EFFECTIVE_BALANCE_INCREMENT);
@@ -46,12 +43,19 @@ export function computeWeakSubjectivityPeriod(config, state) {
46
43
  if (totalActiveBalanceIncrements <= 1) {
47
44
  totalActiveBalanceIncrements = 1;
48
45
  }
46
+ return computeWeakSubjectivityPeriodFromActiveValidators(config, state.slot, {
47
+ activeValidatorCount: activeIndices.length,
48
+ totalActiveBalanceIncrements,
49
+ });
50
+ }
51
+ function computeWeakSubjectivityPeriodFromActiveValidators(config, slot, { activeValidatorCount, totalActiveBalanceIncrements, }) {
52
+ const fork = config.getForkName(slot);
49
53
  const churnLimitsGloas = getGloasChurnLimits(config, totalActiveBalanceIncrements);
50
54
  return isForkPostGloas(fork)
51
55
  ? computeWeakSubjectivityPeriodFromConstituentsGloas(totalActiveBalanceIncrements, churnLimitsGloas.exit, churnLimitsGloas.activation, churnLimitsGloas.consolidation, config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
52
56
  : isForkPostElectra(fork)
53
57
  ? computeWeakSubjectivityPeriodFromConstituentsElectra(totalActiveBalanceIncrements, getBalanceChurnLimit(totalActiveBalanceIncrements, config.CHURN_LIMIT_QUOTIENT, config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA), config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
54
- : computeWeakSubjectivityPeriodFromConstituentsPhase0(activeIndices.length, totalActiveBalanceIncrements, getChurnLimit(config, activeIndices.length), config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY);
58
+ : computeWeakSubjectivityPeriodFromConstituentsPhase0(activeValidatorCount, totalActiveBalanceIncrements, getChurnLimit(config, activeValidatorCount), config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY);
55
59
  }
56
60
  export function computeWeakSubjectivityPeriodFromConstituentsPhase0(activeValidatorCount, totalBalanceByIncrement, churnLimit, minWithdrawabilityDelay) {
57
61
  const N = activeValidatorCount;
@@ -98,28 +102,18 @@ export function getLatestBlockRoot(state) {
98
102
  }
99
103
  return ssz.phase0.BeaconBlockHeader.hashTreeRoot(header);
100
104
  }
101
- export function isWithinWeakSubjectivityPeriod(config, wsState, wsCheckpoint) {
102
- try {
103
- ensureWithinWeakSubjectivityPeriod(config, wsState, wsCheckpoint);
104
- return true;
105
- }
106
- catch (_) {
107
- return false;
108
- }
105
+ /** The metadata must describe the supplied state bytes. */
106
+ export function computeWeakSubjectivitySummaryFromStateBytes(config, bytes, metadata) {
107
+ const { slot, genesisTime } = metadata;
108
+ const stateType = getStateTypeFromBytes(config, bytes);
109
+ const activeValidators = scanActiveValidatorsFromStateBytes(bytes, stateType, computeEpochAtSlot(slot));
110
+ if (activeValidators === null)
111
+ return null;
112
+ const period = computeWeakSubjectivityPeriodFromActiveValidators(config, slot, activeValidators);
113
+ return { checkpointEpoch: computeCheckpointEpochAtStateSlot(slot), genesisTime, period };
109
114
  }
110
- export function ensureWithinWeakSubjectivityPeriod(config, wsState, wsCheckpoint) {
111
- const wsStateEpoch = computeCheckpointEpochAtStateSlot(wsState.slot);
112
- const blockRoot = getLatestBlockRoot(wsState);
113
- if (!ssz.Root.equals(blockRoot, wsCheckpoint.root)) {
114
- throw new Error(`Roots do not match. expected=${toRootHex(wsCheckpoint.root)}, actual=${toRootHex(blockRoot)}`);
115
- }
116
- if (!ssz.Epoch.equals(wsStateEpoch, wsCheckpoint.epoch)) {
117
- throw new Error(`Epochs do not match. expected=${wsCheckpoint.epoch}, actual=${wsStateEpoch}`);
118
- }
119
- const wsPeriod = computeWeakSubjectivityPeriod(config, wsState);
120
- const clockEpoch = computeEpochAtSlot(getCurrentSlot(config, wsState.genesisTime));
121
- if (clockEpoch > wsStateEpoch + wsPeriod) {
122
- throw new Error(`The downloaded state with epoch ${wsStateEpoch} is not within weak subjectivity period of ${wsPeriod} from the current epoch ${clockEpoch}. Please verify your checkpoint source`);
123
- }
115
+ export function isWithinWeakSubjectivityPeriodFromSummary(config, summary, now = Date.now() / 1000) {
116
+ const clockSlot = GENESIS_SLOT + Math.floor((now - summary.genesisTime) / (config.SLOT_DURATION_MS / 1000));
117
+ return computeEpochAtSlot(clockSlot) <= summary.checkpointEpoch + summary.period;
124
118
  }
125
119
  //# sourceMappingURL=weakSubjectivity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"weakSubjectivity.js","sourceRoot":"","sources":["../../src/util/weakSubjectivity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"weakSubjectivity.js","sourceRoot":"","sources":["../../src/util/weakSubjectivity.ts"],"names":[],"mappings":"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"}
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.49.0",
14
+ "version": "1.50.0-dev.023ad6c012",
15
15
  "type": "module",
16
16
  "exports": {
17
17
  ".": {
@@ -69,14 +69,14 @@
69
69
  "@chainsafe/lodestar-z": "catalog:",
70
70
  "@chainsafe/persistent-merkle-tree": "^1.3.1",
71
71
  "@chainsafe/ssz": "^1.8.0",
72
- "@lodestar/config": "^1.49.0",
73
- "@lodestar/params": "^1.49.0",
74
- "@lodestar/types": "^1.49.0",
75
- "@lodestar/utils": "^1.49.0",
72
+ "@lodestar/config": "^1.50.0-dev.023ad6c012",
73
+ "@lodestar/params": "^1.50.0-dev.023ad6c012",
74
+ "@lodestar/types": "^1.50.0-dev.023ad6c012",
75
+ "@lodestar/utils": "^1.50.0-dev.023ad6c012",
76
76
  "@vekexasia/bigint-buffer2": "^1.1.1"
77
77
  },
78
78
  "devDependencies": {
79
- "@lodestar/test-utils": "^1.49.0"
79
+ "@lodestar/test-utils": "^1.50.0-dev.023ad6c012"
80
80
  },
81
81
  "keywords": [
82
82
  "ethereum",
@@ -84,5 +84,5 @@
84
84
  "beacon",
85
85
  "blockchain"
86
86
  ],
87
- "gitHead": "0e1dc8585876c2e17fb7c87d9d788a0162fa337b"
87
+ "gitHead": "40b6728022248f7ec3fa26a2cf33f3febc3340a2"
88
88
  }
@@ -0,0 +1,65 @@
1
+ import {BuilderIndex, Epoch, PubkeyHex} from "@lodestar/types";
2
+ import {Builder} from "@lodestar/types/gloas";
3
+ import {toPubkeyHex} from "@lodestar/utils";
4
+ import {CachedBeaconStateGloas} from "../types.js";
5
+ import {computeEpochAtSlot} from "../util/epoch.js";
6
+ import {createBuilderView} from "../util/gloas.js";
7
+
8
+ /**
9
+ * Block-scoped pubkey -> index map and ascending reuse candidates for `state.builders`, built in one pass.
10
+ * Only valid while builder pubkeys change exclusively via `addBuilderToRegistry()` and no builder becomes
11
+ * newly reusable (candidates are re-checked lazily, never added). Do not use across blocks/slots.
12
+ */
13
+ export class IndexedBuilderState {
14
+ private readonly currentEpoch: Epoch;
15
+ private readonly indexByPubkey = new Map<PubkeyHex, BuilderIndex>();
16
+ private readonly reusableIndexCandidates: BuilderIndex[] = [];
17
+ private candidateCursor = 0;
18
+
19
+ constructor(readonly state: CachedBeaconStateGloas) {
20
+ state.builders.commit();
21
+ const builders = state.builders.getAllReadonlyValues();
22
+ this.currentEpoch = computeEpochAtSlot(state.slot);
23
+ for (const [index, builder] of builders.entries()) {
24
+ const pubkeyHex = toPubkeyHex(builder.pubkey);
25
+ this.indexByPubkey.set(pubkeyHex, index);
26
+ if (canReuseBuilder(builder, this.currentEpoch)) {
27
+ this.reusableIndexCandidates.push(index);
28
+ }
29
+ }
30
+ }
31
+
32
+ findBuilderIndexByPubkey(pubkey: Uint8Array): BuilderIndex | null {
33
+ return this.indexByPubkey.get(toPubkeyHex(pubkey)) ?? null;
34
+ }
35
+
36
+ addBuilderToRegistry(pubkey: Uint8Array, version: number, executionAddress: Uint8Array, amount: number): void {
37
+ const builder = createBuilderView(pubkey, version, executionAddress, amount, this.currentEpoch);
38
+ const reusableIndex = this.findReusableBuilderIndex();
39
+ const index = reusableIndex ?? this.state.builders.length;
40
+ if (reusableIndex !== null) {
41
+ const oldBuilder = this.state.builders.getReadonly(index);
42
+ this.indexByPubkey.delete(toPubkeyHex(oldBuilder.pubkey));
43
+ this.state.builders.set(index, builder);
44
+ } else {
45
+ this.state.builders.push(builder);
46
+ }
47
+ this.indexByPubkey.set(toPubkeyHex(pubkey), index);
48
+ }
49
+
50
+ private findReusableBuilderIndex(): BuilderIndex | null {
51
+ while (this.candidateCursor < this.reusableIndexCandidates.length) {
52
+ const index = this.reusableIndexCandidates[this.candidateCursor++];
53
+ const builder = this.state.builders.getReadonly(index);
54
+ // Top-ups can invalidate initial candidates
55
+ if (canReuseBuilder(builder, this.currentEpoch)) {
56
+ return index;
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+ }
62
+
63
+ function canReuseBuilder(builder: Builder, currentEpoch: Epoch): boolean {
64
+ return builder.withdrawableEpoch <= currentEpoch && builder.balance === 0;
65
+ }
@@ -1,13 +1,8 @@
1
1
  import {FAR_FUTURE_EPOCH, PAYLOAD_BUILDER_VERSION} from "@lodestar/params";
2
2
  import {gloas} from "@lodestar/types";
3
- import {CachedBeaconStateGloas} from "../types.js";
4
3
  import {computeEpochAtSlot} from "../util/epoch.js";
5
- import {
6
- addBuilderToRegistry,
7
- findBuilderIndexByPubkey,
8
- isBuilderWithdrawalCredential,
9
- isValidBuilderDepositSignature,
10
- } from "../util/gloas.js";
4
+ import {isBuilderWithdrawalCredential, isValidBuilderDepositSignature} from "../util/gloas.js";
5
+ import {IndexedBuilderState} from "./indexedBuilderState.js";
11
6
 
12
7
  /**
13
8
  * Process a builder deposit request from the execution layer: register a new builder
@@ -16,9 +11,10 @@ import {
16
11
  * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md#new-process_builder_deposit_request
17
12
  */
18
13
  export function processBuilderDepositRequest(
19
- state: CachedBeaconStateGloas,
14
+ indexedState: IndexedBuilderState,
20
15
  request: gloas.BuilderDepositRequest
21
16
  ): void {
17
+ const {state} = indexedState;
22
18
  const {pubkey, withdrawalCredentials, amount, signature} = request;
23
19
 
24
20
  // Ignore deposits with unexpected withdrawal credential prefixes.
@@ -26,18 +22,11 @@ export function processBuilderDepositRequest(
26
22
  return;
27
23
  }
28
24
 
29
- const builderIndex = findBuilderIndexByPubkey(state, pubkey);
25
+ const builderIndex = indexedState.findBuilderIndexByPubkey(pubkey);
30
26
 
31
27
  if (builderIndex === null) {
32
28
  if (isValidBuilderDepositSignature(state.config, pubkey, withdrawalCredentials, amount, signature)) {
33
- addBuilderToRegistry(
34
- state,
35
- pubkey,
36
- PAYLOAD_BUILDER_VERSION,
37
- withdrawalCredentials.subarray(12),
38
- amount,
39
- state.slot
40
- );
29
+ indexedState.addBuilderToRegistry(pubkey, PAYLOAD_BUILDER_VERSION, withdrawalCredentials.subarray(12), amount);
41
30
  }
42
31
  return;
43
32
  }
@@ -1,12 +1,7 @@
1
1
  import {gloas} from "@lodestar/types";
2
2
  import {byteArrayEquals} from "@lodestar/utils";
3
- import {CachedBeaconStateGloas} from "../types.js";
4
- import {
5
- findBuilderIndexByPubkey,
6
- getPendingBalanceToWithdrawForBuilder,
7
- initiateBuilderExit,
8
- isActiveBuilder,
9
- } from "../util/gloas.js";
3
+ import {getPendingBalanceToWithdrawForBuilder, initiateBuilderExit, isActiveBuilder} from "../util/gloas.js";
4
+ import {IndexedBuilderState} from "./indexedBuilderState.js";
10
5
 
11
6
  /**
12
7
  * Apply a builder exit request. Authorizes the exit via `source_address` (the builder's
@@ -17,8 +12,9 @@ import {
17
12
  *
18
13
  * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md#new-process_builder_exit_request
19
14
  */
20
- export function processBuilderExitRequest(state: CachedBeaconStateGloas, request: gloas.BuilderExitRequest): void {
21
- const builderIndex = findBuilderIndexByPubkey(state, request.pubkey);
15
+ export function processBuilderExitRequest(indexedState: IndexedBuilderState, request: gloas.BuilderExitRequest): void {
16
+ const {state} = indexedState;
17
+ const builderIndex = indexedState.findBuilderIndexByPubkey(request.pubkey);
22
18
  if (builderIndex === null) {
23
19
  return;
24
20
  }
@@ -3,6 +3,7 @@ import {BeaconBlock, gloas, ssz} from "@lodestar/types";
3
3
  import {byteArrayEquals, toRootHex} from "@lodestar/utils";
4
4
  import {CachedBeaconStateGloas} from "../types.js";
5
5
  import {computeEpochAtSlot} from "../util/epoch.js";
6
+ import {IndexedBuilderState} from "./indexedBuilderState.js";
6
7
  import {processBuilderDepositRequest} from "./processBuilderDepositRequest.js";
7
8
  import {processBuilderExitRequest} from "./processBuilderExitRequest.js";
8
9
  import {processConsolidationRequest} from "./processConsolidationRequest.js";
@@ -67,12 +68,14 @@ export function applyParentExecutionPayload(state: CachedBeaconStateGloas, reque
67
68
  processConsolidationRequest(state, consolidation);
68
69
  }
69
70
 
70
- for (const builderDeposit of requests.builderDeposits) {
71
- processBuilderDepositRequest(state, builderDeposit);
72
- }
73
-
74
- for (const builderExit of requests.builderExits) {
75
- processBuilderExitRequest(state, builderExit);
71
+ if (requests.builderDeposits.length > 0 || requests.builderExits.length > 0) {
72
+ const indexedState = new IndexedBuilderState(state);
73
+ for (const builderDeposit of requests.builderDeposits) {
74
+ processBuilderDepositRequest(indexedState, builderDeposit);
75
+ }
76
+ for (const builderExit of requests.builderExits) {
77
+ processBuilderExitRequest(indexedState, builderExit);
78
+ }
76
79
  }
77
80
 
78
81
  // Settle the builder payment
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export {type BlockExternalData, DataAvailabilityStatus, ExecutionPayloadStatus} from "./block/externalData.js";
2
+ export {IndexedBuilderState} from "./block/indexedBuilderState.js";
2
3
  export {getAttestationParticipationStatus, processAttestationsAltair} from "./block/processAttestationsAltair.js";
3
4
  export {assertValidAttesterSlashing} from "./block/processAttesterSlashing.js";
4
5
  export {isValidBlsToExecutionChange} from "./block/processBlsToExecutionChange.js";
@@ -3,7 +3,9 @@ import {BeaconConfig} from "@lodestar/config";
3
3
  import {
4
4
  EFFECTIVE_BALANCE_INCREMENT,
5
5
  ForkName,
6
+ ForkSeq,
6
7
  INACTIVITY_PENALTY_QUOTIENT_ALTAIR,
8
+ INACTIVITY_PENALTY_QUOTIENT_BELLATRIX,
7
9
  MAX_EFFECTIVE_BALANCE,
8
10
  MAX_EFFECTIVE_BALANCE_ELECTRA,
9
11
  PARTICIPATION_FLAG_WEIGHTS,
@@ -16,6 +18,8 @@ import {
16
18
  import {ValidatorIndex, rewards} from "@lodestar/types";
17
19
  import {fromHex} from "@lodestar/utils";
18
20
  import {EpochTransitionCache, beforeProcessEpoch} from "../cache/epochTransitionCache.js";
21
+ import {processInactivityUpdates} from "../epoch/processInactivityUpdates.js";
22
+ import {processJustificationAndFinalization} from "../epoch/processJustificationAndFinalization.js";
19
23
  import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "../types.js";
20
24
  import {
21
25
  FLAG_ELIGIBLE_ATTESTER,
@@ -43,8 +47,13 @@ export async function computeAttestationsRewards(
43
47
  throw Error("Unsupported fork. Attestations rewards calculation is not available in phase0");
44
48
  }
45
49
 
46
- const stateAltair = state as CachedBeaconStateAltair;
50
+ // Rewards are computed after justification and inactivity updates in epoch processing, so apply both to a clone
51
+ // before reading finality and inactivity scores, see
52
+ // https://github.com/ethereum/consensus-specs/blob/v1.7.0-beta.2/specs/altair/beacon-chain.md#epoch-processing
53
+ const stateAltair = state.clone() as CachedBeaconStateAltair;
47
54
  const transitionCache = beforeProcessEpoch(stateAltair);
55
+ processJustificationAndFinalization(stateAltair, transitionCache);
56
+ processInactivityUpdates(stateAltair, transitionCache);
48
57
 
49
58
  const [idealRewards, penalties] = computeIdealAttestationsRewardsAndPenaltiesAltair(
50
59
  config,
@@ -122,9 +131,8 @@ function computeIdealAttestationsRewardsAndPenaltiesAltair(
122
131
  ) {
123
132
  const baseReward = effectiveBalanceByIncrement * baseRewardPerIncrement;
124
133
  const rewardNumerator = baseReward * weight * unslashedStakeByIncrement;
125
- // Both idealReward and penalty are rounded to nearest integer. Loss of precision is minimal as unit is gwei
126
- const idealReward = Math.round(rewardNumerator / activeBalanceByIncrement / WEIGHT_DENOMINATOR);
127
- const penalty = Math.round((baseReward * weight) / WEIGHT_DENOMINATOR); // Positive number indicates penalty
134
+ const idealReward = Math.floor(rewardNumerator / (activeBalanceByIncrement * WEIGHT_DENOMINATOR));
135
+ const penalty = Math.floor((baseReward * weight) / WEIGHT_DENOMINATOR); // Positive number indicates penalty
128
136
 
129
137
  const idealAttestationsReward = idealRewards[effectiveBalanceByIncrement];
130
138
  idealAttestationsReward[flagName] = isInInactivityLeak(state) ? 0 : idealReward; // No attestations rewards during inactivity leak
@@ -156,7 +164,11 @@ function computeTotalAttestationsRewardsAltair(
156
164
  .map((id) => (typeof id === "number" ? id : pubkeyCache.getIndex(fromHex(id))))
157
165
  .filter((index) => index !== undefined); // Validator indices to include in the result
158
166
 
159
- const inactivityPenaltyDenominator = config.INACTIVITY_SCORE_BIAS * INACTIVITY_PENALTY_QUOTIENT_ALTAIR;
167
+ const inactivityPenaltyQuotient =
168
+ config.getForkSeq(state.slot) === ForkSeq.altair
169
+ ? INACTIVITY_PENALTY_QUOTIENT_ALTAIR
170
+ : INACTIVITY_PENALTY_QUOTIENT_BELLATRIX;
171
+ const inactivityPenaltyDenominator = config.INACTIVITY_SCORE_BIAS * inactivityPenaltyQuotient;
160
172
 
161
173
  for (let i = 0; i < flags.length; i++) {
162
174
  if (validatorIndices.length && !validatorIndices.includes(i)) {
@@ -104,6 +104,8 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
104
104
  private _executionPayloadAvailability: BitArray | null = null;
105
105
  private _latestExecutionPayloadBid: ExecutionPayloadBid | null = null;
106
106
  private _payloadExpectedWithdrawals: capella.Withdrawal[] | null = null;
107
+ private _builderPendingPayments: gloas.BuilderPendingPayments | null = null;
108
+ private _builderPendingWithdrawals: gloas.BuilderPendingWithdrawals | null = null;
107
109
 
108
110
  constructor(readonly cachedState: CachedBeaconStateAllForks) {
109
111
  this.config = cachedState.config;
@@ -414,6 +416,30 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
414
416
  return this._payloadExpectedWithdrawals;
415
417
  }
416
418
 
419
+ get builderPendingPayments(): gloas.BuilderPendingPayments {
420
+ if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
421
+ throw new Error("Pending builder payments are not supported before Gloas");
422
+ }
423
+
424
+ if (this._builderPendingPayments === null) {
425
+ this._builderPendingPayments = (this.cachedState as CachedBeaconStateGloas).builderPendingPayments.toValue();
426
+ }
427
+ return this._builderPendingPayments;
428
+ }
429
+
430
+ get builderPendingWithdrawals(): gloas.BuilderPendingWithdrawals {
431
+ if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
432
+ throw new Error("Pending builder withdrawals are not supported before Gloas");
433
+ }
434
+
435
+ if (this._builderPendingWithdrawals === null) {
436
+ this._builderPendingWithdrawals = (
437
+ this.cachedState as CachedBeaconStateGloas
438
+ ).builderPendingWithdrawals.toValue();
439
+ }
440
+ return this._builderPendingWithdrawals;
441
+ }
442
+
417
443
  getBuilder(index: BuilderIndex): gloas.Builder {
418
444
  if (this.config.getForkSeq(this.cachedState.slot) < ForkSeq.gloas) {
419
445
  throw new Error("Builders are not supported before Gloas");