@lodestar/state-transition 1.48.0-dev.7c6505e8e6 → 1.48.0-dev.82e7577c8b
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.
- package/lib/block/index.d.ts.map +1 -1
- package/lib/block/index.js +44 -13
- package/lib/block/index.js.map +1 -1
- package/lib/block/processExecutionPayloadBid.d.ts +2 -2
- package/lib/block/processExecutionPayloadBid.d.ts.map +1 -1
- package/lib/block/processExecutionPayloadBid.js +0 -2
- package/lib/block/processExecutionPayloadBid.js.map +1 -1
- package/lib/block/processOperations.d.ts.map +1 -1
- package/lib/block/processOperations.js +62 -33
- package/lib/block/processOperations.js.map +1 -1
- package/lib/block/processParentExecutionPayload.d.ts.map +1 -1
- package/lib/block/processParentExecutionPayload.js +2 -16
- package/lib/block/processParentExecutionPayload.js.map +1 -1
- package/lib/block/processPayloadAttestation.d.ts +1 -1
- package/lib/block/processPayloadAttestation.d.ts.map +1 -1
- package/lib/block/processPayloadAttestation.js +2 -2
- package/lib/block/processPayloadAttestation.js.map +1 -1
- package/lib/block/types.d.ts +30 -0
- package/lib/block/types.d.ts.map +1 -1
- package/lib/block/types.js +32 -0
- package/lib/block/types.js.map +1 -1
- package/lib/epoch/processPtcWindow.d.ts.map +1 -1
- package/lib/epoch/processPtcWindow.js +12 -9
- package/lib/epoch/processPtcWindow.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/metrics.d.ts +7 -1
- package/lib/metrics.d.ts.map +1 -1
- package/lib/metrics.js +12 -1
- package/lib/metrics.js.map +1 -1
- package/lib/rewards/blockRewards.d.ts.map +1 -1
- package/lib/rewards/blockRewards.js +1 -3
- package/lib/rewards/blockRewards.js.map +1 -1
- package/lib/signatureSets/index.d.ts.map +1 -1
- package/lib/signatureSets/index.js +8 -0
- package/lib/signatureSets/index.js.map +1 -1
- package/lib/slot/upgradeStateToGloas.js +1 -1
- package/lib/slot/upgradeStateToGloas.js.map +1 -1
- package/lib/stateView/beaconStateView.d.ts +4 -0
- package/lib/stateView/beaconStateView.d.ts.map +1 -1
- package/lib/stateView/beaconStateView.js +9 -0
- package/lib/stateView/beaconStateView.js.map +1 -1
- package/lib/stateView/interface.d.ts +1 -0
- package/lib/stateView/interface.d.ts.map +1 -1
- package/lib/stateView/interface.js.map +1 -1
- package/lib/stateView/nativeBeaconStateView.d.ts +1 -0
- package/lib/stateView/nativeBeaconStateView.d.ts.map +1 -1
- package/lib/stateView/nativeBeaconStateView.js +3 -0
- package/lib/stateView/nativeBeaconStateView.js.map +1 -1
- package/lib/util/gloas.d.ts.map +1 -1
- package/lib/util/gloas.js +1 -1
- package/lib/util/gloas.js.map +1 -1
- package/lib/util/seed.d.ts +1 -1
- package/lib/util/seed.d.ts.map +1 -1
- package/lib/util/seed.js +14 -11
- package/lib/util/seed.js.map +1 -1
- package/package.json +8 -8
- package/src/block/index.ts +53 -17
- package/src/block/processExecutionPayloadBid.ts +2 -5
- package/src/block/processOperations.ts +63 -45
- package/src/block/processParentExecutionPayload.ts +2 -27
- package/src/block/processPayloadAttestation.ts +3 -2
- package/src/block/types.ts +32 -0
- package/src/epoch/processPtcWindow.ts +15 -8
- package/src/index.ts +1 -1
- package/src/metrics.ts +13 -2
- package/src/rewards/blockRewards.ts +1 -3
- package/src/signatureSets/index.ts +17 -3
- package/src/slot/upgradeStateToGloas.ts +1 -1
- package/src/stateView/beaconStateView.ts +12 -0
- package/src/stateView/interface.ts +1 -0
- package/src/stateView/nativeBeaconStateView.ts +4 -0
- package/src/util/gloas.ts +1 -0
- package/src/util/seed.ts +25 -13
|
@@ -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
|
-
|
|
65
|
-
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
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
|
-
|
|
74
|
-
|
|
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
|
-
|
|
78
|
-
|
|
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
|
-
|
|
92
|
-
|
|
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
|
-
|
|
96
|
-
|
|
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
|
-
|
|
100
|
-
|
|
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,11 +47,9 @@ 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
|
-
const parentSlot =
|
|
52
|
+
const parentSlot = state.latestBlockHeader.slot;
|
|
63
53
|
const parentEpoch = computeEpochAtSlot(parentSlot);
|
|
64
54
|
const currentEpoch = computeEpochAtSlot(state.slot);
|
|
65
55
|
|
|
@@ -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,
|
|
23
|
+
if (!isValidIndexedPayloadAttestation(state, indexedPayloadAttestation, verifySignature)) {
|
|
23
24
|
throw Error("Invalid payload attestation");
|
|
24
25
|
}
|
|
25
26
|
}
|
package/src/block/types.ts
CHANGED
|
@@ -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
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {MIN_SEED_LOOKAHEAD} from "@lodestar/params";
|
|
1
|
+
import {MIN_SEED_LOOKAHEAD, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
2
2
|
import {ssz} from "@lodestar/types";
|
|
3
3
|
import {CachedBeaconStateGloas, EpochTransitionCache} from "../types.js";
|
|
4
4
|
import {computeEpochShuffling} from "../util/epochShuffling.js";
|
|
@@ -22,17 +22,24 @@ export function processPtcWindow(state: CachedBeaconStateGloas, cache: EpochTran
|
|
|
22
22
|
state,
|
|
23
23
|
nextEpoch,
|
|
24
24
|
nextEpochShuffling.committees,
|
|
25
|
+
nextEpochShuffling.shuffling,
|
|
25
26
|
state.epochCtx.effectiveBalanceIncrements
|
|
26
27
|
);
|
|
27
28
|
|
|
28
29
|
// Stash for finalProcessEpoch to shift into epoch cache
|
|
29
30
|
cache.nextEpochPayloadTimelinessCommittees = newNextPayloadTimelinessCommittees;
|
|
30
31
|
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
// Shift the current and next epochs forward by reusing their SSZ subtrees and cached hashes.
|
|
33
|
+
// Only the newly computed epoch needs new subtrees.
|
|
34
|
+
const ptcWindow = state.ptcWindow;
|
|
35
|
+
const retainedLength = ptcWindow.length - SLOTS_PER_EPOCH;
|
|
36
|
+
for (let i = 0; i < retainedLength; i++) {
|
|
37
|
+
ptcWindow.set(i, ptcWindow.getReadonly(i + SLOTS_PER_EPOCH));
|
|
38
|
+
}
|
|
39
|
+
for (let i = 0; i < SLOTS_PER_EPOCH; i++) {
|
|
40
|
+
ptcWindow.set(
|
|
41
|
+
retainedLength + i,
|
|
42
|
+
ssz.gloas.PayloadTimelinessCommittee.toViewDU(newNextPayloadTimelinessCommittees[i])
|
|
43
|
+
);
|
|
44
|
+
}
|
|
38
45
|
}
|
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",
|
|
@@ -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.
|
|
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);
|
|
@@ -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
|
}
|
package/src/util/gloas.ts
CHANGED
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
|
-
|
|
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
|
}
|