@lodestar/state-transition 1.38.0-dev.548d7aa41e → 1.38.0-dev.688d5584ea
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 +4 -1
- package/lib/block/index.d.ts.map +1 -1
- package/lib/block/index.js +19 -8
- package/lib/block/index.js.map +1 -1
- package/lib/block/isValidIndexedPayloadAttestation.d.ts +4 -0
- package/lib/block/isValidIndexedPayloadAttestation.d.ts.map +1 -0
- package/lib/block/isValidIndexedPayloadAttestation.js +14 -0
- package/lib/block/isValidIndexedPayloadAttestation.js.map +1 -0
- package/lib/block/processAttestationPhase0.d.ts.map +1 -1
- package/lib/block/processAttestationPhase0.js +6 -1
- package/lib/block/processAttestationPhase0.js.map +1 -1
- package/lib/block/processAttestationsAltair.d.ts +3 -3
- package/lib/block/processAttestationsAltair.d.ts.map +1 -1
- package/lib/block/processAttestationsAltair.js +46 -4
- package/lib/block/processAttestationsAltair.js.map +1 -1
- package/lib/block/processConsolidationRequest.d.ts +3 -2
- package/lib/block/processConsolidationRequest.d.ts.map +1 -1
- package/lib/block/processConsolidationRequest.js +2 -2
- package/lib/block/processConsolidationRequest.js.map +1 -1
- package/lib/block/processDepositRequest.d.ts +2 -2
- package/lib/block/processDepositRequest.d.ts.map +1 -1
- package/lib/block/processDepositRequest.js.map +1 -1
- package/lib/block/processExecutionPayloadBid.d.ts +5 -0
- package/lib/block/processExecutionPayloadBid.d.ts.map +1 -0
- package/lib/block/processExecutionPayloadBid.js +89 -0
- package/lib/block/processExecutionPayloadBid.js.map +1 -0
- package/lib/block/processExecutionPayloadEnvelope.d.ts +4 -0
- package/lib/block/processExecutionPayloadEnvelope.d.ts.map +1 -0
- package/lib/block/processExecutionPayloadEnvelope.js +118 -0
- package/lib/block/processExecutionPayloadEnvelope.js.map +1 -0
- package/lib/block/processOperations.d.ts.map +1 -1
- package/lib/block/processOperations.js +8 -2
- package/lib/block/processOperations.js.map +1 -1
- package/lib/block/processPayloadAttestation.d.ts +4 -0
- package/lib/block/processPayloadAttestation.d.ts.map +1 -0
- package/lib/block/processPayloadAttestation.js +16 -0
- package/lib/block/processPayloadAttestation.js.map +1 -0
- package/lib/block/processProposerSlashing.d.ts.map +1 -1
- package/lib/block/processProposerSlashing.js +16 -1
- package/lib/block/processProposerSlashing.js.map +1 -1
- package/lib/block/processVoluntaryExit.js +1 -1
- package/lib/block/processVoluntaryExit.js.map +1 -1
- package/lib/block/processWithdrawalRequest.d.ts +2 -2
- package/lib/block/processWithdrawalRequest.d.ts.map +1 -1
- package/lib/block/processWithdrawalRequest.js +1 -1
- package/lib/block/processWithdrawalRequest.js.map +1 -1
- package/lib/block/processWithdrawals.d.ts +4 -3
- package/lib/block/processWithdrawals.d.ts.map +1 -1
- package/lib/block/processWithdrawals.js +89 -19
- package/lib/block/processWithdrawals.js.map +1 -1
- package/lib/cache/epochCache.d.ts +5 -1
- package/lib/cache/epochCache.d.ts.map +1 -1
- package/lib/cache/epochCache.js +34 -1
- package/lib/cache/epochCache.js.map +1 -1
- package/lib/epoch/index.d.ts +4 -2
- package/lib/epoch/index.d.ts.map +1 -1
- package/lib/epoch/index.js +10 -1
- package/lib/epoch/index.js.map +1 -1
- package/lib/epoch/processBuilderPendingPayments.d.ts +6 -0
- package/lib/epoch/processBuilderPendingPayments.d.ts.map +1 -0
- package/lib/epoch/processBuilderPendingPayments.js +28 -0
- package/lib/epoch/processBuilderPendingPayments.js.map +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/signatureSets/index.d.ts +3 -2
- package/lib/signatureSets/index.d.ts.map +1 -1
- package/lib/signatureSets/index.js +3 -2
- package/lib/signatureSets/index.js.map +1 -1
- package/lib/signatureSets/indexedAttestation.d.ts +1 -1
- package/lib/signatureSets/indexedAttestation.d.ts.map +1 -1
- package/lib/signatureSets/indexedAttestation.js +5 -3
- package/lib/signatureSets/indexedAttestation.js.map +1 -1
- package/lib/signatureSets/indexedPayloadAttestation.d.ts +6 -0
- package/lib/signatureSets/indexedPayloadAttestation.d.ts.map +1 -0
- package/lib/signatureSets/indexedPayloadAttestation.js +11 -0
- package/lib/signatureSets/indexedPayloadAttestation.js.map +1 -0
- package/lib/slot/index.d.ts +2 -1
- package/lib/slot/index.d.ts.map +1 -1
- package/lib/slot/index.js +6 -2
- package/lib/slot/index.js.map +1 -1
- package/lib/slot/upgradeStateToAltair.js +1 -1
- package/lib/slot/upgradeStateToAltair.js.map +1 -1
- package/lib/slot/upgradeStateToGloas.d.ts +0 -1
- package/lib/slot/upgradeStateToGloas.d.ts.map +1 -1
- package/lib/slot/upgradeStateToGloas.js +47 -5
- package/lib/slot/upgradeStateToGloas.js.map +1 -1
- package/lib/stateTransition.js +4 -3
- package/lib/stateTransition.js.map +1 -1
- package/lib/util/electra.d.ts +5 -5
- package/lib/util/electra.d.ts.map +1 -1
- package/lib/util/electra.js +2 -1
- package/lib/util/electra.js.map +1 -1
- package/lib/util/epoch.d.ts +3 -3
- package/lib/util/epoch.d.ts.map +1 -1
- package/lib/util/epoch.js.map +1 -1
- package/lib/util/gloas.d.ts +11 -0
- package/lib/util/gloas.d.ts.map +1 -0
- package/lib/util/gloas.js +35 -0
- package/lib/util/gloas.js.map +1 -0
- package/lib/util/seed.d.ts +5 -1
- package/lib/util/seed.d.ts.map +1 -1
- package/lib/util/seed.js +33 -1
- package/lib/util/seed.js.map +1 -1
- package/lib/util/validator.d.ts +2 -2
- package/lib/util/validator.d.ts.map +1 -1
- package/lib/util/validator.js +14 -1
- package/lib/util/validator.js.map +1 -1
- package/package.json +6 -6
- package/src/block/index.ts +35 -14
- package/src/block/isValidIndexedPayloadAttestation.ts +23 -0
- package/src/block/processAttestationPhase0.ts +5 -1
- package/src/block/processAttestationsAltair.ts +62 -5
- package/src/block/processConsolidationRequest.ts +6 -5
- package/src/block/processDepositRequest.ts +5 -2
- package/src/block/processExecutionPayloadBid.ts +120 -0
- package/src/block/processExecutionPayloadEnvelope.ts +181 -0
- package/src/block/processOperations.ts +16 -4
- package/src/block/processPayloadAttestation.ts +25 -0
- package/src/block/processProposerSlashing.ts +24 -3
- package/src/block/processVoluntaryExit.ts +1 -1
- package/src/block/processWithdrawalRequest.ts +4 -4
- package/src/block/processWithdrawals.ts +118 -27
- package/src/cache/epochCache.ts +58 -1
- package/src/epoch/index.ts +12 -0
- package/src/epoch/processBuilderPendingPayments.ts +31 -0
- package/src/index.ts +2 -0
- package/src/signatureSets/index.ts +4 -2
- package/src/signatureSets/indexedAttestation.ts +8 -8
- package/src/signatureSets/indexedPayloadAttestation.ts +24 -0
- package/src/slot/index.ts +11 -3
- package/src/slot/upgradeStateToAltair.ts +2 -1
- package/src/slot/upgradeStateToGloas.ts +49 -5
- package/src/stateTransition.ts +4 -4
- package/src/util/electra.ts +15 -6
- package/src/util/epoch.ts +6 -3
- package/src/util/gloas.ts +58 -0
- package/src/util/seed.ts +57 -1
- package/src/util/validator.ts +21 -2
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import {ForkSeq} from "@lodestar/params";
|
|
2
|
-
import {BeaconBlockBody, capella, electra} from "@lodestar/types";
|
|
2
|
+
import {BeaconBlockBody, capella, electra, gloas} from "@lodestar/types";
|
|
3
3
|
import {BeaconStateTransitionMetrics} from "../metrics.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
CachedBeaconStateAllForks,
|
|
6
|
+
CachedBeaconStateCapella,
|
|
7
|
+
CachedBeaconStateElectra,
|
|
8
|
+
CachedBeaconStateGloas,
|
|
9
|
+
} from "../types.js";
|
|
5
10
|
import {getEth1DepositCount} from "../util/deposit.js";
|
|
6
11
|
import {processAttestations} from "./processAttestations.js";
|
|
7
12
|
import {processAttesterSlashing} from "./processAttesterSlashing.js";
|
|
@@ -9,6 +14,7 @@ import {processBlsToExecutionChange} from "./processBlsToExecutionChange.js";
|
|
|
9
14
|
import {processConsolidationRequest} from "./processConsolidationRequest.js";
|
|
10
15
|
import {processDeposit} from "./processDeposit.js";
|
|
11
16
|
import {processDepositRequest} from "./processDepositRequest.js";
|
|
17
|
+
import {processPayloadAttestation} from "./processPayloadAttestation.ts";
|
|
12
18
|
import {processProposerSlashing} from "./processProposerSlashing.js";
|
|
13
19
|
import {processVoluntaryExit} from "./processVoluntaryExit.js";
|
|
14
20
|
import {processWithdrawalRequest} from "./processWithdrawalRequest.js";
|
|
@@ -64,7 +70,7 @@ export function processOperations(
|
|
|
64
70
|
}
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
if (fork >= ForkSeq.electra) {
|
|
73
|
+
if (fork >= ForkSeq.electra && fork < ForkSeq.gloas) {
|
|
68
74
|
const stateElectra = state as CachedBeaconStateElectra;
|
|
69
75
|
const bodyElectra = body as electra.BeaconBlockBody;
|
|
70
76
|
|
|
@@ -77,7 +83,13 @@ export function processOperations(
|
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
for (const elConsolidationRequest of bodyElectra.executionRequests.consolidations) {
|
|
80
|
-
processConsolidationRequest(stateElectra, elConsolidationRequest);
|
|
86
|
+
processConsolidationRequest(fork, stateElectra, elConsolidationRequest);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (fork >= ForkSeq.gloas) {
|
|
91
|
+
for (const payloadAttestation of (body as gloas.BeaconBlockBody).payloadAttestations) {
|
|
92
|
+
processPayloadAttestation(state as CachedBeaconStateGloas, payloadAttestation);
|
|
81
93
|
}
|
|
82
94
|
}
|
|
83
95
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {byteArrayEquals} from "@chainsafe/ssz";
|
|
2
|
+
import {gloas} from "@lodestar/types";
|
|
3
|
+
import {CachedBeaconStateGloas} from "../types.ts";
|
|
4
|
+
import {isValidIndexedPayloadAttestation} from "./isValidIndexedPayloadAttestation.ts";
|
|
5
|
+
|
|
6
|
+
export function processPayloadAttestation(
|
|
7
|
+
state: CachedBeaconStateGloas,
|
|
8
|
+
payloadAttestation: gloas.PayloadAttestation
|
|
9
|
+
): void {
|
|
10
|
+
const data = payloadAttestation.data;
|
|
11
|
+
|
|
12
|
+
if (!byteArrayEquals(data.beaconBlockRoot, state.latestBlockHeader.parentRoot)) {
|
|
13
|
+
throw Error("Payload attestation is referring to the wrong block");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (data.slot + 1 !== state.slot) {
|
|
17
|
+
throw Error("Payload attestation is not from previous slot");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const indexedPayloadAttestation = state.epochCtx.getIndexedPayloadAttestation(data.slot, payloadAttestation);
|
|
21
|
+
|
|
22
|
+
if (!isValidIndexedPayloadAttestation(state, indexedPayloadAttestation, true)) {
|
|
23
|
+
throw Error("Invalid payload attestation");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {ForkSeq} from "@lodestar/params";
|
|
1
|
+
import {ForkSeq, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
2
2
|
import {phase0, ssz} from "@lodestar/types";
|
|
3
3
|
import {getProposerSlashingSignatureSets} from "../signatureSets/index.js";
|
|
4
|
-
import {CachedBeaconStateAllForks} from "../types.js";
|
|
5
|
-
import {isSlashableValidator} from "../util/index.js";
|
|
4
|
+
import {CachedBeaconStateAllForks, CachedBeaconStateGloas} from "../types.js";
|
|
5
|
+
import {computeEpochAtSlot, isSlashableValidator} from "../util/index.js";
|
|
6
6
|
import {verifySignatureSet} from "../util/signatureSets.js";
|
|
7
7
|
import {slashValidator} from "./slashValidator.js";
|
|
8
8
|
|
|
@@ -20,6 +20,27 @@ export function processProposerSlashing(
|
|
|
20
20
|
): void {
|
|
21
21
|
assertValidProposerSlashing(state, proposerSlashing, verifySignatures);
|
|
22
22
|
|
|
23
|
+
if (fork >= ForkSeq.gloas) {
|
|
24
|
+
const slot = Number(proposerSlashing.signedHeader1.message.slot);
|
|
25
|
+
const proposalEpoch = computeEpochAtSlot(slot);
|
|
26
|
+
const currentEpoch = state.epochCtx.epoch;
|
|
27
|
+
const previousEpoch = currentEpoch - 1;
|
|
28
|
+
|
|
29
|
+
const paymentIndex =
|
|
30
|
+
proposalEpoch === currentEpoch
|
|
31
|
+
? SLOTS_PER_EPOCH + (slot % SLOTS_PER_EPOCH)
|
|
32
|
+
: proposalEpoch === previousEpoch
|
|
33
|
+
? slot % SLOTS_PER_EPOCH
|
|
34
|
+
: undefined;
|
|
35
|
+
|
|
36
|
+
if (paymentIndex !== undefined) {
|
|
37
|
+
(state as CachedBeaconStateGloas).builderPendingPayments.set(
|
|
38
|
+
paymentIndex,
|
|
39
|
+
ssz.gloas.BuilderPendingPayment.defaultViewDU()
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
23
44
|
slashValidator(fork, state, proposerSlashing.signedHeader1.message.proposerIndex);
|
|
24
45
|
}
|
|
25
46
|
|
|
@@ -69,7 +69,7 @@ export function getVoluntaryExitValidity(
|
|
|
69
69
|
// only exit validator if it has no pending withdrawals in the queue
|
|
70
70
|
if (
|
|
71
71
|
fork >= ForkSeq.electra &&
|
|
72
|
-
getPendingBalanceToWithdraw(state as CachedBeaconStateElectra, voluntaryExit.validatorIndex) !== 0
|
|
72
|
+
getPendingBalanceToWithdraw(fork, state as CachedBeaconStateElectra, voluntaryExit.validatorIndex) !== 0
|
|
73
73
|
) {
|
|
74
74
|
return VoluntaryExitValidity.pendingWithdrawals;
|
|
75
75
|
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "@lodestar/params";
|
|
8
8
|
import {electra, phase0, ssz} from "@lodestar/types";
|
|
9
9
|
import {toHex} from "@lodestar/utils";
|
|
10
|
-
import {CachedBeaconStateElectra} from "../types.js";
|
|
10
|
+
import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
11
11
|
import {hasCompoundingWithdrawalCredential, hasExecutionWithdrawalCredential} from "../util/electra.js";
|
|
12
12
|
import {computeExitEpochAndUpdateChurn} from "../util/epoch.js";
|
|
13
13
|
import {getPendingBalanceToWithdraw, isActiveValidator} from "../util/validator.js";
|
|
@@ -15,7 +15,7 @@ import {initiateValidatorExit} from "./initiateValidatorExit.js";
|
|
|
15
15
|
|
|
16
16
|
export function processWithdrawalRequest(
|
|
17
17
|
fork: ForkSeq,
|
|
18
|
-
state: CachedBeaconStateElectra,
|
|
18
|
+
state: CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
19
19
|
withdrawalRequest: electra.WithdrawalRequest
|
|
20
20
|
): void {
|
|
21
21
|
const amount = Number(withdrawalRequest.amount);
|
|
@@ -42,7 +42,7 @@ export function processWithdrawalRequest(
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// TODO Electra: Consider caching pendingPartialWithdrawals
|
|
45
|
-
const pendingBalanceToWithdraw = getPendingBalanceToWithdraw(state, validatorIndex);
|
|
45
|
+
const pendingBalanceToWithdraw = getPendingBalanceToWithdraw(fork, state, validatorIndex);
|
|
46
46
|
const validatorBalance = state.balances.get(validatorIndex);
|
|
47
47
|
|
|
48
48
|
if (isFullExitRequest) {
|
|
@@ -81,7 +81,7 @@ export function processWithdrawalRequest(
|
|
|
81
81
|
function isValidatorEligibleForWithdrawOrExit(
|
|
82
82
|
validator: phase0.Validator,
|
|
83
83
|
sourceAddress: Uint8Array,
|
|
84
|
-
state: CachedBeaconStateElectra
|
|
84
|
+
state: CachedBeaconStateElectra | CachedBeaconStateGloas
|
|
85
85
|
): boolean {
|
|
86
86
|
const {withdrawalCredentials} = validator;
|
|
87
87
|
const addressStr = toHex(withdrawalCredentials.subarray(12));
|
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
} from "@lodestar/params";
|
|
11
11
|
import {ValidatorIndex, capella, ssz} from "@lodestar/types";
|
|
12
12
|
import {MapDef, toRootHex} from "@lodestar/utils";
|
|
13
|
-
import {CachedBeaconStateCapella, CachedBeaconStateElectra} from "../types.js";
|
|
13
|
+
import {CachedBeaconStateCapella, CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
14
|
+
import {isBuilderPaymentWithdrawable, isParentBlockFull} from "../util/gloas.ts";
|
|
14
15
|
import {
|
|
15
16
|
decreaseBalance,
|
|
16
17
|
getMaxEffectiveBalance,
|
|
@@ -21,31 +22,48 @@ import {
|
|
|
21
22
|
|
|
22
23
|
export function processWithdrawals(
|
|
23
24
|
fork: ForkSeq,
|
|
24
|
-
state: CachedBeaconStateCapella | CachedBeaconStateElectra,
|
|
25
|
-
payload
|
|
25
|
+
state: CachedBeaconStateCapella | CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
26
|
+
payload?: capella.FullOrBlindedExecutionPayload
|
|
26
27
|
): void {
|
|
28
|
+
// Return early if the parent block is empty
|
|
29
|
+
if (fork >= ForkSeq.gloas && !isParentBlockFull(state as CachedBeaconStateGloas)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
// processedPartialWithdrawalsCount is withdrawals coming from EL since electra (EIP-7002)
|
|
28
|
-
|
|
34
|
+
// processedBuilderWithdrawalsCount is withdrawals coming from builder payment since gloas (EIP-7732)
|
|
35
|
+
const {
|
|
36
|
+
withdrawals: expectedWithdrawals,
|
|
37
|
+
processedPartialWithdrawalsCount,
|
|
38
|
+
processedBuilderWithdrawalsCount,
|
|
39
|
+
} = getExpectedWithdrawals(fork, state);
|
|
29
40
|
const numWithdrawals = expectedWithdrawals.length;
|
|
30
41
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
throw Error(
|
|
36
|
-
`Invalid withdrawalsRoot of executionPayloadHeader, expected=${toRootHex(
|
|
37
|
-
expectedWithdrawalsRoot
|
|
38
|
-
)}, actual=${toRootHex(actualWithdrawalsRoot)}`
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
} else {
|
|
42
|
-
if (expectedWithdrawals.length !== payload.withdrawals.length) {
|
|
43
|
-
throw Error(`Invalid withdrawals length expected=${numWithdrawals} actual=${payload.withdrawals.length}`);
|
|
42
|
+
// After gloas, withdrawals are verified later in processExecutionPayloadEnvelope
|
|
43
|
+
if (fork < ForkSeq.gloas) {
|
|
44
|
+
if (payload === undefined) {
|
|
45
|
+
throw Error("payload is required for pre-gloas processWithdrawals");
|
|
44
46
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
|
|
48
|
+
if (isCapellaPayloadHeader(payload)) {
|
|
49
|
+
const expectedWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(expectedWithdrawals);
|
|
50
|
+
const actualWithdrawalsRoot = payload.withdrawalsRoot;
|
|
51
|
+
if (!byteArrayEquals(expectedWithdrawalsRoot, actualWithdrawalsRoot)) {
|
|
52
|
+
throw Error(
|
|
53
|
+
`Invalid withdrawalsRoot of executionPayloadHeader, expected=${toRootHex(
|
|
54
|
+
expectedWithdrawalsRoot
|
|
55
|
+
)}, actual=${toRootHex(actualWithdrawalsRoot)}`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
if (expectedWithdrawals.length !== payload.withdrawals.length) {
|
|
60
|
+
throw Error(`Invalid withdrawals length expected=${numWithdrawals} actual=${payload.withdrawals.length}`);
|
|
61
|
+
}
|
|
62
|
+
for (let i = 0; i < numWithdrawals; i++) {
|
|
63
|
+
const withdrawal = expectedWithdrawals[i];
|
|
64
|
+
if (!ssz.capella.Withdrawal.equals(withdrawal, payload.withdrawals[i])) {
|
|
65
|
+
throw Error(`Withdrawal mismatch at index=${i}`);
|
|
66
|
+
}
|
|
49
67
|
}
|
|
50
68
|
}
|
|
51
69
|
}
|
|
@@ -62,6 +80,24 @@ export function processWithdrawals(
|
|
|
62
80
|
);
|
|
63
81
|
}
|
|
64
82
|
|
|
83
|
+
if (fork >= ForkSeq.gloas) {
|
|
84
|
+
const stateGloas = state as CachedBeaconStateGloas;
|
|
85
|
+
stateGloas.latestWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(expectedWithdrawals);
|
|
86
|
+
|
|
87
|
+
const unprocessedWithdrawals = stateGloas.builderPendingWithdrawals
|
|
88
|
+
.getAllReadonly()
|
|
89
|
+
.slice(0, processedBuilderWithdrawalsCount)
|
|
90
|
+
.filter((w) => !isBuilderPaymentWithdrawable(stateGloas, w));
|
|
91
|
+
const remainingWithdrawals = stateGloas.builderPendingWithdrawals
|
|
92
|
+
.sliceFrom(processedBuilderWithdrawalsCount)
|
|
93
|
+
.getAllReadonly();
|
|
94
|
+
|
|
95
|
+
stateGloas.builderPendingWithdrawals = ssz.gloas.BeaconState.fields.builderPendingWithdrawals.toViewDU([
|
|
96
|
+
...unprocessedWithdrawals,
|
|
97
|
+
...remainingWithdrawals,
|
|
98
|
+
]);
|
|
99
|
+
}
|
|
100
|
+
|
|
65
101
|
// Update the nextWithdrawalIndex
|
|
66
102
|
const latestWithdrawal = expectedWithdrawals.at(-1);
|
|
67
103
|
if (latestWithdrawal) {
|
|
@@ -82,11 +118,12 @@ export function processWithdrawals(
|
|
|
82
118
|
|
|
83
119
|
export function getExpectedWithdrawals(
|
|
84
120
|
fork: ForkSeq,
|
|
85
|
-
state: CachedBeaconStateCapella | CachedBeaconStateElectra
|
|
121
|
+
state: CachedBeaconStateCapella | CachedBeaconStateElectra | CachedBeaconStateGloas
|
|
86
122
|
): {
|
|
87
123
|
withdrawals: capella.Withdrawal[];
|
|
88
124
|
sampledValidators: number;
|
|
89
125
|
processedPartialWithdrawalsCount: number;
|
|
126
|
+
processedBuilderWithdrawalsCount: number;
|
|
90
127
|
} {
|
|
91
128
|
if (fork < ForkSeq.capella) {
|
|
92
129
|
throw new Error(`getExpectedWithdrawals not supported at forkSeq=${fork} < ForkSeq.capella`);
|
|
@@ -99,17 +136,71 @@ export function getExpectedWithdrawals(
|
|
|
99
136
|
const withdrawals: capella.Withdrawal[] = [];
|
|
100
137
|
const withdrawnBalances = new MapDef<ValidatorIndex, number>(() => 0);
|
|
101
138
|
const isPostElectra = fork >= ForkSeq.electra;
|
|
139
|
+
const isPostGloas = fork >= ForkSeq.gloas;
|
|
102
140
|
// partialWithdrawalsCount is withdrawals coming from EL since electra (EIP-7002)
|
|
103
141
|
let processedPartialWithdrawalsCount = 0;
|
|
142
|
+
// builderWithdrawalsCount is withdrawals coming from builder payments since Gloas (EIP-7732)
|
|
143
|
+
let processedBuilderWithdrawalsCount = 0;
|
|
144
|
+
|
|
145
|
+
if (isPostGloas) {
|
|
146
|
+
const stateGloas = state as CachedBeaconStateGloas;
|
|
147
|
+
|
|
148
|
+
const allBuilderPendingWithdrawals =
|
|
149
|
+
stateGloas.builderPendingWithdrawals.length <= MAX_WITHDRAWALS_PER_PAYLOAD
|
|
150
|
+
? stateGloas.builderPendingWithdrawals.getAllReadonly()
|
|
151
|
+
: null;
|
|
152
|
+
|
|
153
|
+
for (let i = 0; i < stateGloas.builderPendingWithdrawals.length; i++) {
|
|
154
|
+
const withdrawal = allBuilderPendingWithdrawals
|
|
155
|
+
? allBuilderPendingWithdrawals[i]
|
|
156
|
+
: stateGloas.builderPendingWithdrawals.getReadonly(i);
|
|
157
|
+
|
|
158
|
+
if (withdrawal.withdrawableEpoch > epoch || withdrawals.length + 1 === MAX_WITHDRAWALS_PER_PAYLOAD) {
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (isBuilderPaymentWithdrawable(stateGloas, withdrawal)) {
|
|
163
|
+
const totalWithdrawn = withdrawnBalances.getOrDefault(withdrawal.builderIndex);
|
|
164
|
+
const balance = state.balances.get(withdrawal.builderIndex) - totalWithdrawn;
|
|
165
|
+
const builder = state.validators.get(withdrawal.builderIndex);
|
|
166
|
+
|
|
167
|
+
let withdrawableBalance = 0;
|
|
168
|
+
|
|
169
|
+
if (builder.slashed) {
|
|
170
|
+
withdrawableBalance = balance < withdrawal.amount ? balance : withdrawal.amount;
|
|
171
|
+
} else if (balance > MIN_ACTIVATION_BALANCE) {
|
|
172
|
+
withdrawableBalance =
|
|
173
|
+
balance - MIN_ACTIVATION_BALANCE < withdrawal.amount ? balance - MIN_ACTIVATION_BALANCE : withdrawal.amount;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (withdrawableBalance > 0) {
|
|
177
|
+
withdrawals.push({
|
|
178
|
+
index: withdrawalIndex,
|
|
179
|
+
validatorIndex: withdrawal.builderIndex,
|
|
180
|
+
address: withdrawal.feeRecipient,
|
|
181
|
+
amount: BigInt(withdrawableBalance),
|
|
182
|
+
});
|
|
183
|
+
withdrawalIndex++;
|
|
184
|
+
withdrawnBalances.set(withdrawal.builderIndex, totalWithdrawn + withdrawableBalance);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
processedBuilderWithdrawalsCount++;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
104
190
|
|
|
105
191
|
if (isPostElectra) {
|
|
192
|
+
// In pre-gloas, partialWithdrawalBound == MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP
|
|
193
|
+
const partialWithdrawalBound = Math.min(
|
|
194
|
+
withdrawals.length + MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP,
|
|
195
|
+
MAX_WITHDRAWALS_PER_PAYLOAD - 1
|
|
196
|
+
);
|
|
106
197
|
const stateElectra = state as CachedBeaconStateElectra;
|
|
107
198
|
|
|
108
199
|
// MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP = 8, PENDING_PARTIAL_WITHDRAWALS_LIMIT: 134217728 so we should only call getAllReadonly() if it makes sense
|
|
109
200
|
// pendingPartialWithdrawals comes from EIP-7002 smart contract where it takes fee so it's more likely than not validator is in correct condition to withdraw
|
|
110
201
|
// also we may break early if withdrawableEpoch > epoch
|
|
111
202
|
const allPendingPartialWithdrawals =
|
|
112
|
-
stateElectra.pendingPartialWithdrawals.length <=
|
|
203
|
+
stateElectra.pendingPartialWithdrawals.length <= partialWithdrawalBound
|
|
113
204
|
? stateElectra.pendingPartialWithdrawals.getAllReadonly()
|
|
114
205
|
: null;
|
|
115
206
|
|
|
@@ -118,7 +209,7 @@ export function getExpectedWithdrawals(
|
|
|
118
209
|
const withdrawal = allPendingPartialWithdrawals
|
|
119
210
|
? allPendingPartialWithdrawals[i]
|
|
120
211
|
: stateElectra.pendingPartialWithdrawals.getReadonly(i);
|
|
121
|
-
if (withdrawal.withdrawableEpoch > epoch || withdrawals.length ===
|
|
212
|
+
if (withdrawal.withdrawableEpoch > epoch || withdrawals.length === partialWithdrawalBound) {
|
|
122
213
|
break;
|
|
123
214
|
}
|
|
124
215
|
|
|
@@ -147,11 +238,11 @@ export function getExpectedWithdrawals(
|
|
|
147
238
|
}
|
|
148
239
|
}
|
|
149
240
|
|
|
150
|
-
const
|
|
241
|
+
const withdrawalBound = Math.min(validators.length, MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP);
|
|
151
242
|
let n = 0;
|
|
152
243
|
// Just run a bounded loop max iterating over all withdrawals
|
|
153
244
|
// however breaks out once we have MAX_WITHDRAWALS_PER_PAYLOAD
|
|
154
|
-
for (n = 0; n <
|
|
245
|
+
for (n = 0; n < withdrawalBound; n++) {
|
|
155
246
|
// Get next validator in turn
|
|
156
247
|
const validatorIndex = (nextWithdrawalValidatorIndex + n) % validators.length;
|
|
157
248
|
|
|
@@ -203,5 +294,5 @@ export function getExpectedWithdrawals(
|
|
|
203
294
|
}
|
|
204
295
|
}
|
|
205
296
|
|
|
206
|
-
return {withdrawals, sampledValidators: n, processedPartialWithdrawalsCount};
|
|
297
|
+
return {withdrawals, sampledValidators: n, processedPartialWithdrawalsCount, processedBuilderWithdrawalsCount};
|
|
207
298
|
}
|
package/src/cache/epochCache.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
SyncPeriod,
|
|
25
25
|
ValidatorIndex,
|
|
26
26
|
electra,
|
|
27
|
+
gloas,
|
|
27
28
|
phase0,
|
|
28
29
|
} from "@lodestar/types";
|
|
29
30
|
import {LodestarError} from "@lodestar/utils";
|
|
@@ -46,6 +47,7 @@ import {
|
|
|
46
47
|
getSeed,
|
|
47
48
|
isActiveValidator,
|
|
48
49
|
isAggregatorFromCommitteeLength,
|
|
50
|
+
naiveGetPayloadTimlinessCommitteeIndices,
|
|
49
51
|
} from "../util/index.js";
|
|
50
52
|
import {computeBaseRewardPerIncrement, computeSyncParticipantReward} from "../util/syncCommittee.js";
|
|
51
53
|
import {sumTargetUnslashedBalanceIncrements} from "../util/targetUnslashedBalance.js";
|
|
@@ -59,7 +61,7 @@ import {
|
|
|
59
61
|
computeSyncCommitteeCache,
|
|
60
62
|
getSyncCommitteeCache,
|
|
61
63
|
} from "./syncCommitteeCache.js";
|
|
62
|
-
import {BeaconStateAllForks, BeaconStateAltair} from "./types.js";
|
|
64
|
+
import {BeaconStateAllForks, BeaconStateAltair, BeaconStateGloas} from "./types.js";
|
|
63
65
|
|
|
64
66
|
/** `= PROPOSER_WEIGHT / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)` */
|
|
65
67
|
export const PROPOSER_WEIGHT_FACTOR = PROPOSER_WEIGHT / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT);
|
|
@@ -238,6 +240,10 @@ export class EpochCache {
|
|
|
238
240
|
/** TODO: Indexed SyncCommitteeCache */
|
|
239
241
|
nextSyncCommitteeIndexed: SyncCommitteeCache;
|
|
240
242
|
|
|
243
|
+
// TODO GLOAS: See if we need to cached PTC for prev/next epoch
|
|
244
|
+
// PTC for current epoch
|
|
245
|
+
payloadTimelinessCommittee: ValidatorIndex[][];
|
|
246
|
+
|
|
241
247
|
// TODO: Helper stats
|
|
242
248
|
syncPeriod: SyncPeriod;
|
|
243
249
|
|
|
@@ -276,6 +282,7 @@ export class EpochCache {
|
|
|
276
282
|
previousTargetUnslashedBalanceIncrements: number;
|
|
277
283
|
currentSyncCommitteeIndexed: SyncCommitteeCache;
|
|
278
284
|
nextSyncCommitteeIndexed: SyncCommitteeCache;
|
|
285
|
+
payloadTimelinessCommittee: ValidatorIndex[][];
|
|
279
286
|
epoch: Epoch;
|
|
280
287
|
syncPeriod: SyncPeriod;
|
|
281
288
|
}) {
|
|
@@ -307,6 +314,7 @@ export class EpochCache {
|
|
|
307
314
|
this.previousTargetUnslashedBalanceIncrements = data.previousTargetUnslashedBalanceIncrements;
|
|
308
315
|
this.currentSyncCommitteeIndexed = data.currentSyncCommitteeIndexed;
|
|
309
316
|
this.nextSyncCommitteeIndexed = data.nextSyncCommitteeIndexed;
|
|
317
|
+
this.payloadTimelinessCommittee = data.payloadTimelinessCommittee;
|
|
310
318
|
this.epoch = data.epoch;
|
|
311
319
|
this.syncPeriod = data.syncPeriod;
|
|
312
320
|
}
|
|
@@ -485,6 +493,17 @@ export class EpochCache {
|
|
|
485
493
|
nextSyncCommitteeIndexed = new SyncCommitteeCacheEmpty();
|
|
486
494
|
}
|
|
487
495
|
|
|
496
|
+
// Compute PTC for this epoch
|
|
497
|
+
let payloadTimelinessCommittee: ValidatorIndex[][] = [];
|
|
498
|
+
if (currentEpoch >= config.GLOAS_FORK_EPOCH) {
|
|
499
|
+
payloadTimelinessCommittee = naiveGetPayloadTimlinessCommitteeIndices(
|
|
500
|
+
state as BeaconStateGloas,
|
|
501
|
+
currentShuffling,
|
|
502
|
+
effectiveBalanceIncrements,
|
|
503
|
+
currentEpoch
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
|
|
488
507
|
// Precompute churnLimit for efficient initiateValidatorExit() during block proposing MUST be recompute everytime the
|
|
489
508
|
// active validator indices set changes in size. Validators change active status only when:
|
|
490
509
|
// - validator.activation_epoch is set. Only changes in process_registry_updates() if validator can be activated. If
|
|
@@ -559,6 +578,7 @@ export class EpochCache {
|
|
|
559
578
|
currentTargetUnslashedBalanceIncrements,
|
|
560
579
|
currentSyncCommitteeIndexed,
|
|
561
580
|
nextSyncCommitteeIndexed,
|
|
581
|
+
payloadTimelinessCommittee: payloadTimelinessCommittee,
|
|
562
582
|
epoch: currentEpoch,
|
|
563
583
|
syncPeriod: computeSyncPeriodAtEpoch(currentEpoch),
|
|
564
584
|
});
|
|
@@ -605,6 +625,7 @@ export class EpochCache {
|
|
|
605
625
|
currentTargetUnslashedBalanceIncrements: this.currentTargetUnslashedBalanceIncrements,
|
|
606
626
|
currentSyncCommitteeIndexed: this.currentSyncCommitteeIndexed,
|
|
607
627
|
nextSyncCommitteeIndexed: this.nextSyncCommitteeIndexed,
|
|
628
|
+
payloadTimelinessCommittee: this.payloadTimelinessCommittee,
|
|
608
629
|
epoch: this.epoch,
|
|
609
630
|
syncPeriod: this.syncPeriod,
|
|
610
631
|
});
|
|
@@ -750,6 +771,14 @@ export class EpochCache {
|
|
|
750
771
|
const epochAfterUpcoming = upcomingEpoch + 1;
|
|
751
772
|
|
|
752
773
|
this.proposersPrevEpoch = this.proposers;
|
|
774
|
+
if (upcomingEpoch >= this.config.GLOAS_FORK_EPOCH) {
|
|
775
|
+
this.payloadTimelinessCommittee = naiveGetPayloadTimlinessCommitteeIndices(
|
|
776
|
+
state as BeaconStateGloas,
|
|
777
|
+
this.currentShuffling,
|
|
778
|
+
this.effectiveBalanceIncrements,
|
|
779
|
+
upcomingEpoch
|
|
780
|
+
);
|
|
781
|
+
}
|
|
753
782
|
if (upcomingEpoch >= this.config.FULU_FORK_EPOCH) {
|
|
754
783
|
// Populate proposer cache with lookahead from state
|
|
755
784
|
const proposerLookahead = (state as CachedBeaconStateFulu).proposerLookahead.getAll();
|
|
@@ -1151,6 +1180,34 @@ export class EpochCache {
|
|
|
1151
1180
|
isPostElectra(): boolean {
|
|
1152
1181
|
return this.epoch >= this.config.ELECTRA_FORK_EPOCH;
|
|
1153
1182
|
}
|
|
1183
|
+
|
|
1184
|
+
getPayloadTimelinessCommittee(slot: Slot): ValidatorIndex[] {
|
|
1185
|
+
const epoch = computeEpochAtSlot(slot);
|
|
1186
|
+
|
|
1187
|
+
if (epoch < this.config.GLOAS_FORK_EPOCH) {
|
|
1188
|
+
throw new Error("Payload Timeliness Committee is not available before gloas fork");
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
if (epoch === this.epoch) {
|
|
1192
|
+
return this.payloadTimelinessCommittee[slot % SLOTS_PER_EPOCH];
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
throw new Error(`Payload Timeliness Committee is not available for slot=${slot}`);
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
getIndexedPayloadAttestation(
|
|
1199
|
+
slot: Slot,
|
|
1200
|
+
payloadAttestation: gloas.PayloadAttestation
|
|
1201
|
+
): gloas.IndexedPayloadAttestation {
|
|
1202
|
+
const payloadTimelinessCommittee = this.getPayloadTimelinessCommittee(slot);
|
|
1203
|
+
const attestingIndices = payloadAttestation.aggregationBits.intersectValues(payloadTimelinessCommittee);
|
|
1204
|
+
|
|
1205
|
+
return {
|
|
1206
|
+
attestingIndices: attestingIndices.sort((a, b) => a - b),
|
|
1207
|
+
data: payloadAttestation.data,
|
|
1208
|
+
signature: payloadAttestation.signature,
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1154
1211
|
}
|
|
1155
1212
|
|
|
1156
1213
|
function getEffectiveBalanceIncrementsByteLen(validatorCount: number): number {
|
package/src/epoch/index.ts
CHANGED
|
@@ -12,9 +12,11 @@ import {
|
|
|
12
12
|
CachedBeaconStateCapella,
|
|
13
13
|
CachedBeaconStateElectra,
|
|
14
14
|
CachedBeaconStateFulu,
|
|
15
|
+
CachedBeaconStateGloas,
|
|
15
16
|
CachedBeaconStatePhase0,
|
|
16
17
|
EpochTransitionCache,
|
|
17
18
|
} from "../types.js";
|
|
19
|
+
import {processBuilderPendingPayments} from "./processBuilderPendingPayments.ts";
|
|
18
20
|
import {processEffectiveBalanceUpdates} from "./processEffectiveBalanceUpdates.js";
|
|
19
21
|
import {processEth1DataReset} from "./processEth1DataReset.js";
|
|
20
22
|
import {processHistoricalRootsUpdate} from "./processHistoricalRootsUpdate.js";
|
|
@@ -53,6 +55,7 @@ export {
|
|
|
53
55
|
processPendingDeposits,
|
|
54
56
|
processPendingConsolidations,
|
|
55
57
|
processProposerLookahead,
|
|
58
|
+
processBuilderPendingPayments,
|
|
56
59
|
};
|
|
57
60
|
|
|
58
61
|
export {computeUnrealizedCheckpoints} from "./computeUnrealizedCheckpoints.js";
|
|
@@ -78,6 +81,7 @@ export enum EpochTransitionStep {
|
|
|
78
81
|
processPendingDeposits = "processPendingDeposits",
|
|
79
82
|
processPendingConsolidations = "processPendingConsolidations",
|
|
80
83
|
processProposerLookahead = "processProposerLookahead",
|
|
84
|
+
processBuilderPendingPayments = "processBuilderPendingPayments",
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
export function processEpoch(
|
|
@@ -154,6 +158,14 @@ export function processEpoch(
|
|
|
154
158
|
}
|
|
155
159
|
}
|
|
156
160
|
|
|
161
|
+
if (fork >= ForkSeq.gloas) {
|
|
162
|
+
const timer = metrics?.epochTransitionStepTime.startTimer({
|
|
163
|
+
step: EpochTransitionStep.processBuilderPendingPayments,
|
|
164
|
+
});
|
|
165
|
+
processBuilderPendingPayments(state as CachedBeaconStateGloas);
|
|
166
|
+
timer?.();
|
|
167
|
+
}
|
|
168
|
+
|
|
157
169
|
{
|
|
158
170
|
const timer = metrics?.epochTransitionStepTime.startTimer({
|
|
159
171
|
step: EpochTransitionStep.processEffectiveBalanceUpdates,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
2
|
+
import {ssz} from "@lodestar/types";
|
|
3
|
+
import {CachedBeaconStateGloas} from "../types.ts";
|
|
4
|
+
import {computeExitEpochAndUpdateChurn} from "../util/epoch.ts";
|
|
5
|
+
import {getBuilderPaymentQuorumThreshold} from "../util/gloas.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Processes the builder pending payments from the previous epoch.
|
|
9
|
+
*/
|
|
10
|
+
export function processBuilderPendingPayments(state: CachedBeaconStateGloas): void {
|
|
11
|
+
const quorum = getBuilderPaymentQuorumThreshold(state);
|
|
12
|
+
|
|
13
|
+
for (let i = 0; i < SLOTS_PER_EPOCH; i++) {
|
|
14
|
+
const payment = state.builderPendingPayments.get(i);
|
|
15
|
+
if (payment.weight > quorum) {
|
|
16
|
+
const exitQueueEpoch = computeExitEpochAndUpdateChurn(state, BigInt(payment.withdrawal.amount));
|
|
17
|
+
payment.withdrawal.withdrawableEpoch = exitQueueEpoch + state.config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY;
|
|
18
|
+
|
|
19
|
+
state.builderPendingWithdrawals.push(payment.withdrawal);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// TODO GLOAS: Optimize this
|
|
24
|
+
for (let i = 0; i < state.builderPendingPayments.length; i++) {
|
|
25
|
+
if (i < SLOTS_PER_EPOCH) {
|
|
26
|
+
state.builderPendingPayments.set(i, state.builderPendingPayments.get(i + SLOTS_PER_EPOCH).clone());
|
|
27
|
+
} else {
|
|
28
|
+
state.builderPendingPayments.set(i, ssz.gloas.BuilderPendingPayment.defaultViewDU());
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -52,6 +52,7 @@ export type {
|
|
|
52
52
|
BeaconStateElectra,
|
|
53
53
|
BeaconStateExecutions,
|
|
54
54
|
BeaconStateFulu,
|
|
55
|
+
BeaconStateGloas,
|
|
55
56
|
// Non-cached states
|
|
56
57
|
BeaconStatePhase0,
|
|
57
58
|
CachedBeaconStateAllForks,
|
|
@@ -62,6 +63,7 @@ export type {
|
|
|
62
63
|
CachedBeaconStateElectra,
|
|
63
64
|
CachedBeaconStateExecutions,
|
|
64
65
|
CachedBeaconStateFulu,
|
|
66
|
+
CachedBeaconStateGloas,
|
|
65
67
|
CachedBeaconStatePhase0,
|
|
66
68
|
} from "./types.js";
|
|
67
69
|
export * from "./util/index.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ForkSeq} from "@lodestar/params";
|
|
2
|
-
import {SignedBeaconBlock, altair, capella} from "@lodestar/types";
|
|
2
|
+
import {IndexedAttestation, SignedBeaconBlock, altair, capella} from "@lodestar/types";
|
|
3
3
|
import {getSyncCommitteeSignatureSet} from "../block/processSyncCommittee.js";
|
|
4
4
|
import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "../types.js";
|
|
5
5
|
import {ISignatureSet} from "../util/index.js";
|
|
@@ -14,6 +14,7 @@ import {getVoluntaryExitsSignatureSets} from "./voluntaryExits.js";
|
|
|
14
14
|
export * from "./attesterSlashings.js";
|
|
15
15
|
export * from "./blsToExecutionChange.js";
|
|
16
16
|
export * from "./indexedAttestation.js";
|
|
17
|
+
export * from "./indexedPayloadAttestation.ts";
|
|
17
18
|
export * from "./proposer.js";
|
|
18
19
|
export * from "./proposerSlashings.js";
|
|
19
20
|
export * from "./randao.js";
|
|
@@ -26,6 +27,7 @@ export * from "./voluntaryExits.js";
|
|
|
26
27
|
export function getBlockSignatureSets(
|
|
27
28
|
state: CachedBeaconStateAllForks,
|
|
28
29
|
signedBlock: SignedBeaconBlock,
|
|
30
|
+
indexedAttestations: IndexedAttestation[],
|
|
29
31
|
opts?: {
|
|
30
32
|
/** Useful since block proposer signature is verified beforehand on gossip validation */
|
|
31
33
|
skipProposerSignature?: boolean;
|
|
@@ -38,7 +40,7 @@ export function getBlockSignatureSets(
|
|
|
38
40
|
getRandaoRevealSignatureSet(state, signedBlock.message),
|
|
39
41
|
...getProposerSlashingsSignatureSets(state, signedBlock),
|
|
40
42
|
...getAttesterSlashingsSignatureSets(state, signedBlock),
|
|
41
|
-
...getAttestationsSignatureSets(state, signedBlock),
|
|
43
|
+
...getAttestationsSignatureSets(state, signedBlock, indexedAttestations),
|
|
42
44
|
...getVoluntaryExitsSignatureSets(state, signedBlock),
|
|
43
45
|
];
|
|
44
46
|
|
|
@@ -39,13 +39,13 @@ export function getIndexedAttestationSignatureSet(
|
|
|
39
39
|
|
|
40
40
|
export function getAttestationsSignatureSets(
|
|
41
41
|
state: CachedBeaconStateAllForks,
|
|
42
|
-
signedBlock: SignedBeaconBlock
|
|
42
|
+
signedBlock: SignedBeaconBlock,
|
|
43
|
+
indexedAttestations: IndexedAttestation[]
|
|
43
44
|
): ISignatureSet[] {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
);
|
|
45
|
+
if (indexedAttestations.length !== signedBlock.message.body.attestations.length) {
|
|
46
|
+
throw Error(
|
|
47
|
+
`Indexed attestations length mismatch: got ${indexedAttestations.length}, expected ${signedBlock.message.body.attestations.length}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return indexedAttestations.map((indexedAttestation) => getIndexedAttestationSignatureSet(state, indexedAttestation));
|
|
51
51
|
}
|