@lodestar/state-transition 1.48.0-dev.e1303d42b0 → 1.48.0-dev.e22a22a11d

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 (51) hide show
  1. package/lib/block/index.d.ts.map +1 -1
  2. package/lib/block/index.js +41 -11
  3. package/lib/block/index.js.map +1 -1
  4. package/lib/block/processOperations.d.ts.map +1 -1
  5. package/lib/block/processOperations.js +62 -33
  6. package/lib/block/processOperations.js.map +1 -1
  7. package/lib/block/processParentExecutionPayload.d.ts.map +1 -1
  8. package/lib/block/processParentExecutionPayload.js +1 -15
  9. package/lib/block/processParentExecutionPayload.js.map +1 -1
  10. package/lib/block/processPayloadAttestation.d.ts +1 -1
  11. package/lib/block/processPayloadAttestation.d.ts.map +1 -1
  12. package/lib/block/processPayloadAttestation.js +2 -2
  13. package/lib/block/processPayloadAttestation.js.map +1 -1
  14. package/lib/block/types.d.ts +30 -0
  15. package/lib/block/types.d.ts.map +1 -1
  16. package/lib/block/types.js +32 -0
  17. package/lib/block/types.js.map +1 -1
  18. package/lib/index.d.ts +1 -1
  19. package/lib/index.d.ts.map +1 -1
  20. package/lib/index.js +1 -1
  21. package/lib/index.js.map +1 -1
  22. package/lib/metrics.d.ts +7 -1
  23. package/lib/metrics.d.ts.map +1 -1
  24. package/lib/metrics.js +12 -1
  25. package/lib/metrics.js.map +1 -1
  26. package/lib/signatureSets/index.d.ts.map +1 -1
  27. package/lib/signatureSets/index.js +8 -0
  28. package/lib/signatureSets/index.js.map +1 -1
  29. package/lib/stateView/beaconStateView.d.ts +4 -0
  30. package/lib/stateView/beaconStateView.d.ts.map +1 -1
  31. package/lib/stateView/beaconStateView.js +9 -0
  32. package/lib/stateView/beaconStateView.js.map +1 -1
  33. package/lib/stateView/interface.d.ts +1 -0
  34. package/lib/stateView/interface.d.ts.map +1 -1
  35. package/lib/stateView/interface.js.map +1 -1
  36. package/lib/stateView/nativeBeaconStateView.d.ts +1 -0
  37. package/lib/stateView/nativeBeaconStateView.d.ts.map +1 -1
  38. package/lib/stateView/nativeBeaconStateView.js +3 -0
  39. package/lib/stateView/nativeBeaconStateView.js.map +1 -1
  40. package/package.json +8 -8
  41. package/src/block/index.ts +48 -15
  42. package/src/block/processOperations.ts +63 -45
  43. package/src/block/processParentExecutionPayload.ts +1 -26
  44. package/src/block/processPayloadAttestation.ts +3 -2
  45. package/src/block/types.ts +32 -0
  46. package/src/index.ts +1 -1
  47. package/src/metrics.ts +13 -2
  48. package/src/signatureSets/index.ts +17 -3
  49. package/src/stateView/beaconStateView.ts +12 -0
  50. package/src/stateView/interface.ts +1 -0
  51. package/src/stateView/nativeBeaconStateView.ts +4 -0
@@ -1,12 +1,4 @@
1
- import {
2
- ForkSeq,
3
- MAX_ATTESTATIONS_ELECTRA,
4
- MAX_ATTESTER_SLASHINGS_ELECTRA,
5
- MAX_BLS_TO_EXECUTION_CHANGES,
6
- MAX_PAYLOAD_ATTESTATIONS,
7
- MAX_PROPOSER_SLASHINGS,
8
- MAX_VOLUNTARY_EXITS,
9
- } from "@lodestar/params";
1
+ import {ForkSeq} from "@lodestar/params";
10
2
  import {BeaconBlockBody, Slot, capella, electra, gloas} from "@lodestar/types";
11
3
  import {BeaconStateTransitionMetrics} from "../metrics.js";
12
4
  import {
@@ -26,7 +18,7 @@ import {processPayloadAttestation} from "./processPayloadAttestation.js";
26
18
  import {processProposerSlashing} from "./processProposerSlashing.js";
27
19
  import {processVoluntaryExit} from "./processVoluntaryExit.js";
28
20
  import {processWithdrawalRequest} from "./processWithdrawalRequest.js";
29
- import {ProcessBlockOpts} from "./types.js";
21
+ import {ProcessBlockOpts, ProcessOperationsStep} from "./types.js";
30
22
 
31
23
  export {
32
24
  processProposerSlashing,
@@ -48,10 +40,6 @@ export function processOperations(
48
40
  opts: ProcessBlockOpts = {verifySignatures: true},
49
41
  metrics?: BeaconStateTransitionMetrics | null
50
42
  ): void {
51
- if (fork >= ForkSeq.gloas) {
52
- assertGloasOperationLimits(body as gloas.BeaconBlockBody);
53
- }
54
-
55
43
  // verify that outstanding deposits are processed up to the maximum number of deposits.
56
44
  // From Fulu the eth1 bridge deposit mechanism was removed, so blocks must not contain any deposits.
57
45
  const maxDeposits = fork >= ForkSeq.fulu ? 0 : getEth1DepositCount(state);
@@ -61,64 +49,94 @@ export function processOperations(
61
49
  );
62
50
  }
63
51
 
64
- for (const proposerSlashing of body.proposerSlashings) {
65
- processProposerSlashing(fork, state, proposerSlashing, opts.verifySignatures);
52
+ {
53
+ const timer = metrics?.processOperationsStepTime.startTimer({step: ProcessOperationsStep.processProposerSlashing});
54
+ for (const proposerSlashing of body.proposerSlashings) {
55
+ processProposerSlashing(fork, state, proposerSlashing, opts.verifySignatures);
56
+ }
57
+ timer?.();
66
58
  }
67
- for (const attesterSlashing of body.attesterSlashings) {
68
- processAttesterSlashing(fork, state, attesterSlashing, opts.verifySignatures);
59
+
60
+ {
61
+ const timer = metrics?.processOperationsStepTime.startTimer({step: ProcessOperationsStep.processAttesterSlashing});
62
+ for (const attesterSlashing of body.attesterSlashings) {
63
+ processAttesterSlashing(fork, state, attesterSlashing, opts.verifySignatures);
64
+ }
65
+ timer?.();
69
66
  }
70
67
 
71
- processAttestations(fork, state, body.attestations, parentSlot, opts.verifySignatures, metrics);
68
+ {
69
+ const timer = metrics?.processOperationsStepTime.startTimer({step: ProcessOperationsStep.processAttestations});
70
+ processAttestations(fork, state, body.attestations, parentSlot, opts.verifySignatures, metrics);
71
+ timer?.();
72
+ }
72
73
 
73
- for (const deposit of body.deposits) {
74
- processDeposit(fork, state, deposit);
74
+ {
75
+ const timer = metrics?.processOperationsStepTime.startTimer({step: ProcessOperationsStep.processDeposit});
76
+ for (const deposit of body.deposits) {
77
+ processDeposit(fork, state, deposit);
78
+ }
79
+ timer?.();
75
80
  }
76
81
 
77
- for (const voluntaryExit of body.voluntaryExits) {
78
- processVoluntaryExit(fork, state, voluntaryExit, opts.verifySignatures);
82
+ {
83
+ const timer = metrics?.processOperationsStepTime.startTimer({step: ProcessOperationsStep.processVoluntaryExit});
84
+ for (const voluntaryExit of body.voluntaryExits) {
85
+ processVoluntaryExit(fork, state, voluntaryExit, opts.verifySignatures);
86
+ }
87
+ timer?.();
79
88
  }
80
89
 
81
90
  if (fork >= ForkSeq.capella) {
91
+ const timer = metrics?.processOperationsStepTime.startTimer({
92
+ step: ProcessOperationsStep.processBlsToExecutionChange,
93
+ });
82
94
  for (const blsToExecutionChange of (body as capella.BeaconBlockBody).blsToExecutionChanges) {
83
95
  processBlsToExecutionChange(state as CachedBeaconStateCapella, blsToExecutionChange);
84
96
  }
97
+ timer?.();
85
98
  }
86
99
 
87
100
  if (fork >= ForkSeq.electra && fork < ForkSeq.gloas) {
88
101
  const stateElectra = state as CachedBeaconStateElectra;
89
102
  const bodyElectra = body as electra.BeaconBlockBody;
90
103
 
91
- for (const depositRequest of bodyElectra.executionRequests.deposits) {
92
- processDepositRequest(fork, stateElectra, depositRequest);
104
+ {
105
+ const timer = metrics?.processOperationsStepTime.startTimer({step: ProcessOperationsStep.processDepositRequest});
106
+ for (const depositRequest of bodyElectra.executionRequests.deposits) {
107
+ processDepositRequest(fork, stateElectra, depositRequest);
108
+ }
109
+ timer?.();
93
110
  }
94
111
 
95
- for (const elWithdrawalRequest of bodyElectra.executionRequests.withdrawals) {
96
- processWithdrawalRequest(fork, stateElectra, elWithdrawalRequest);
112
+ {
113
+ const timer = metrics?.processOperationsStepTime.startTimer({
114
+ step: ProcessOperationsStep.processWithdrawalRequest,
115
+ });
116
+ for (const elWithdrawalRequest of bodyElectra.executionRequests.withdrawals) {
117
+ processWithdrawalRequest(fork, stateElectra, elWithdrawalRequest);
118
+ }
119
+ timer?.();
97
120
  }
98
121
 
99
- for (const elConsolidationRequest of bodyElectra.executionRequests.consolidations) {
100
- processConsolidationRequest(stateElectra, elConsolidationRequest);
122
+ {
123
+ const timer = metrics?.processOperationsStepTime.startTimer({
124
+ step: ProcessOperationsStep.processConsolidationRequest,
125
+ });
126
+ for (const elConsolidationRequest of bodyElectra.executionRequests.consolidations) {
127
+ processConsolidationRequest(stateElectra, elConsolidationRequest);
128
+ }
129
+ timer?.();
101
130
  }
102
131
  }
103
132
 
104
133
  if (fork >= ForkSeq.gloas) {
134
+ const timer = metrics?.processOperationsStepTime.startTimer({
135
+ step: ProcessOperationsStep.processPayloadAttestation,
136
+ });
105
137
  for (const payloadAttestation of (body as gloas.BeaconBlockBody).payloadAttestations) {
106
- processPayloadAttestation(state as CachedBeaconStateGloas, payloadAttestation);
138
+ processPayloadAttestation(state as CachedBeaconStateGloas, payloadAttestation, opts.verifySignatures);
107
139
  }
108
- }
109
- }
110
-
111
- function assertGloasOperationLimits(body: gloas.BeaconBlockBody): void {
112
- assertMaxLength("proposerSlashings", body.proposerSlashings.length, MAX_PROPOSER_SLASHINGS);
113
- assertMaxLength("attesterSlashings", body.attesterSlashings.length, MAX_ATTESTER_SLASHINGS_ELECTRA);
114
- assertMaxLength("attestations", body.attestations.length, MAX_ATTESTATIONS_ELECTRA);
115
- assertMaxLength("voluntaryExits", body.voluntaryExits.length, MAX_VOLUNTARY_EXITS);
116
- assertMaxLength("blsToExecutionChanges", body.blsToExecutionChanges.length, MAX_BLS_TO_EXECUTION_CHANGES);
117
- assertMaxLength("payloadAttestations", body.payloadAttestations.length, MAX_PAYLOAD_ATTESTATIONS);
118
- }
119
-
120
- function assertMaxLength(name: string, length: number, limit: number): void {
121
- if (length > limit) {
122
- throw new Error(`Block contains too many ${name}: count=${length} limit=${limit}`);
140
+ timer?.();
123
141
  }
124
142
  }
@@ -1,12 +1,4 @@
1
- import {
2
- ForkPostGloas,
3
- MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD,
4
- MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD,
5
- MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD,
6
- MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD,
7
- SLOTS_PER_EPOCH,
8
- SLOTS_PER_HISTORICAL_ROOT,
9
- } from "@lodestar/params";
1
+ import {ForkPostGloas, SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
10
2
  import {BeaconBlock, gloas, ssz} from "@lodestar/types";
11
3
  import {byteArrayEquals, toRootHex} from "@lodestar/utils";
12
4
  import {CachedBeaconStateGloas} from "../types.js";
@@ -55,8 +47,6 @@ export function processParentExecutionPayload(state: CachedBeaconStateGloas, blo
55
47
  * Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-apply_parent_execution_payload
56
48
  */
57
49
  export function applyParentExecutionPayload(state: CachedBeaconStateGloas, requests: gloas.ExecutionRequests): void {
58
- assertExecutionRequestsWithinLimits(requests);
59
-
60
50
  const fork = state.config.getForkSeq(state.slot);
61
51
  const parentBid = state.latestExecutionPayloadBid;
62
52
  const parentSlot = state.latestBlockHeader.slot;
@@ -126,21 +116,6 @@ function settleBuilderPayment(state: CachedBeaconStateGloas, paymentIndex: numbe
126
116
  state.builderPendingPayments.set(paymentIndex, ssz.gloas.BuilderPendingPayment.defaultViewDU());
127
117
  }
128
118
 
129
- function assertExecutionRequestsWithinLimits(requests: gloas.ExecutionRequests): void {
130
- assertMaxLength("withdrawals", requests.withdrawals.length, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD);
131
- assertMaxLength("consolidations", requests.consolidations.length, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD);
132
- // New in GLOAS:EIP8282
133
- assertMaxLength("builderDeposits", requests.builderDeposits.length, MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD);
134
- // New in GLOAS:EIP8282
135
- assertMaxLength("builderExits", requests.builderExits.length, MAX_BUILDER_EXIT_REQUESTS_PER_PAYLOAD);
136
- }
137
-
138
- function assertMaxLength(name: string, length: number, limit: number): void {
139
- if (length > limit) {
140
- throw new Error(`Too many parent execution request ${name} count=${length} limit=${limit}`);
141
- }
142
- }
143
-
144
119
  function assertEmptyExecutionRequests(requests: gloas.ExecutionRequests): void {
145
120
  if (
146
121
  requests.deposits.length !== 0 ||
@@ -5,7 +5,8 @@ import {isValidIndexedPayloadAttestation} from "./isValidIndexedPayloadAttestati
5
5
 
6
6
  export function processPayloadAttestation(
7
7
  state: CachedBeaconStateGloas,
8
- payloadAttestation: gloas.PayloadAttestation
8
+ payloadAttestation: gloas.PayloadAttestation,
9
+ verifySignature = true
9
10
  ): void {
10
11
  const data = payloadAttestation.data;
11
12
 
@@ -19,7 +20,7 @@ export function processPayloadAttestation(
19
20
 
20
21
  const indexedPayloadAttestation = state.epochCtx.getIndexedPayloadAttestation(data.slot, payloadAttestation);
21
22
 
22
- if (!isValidIndexedPayloadAttestation(state, indexedPayloadAttestation, true)) {
23
+ if (!isValidIndexedPayloadAttestation(state, indexedPayloadAttestation, verifySignature)) {
23
24
  throw Error("Invalid payload attestation");
24
25
  }
25
26
  }
@@ -7,3 +7,35 @@ export enum ProposerRewardType {
7
7
  syncAggregate = "sync_aggregate",
8
8
  slashing = "slashing",
9
9
  }
10
+
11
+ /**
12
+ * Steps of `processBlock()` tracked in metrics
13
+ */
14
+ export enum BlockProcessStep {
15
+ processParentExecutionPayload = "processParentExecutionPayload",
16
+ processBlockHeader = "processBlockHeader",
17
+ processWithdrawals = "processWithdrawals",
18
+ processExecutionPayload = "processExecutionPayload",
19
+ processExecutionPayloadBid = "processExecutionPayloadBid",
20
+ processRandao = "processRandao",
21
+ processEth1Data = "processEth1Data",
22
+ processOperations = "processOperations",
23
+ processSyncAggregate = "processSyncAggregate",
24
+ processBlobKzgCommitments = "processBlobKzgCommitments",
25
+ }
26
+
27
+ /**
28
+ * Steps of `processOperations()` tracked in metrics
29
+ */
30
+ export enum ProcessOperationsStep {
31
+ processProposerSlashing = "processProposerSlashing",
32
+ processAttesterSlashing = "processAttesterSlashing",
33
+ processAttestations = "processAttestations",
34
+ processDeposit = "processDeposit",
35
+ processVoluntaryExit = "processVoluntaryExit",
36
+ processBlsToExecutionChange = "processBlsToExecutionChange",
37
+ processDepositRequest = "processDepositRequest",
38
+ processWithdrawalRequest = "processWithdrawalRequest",
39
+ processConsolidationRequest = "processConsolidationRequest",
40
+ processPayloadAttestation = "processPayloadAttestation",
41
+ }
package/src/index.ts CHANGED
@@ -13,7 +13,7 @@ export {
13
13
  } from "./block/processVoluntaryExit.js";
14
14
  // Withdrawals for new blocks
15
15
  export {getExpectedWithdrawals} from "./block/processWithdrawals.js";
16
- export {ProposerRewardType} from "./block/types.js";
16
+ export {BlockProcessStep, ProcessOperationsStep, ProposerRewardType} from "./block/types.js";
17
17
  export {
18
18
  type EffectiveBalanceIncrements,
19
19
  getEffectiveBalanceIncrementsWithLen,
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",
@@ -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
  }
@@ -456,6 +456,18 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
456
456
  }
457
457
  throw new Error(`PTC committees are not available for epoch=${epoch}`);
458
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
+
459
471
  /**
460
472
  * Return all positions of the validator in the PTC committee for the given slot.
461
473
  *
@@ -285,6 +285,7 @@ export interface IBeaconStateViewGloas extends IBeaconStateViewFulu {
285
285
  getBuildersLength(): number;
286
286
  canBuilderCoverBid(builderIndex: BuilderIndex, bidAmount: number): boolean;
287
287
  getEpochPTCs(epoch: Epoch): Uint32Array[];
288
+ getPayloadTimelinessCommittee(slot: Slot): Uint32Array;
288
289
  getIndicesInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number[];
289
290
  /**
290
291
  * Clone the state and apply parent execution payload effects.
@@ -926,6 +926,10 @@ export class NativeBeaconStateView implements IBeaconStateViewLatestFork {
926
926
  return cached;
927
927
  }
928
928
 
929
+ getPayloadTimelinessCommittee(slot: Slot): Uint32Array {
930
+ return this.binding.getPayloadTimelinessCommittee(slot);
931
+ }
932
+
929
933
  getIndicesInPayloadTimelinessCommittee(validatorIndex: ValidatorIndex, slot: Slot): number[] {
930
934
  return this.binding.getIndicesInPayloadTimelinessCommittee(validatorIndex, slot);
931
935
  }