@lodestar/state-transition 1.22.0-dev.9c62011986 → 1.22.0-dev.9f4bf50408
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/LICENSE +201 -165
- package/lib/block/index.js +1 -1
- package/lib/block/index.js.map +1 -1
- package/lib/block/initiateValidatorExit.d.ts +2 -1
- package/lib/block/initiateValidatorExit.js +21 -13
- package/lib/block/initiateValidatorExit.js.map +1 -1
- package/lib/block/isValidIndexedAttestation.js +5 -2
- package/lib/block/isValidIndexedAttestation.js.map +1 -1
- package/lib/block/processAttestationPhase0.d.ts +2 -2
- package/lib/block/processAttestationPhase0.js +33 -11
- package/lib/block/processAttestationPhase0.js.map +1 -1
- package/lib/block/processAttestations.d.ts +2 -2
- package/lib/block/processAttestations.js.map +1 -1
- package/lib/block/processAttestationsAltair.d.ts +2 -2
- package/lib/block/processAttestationsAltair.js +3 -3
- package/lib/block/processAttestationsAltair.js.map +1 -1
- package/lib/block/processBlockHeader.js +3 -2
- package/lib/block/processBlockHeader.js.map +1 -1
- package/lib/block/processBlsToExecutionChange.js +3 -2
- package/lib/block/processBlsToExecutionChange.js.map +1 -1
- package/lib/block/processConsolidationRequest.d.ts +4 -0
- package/lib/block/processConsolidationRequest.js +55 -0
- package/lib/block/processConsolidationRequest.js.map +1 -0
- package/lib/block/processDeposit.d.ts +8 -0
- package/lib/block/processDeposit.js +94 -54
- package/lib/block/processDeposit.js.map +1 -1
- package/lib/block/processDepositRequest.d.ts +5 -0
- package/lib/block/processDepositRequest.js +9 -0
- package/lib/block/processDepositRequest.js.map +1 -0
- package/lib/block/processExecutionPayload.js +4 -3
- package/lib/block/processExecutionPayload.js.map +1 -1
- package/lib/block/processOperations.d.ts +4 -1
- package/lib/block/processOperations.js +21 -4
- package/lib/block/processOperations.js.map +1 -1
- package/lib/block/processVoluntaryExit.d.ts +2 -1
- package/lib/block/processVoluntaryExit.js +16 -6
- package/lib/block/processVoluntaryExit.js.map +1 -1
- package/lib/block/processWithdrawalRequest.d.ts +5 -0
- package/lib/block/processWithdrawalRequest.js +67 -0
- package/lib/block/processWithdrawalRequest.js.map +1 -0
- package/lib/block/processWithdrawals.d.ts +5 -3
- package/lib/block/processWithdrawals.js +70 -17
- package/lib/block/processWithdrawals.js.map +1 -1
- package/lib/block/slashValidator.js +9 -5
- package/lib/block/slashValidator.js.map +1 -1
- package/lib/cache/effectiveBalanceIncrements.d.ts +3 -4
- package/lib/cache/effectiveBalanceIncrements.js +5 -5
- package/lib/cache/effectiveBalanceIncrements.js.map +1 -1
- package/lib/cache/epochCache.d.ts +66 -8
- package/lib/cache/epochCache.js +185 -22
- package/lib/cache/epochCache.js.map +1 -1
- package/lib/cache/epochTransitionCache.d.ts +12 -2
- package/lib/cache/epochTransitionCache.js +6 -3
- package/lib/cache/epochTransitionCache.js.map +1 -1
- package/lib/cache/pubkeyCache.d.ts +23 -3
- package/lib/cache/pubkeyCache.js +8 -1
- package/lib/cache/pubkeyCache.js.map +1 -1
- package/lib/cache/stateCache.d.ts +4 -2
- package/lib/cache/stateCache.js +2 -1
- package/lib/cache/stateCache.js.map +1 -1
- package/lib/cache/syncCommitteeCache.js +2 -2
- package/lib/cache/syncCommitteeCache.js.map +1 -1
- package/lib/cache/types.d.ts +1 -0
- package/lib/epoch/index.d.ts +6 -2
- package/lib/epoch/index.js +27 -5
- package/lib/epoch/index.js.map +1 -1
- package/lib/epoch/processEffectiveBalanceUpdates.d.ts +4 -1
- package/lib/epoch/processEffectiveBalanceUpdates.js +25 -6
- package/lib/epoch/processEffectiveBalanceUpdates.js.map +1 -1
- package/lib/epoch/processPendingBalanceDeposits.d.ts +12 -0
- package/lib/epoch/processPendingBalanceDeposits.js +68 -0
- package/lib/epoch/processPendingBalanceDeposits.js.map +1 -0
- package/lib/epoch/processPendingConsolidations.d.ts +16 -0
- package/lib/epoch/processPendingConsolidations.js +49 -0
- package/lib/epoch/processPendingConsolidations.js.map +1 -0
- package/lib/epoch/processRegistryUpdates.d.ts +2 -1
- package/lib/epoch/processRegistryUpdates.js +6 -3
- package/lib/epoch/processRegistryUpdates.js.map +1 -1
- package/lib/epoch/processRewardsAndPenalties.js +2 -1
- package/lib/epoch/processRewardsAndPenalties.js.map +1 -1
- package/lib/epoch/processSyncCommitteeUpdates.d.ts +2 -1
- package/lib/epoch/processSyncCommitteeUpdates.js +4 -3
- package/lib/epoch/processSyncCommitteeUpdates.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/metrics.d.ts +5 -0
- package/lib/metrics.js.map +1 -1
- package/lib/signatureSets/attesterSlashings.d.ts +3 -3
- package/lib/signatureSets/attesterSlashings.js +1 -2
- package/lib/signatureSets/attesterSlashings.js.map +1 -1
- package/lib/signatureSets/index.js +2 -2
- package/lib/signatureSets/index.js.map +1 -1
- package/lib/signatureSets/indexedAttestation.js +2 -1
- package/lib/signatureSets/indexedAttestation.js.map +1 -1
- package/lib/slot/index.d.ts +1 -0
- package/lib/slot/index.js +1 -0
- 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/upgradeStateToElectra.d.ts +8 -0
- package/lib/slot/upgradeStateToElectra.js +138 -0
- package/lib/slot/upgradeStateToElectra.js.map +1 -0
- package/lib/stateTransition.d.ts +1 -0
- package/lib/stateTransition.js +12 -8
- package/lib/stateTransition.js.map +1 -1
- package/lib/types.d.ts +2 -2
- package/lib/util/balance.js +2 -2
- package/lib/util/balance.js.map +1 -1
- package/lib/util/deposit.d.ts +4 -0
- package/lib/util/deposit.js +22 -0
- package/lib/util/deposit.js.map +1 -0
- package/lib/util/electra.d.ts +8 -0
- package/lib/util/electra.js +47 -0
- package/lib/util/electra.js.map +1 -0
- package/lib/util/epoch.d.ts +4 -1
- package/lib/util/epoch.js +37 -0
- package/lib/util/epoch.js.map +1 -1
- package/lib/util/epochShuffling.js +2 -3
- package/lib/util/epochShuffling.js.map +1 -1
- package/lib/util/execution.js +8 -0
- package/lib/util/execution.js.map +1 -1
- package/lib/util/genesis.d.ts +1 -1
- package/lib/util/genesis.js +30 -9
- package/lib/util/genesis.js.map +1 -1
- package/lib/util/index.d.ts +3 -0
- package/lib/util/index.js +3 -0
- package/lib/util/index.js.map +1 -1
- package/lib/util/loadState/index.d.ts +1 -1
- package/lib/util/loadState/index.js +1 -1
- package/lib/util/loadState/index.js.map +1 -1
- package/lib/util/loadState/loadState.d.ts +7 -0
- package/lib/util/loadState/loadState.js +15 -0
- package/lib/util/loadState/loadState.js.map +1 -1
- package/lib/util/seed.d.ts +4 -3
- package/lib/util/seed.js +11 -10
- package/lib/util/seed.js.map +1 -1
- package/lib/util/syncCommittee.d.ts +2 -1
- package/lib/util/syncCommittee.js +2 -2
- package/lib/util/syncCommittee.js.map +1 -1
- package/lib/util/validator.d.ts +10 -1
- package/lib/util/validator.js +35 -1
- package/lib/util/validator.js.map +1 -1
- package/lib/util/weakSubjectivity.js +2 -2
- package/lib/util/weakSubjectivity.js.map +1 -1
- package/package.json +9 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FAR_FUTURE_EPOCH } from "@lodestar/params";
|
|
2
|
-
import { isActiveValidator } from "../util/index.js";
|
|
1
|
+
import { FAR_FUTURE_EPOCH, ForkSeq } from "@lodestar/params";
|
|
2
|
+
import { getPendingBalanceToWithdraw, isActiveValidator } from "../util/index.js";
|
|
3
3
|
import { verifyVoluntaryExitSignature } from "../signatureSets/index.js";
|
|
4
4
|
import { initiateValidatorExit } from "./index.js";
|
|
5
5
|
/**
|
|
@@ -7,12 +7,15 @@ import { initiateValidatorExit } from "./index.js";
|
|
|
7
7
|
*
|
|
8
8
|
* PERF: Work depends on number of VoluntaryExit per block. On regular networks the average is 0 / block.
|
|
9
9
|
*/
|
|
10
|
-
export function processVoluntaryExit(state, signedVoluntaryExit, verifySignature = true) {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
export function processVoluntaryExit(fork, state, signedVoluntaryExit, verifySignature = true) {
|
|
11
|
+
const isValidExit = fork >= ForkSeq.electra
|
|
12
|
+
? isValidVoluntaryExitElectra(state, signedVoluntaryExit, verifySignature)
|
|
13
|
+
: isValidVoluntaryExit(state, signedVoluntaryExit, verifySignature);
|
|
14
|
+
if (!isValidExit) {
|
|
15
|
+
throw Error(`Invalid voluntary exit at forkSeq=${fork}`);
|
|
13
16
|
}
|
|
14
17
|
const validator = state.validators.get(signedVoluntaryExit.message.validatorIndex);
|
|
15
|
-
initiateValidatorExit(state, validator);
|
|
18
|
+
initiateValidatorExit(fork, state, validator);
|
|
16
19
|
}
|
|
17
20
|
export function isValidVoluntaryExit(state, signedVoluntaryExit, verifySignature = true) {
|
|
18
21
|
const { config, epochCtx } = state;
|
|
@@ -31,4 +34,11 @@ export function isValidVoluntaryExit(state, signedVoluntaryExit, verifySignature
|
|
|
31
34
|
// verify signature
|
|
32
35
|
(!verifySignature || verifyVoluntaryExitSignature(state, signedVoluntaryExit)));
|
|
33
36
|
}
|
|
37
|
+
function isValidVoluntaryExitElectra(state, signedVoluntaryExit, verifySignature = true) {
|
|
38
|
+
// only exit validator if it has no pending withdrawals in the queue (post-Electra only)
|
|
39
|
+
if (getPendingBalanceToWithdraw(state, signedVoluntaryExit.message.validatorIndex) === 0) {
|
|
40
|
+
return isValidVoluntaryExit(state, signedVoluntaryExit, verifySignature);
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
34
44
|
//# sourceMappingURL=processVoluntaryExit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processVoluntaryExit.js","sourceRoot":"","sources":["../../src/block/processVoluntaryExit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"processVoluntaryExit.js","sourceRoot":"","sources":["../../src/block/processVoluntaryExit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAE,OAAO,EAAC,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAC,2BAA2B,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhF,OAAO,EAAC,4BAA4B,EAAC,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAC,qBAAqB,EAAC,MAAM,YAAY,CAAC;AAEjD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAa,EACb,KAAgC,EAChC,mBAA+C,EAC/C,eAAe,GAAG,IAAI;IAEtB,MAAM,WAAW,GACf,IAAI,IAAI,OAAO,CAAC,OAAO;QACrB,CAAC,CAAC,2BAA2B,CAAC,KAAiC,EAAE,mBAAmB,EAAE,eAAe,CAAC;QACtG,CAAC,CAAC,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,EAAE,eAAe,CAAC,CAAC;IACxE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,KAAK,CAAC,qCAAqC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,mBAAmB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACnF,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,KAAgC,EAChC,mBAA+C,EAC/C,eAAe,GAAG,IAAI;IAEtB,MAAM,EAAC,MAAM,EAAE,QAAQ,EAAC,GAAG,KAAK,CAAC;IACjC,MAAM,aAAa,GAAG,mBAAmB,CAAC,OAAO,CAAC;IAClD,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;IACrE,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC;IAEpC,OAAO;IACL,iCAAiC;IACjC,iBAAiB,CAAC,SAAS,EAAE,YAAY,CAAC;QAC1C,qCAAqC;QACrC,SAAS,CAAC,SAAS,KAAK,gBAAgB;QACxC,qFAAqF;QACrF,YAAY,IAAI,aAAa,CAAC,KAAK;QACnC,mDAAmD;QACnD,YAAY,IAAI,SAAS,CAAC,eAAe,GAAG,MAAM,CAAC,sBAAsB;QACzE,mBAAmB;QACnB,CAAC,CAAC,eAAe,IAAI,4BAA4B,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAC/E,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAClC,KAA+B,EAC/B,mBAA+C,EAC/C,eAAe,GAAG,IAAI;IAEtB,wFAAwF;IACxF,IAAI,2BAA2B,CAAC,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QACzF,OAAO,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,EAAE,eAAe,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { electra } from "@lodestar/types";
|
|
2
|
+
import { ForkSeq } from "@lodestar/params";
|
|
3
|
+
import { CachedBeaconStateElectra } from "../types.js";
|
|
4
|
+
export declare function processWithdrawalRequest(fork: ForkSeq, state: CachedBeaconStateElectra, withdrawalRequest: electra.WithdrawalRequest): void;
|
|
5
|
+
//# sourceMappingURL=processWithdrawalRequest.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ssz } from "@lodestar/types";
|
|
2
|
+
import { FAR_FUTURE_EPOCH, MIN_ACTIVATION_BALANCE, PENDING_PARTIAL_WITHDRAWALS_LIMIT, FULL_EXIT_REQUEST_AMOUNT, } from "@lodestar/params";
|
|
3
|
+
import { toHex } from "@lodestar/utils";
|
|
4
|
+
import { hasCompoundingWithdrawalCredential, hasExecutionWithdrawalCredential } from "../util/electra.js";
|
|
5
|
+
import { getPendingBalanceToWithdraw, isActiveValidator } from "../util/validator.js";
|
|
6
|
+
import { computeExitEpochAndUpdateChurn } from "../util/epoch.js";
|
|
7
|
+
import { initiateValidatorExit } from "./initiateValidatorExit.js";
|
|
8
|
+
export function processWithdrawalRequest(fork, state, withdrawalRequest) {
|
|
9
|
+
const amount = Number(withdrawalRequest.amount);
|
|
10
|
+
const { pendingPartialWithdrawals, validators, epochCtx } = state;
|
|
11
|
+
// no need to use unfinalized pubkey cache from 6110 as validator won't be active anyway
|
|
12
|
+
const { pubkey2index, config } = epochCtx;
|
|
13
|
+
const isFullExitRequest = amount === FULL_EXIT_REQUEST_AMOUNT;
|
|
14
|
+
// If partial withdrawal queue is full, only full exits are processed
|
|
15
|
+
if (pendingPartialWithdrawals.length >= PENDING_PARTIAL_WITHDRAWALS_LIMIT && !isFullExitRequest) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// bail out if validator is not in beacon state
|
|
19
|
+
// note that we don't need to check for 6110 unfinalized vals as they won't be eligible for withdraw/exit anyway
|
|
20
|
+
const validatorIndex = pubkey2index.get(withdrawalRequest.validatorPubkey);
|
|
21
|
+
if (validatorIndex === undefined) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const validator = validators.get(validatorIndex);
|
|
25
|
+
if (!isValidatorEligibleForWithdrawOrExit(validator, withdrawalRequest.sourceAddress, state)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// TODO Electra: Consider caching pendingPartialWithdrawals
|
|
29
|
+
const pendingBalanceToWithdraw = getPendingBalanceToWithdraw(state, validatorIndex);
|
|
30
|
+
const validatorBalance = state.balances.get(validatorIndex);
|
|
31
|
+
if (isFullExitRequest) {
|
|
32
|
+
// only exit validator if it has no pending withdrawals in the queue
|
|
33
|
+
if (pendingBalanceToWithdraw === 0) {
|
|
34
|
+
initiateValidatorExit(fork, state, validator);
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// partial withdrawal request
|
|
39
|
+
const hasSufficientEffectiveBalance = validator.effectiveBalance >= MIN_ACTIVATION_BALANCE;
|
|
40
|
+
const hasExcessBalance = validatorBalance > MIN_ACTIVATION_BALANCE + pendingBalanceToWithdraw;
|
|
41
|
+
// Only allow partial withdrawals with compounding withdrawal credentials
|
|
42
|
+
if (hasCompoundingWithdrawalCredential(validator.withdrawalCredentials) &&
|
|
43
|
+
hasSufficientEffectiveBalance &&
|
|
44
|
+
hasExcessBalance) {
|
|
45
|
+
const amountToWithdraw = BigInt(Math.min(validatorBalance - MIN_ACTIVATION_BALANCE - pendingBalanceToWithdraw, amount));
|
|
46
|
+
const exitQueueEpoch = computeExitEpochAndUpdateChurn(state, amountToWithdraw);
|
|
47
|
+
const withdrawableEpoch = exitQueueEpoch + config.MIN_VALIDATOR_WITHDRAWABILITY_DELAY;
|
|
48
|
+
const pendingPartialWithdrawal = ssz.electra.PendingPartialWithdrawal.toViewDU({
|
|
49
|
+
index: validatorIndex,
|
|
50
|
+
amount: amountToWithdraw,
|
|
51
|
+
withdrawableEpoch,
|
|
52
|
+
});
|
|
53
|
+
state.pendingPartialWithdrawals.push(pendingPartialWithdrawal);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function isValidatorEligibleForWithdrawOrExit(validator, sourceAddress, state) {
|
|
57
|
+
const { withdrawalCredentials } = validator;
|
|
58
|
+
const addressStr = toHex(withdrawalCredentials.subarray(12));
|
|
59
|
+
const sourceAddressStr = toHex(sourceAddress);
|
|
60
|
+
const { epoch: currentEpoch, config } = state.epochCtx;
|
|
61
|
+
return (hasExecutionWithdrawalCredential(withdrawalCredentials) &&
|
|
62
|
+
addressStr === sourceAddressStr &&
|
|
63
|
+
isActiveValidator(validator, currentEpoch) &&
|
|
64
|
+
validator.exitEpoch === FAR_FUTURE_EPOCH &&
|
|
65
|
+
currentEpoch >= validator.activationEpoch + config.SHARD_COMMITTEE_PERIOD);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=processWithdrawalRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processWithdrawalRequest.js","sourceRoot":"","sources":["../../src/block/processWithdrawalRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,GAAG,EAAC,MAAM,iBAAiB,CAAC;AACrD,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,iCAAiC,EACjC,wBAAwB,GAEzB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAEtC,OAAO,EAAC,kCAAkC,EAAE,gCAAgC,EAAC,MAAM,oBAAoB,CAAC;AACxG,OAAO,EAAC,2BAA2B,EAAE,iBAAiB,EAAC,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAC,8BAA8B,EAAC,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAC,qBAAqB,EAAC,MAAM,4BAA4B,CAAC;AAEjE,MAAM,UAAU,wBAAwB,CACtC,IAAa,EACb,KAA+B,EAC/B,iBAA4C;IAE5C,MAAM,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,EAAC,yBAAyB,EAAE,UAAU,EAAE,QAAQ,EAAC,GAAG,KAAK,CAAC;IAChE,wFAAwF;IACxF,MAAM,EAAC,YAAY,EAAE,MAAM,EAAC,GAAG,QAAQ,CAAC;IACxC,MAAM,iBAAiB,GAAG,MAAM,KAAK,wBAAwB,CAAC;IAE9D,qEAAqE;IACrE,IAAI,yBAAyB,CAAC,MAAM,IAAI,iCAAiC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAChG,OAAO;IACT,CAAC;IAED,+CAA+C;IAC/C,gHAAgH;IAChH,MAAM,cAAc,GAAG,YAAY,CAAC,GAAG,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;IAC3E,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACjD,IAAI,CAAC,oCAAoC,CAAC,SAAS,EAAE,iBAAiB,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC;QAC7F,OAAO;IACT,CAAC;IAED,2DAA2D;IAC3D,MAAM,wBAAwB,GAAG,2BAA2B,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IACpF,MAAM,gBAAgB,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAE5D,IAAI,iBAAiB,EAAE,CAAC;QACtB,oEAAoE;QACpE,IAAI,wBAAwB,KAAK,CAAC,EAAE,CAAC;YACnC,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QAChD,CAAC;QACD,OAAO;IACT,CAAC;IAED,6BAA6B;IAC7B,MAAM,6BAA6B,GAAG,SAAS,CAAC,gBAAgB,IAAI,sBAAsB,CAAC;IAC3F,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,sBAAsB,GAAG,wBAAwB,CAAC;IAE9F,yEAAyE;IACzE,IACE,kCAAkC,CAAC,SAAS,CAAC,qBAAqB,CAAC;QACnE,6BAA6B;QAC7B,gBAAgB,EAChB,CAAC;QACD,MAAM,gBAAgB,GAAG,MAAM,CAC7B,IAAI,CAAC,GAAG,CAAC,gBAAgB,GAAG,sBAAsB,GAAG,wBAAwB,EAAE,MAAM,CAAC,CACvF,CAAC;QACF,MAAM,cAAc,GAAG,8BAA8B,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAC/E,MAAM,iBAAiB,GAAG,cAAc,GAAG,MAAM,CAAC,mCAAmC,CAAC;QAEtF,MAAM,wBAAwB,GAAG,GAAG,CAAC,OAAO,CAAC,wBAAwB,CAAC,QAAQ,CAAC;YAC7E,KAAK,EAAE,cAAc;YACrB,MAAM,EAAE,gBAAgB;YACxB,iBAAiB;SAClB,CAAC,CAAC;QACH,KAAK,CAAC,yBAAyB,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,SAAS,oCAAoC,CAC3C,SAA2B,EAC3B,aAAyB,EACzB,KAA+B;IAE/B,MAAM,EAAC,qBAAqB,EAAC,GAAG,SAAS,CAAC;IAC1C,MAAM,UAAU,GAAG,KAAK,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7D,MAAM,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC;IAC9C,MAAM,EAAC,KAAK,EAAE,YAAY,EAAE,MAAM,EAAC,GAAG,KAAK,CAAC,QAAQ,CAAC;IAErD,OAAO,CACL,gCAAgC,CAAC,qBAAqB,CAAC;QACvD,UAAU,KAAK,gBAAgB;QAC/B,iBAAiB,CAAC,SAAS,EAAE,YAAY,CAAC;QAC1C,SAAS,CAAC,SAAS,KAAK,gBAAgB;QACxC,YAAY,IAAI,SAAS,CAAC,eAAe,GAAG,MAAM,CAAC,sBAAsB,CAC1E,CAAC;AACJ,CAAC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { capella } from "@lodestar/types";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export declare function
|
|
2
|
+
import { ForkSeq } from "@lodestar/params";
|
|
3
|
+
import { CachedBeaconStateCapella, CachedBeaconStateElectra } from "../types.js";
|
|
4
|
+
export declare function processWithdrawals(fork: ForkSeq, state: CachedBeaconStateCapella | CachedBeaconStateElectra, payload: capella.FullOrBlindedExecutionPayload): void;
|
|
5
|
+
export declare function getExpectedWithdrawals(fork: ForkSeq, state: CachedBeaconStateCapella | CachedBeaconStateElectra): {
|
|
5
6
|
withdrawals: capella.Withdrawal[];
|
|
6
7
|
sampledValidators: number;
|
|
8
|
+
partialWithdrawalsCount: number;
|
|
7
9
|
};
|
|
8
10
|
//# sourceMappingURL=processWithdrawals.d.ts.map
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { byteArrayEquals
|
|
1
|
+
import { byteArrayEquals } from "@chainsafe/ssz";
|
|
2
2
|
import { ssz } from "@lodestar/types";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { MAX_WITHDRAWALS_PER_PAYLOAD, MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP, ForkSeq, MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP, FAR_FUTURE_EPOCH, MIN_ACTIVATION_BALANCE, MAX_EFFECTIVE_BALANCE, } from "@lodestar/params";
|
|
4
|
+
import { toRootHex } from "@lodestar/utils";
|
|
5
|
+
import { decreaseBalance, getMaxEffectiveBalance, hasEth1WithdrawalCredential, hasExecutionWithdrawalCredential, isCapellaPayloadHeader, } from "../util/index.js";
|
|
6
|
+
export function processWithdrawals(fork, state, payload) {
|
|
7
|
+
// partialWithdrawalsCount is withdrawals coming from EL since electra (EIP-7002)
|
|
8
|
+
// TODO - electra: may switch to executionWithdrawalsCount
|
|
9
|
+
const { withdrawals: expectedWithdrawals, partialWithdrawalsCount } = getExpectedWithdrawals(fork, state);
|
|
7
10
|
const numWithdrawals = expectedWithdrawals.length;
|
|
8
11
|
if (isCapellaPayloadHeader(payload)) {
|
|
9
12
|
const expectedWithdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(expectedWithdrawals);
|
|
10
13
|
const actualWithdrawalsRoot = payload.withdrawalsRoot;
|
|
11
14
|
if (!byteArrayEquals(expectedWithdrawalsRoot, actualWithdrawalsRoot)) {
|
|
12
|
-
throw Error(`Invalid withdrawalsRoot of executionPayloadHeader, expected=${
|
|
15
|
+
throw Error(`Invalid withdrawalsRoot of executionPayloadHeader, expected=${toRootHex(expectedWithdrawalsRoot)}, actual=${toRootHex(actualWithdrawalsRoot)}`);
|
|
13
16
|
}
|
|
14
17
|
}
|
|
15
18
|
else {
|
|
@@ -27,6 +30,10 @@ export function processWithdrawals(state, payload) {
|
|
|
27
30
|
const withdrawal = expectedWithdrawals[i];
|
|
28
31
|
decreaseBalance(state, withdrawal.validatorIndex, Number(withdrawal.amount));
|
|
29
32
|
}
|
|
33
|
+
if (fork >= ForkSeq.electra) {
|
|
34
|
+
const stateElectra = state;
|
|
35
|
+
stateElectra.pendingPartialWithdrawals = stateElectra.pendingPartialWithdrawals.sliceFrom(partialWithdrawalsCount);
|
|
36
|
+
}
|
|
30
37
|
// Update the nextWithdrawalIndex
|
|
31
38
|
if (expectedWithdrawals.length > 0) {
|
|
32
39
|
const latestWithdrawal = expectedWithdrawals[expectedWithdrawals.length - 1];
|
|
@@ -45,39 +52,85 @@ export function processWithdrawals(state, payload) {
|
|
|
45
52
|
(state.nextWithdrawalValidatorIndex + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) % state.validators.length;
|
|
46
53
|
}
|
|
47
54
|
}
|
|
48
|
-
export function getExpectedWithdrawals(state) {
|
|
55
|
+
export function getExpectedWithdrawals(fork, state) {
|
|
56
|
+
if (fork < ForkSeq.capella) {
|
|
57
|
+
throw new Error(`getExpectedWithdrawals not supported at forkSeq=${fork} < ForkSeq.capella`);
|
|
58
|
+
}
|
|
49
59
|
const epoch = state.epochCtx.epoch;
|
|
50
60
|
let withdrawalIndex = state.nextWithdrawalIndex;
|
|
51
61
|
const { validators, balances, nextWithdrawalValidatorIndex } = state;
|
|
62
|
+
const withdrawals = [];
|
|
63
|
+
const isPostElectra = fork >= ForkSeq.electra;
|
|
64
|
+
if (isPostElectra) {
|
|
65
|
+
const stateElectra = state;
|
|
66
|
+
// MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP = 8, PENDING_PARTIAL_WITHDRAWALS_LIMIT: 134217728 so we should only call getAllReadonly() if it makes sense
|
|
67
|
+
// 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
|
|
68
|
+
// also we may break early if withdrawableEpoch > epoch
|
|
69
|
+
const allPendingPartialWithdrawals = stateElectra.pendingPartialWithdrawals.length <= MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP
|
|
70
|
+
? stateElectra.pendingPartialWithdrawals.getAllReadonly()
|
|
71
|
+
: null;
|
|
72
|
+
// EIP-7002: Execution layer triggerable withdrawals
|
|
73
|
+
for (let i = 0; i < stateElectra.pendingPartialWithdrawals.length; i++) {
|
|
74
|
+
const withdrawal = allPendingPartialWithdrawals
|
|
75
|
+
? allPendingPartialWithdrawals[i]
|
|
76
|
+
: stateElectra.pendingPartialWithdrawals.getReadonly(i);
|
|
77
|
+
if (withdrawal.withdrawableEpoch > epoch || withdrawals.length === MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP) {
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
const validator = validators.getReadonly(withdrawal.index);
|
|
81
|
+
if (validator.exitEpoch === FAR_FUTURE_EPOCH &&
|
|
82
|
+
validator.effectiveBalance >= MIN_ACTIVATION_BALANCE &&
|
|
83
|
+
balances.get(withdrawal.index) > MIN_ACTIVATION_BALANCE) {
|
|
84
|
+
const balanceOverMinActivationBalance = BigInt(balances.get(withdrawal.index) - MIN_ACTIVATION_BALANCE);
|
|
85
|
+
const withdrawableBalance = balanceOverMinActivationBalance < withdrawal.amount ? balanceOverMinActivationBalance : withdrawal.amount;
|
|
86
|
+
withdrawals.push({
|
|
87
|
+
index: withdrawalIndex,
|
|
88
|
+
validatorIndex: withdrawal.index,
|
|
89
|
+
address: validator.withdrawalCredentials.subarray(12),
|
|
90
|
+
amount: withdrawableBalance,
|
|
91
|
+
});
|
|
92
|
+
withdrawalIndex++;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// partialWithdrawalsCount is withdrawals coming from EL since electra (EIP-7002)
|
|
97
|
+
const partialWithdrawalsCount = withdrawals.length;
|
|
52
98
|
const bound = Math.min(validators.length, MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP);
|
|
53
99
|
let n = 0;
|
|
54
|
-
const withdrawals = [];
|
|
55
100
|
// Just run a bounded loop max iterating over all withdrawals
|
|
56
101
|
// however breaks out once we have MAX_WITHDRAWALS_PER_PAYLOAD
|
|
57
102
|
for (n = 0; n < bound; n++) {
|
|
58
103
|
// Get next validator in turn
|
|
59
104
|
const validatorIndex = (nextWithdrawalValidatorIndex + n) % validators.length;
|
|
60
|
-
// It's most likely for validators to not have set eth1 credentials, than having 0 balance
|
|
61
105
|
const validator = validators.getReadonly(validatorIndex);
|
|
62
|
-
|
|
106
|
+
const balance = balances.get(validatorIndex);
|
|
107
|
+
const { withdrawableEpoch, withdrawalCredentials, effectiveBalance } = validator;
|
|
108
|
+
const hasWithdrawableCredentials = isPostElectra
|
|
109
|
+
? hasExecutionWithdrawalCredential(withdrawalCredentials)
|
|
110
|
+
: hasEth1WithdrawalCredential(withdrawalCredentials);
|
|
111
|
+
// early skip for balance = 0 as its now more likely that validator has exited/slahed with
|
|
112
|
+
// balance zero than not have withdrawal credentials set
|
|
113
|
+
if (balance === 0 || !hasWithdrawableCredentials) {
|
|
63
114
|
continue;
|
|
64
115
|
}
|
|
65
|
-
|
|
66
|
-
if (
|
|
116
|
+
// capella full withdrawal
|
|
117
|
+
if (withdrawableEpoch <= epoch) {
|
|
67
118
|
withdrawals.push({
|
|
68
119
|
index: withdrawalIndex,
|
|
69
120
|
validatorIndex,
|
|
70
|
-
address: validator.withdrawalCredentials.
|
|
121
|
+
address: validator.withdrawalCredentials.subarray(12),
|
|
71
122
|
amount: BigInt(balance),
|
|
72
123
|
});
|
|
73
124
|
withdrawalIndex++;
|
|
74
125
|
}
|
|
75
|
-
else if (
|
|
126
|
+
else if (effectiveBalance === (isPostElectra ? getMaxEffectiveBalance(withdrawalCredentials) : MAX_EFFECTIVE_BALANCE) &&
|
|
127
|
+
balance > effectiveBalance) {
|
|
128
|
+
// capella partial withdrawal
|
|
76
129
|
withdrawals.push({
|
|
77
130
|
index: withdrawalIndex,
|
|
78
131
|
validatorIndex,
|
|
79
|
-
address: validator.withdrawalCredentials.
|
|
80
|
-
amount: BigInt(balance -
|
|
132
|
+
address: validator.withdrawalCredentials.subarray(12),
|
|
133
|
+
amount: BigInt(balance - effectiveBalance),
|
|
81
134
|
});
|
|
82
135
|
withdrawalIndex++;
|
|
83
136
|
}
|
|
@@ -86,6 +139,6 @@ export function getExpectedWithdrawals(state) {
|
|
|
86
139
|
break;
|
|
87
140
|
}
|
|
88
141
|
}
|
|
89
|
-
return { withdrawals, sampledValidators: n };
|
|
142
|
+
return { withdrawals, sampledValidators: n, partialWithdrawalsCount };
|
|
90
143
|
}
|
|
91
144
|
//# sourceMappingURL=processWithdrawals.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processWithdrawals.js","sourceRoot":"","sources":["../../src/block/processWithdrawals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,
|
|
1
|
+
{"version":3,"file":"processWithdrawals.js","sourceRoot":"","sources":["../../src/block/processWithdrawals.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EFFECTIVE_BALANCE_INCREMENT, EPOCHS_PER_SLASHINGS_VECTOR, ForkSeq, MIN_SLASHING_PENALTY_QUOTIENT, MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR, MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX, PROPOSER_REWARD_QUOTIENT, PROPOSER_WEIGHT, TIMELY_TARGET_FLAG_INDEX, WEIGHT_DENOMINATOR, WHISTLEBLOWER_REWARD_QUOTIENT, } from "@lodestar/params";
|
|
1
|
+
import { EFFECTIVE_BALANCE_INCREMENT, EPOCHS_PER_SLASHINGS_VECTOR, ForkSeq, MIN_SLASHING_PENALTY_QUOTIENT, MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR, MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX, MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA, PROPOSER_REWARD_QUOTIENT, PROPOSER_WEIGHT, TIMELY_TARGET_FLAG_INDEX, WEIGHT_DENOMINATOR, WHISTLEBLOWER_REWARD_QUOTIENT, WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA, } from "@lodestar/params";
|
|
2
2
|
import { decreaseBalance, increaseBalance } from "../util/index.js";
|
|
3
3
|
import { initiateValidatorExit } from "./initiateValidatorExit.js";
|
|
4
4
|
/** Same to https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.5/specs/altair/beacon-chain.md#has_flag */
|
|
@@ -8,14 +8,14 @@ export function slashValidator(fork, state, slashedIndex, whistleblowerIndex) {
|
|
|
8
8
|
const { epoch, effectiveBalanceIncrements } = epochCtx;
|
|
9
9
|
const validator = state.validators.get(slashedIndex);
|
|
10
10
|
// TODO: Bellatrix initiateValidatorExit validators.update() with the one below
|
|
11
|
-
initiateValidatorExit(state, validator);
|
|
11
|
+
initiateValidatorExit(fork, state, validator);
|
|
12
12
|
validator.slashed = true;
|
|
13
13
|
validator.withdrawableEpoch = Math.max(validator.withdrawableEpoch, epoch + EPOCHS_PER_SLASHINGS_VECTOR);
|
|
14
14
|
const { effectiveBalance } = validator;
|
|
15
15
|
// state.slashings is initially a Gwei (BigInt) vector, however since Nov 2023 it's converted to UintNum64 (number) vector in the state transition because:
|
|
16
16
|
// - state.slashings[nextEpoch % EPOCHS_PER_SLASHINGS_VECTOR] is reset per epoch in processSlashingsReset()
|
|
17
17
|
// - max slashed validators per epoch is SLOTS_PER_EPOCH * MAX_ATTESTER_SLASHINGS * MAX_VALIDATORS_PER_COMMITTEE which is 32 * 2 * 2048 = 131072 on mainnet
|
|
18
|
-
// - with that and 32_000_000_000 MAX_EFFECTIVE_BALANCE, it still fits in a number given that Math.floor(Number.MAX_SAFE_INTEGER / 32_000_000_000) = 281474
|
|
18
|
+
// - with that and 32_000_000_000 MAX_EFFECTIVE_BALANCE or 2048_000_000_000 MAX_EFFECTIVE_BALANCE_ELECTRA, it still fits in a number given that Math.floor(Number.MAX_SAFE_INTEGER / 32_000_000_000) = 281474
|
|
19
19
|
// - we don't need to compute the total slashings from state.slashings, it's handled by totalSlashingsByIncrement in EpochCache
|
|
20
20
|
const slashingIndex = epoch % EPOCHS_PER_SLASHINGS_VECTOR;
|
|
21
21
|
state.slashings.set(slashingIndex, (state.slashings.get(slashingIndex) ?? 0) + effectiveBalance);
|
|
@@ -24,10 +24,14 @@ export function slashValidator(fork, state, slashedIndex, whistleblowerIndex) {
|
|
|
24
24
|
? MIN_SLASHING_PENALTY_QUOTIENT
|
|
25
25
|
: fork === ForkSeq.altair
|
|
26
26
|
? MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR
|
|
27
|
-
:
|
|
27
|
+
: fork < ForkSeq.electra // no change from bellatrix to deneb
|
|
28
|
+
? MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX
|
|
29
|
+
: MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA;
|
|
28
30
|
decreaseBalance(state, slashedIndex, Math.floor(effectiveBalance / minSlashingPenaltyQuotient));
|
|
29
31
|
// apply proposer and whistleblower rewards
|
|
30
|
-
const whistleblowerReward =
|
|
32
|
+
const whistleblowerReward = fork < ForkSeq.electra
|
|
33
|
+
? Math.floor(effectiveBalance / WHISTLEBLOWER_REWARD_QUOTIENT)
|
|
34
|
+
: Math.floor(effectiveBalance / WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA);
|
|
31
35
|
const proposerReward = fork === ForkSeq.phase0
|
|
32
36
|
? Math.floor(whistleblowerReward / PROPOSER_REWARD_QUOTIENT)
|
|
33
37
|
: Math.floor((whistleblowerReward * PROPOSER_WEIGHT) / WEIGHT_DENOMINATOR);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slashValidator.js","sourceRoot":"","sources":["../../src/block/slashValidator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,OAAO,EACP,6BAA6B,EAC7B,oCAAoC,EACpC,uCAAuC,EACvC,wBAAwB,EACxB,eAAe,EACf,wBAAwB,EACxB,kBAAkB,EAClB,6BAA6B,
|
|
1
|
+
{"version":3,"file":"slashValidator.js","sourceRoot":"","sources":["../../src/block/slashValidator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { BeaconStateAllForks } from "../types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Alias to allow easier refactoring.
|
|
4
|
-
* TODO: Estimate the risk of future proof of MAX_EFFECTIVE_BALANCE_INCREMENT < 255
|
|
5
4
|
*/
|
|
6
|
-
export type EffectiveBalanceIncrements =
|
|
7
|
-
/** Helper to prevent re-writting tests downstream if we change
|
|
5
|
+
export type EffectiveBalanceIncrements = Uint16Array;
|
|
6
|
+
/** Helper to prevent re-writting tests downstream if we change Uint16Array to number[] */
|
|
8
7
|
export declare function getEffectiveBalanceIncrementsZeroed(len: number): EffectiveBalanceIncrements;
|
|
9
8
|
/**
|
|
10
9
|
* effectiveBalanceIncrements length will always be equal or greater than validatorCount. The
|
|
11
|
-
* getEffectiveBalanceIncrementsByteLen() modulo is used to reduce the frequency at which its
|
|
10
|
+
* getEffectiveBalanceIncrementsByteLen() modulo is used to reduce the frequency at which its Uint16Array is recreated.
|
|
12
11
|
* if effectiveBalanceIncrements has length greater than validatorCount it's not a problem since those values would
|
|
13
12
|
* never be accessed.
|
|
14
13
|
*/
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { EFFECTIVE_BALANCE_INCREMENT } from "@lodestar/params";
|
|
2
|
-
/** Helper to prevent re-writting tests downstream if we change
|
|
2
|
+
/** Helper to prevent re-writting tests downstream if we change Uint16Array to number[] */
|
|
3
3
|
export function getEffectiveBalanceIncrementsZeroed(len) {
|
|
4
|
-
return new
|
|
4
|
+
return new Uint16Array(len);
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
7
|
* effectiveBalanceIncrements length will always be equal or greater than validatorCount. The
|
|
8
|
-
* getEffectiveBalanceIncrementsByteLen() modulo is used to reduce the frequency at which its
|
|
8
|
+
* getEffectiveBalanceIncrementsByteLen() modulo is used to reduce the frequency at which its Uint16Array is recreated.
|
|
9
9
|
* if effectiveBalanceIncrements has length greater than validatorCount it's not a problem since those values would
|
|
10
10
|
* never be accessed.
|
|
11
11
|
*/
|
|
12
12
|
export function getEffectiveBalanceIncrementsWithLen(validatorCount) {
|
|
13
13
|
// TODO: Research what's the best number to minimize both memory cost and copy costs
|
|
14
14
|
const byteLen = 1024 * Math.ceil(validatorCount / 1024);
|
|
15
|
-
return new
|
|
15
|
+
return new Uint16Array(byteLen);
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* Shows how EffectiveBalanceIncrements is meant to be populated.
|
|
@@ -21,7 +21,7 @@ export function getEffectiveBalanceIncrementsWithLen(validatorCount) {
|
|
|
21
21
|
*/
|
|
22
22
|
export function getEffectiveBalanceIncrements(state) {
|
|
23
23
|
const validatorsArr = state.validators.getAllReadonlyValues();
|
|
24
|
-
const effectiveBalanceIncrements = new
|
|
24
|
+
const effectiveBalanceIncrements = new Uint16Array(validatorsArr.length);
|
|
25
25
|
for (let i = 0; i < validatorsArr.length; i++) {
|
|
26
26
|
effectiveBalanceIncrements[i] = Math.floor(validatorsArr[i].effectiveBalance / EFFECTIVE_BALANCE_INCREMENT);
|
|
27
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effectiveBalanceIncrements.js","sourceRoot":"","sources":["../../src/cache/effectiveBalanceIncrements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,2BAA2B,EAAC,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"effectiveBalanceIncrements.js","sourceRoot":"","sources":["../../src/cache/effectiveBalanceIncrements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,2BAA2B,EAAC,MAAM,kBAAkB,CAAC;AAQ7D,0FAA0F;AAC1F,MAAM,UAAU,mCAAmC,CAAC,GAAW;IAC7D,OAAO,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oCAAoC,CAAC,cAAsB;IACzE,oFAAoF;IACpF,MAAM,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAExD,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAAC,KAA0B;IACtE,MAAM,aAAa,GAAG,KAAK,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC;IAC9D,MAAM,0BAA0B,GAAG,IAAI,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACzE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,0BAA0B,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,gBAAgB,GAAG,2BAA2B,CAAC,CAAC;IAC9G,CAAC;IACD,OAAO,0BAA0B,CAAC;AACpC,CAAC"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PublicKey } from "@chainsafe/blst";
|
|
2
|
+
import * as immutable from "immutable";
|
|
3
|
+
import { BLSSignature, CommitteeIndex, Epoch, Slot, ValidatorIndex, phase0, SyncPeriod, Attestation, IndexedAttestation } from "@lodestar/types";
|
|
2
4
|
import { BeaconConfig, ChainConfig } from "@lodestar/config";
|
|
5
|
+
import { ForkSeq } from "@lodestar/params";
|
|
3
6
|
import { LodestarError } from "@lodestar/utils";
|
|
4
7
|
import { EpochShuffling } from "../util/epochShuffling.js";
|
|
8
|
+
import { EpochCacheMetrics } from "../metrics.js";
|
|
5
9
|
import { EffectiveBalanceIncrements } from "./effectiveBalanceIncrements.js";
|
|
6
|
-
import { Index2PubkeyCache, PubkeyIndexMap } from "./pubkeyCache.js";
|
|
10
|
+
import { Index2PubkeyCache, PubkeyIndexMap, UnfinalizedPubkeyIndexMap, PubkeyHex } from "./pubkeyCache.js";
|
|
7
11
|
import { BeaconStateAllForks, ShufflingGetter } from "./types.js";
|
|
8
12
|
import { SyncCommitteeCache } from "./syncCommitteeCache.js";
|
|
9
13
|
/** `= PROPOSER_WEIGHT / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)` */
|
|
@@ -51,23 +55,30 @@ type ProposersDeferred = {
|
|
|
51
55
|
export declare class EpochCache {
|
|
52
56
|
config: BeaconConfig;
|
|
53
57
|
/**
|
|
54
|
-
* Unique globally shared pubkey registry. There should only exist one for the entire application.
|
|
58
|
+
* Unique globally shared finalized pubkey registry. There should only exist one for the entire application.
|
|
55
59
|
*
|
|
56
60
|
* TODO: this is a hack, we need a safety mechanism in case a bad eth1 majority vote is in,
|
|
57
61
|
* or handle non finalized data differently, or use an immutable.js structure for cheap copies
|
|
58
|
-
*
|
|
62
|
+
*
|
|
63
|
+
* New: This would include only validators whose activation_eligibility_epoch != FAR_FUTURE_EPOCH and hence it is
|
|
64
|
+
* insert only. Validators could be 1) Active 2) In the activation queue 3) Initialized but pending queued
|
|
59
65
|
*
|
|
60
66
|
* $VALIDATOR_COUNT x 192 char String -> Number Map
|
|
61
67
|
*/
|
|
62
68
|
pubkey2index: PubkeyIndexMap;
|
|
63
69
|
/**
|
|
64
|
-
* Unique globally shared pubkey registry. There should only exist one for the entire application.
|
|
70
|
+
* Unique globally shared finalized pubkey registry. There should only exist one for the entire application.
|
|
65
71
|
*
|
|
66
|
-
*
|
|
72
|
+
* New: This would include only validators whose activation_eligibility_epoch != FAR_FUTURE_EPOCH and hence it is
|
|
73
|
+
* insert only. Validators could be 1) Active 2) In the activation queue 3) Initialized but pending queued
|
|
67
74
|
*
|
|
68
75
|
* $VALIDATOR_COUNT x BLST deserialized pubkey (Jacobian coordinates)
|
|
69
76
|
*/
|
|
70
77
|
index2pubkey: Index2PubkeyCache;
|
|
78
|
+
/**
|
|
79
|
+
* Unique pubkey registry shared in the same fork. There should only exist one for the fork.
|
|
80
|
+
*/
|
|
81
|
+
unfinalizedPubkey2index: UnfinalizedPubkeyIndexMap;
|
|
71
82
|
/**
|
|
72
83
|
* Indexes of the block proposers for the current epoch.
|
|
73
84
|
*
|
|
@@ -125,6 +136,7 @@ export declare class EpochCache {
|
|
|
125
136
|
* initiateValidatorExit(). This value may vary on each fork of the state.
|
|
126
137
|
*
|
|
127
138
|
* NOTE: Changes block to block
|
|
139
|
+
* NOTE: No longer used by initiateValidatorExit post-electra
|
|
128
140
|
*/
|
|
129
141
|
exitQueueEpoch: Epoch;
|
|
130
142
|
/**
|
|
@@ -132,6 +144,7 @@ export declare class EpochCache {
|
|
|
132
144
|
* initiateValidatorExit(). This value may vary on each fork of the state.
|
|
133
145
|
*
|
|
134
146
|
* NOTE: Changes block to block
|
|
147
|
+
* NOTE: No longer used by initiateValidatorExit post-electra
|
|
135
148
|
*/
|
|
136
149
|
exitQueueChurn: number;
|
|
137
150
|
/**
|
|
@@ -158,10 +171,20 @@ export declare class EpochCache {
|
|
|
158
171
|
nextSyncCommitteeIndexed: SyncCommitteeCache;
|
|
159
172
|
epoch: Epoch;
|
|
160
173
|
syncPeriod: SyncPeriod;
|
|
174
|
+
/**
|
|
175
|
+
* state.validators.length of every state at epoch boundary
|
|
176
|
+
* They are saved in increasing order of epoch.
|
|
177
|
+
* The first validator length in the list corresponds to the state AFTER the latest finalized checkpoint state. ie. state.finalizedCheckpoint.epoch - 1
|
|
178
|
+
* The last validator length corresponds to the latest epoch state ie. this.epoch
|
|
179
|
+
* eg. latest epoch = 105, latest finalized cp state epoch = 102
|
|
180
|
+
* then the list will be (in terms of epoch) [103, 104, 105]
|
|
181
|
+
*/
|
|
182
|
+
historicalValidatorLengths: immutable.List<number>;
|
|
161
183
|
constructor(data: {
|
|
162
184
|
config: BeaconConfig;
|
|
163
185
|
pubkey2index: PubkeyIndexMap;
|
|
164
186
|
index2pubkey: Index2PubkeyCache;
|
|
187
|
+
unfinalizedPubkey2index: UnfinalizedPubkeyIndexMap;
|
|
165
188
|
proposers: number[];
|
|
166
189
|
proposersPrevEpoch: number[] | null;
|
|
167
190
|
proposersNextEpoch: ProposersDeferred;
|
|
@@ -184,10 +207,11 @@ export declare class EpochCache {
|
|
|
184
207
|
nextSyncCommitteeIndexed: SyncCommitteeCache;
|
|
185
208
|
epoch: Epoch;
|
|
186
209
|
syncPeriod: SyncPeriod;
|
|
210
|
+
historialValidatorLengths: immutable.List<number>;
|
|
187
211
|
});
|
|
188
212
|
/**
|
|
189
213
|
* Create an epoch cache
|
|
190
|
-
* @param
|
|
214
|
+
* @param state a finalized beacon state. Passing in unfinalized state may cause unexpected behaviour eg. empty unfinalized cache
|
|
191
215
|
*
|
|
192
216
|
* SLOW CODE - 🐢
|
|
193
217
|
*/
|
|
@@ -201,6 +225,7 @@ export declare class EpochCache {
|
|
|
201
225
|
* new epoch.
|
|
202
226
|
*/
|
|
203
227
|
afterProcessEpoch(state: BeaconStateAllForks, epochTransitionCache: {
|
|
228
|
+
indicesEligibleForActivationQueue: ValidatorIndex[];
|
|
204
229
|
nextEpochShufflingActiveValidatorIndices: ValidatorIndex[];
|
|
205
230
|
nextEpochShufflingActiveIndicesLength: number;
|
|
206
231
|
nextEpochTotalActiveBalanceByIncrement: number;
|
|
@@ -210,6 +235,10 @@ export declare class EpochCache {
|
|
|
210
235
|
* Return the beacon committee at slot for index.
|
|
211
236
|
*/
|
|
212
237
|
getBeaconCommittee(slot: Slot, index: CommitteeIndex): Uint32Array;
|
|
238
|
+
/**
|
|
239
|
+
* Return a single Uint32Array representing concatted committees of indices
|
|
240
|
+
*/
|
|
241
|
+
getBeaconCommittees(slot: Slot, indices: CommitteeIndex[]): Uint32Array;
|
|
213
242
|
getCommitteeCountPerSlot(epoch: Epoch): number;
|
|
214
243
|
/**
|
|
215
244
|
* Compute the correct subnet for a slot/committee index
|
|
@@ -258,7 +287,11 @@ export declare class EpochCache {
|
|
|
258
287
|
/**
|
|
259
288
|
* Return the indexed attestation corresponding to ``attestation``.
|
|
260
289
|
*/
|
|
261
|
-
getIndexedAttestation(attestation:
|
|
290
|
+
getIndexedAttestation(fork: ForkSeq, attestation: Attestation): IndexedAttestation;
|
|
291
|
+
/**
|
|
292
|
+
* Return indices of validators who attestested in `attestation`
|
|
293
|
+
*/
|
|
294
|
+
getAttestingIndices(fork: ForkSeq, attestation: Attestation): number[];
|
|
262
295
|
getCommitteeAssignments(epoch: Epoch, requestedValidatorIndices: ValidatorIndex[]): Map<ValidatorIndex, AttesterDuty>;
|
|
263
296
|
/**
|
|
264
297
|
* Return the committee assignment in the ``epoch`` for ``validator_index``.
|
|
@@ -270,7 +303,30 @@ export declare class EpochCache {
|
|
|
270
303
|
*/
|
|
271
304
|
getCommitteeAssignment(epoch: Epoch, validatorIndex: ValidatorIndex): phase0.CommitteeAssignment | null;
|
|
272
305
|
isAggregator(slot: Slot, index: CommitteeIndex, slotSignature: BLSSignature): boolean;
|
|
306
|
+
/**
|
|
307
|
+
* Return finalized pubkey given the validator index.
|
|
308
|
+
* Only finalized pubkey as we do not store unfinalized pubkey because no where in the spec has a
|
|
309
|
+
* need to make such enquiry
|
|
310
|
+
*/
|
|
311
|
+
getPubkey(index: ValidatorIndex): PublicKey | undefined;
|
|
312
|
+
getValidatorIndex(pubkey: Uint8Array | PubkeyHex): ValidatorIndex | undefined;
|
|
313
|
+
/**
|
|
314
|
+
*
|
|
315
|
+
* Add unfinalized pubkeys
|
|
316
|
+
*
|
|
317
|
+
*/
|
|
273
318
|
addPubkey(index: ValidatorIndex, pubkey: Uint8Array): void;
|
|
319
|
+
addUnFinalizedPubkey(index: ValidatorIndex, pubkey: PubkeyHex | Uint8Array, metrics?: EpochCacheMetrics): void;
|
|
320
|
+
addFinalizedPubkeys(pubkeyMap: UnfinalizedPubkeyIndexMap, metrics?: EpochCacheMetrics): void;
|
|
321
|
+
/**
|
|
322
|
+
* Add finalized validator index and pubkey into finalized cache.
|
|
323
|
+
* Since addFinalizedPubkey() primarily takes pubkeys from unfinalized cache, it can take pubkey hex string directly
|
|
324
|
+
*/
|
|
325
|
+
addFinalizedPubkey(index: ValidatorIndex, pubkey: PubkeyHex | Uint8Array, metrics?: EpochCacheMetrics): void;
|
|
326
|
+
/**
|
|
327
|
+
* Delete pubkeys from unfinalized cache
|
|
328
|
+
*/
|
|
329
|
+
deleteUnfinalizedPubkeys(pubkeys: Iterable<PubkeyHex>): void;
|
|
274
330
|
getShufflingAtSlot(slot: Slot): EpochShuffling;
|
|
275
331
|
getShufflingAtSlotOrNull(slot: Slot): EpochShuffling | null;
|
|
276
332
|
getShufflingAtEpoch(epoch: Epoch): EpochShuffling;
|
|
@@ -292,6 +348,8 @@ export declare class EpochCache {
|
|
|
292
348
|
/** On phase0 -> altair fork, set both current and nextSyncCommitteeIndexed */
|
|
293
349
|
setSyncCommitteesIndexed(nextSyncCommitteeIndices: number[]): void;
|
|
294
350
|
effectiveBalanceIncrementsSet(index: number, effectiveBalance: number): void;
|
|
351
|
+
isPostElectra(): boolean;
|
|
352
|
+
getValidatorCountAtEpoch(targetEpoch: Epoch): number | undefined;
|
|
295
353
|
}
|
|
296
354
|
type AttesterDuty = {
|
|
297
355
|
validatorIndex: ValidatorIndex;
|