@lodestar/state-transition 1.40.0-dev.3be9500fa9 → 1.40.0-dev.63c5c3e7f7
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 +1 -0
- package/lib/block/index.d.ts.map +1 -1
- package/lib/block/index.js +1 -0
- package/lib/block/index.js.map +1 -1
- package/lib/block/processConsolidationRequest.d.ts +1 -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 +8 -2
- package/lib/block/processDepositRequest.d.ts.map +1 -1
- package/lib/block/processDepositRequest.js +81 -8
- package/lib/block/processDepositRequest.js.map +1 -1
- package/lib/block/processExecutionPayloadBid.d.ts.map +1 -1
- package/lib/block/processExecutionPayloadBid.js +14 -27
- package/lib/block/processExecutionPayloadBid.js.map +1 -1
- package/lib/block/processExecutionPayloadEnvelope.d.ts.map +1 -1
- package/lib/block/processExecutionPayloadEnvelope.js +26 -25
- package/lib/block/processExecutionPayloadEnvelope.js.map +1 -1
- package/lib/block/processOperations.js +2 -2
- package/lib/block/processOperations.js.map +1 -1
- package/lib/block/processVoluntaryExit.d.ts +1 -1
- package/lib/block/processVoluntaryExit.d.ts.map +1 -1
- package/lib/block/processVoluntaryExit.js +45 -3
- package/lib/block/processVoluntaryExit.js.map +1 -1
- package/lib/block/processWithdrawalRequest.js +1 -1
- package/lib/block/processWithdrawalRequest.js.map +1 -1
- package/lib/block/processWithdrawals.d.ts +1 -0
- package/lib/block/processWithdrawals.d.ts.map +1 -1
- package/lib/block/processWithdrawals.js +121 -66
- package/lib/block/processWithdrawals.js.map +1 -1
- package/lib/epoch/processBuilderPendingPayments.d.ts.map +1 -1
- package/lib/epoch/processBuilderPendingPayments.js +1 -4
- package/lib/epoch/processBuilderPendingPayments.js.map +1 -1
- package/lib/util/electra.d.ts.map +1 -1
- package/lib/util/electra.js +1 -2
- package/lib/util/electra.js.map +1 -1
- package/lib/util/gloas.d.ts +43 -3
- package/lib/util/gloas.d.ts.map +1 -1
- package/lib/util/gloas.js +93 -5
- package/lib/util/gloas.js.map +1 -1
- package/lib/util/validator.d.ts +6 -1
- package/lib/util/validator.d.ts.map +1 -1
- package/lib/util/validator.js +26 -16
- package/lib/util/validator.js.map +1 -1
- package/package.json +7 -7
- package/src/block/index.ts +1 -0
- package/src/block/processConsolidationRequest.ts +2 -3
- package/src/block/processDepositRequest.ts +101 -8
- package/src/block/processExecutionPayloadBid.ts +18 -40
- package/src/block/processExecutionPayloadEnvelope.ts +34 -30
- package/src/block/processOperations.ts +2 -2
- package/src/block/processVoluntaryExit.ts +60 -5
- package/src/block/processWithdrawalRequest.ts +1 -1
- package/src/block/processWithdrawals.ts +168 -70
- package/src/epoch/processBuilderPendingPayments.ts +1 -5
- package/src/util/electra.ts +1 -4
- package/src/util/gloas.ts +109 -8
- package/src/util/validator.ts +31 -16
package/lib/util/gloas.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gloas.d.ts","sourceRoot":"","sources":["../../src/util/gloas.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gloas.d.ts","sourceRoot":"","sources":["../../src/util/gloas.ts"],"names":[],"mappings":"AAWA,OAAO,EAAC,eAAe,EAAC,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAC,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAGnD,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAEzC,wBAAgB,6BAA6B,CAAC,qBAAqB,EAAE,UAAU,GAAG,OAAO,CAExF;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAMtF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAElF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAK5F;AAED;;;GAGG;AACH,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAoBjH;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAUlH;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAW7F;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAOzG;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,sBAAsB,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAOnG;AAED,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAOnG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAExE"}
|
package/lib/util/gloas.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { byteArrayEquals } from "@chainsafe/ssz";
|
|
2
|
-
import { BUILDER_PAYMENT_THRESHOLD_DENOMINATOR, BUILDER_PAYMENT_THRESHOLD_NUMERATOR, BUILDER_WITHDRAWAL_PREFIX, EFFECTIVE_BALANCE_INCREMENT, SLOTS_PER_EPOCH, } from "@lodestar/params";
|
|
2
|
+
import { BUILDER_INDEX_FLAG, BUILDER_PAYMENT_THRESHOLD_DENOMINATOR, BUILDER_PAYMENT_THRESHOLD_NUMERATOR, BUILDER_WITHDRAWAL_PREFIX, EFFECTIVE_BALANCE_INCREMENT, FAR_FUTURE_EPOCH, MIN_DEPOSIT_AMOUNT, SLOTS_PER_EPOCH, } from "@lodestar/params";
|
|
3
3
|
import { getBlockRootAtSlot } from "./blockRoot.js";
|
|
4
4
|
import { computeEpochAtSlot } from "./epoch.js";
|
|
5
|
-
export function
|
|
5
|
+
export function isBuilderWithdrawalCredential(withdrawalCredentials) {
|
|
6
6
|
return withdrawalCredentials[0] === BUILDER_WITHDRAWAL_PREFIX;
|
|
7
7
|
}
|
|
8
8
|
export function getBuilderPaymentQuorumThreshold(state) {
|
|
@@ -10,10 +10,98 @@ export function getBuilderPaymentQuorumThreshold(state) {
|
|
|
10
10
|
BUILDER_PAYMENT_THRESHOLD_NUMERATOR;
|
|
11
11
|
return Math.floor(quorum / BUILDER_PAYMENT_THRESHOLD_DENOMINATOR);
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Check if a validator index represents a builder (has the builder flag set).
|
|
15
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-is_builder_index
|
|
16
|
+
*/
|
|
17
|
+
export function isBuilderIndex(validatorIndex) {
|
|
18
|
+
return (validatorIndex & BUILDER_INDEX_FLAG) !== 0;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Convert a builder index to a flagged validator index for use in Withdrawal containers.
|
|
22
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-convert_builder_index_to_validator_index
|
|
23
|
+
*/
|
|
24
|
+
export function convertBuilderIndexToValidatorIndex(builderIndex) {
|
|
25
|
+
return builderIndex | BUILDER_INDEX_FLAG;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Convert a flagged validator index back to a builder index.
|
|
29
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-convert_validator_index_to_builder_index
|
|
30
|
+
*/
|
|
31
|
+
export function convertValidatorIndexToBuilderIndex(validatorIndex) {
|
|
32
|
+
return validatorIndex & ~BUILDER_INDEX_FLAG;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if a builder is active (deposited and not yet withdrawable).
|
|
36
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#isactivebuilder
|
|
37
|
+
*/
|
|
38
|
+
export function isActiveBuilder(state, builderIndex) {
|
|
39
|
+
const builder = state.builders.getReadonly(builderIndex);
|
|
40
|
+
const finalizedEpoch = state.finalizedCheckpoint.epoch;
|
|
41
|
+
return builder.depositEpoch < finalizedEpoch && builder.withdrawableEpoch === FAR_FUTURE_EPOCH;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the total pending balance to withdraw for a builder (from withdrawals + payments).
|
|
45
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-get_pending_balance_to_withdraw_for_builder
|
|
46
|
+
*/
|
|
47
|
+
export function getPendingBalanceToWithdrawForBuilder(state, builderIndex) {
|
|
48
|
+
let pendingBalance = 0;
|
|
49
|
+
// Sum pending withdrawals
|
|
50
|
+
for (let i = 0; i < state.builderPendingWithdrawals.length; i++) {
|
|
51
|
+
const withdrawal = state.builderPendingWithdrawals.getReadonly(i);
|
|
52
|
+
if (withdrawal.builderIndex === builderIndex) {
|
|
53
|
+
pendingBalance += withdrawal.amount;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Sum pending payments
|
|
57
|
+
for (let i = 0; i < state.builderPendingPayments.length; i++) {
|
|
58
|
+
const payment = state.builderPendingPayments.getReadonly(i);
|
|
59
|
+
if (payment.withdrawal.builderIndex === builderIndex) {
|
|
60
|
+
pendingBalance += payment.withdrawal.amount;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return pendingBalance;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check if a builder has sufficient balance to cover a bid amount.
|
|
67
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-can_builder_cover_bid
|
|
68
|
+
*/
|
|
69
|
+
export function canBuilderCoverBid(state, builderIndex, bidAmount) {
|
|
70
|
+
const builder = state.builders.getReadonly(builderIndex);
|
|
71
|
+
const pendingBalance = getPendingBalanceToWithdrawForBuilder(state, builderIndex);
|
|
72
|
+
const minBalance = MIN_DEPOSIT_AMOUNT + pendingBalance;
|
|
73
|
+
if (builder.balance < minBalance) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return builder.balance - minBalance >= bidAmount;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Initiate a builder exit by setting their withdrawable epoch.
|
|
80
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-initiate_builder_exit
|
|
81
|
+
*/
|
|
82
|
+
export function initiateBuilderExit(state, builderIndex) {
|
|
83
|
+
const builder = state.builders.get(builderIndex);
|
|
84
|
+
// Return if builder already initiated exit
|
|
85
|
+
if (builder.withdrawableEpoch !== FAR_FUTURE_EPOCH) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Set builder exit epoch
|
|
15
89
|
const currentEpoch = computeEpochAtSlot(state.slot);
|
|
16
|
-
|
|
90
|
+
builder.withdrawableEpoch = currentEpoch + state.config.MIN_BUILDER_WITHDRAWABILITY_DELAY;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Find the index of a builder by their public key.
|
|
94
|
+
* Returns null if not found.
|
|
95
|
+
*
|
|
96
|
+
* May consider builder pubkey cache if performance becomes an issue.
|
|
97
|
+
*/
|
|
98
|
+
export function findBuilderIndexByPubkey(state, pubkey) {
|
|
99
|
+
for (let i = 0; i < state.builders.length; i++) {
|
|
100
|
+
if (byteArrayEquals(state.builders.getReadonly(i).pubkey, pubkey)) {
|
|
101
|
+
return i;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
17
105
|
}
|
|
18
106
|
export function isAttestationSameSlot(state, data) {
|
|
19
107
|
if (data.slot === 0)
|
package/lib/util/gloas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gloas.js","sourceRoot":"","sources":["../../src/util/gloas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EACL,qCAAqC,EACrC,mCAAmC,EACnC,yBAAyB,EACzB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"gloas.js","sourceRoot":"","sources":["../../src/util/gloas.ts"],"names":[],"mappings":"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"}
|
package/lib/util/validator.d.ts
CHANGED
|
@@ -26,5 +26,10 @@ export declare function getBalanceChurnLimitFromCache(epochCtx: EpochCache): num
|
|
|
26
26
|
export declare function getActivationExitChurnLimit(epochCtx: EpochCache): number;
|
|
27
27
|
export declare function getConsolidationChurnLimit(epochCtx: EpochCache): number;
|
|
28
28
|
export declare function getMaxEffectiveBalance(withdrawalCredentials: Uint8Array): number;
|
|
29
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Check if validator is partially withdrawable.
|
|
31
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/electra/beacon-chain.md#modified-is_partially_withdrawable_validator
|
|
32
|
+
*/
|
|
33
|
+
export declare function isPartiallyWithdrawableValidator(fork: ForkSeq, validator: phase0.Validator, balance: number): boolean;
|
|
34
|
+
export declare function getPendingBalanceToWithdraw(state: CachedBeaconStateElectra | CachedBeaconStateGloas, validatorIndex: ValidatorIndex): number;
|
|
30
35
|
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/util/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAEL,OAAO,
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/util/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAEL,OAAO,EAIR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAAC,mBAAmB,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,UAAU,EAAC,MAAM,aAAa,CAAC;AAI9G;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAEpF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAEvF;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,KAAK,GAAG,WAAW,CAW/F;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAKpH;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,4BAA4B,EAAE,MAAM,EACpC,kBAAkB,EAAE,MAAM,EAC1B,qBAAqB,EAAE,MAAM,GAC5B,MAAM,CAQR;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAM1E;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAExE;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAEvE;AAED,wBAAgB,sBAAsB,CAAC,qBAAqB,EAAE,UAAU,GAAG,MAAM,CAMhF;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAsBrH;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,wBAAwB,GAAG,sBAAsB,EACxD,cAAc,EAAE,cAAc,GAC7B,MAAM,CASR"}
|
package/lib/util/validator.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { EFFECTIVE_BALANCE_INCREMENT, ForkSeq, MAX_EFFECTIVE_BALANCE_ELECTRA, MIN_ACTIVATION_BALANCE, } from "@lodestar/params";
|
|
1
|
+
import { EFFECTIVE_BALANCE_INCREMENT, ForkSeq, MAX_EFFECTIVE_BALANCE, MAX_EFFECTIVE_BALANCE_ELECTRA, MIN_ACTIVATION_BALANCE, } from "@lodestar/params";
|
|
2
2
|
import { intDiv } from "@lodestar/utils";
|
|
3
|
-
import {
|
|
3
|
+
import { hasEth1WithdrawalCredential } from "./capella.js";
|
|
4
|
+
import { hasCompoundingWithdrawalCredential, hasExecutionWithdrawalCredential } from "./electra.js";
|
|
4
5
|
/**
|
|
5
6
|
* Check if [[validator]] is active
|
|
6
7
|
*/
|
|
@@ -61,26 +62,35 @@ export function getMaxEffectiveBalance(withdrawalCredentials) {
|
|
|
61
62
|
}
|
|
62
63
|
return MIN_ACTIVATION_BALANCE;
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Check if validator is partially withdrawable.
|
|
67
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/electra/beacon-chain.md#modified-is_partially_withdrawable_validator
|
|
68
|
+
*/
|
|
69
|
+
export function isPartiallyWithdrawableValidator(fork, validator, balance) {
|
|
70
|
+
const isPostElectra = fork >= ForkSeq.electra;
|
|
71
|
+
// Check withdrawal credentials
|
|
72
|
+
const hasWithdrawableCredentials = isPostElectra
|
|
73
|
+
? hasExecutionWithdrawalCredential(validator.withdrawalCredentials)
|
|
74
|
+
: hasEth1WithdrawalCredential(validator.withdrawalCredentials);
|
|
75
|
+
if (!hasWithdrawableCredentials) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
// Get max effective balance based on fork
|
|
79
|
+
const maxEffectiveBalance = isPostElectra
|
|
80
|
+
? getMaxEffectiveBalance(validator.withdrawalCredentials)
|
|
81
|
+
: MAX_EFFECTIVE_BALANCE;
|
|
82
|
+
// Check if at max effective balance and has excess balance
|
|
83
|
+
const hasMaxEffectiveBalance = validator.effectiveBalance === maxEffectiveBalance;
|
|
84
|
+
const hasExcessBalance = balance > maxEffectiveBalance;
|
|
85
|
+
return hasMaxEffectiveBalance && hasExcessBalance;
|
|
86
|
+
}
|
|
87
|
+
export function getPendingBalanceToWithdraw(state, validatorIndex) {
|
|
65
88
|
let total = 0;
|
|
66
89
|
for (const item of state.pendingPartialWithdrawals.getAllReadonly()) {
|
|
67
90
|
if (item.validatorIndex === validatorIndex) {
|
|
68
91
|
total += Number(item.amount);
|
|
69
92
|
}
|
|
70
93
|
}
|
|
71
|
-
if (fork >= ForkSeq.gloas) {
|
|
72
|
-
const stateGloas = state;
|
|
73
|
-
for (const item of stateGloas.builderPendingWithdrawals.getAllReadonly()) {
|
|
74
|
-
if (item.builderIndex === validatorIndex) {
|
|
75
|
-
total += item.amount;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
for (const item of stateGloas.builderPendingPayments.getAllReadonly()) {
|
|
79
|
-
if (item.withdrawal.builderIndex === validatorIndex) {
|
|
80
|
-
total += item.withdrawal.amount;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
94
|
return total;
|
|
85
95
|
}
|
|
86
96
|
//# sourceMappingURL=validator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/util/validator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,2BAA2B,EAC3B,OAAO,EACP,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEvC,OAAO,EAAC,kCAAkC,EAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/util/validator.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/ChainSafe/lodestar/issues"
|
|
13
13
|
},
|
|
14
|
-
"version": "1.40.0-dev.
|
|
14
|
+
"version": "1.40.0-dev.63c5c3e7f7",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -62,14 +62,14 @@
|
|
|
62
62
|
"@chainsafe/pubkey-index-map": "^3.0.0",
|
|
63
63
|
"@chainsafe/ssz": "^1.2.2",
|
|
64
64
|
"@chainsafe/swap-or-not-shuffle": "^1.2.1",
|
|
65
|
-
"@lodestar/config": "^1.40.0-dev.
|
|
66
|
-
"@lodestar/params": "^1.40.0-dev.
|
|
67
|
-
"@lodestar/types": "^1.40.0-dev.
|
|
68
|
-
"@lodestar/utils": "^1.40.0-dev.
|
|
65
|
+
"@lodestar/config": "^1.40.0-dev.63c5c3e7f7",
|
|
66
|
+
"@lodestar/params": "^1.40.0-dev.63c5c3e7f7",
|
|
67
|
+
"@lodestar/types": "^1.40.0-dev.63c5c3e7f7",
|
|
68
|
+
"@lodestar/utils": "^1.40.0-dev.63c5c3e7f7",
|
|
69
69
|
"bigint-buffer": "^1.1.5"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@lodestar/api": "^1.40.0-dev.
|
|
72
|
+
"@lodestar/api": "^1.40.0-dev.63c5c3e7f7"
|
|
73
73
|
},
|
|
74
74
|
"keywords": [
|
|
75
75
|
"ethereum",
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"beacon",
|
|
78
78
|
"blockchain"
|
|
79
79
|
],
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "33496b1175076866e5b367c8cc5c530ff76f9ad6"
|
|
81
81
|
}
|
package/src/block/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ export {
|
|
|
38
38
|
export * from "./externalData.js";
|
|
39
39
|
export * from "./initiateValidatorExit.js";
|
|
40
40
|
export * from "./isValidIndexedAttestation.js";
|
|
41
|
+
export * from "./processDepositRequest.js";
|
|
41
42
|
export * from "./processOperations.js";
|
|
42
43
|
|
|
43
44
|
export function processBlock(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {FAR_FUTURE_EPOCH,
|
|
1
|
+
import {FAR_FUTURE_EPOCH, MIN_ACTIVATION_BALANCE, PENDING_CONSOLIDATIONS_LIMIT} from "@lodestar/params";
|
|
2
2
|
import {electra, ssz} from "@lodestar/types";
|
|
3
3
|
import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
4
4
|
import {hasEth1WithdrawalCredential} from "../util/capella.js";
|
|
@@ -13,7 +13,6 @@ import {getConsolidationChurnLimit, getPendingBalanceToWithdraw, isActiveValidat
|
|
|
13
13
|
|
|
14
14
|
// TODO Electra: Clean up necessary as there is a lot of overlap with isValidSwitchToCompoundRequest
|
|
15
15
|
export function processConsolidationRequest(
|
|
16
|
-
fork: ForkSeq,
|
|
17
16
|
state: CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
18
17
|
consolidationRequest: electra.ConsolidationRequest
|
|
19
18
|
): void {
|
|
@@ -83,7 +82,7 @@ export function processConsolidationRequest(
|
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
// Verify the source has no pending withdrawals in the queue
|
|
86
|
-
if (getPendingBalanceToWithdraw(
|
|
85
|
+
if (getPendingBalanceToWithdraw(state, sourceIndex) > 0) {
|
|
87
86
|
return;
|
|
88
87
|
}
|
|
89
88
|
|
|
@@ -1,21 +1,114 @@
|
|
|
1
|
-
import {UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
|
|
2
|
-
import {electra, ssz} from "@lodestar/types";
|
|
1
|
+
import {FAR_FUTURE_EPOCH, ForkSeq, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
|
|
2
|
+
import {BLSPubkey, Bytes32, UintNum64, electra, ssz} from "@lodestar/types";
|
|
3
3
|
import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
4
|
+
import {findBuilderIndexByPubkey, isBuilderWithdrawalCredential} from "../util/gloas.js";
|
|
5
|
+
import {computeEpochAtSlot, isValidatorKnown} from "../util/index.js";
|
|
6
|
+
import {isValidDepositSignature} from "./processDeposit.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Apply a deposit for a builder. Either increases balance for existing builder or adds new builder to registry.
|
|
10
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-apply_deposit_for_builder
|
|
11
|
+
*/
|
|
12
|
+
export function applyDepositForBuilder(
|
|
13
|
+
state: CachedBeaconStateGloas,
|
|
14
|
+
pubkey: BLSPubkey,
|
|
15
|
+
withdrawalCredentials: Bytes32,
|
|
16
|
+
amount: UintNum64,
|
|
17
|
+
signature: Bytes32
|
|
18
|
+
): void {
|
|
19
|
+
const builderIndex = findBuilderIndexByPubkey(state, pubkey);
|
|
20
|
+
|
|
21
|
+
if (builderIndex !== null) {
|
|
22
|
+
// Existing builder - increase balance
|
|
23
|
+
const builder = state.builders.get(builderIndex);
|
|
24
|
+
builder.balance += amount;
|
|
25
|
+
} else {
|
|
26
|
+
// New builder - verify signature and add to registry
|
|
27
|
+
if (isValidDepositSignature(state.config, pubkey, withdrawalCredentials, amount, signature)) {
|
|
28
|
+
addBuilderToRegistry(state, pubkey, withdrawalCredentials, amount);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Add a new builder to the builders registry.
|
|
35
|
+
* Reuses slots from exited and fully withdrawn builders if available.
|
|
36
|
+
*/
|
|
37
|
+
function addBuilderToRegistry(
|
|
38
|
+
state: CachedBeaconStateGloas,
|
|
39
|
+
pubkey: BLSPubkey,
|
|
40
|
+
withdrawalCredentials: Bytes32,
|
|
41
|
+
amount: UintNum64
|
|
42
|
+
): void {
|
|
43
|
+
const currentEpoch = computeEpochAtSlot(state.slot);
|
|
44
|
+
|
|
45
|
+
// Try to find a reusable slot from an exited builder with zero balance
|
|
46
|
+
let builderIndex = state.builders.length;
|
|
47
|
+
for (let i = 0; i < state.builders.length; i++) {
|
|
48
|
+
const builder = state.builders.getReadonly(i);
|
|
49
|
+
if (builder.withdrawableEpoch <= currentEpoch && builder.balance === 0) {
|
|
50
|
+
builderIndex = i;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Create new builder
|
|
56
|
+
const newBuilder = ssz.gloas.Builder.toViewDU({
|
|
57
|
+
pubkey,
|
|
58
|
+
version: withdrawalCredentials[0],
|
|
59
|
+
executionAddress: withdrawalCredentials.subarray(12),
|
|
60
|
+
balance: amount,
|
|
61
|
+
depositEpoch: currentEpoch,
|
|
62
|
+
withdrawableEpoch: FAR_FUTURE_EPOCH,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (builderIndex < state.builders.length) {
|
|
66
|
+
// Reuse existing slot
|
|
67
|
+
state.builders.set(builderIndex, newBuilder);
|
|
68
|
+
} else {
|
|
69
|
+
// Append to end
|
|
70
|
+
state.builders.push(newBuilder);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
4
73
|
|
|
5
74
|
export function processDepositRequest(
|
|
75
|
+
fork: ForkSeq,
|
|
6
76
|
state: CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
7
77
|
depositRequest: electra.DepositRequest
|
|
8
78
|
): void {
|
|
9
|
-
|
|
79
|
+
const {pubkey, withdrawalCredentials, amount, signature} = depositRequest;
|
|
80
|
+
|
|
81
|
+
// Check if this is a builder or validator deposit
|
|
82
|
+
if (fork >= ForkSeq.gloas) {
|
|
83
|
+
const stateGloas = state as CachedBeaconStateGloas;
|
|
84
|
+
const builderIndex = findBuilderIndexByPubkey(stateGloas, pubkey);
|
|
85
|
+
const validatorIndex = state.epochCtx.getValidatorIndex(pubkey);
|
|
86
|
+
|
|
87
|
+
// Regardless of the withdrawal credentials prefix, if a builder/validator
|
|
88
|
+
// already exists with this pubkey, apply the deposit to their balance
|
|
89
|
+
const isBuilder = builderIndex !== null;
|
|
90
|
+
const isValidator = isValidatorKnown(state, validatorIndex);
|
|
91
|
+
const isBuilderPrefix = isBuilderWithdrawalCredential(withdrawalCredentials);
|
|
92
|
+
|
|
93
|
+
// Route to builder if it's an existing builder OR has builder prefix and is not a validator
|
|
94
|
+
if (isBuilder || (isBuilderPrefix && !isValidator)) {
|
|
95
|
+
// Apply builder deposits immediately
|
|
96
|
+
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Only set deposit_requests_start_index in Electra fork, not Gloas
|
|
102
|
+
if (fork < ForkSeq.gloas && state.depositRequestsStartIndex === UNSET_DEPOSIT_REQUESTS_START_INDEX) {
|
|
10
103
|
state.depositRequestsStartIndex = depositRequest.index;
|
|
11
104
|
}
|
|
12
105
|
|
|
13
|
-
//
|
|
106
|
+
// Add validator deposits to the queue
|
|
14
107
|
const pendingDeposit = ssz.electra.PendingDeposit.toViewDU({
|
|
15
|
-
pubkey
|
|
16
|
-
withdrawalCredentials
|
|
17
|
-
amount
|
|
18
|
-
signature
|
|
108
|
+
pubkey,
|
|
109
|
+
withdrawalCredentials,
|
|
110
|
+
amount,
|
|
111
|
+
signature,
|
|
19
112
|
slot: state.slot,
|
|
20
113
|
});
|
|
21
114
|
state.pendingDeposits.push(pendingDeposit);
|
|
@@ -1,68 +1,47 @@
|
|
|
1
1
|
import {PublicKey, Signature, verify} from "@chainsafe/blst";
|
|
2
2
|
import {byteArrayEquals} from "@chainsafe/ssz";
|
|
3
|
-
import {
|
|
4
|
-
DOMAIN_BEACON_BUILDER,
|
|
5
|
-
FAR_FUTURE_EPOCH,
|
|
6
|
-
ForkPostGloas,
|
|
7
|
-
MIN_ACTIVATION_BALANCE,
|
|
8
|
-
SLOTS_PER_EPOCH,
|
|
9
|
-
} from "@lodestar/params";
|
|
3
|
+
import {BUILDER_INDEX_SELF_BUILD, DOMAIN_BEACON_BUILDER, ForkPostGloas, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
10
4
|
import {BeaconBlock, gloas, ssz} from "@lodestar/types";
|
|
11
5
|
import {toHex, toRootHex} from "@lodestar/utils";
|
|
12
6
|
import {G2_POINT_AT_INFINITY} from "../constants/constants.ts";
|
|
13
7
|
import {CachedBeaconStateGloas} from "../types.ts";
|
|
14
|
-
import {
|
|
15
|
-
import {computeSigningRoot, getCurrentEpoch, getRandaoMix
|
|
8
|
+
import {canBuilderCoverBid, isActiveBuilder} from "../util/gloas.ts";
|
|
9
|
+
import {computeSigningRoot, getCurrentEpoch, getRandaoMix} from "../util/index.ts";
|
|
16
10
|
|
|
17
11
|
export function processExecutionPayloadBid(state: CachedBeaconStateGloas, block: BeaconBlock<ForkPostGloas>): void {
|
|
18
12
|
const signedBid = block.body.signedExecutionPayloadBid;
|
|
19
13
|
const bid = signedBid.message;
|
|
20
14
|
const {builderIndex, value: amount} = bid;
|
|
21
|
-
const builder = state.validators.getReadonly(builderIndex);
|
|
22
15
|
|
|
23
16
|
// For self-builds, amount must be zero regardless of withdrawal credential prefix
|
|
24
|
-
if (builderIndex ===
|
|
17
|
+
if (builderIndex === BUILDER_INDEX_SELF_BUILD) {
|
|
25
18
|
if (amount !== 0) {
|
|
26
19
|
throw Error(`Invalid execution payload bid: self-build with non-zero amount ${amount}`);
|
|
27
20
|
}
|
|
28
21
|
if (!byteArrayEquals(signedBid.signature, G2_POINT_AT_INFINITY)) {
|
|
29
22
|
throw Error("Invalid execution payload bid: self-build with non-zero signature");
|
|
30
23
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
}
|
|
25
|
+
// Non-self builds require active builder with valid signature
|
|
26
|
+
else {
|
|
27
|
+
const builder = state.builders.getReadonly(builderIndex);
|
|
28
|
+
|
|
29
|
+
// Verify that the builder is active
|
|
30
|
+
if (!isActiveBuilder(state, builderIndex)) {
|
|
31
|
+
throw Error(`Invalid execution payload bid: builder ${builderIndex} is not active`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Verify that the builder has funds to cover the bid
|
|
35
|
+
if (!canBuilderCoverBid(state, builderIndex, amount)) {
|
|
36
|
+
throw Error(`Invalid execution payload bid: builder ${builderIndex} has insufficient balance`);
|
|
35
37
|
}
|
|
36
38
|
|
|
39
|
+
// Verify that the bid signature is valid
|
|
37
40
|
if (!verifyExecutionPayloadBidSignature(state, builder.pubkey, signedBid)) {
|
|
38
41
|
throw Error(`Invalid execution payload bid: invalid signature for builder ${builderIndex}`);
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
if (!isActiveValidator(builder, getCurrentEpoch(state))) {
|
|
43
|
-
throw Error(`Invalid execution payload bid: builder ${builderIndex} is not active`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (builder.slashed) {
|
|
47
|
-
throw Error(`Invalid execution payload bid: builder ${builderIndex} is slashed`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const pendingPayments = state.builderPendingPayments
|
|
51
|
-
.getAllReadonly()
|
|
52
|
-
.filter((payment) => payment.withdrawal.builderIndex === builderIndex)
|
|
53
|
-
.reduce((acc, payment) => acc + payment.withdrawal.amount, 0);
|
|
54
|
-
const pendingWithdrawals = state.builderPendingWithdrawals
|
|
55
|
-
.getAllReadonly()
|
|
56
|
-
.filter((withdrawal) => withdrawal.builderIndex === builderIndex)
|
|
57
|
-
.reduce((acc, withdrawal) => acc + withdrawal.amount, 0);
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
amount !== 0 &&
|
|
61
|
-
state.balances.get(builderIndex) < amount + pendingPayments + pendingWithdrawals + MIN_ACTIVATION_BALANCE
|
|
62
|
-
) {
|
|
63
|
-
throw Error("Insufficient builder balance");
|
|
64
|
-
}
|
|
65
|
-
|
|
66
45
|
if (bid.slot !== block.slot) {
|
|
67
46
|
throw Error(`Bid slot ${bid.slot} does not match block slot ${block.slot}`);
|
|
68
47
|
}
|
|
@@ -91,7 +70,6 @@ export function processExecutionPayloadBid(state: CachedBeaconStateGloas, block:
|
|
|
91
70
|
feeRecipient: bid.feeRecipient,
|
|
92
71
|
amount,
|
|
93
72
|
builderIndex,
|
|
94
|
-
withdrawableEpoch: FAR_FUTURE_EPOCH,
|
|
95
73
|
}),
|
|
96
74
|
});
|
|
97
75
|
|