@lodestar/state-transition 1.43.0-dev.bc569affb9 → 1.43.0-dev.c98da75ec7
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/processConsolidationRequest.d.ts.map +1 -1
- package/lib/block/processConsolidationRequest.js +2 -1
- package/lib/block/processConsolidationRequest.js.map +1 -1
- package/lib/block/processDepositRequest.d.ts +3 -11
- package/lib/block/processDepositRequest.d.ts.map +1 -1
- package/lib/block/processDepositRequest.js +27 -35
- package/lib/block/processDepositRequest.js.map +1 -1
- package/lib/block/processParentExecutionPayload.d.ts +2 -2
- package/lib/block/processParentExecutionPayload.d.ts.map +1 -1
- package/lib/block/processParentExecutionPayload.js +7 -6
- package/lib/block/processParentExecutionPayload.js.map +1 -1
- package/lib/block/processWithdrawals.d.ts.map +1 -1
- package/lib/block/processWithdrawals.js +4 -6
- package/lib/block/processWithdrawals.js.map +1 -1
- package/lib/cache/epochCache.js +3 -3
- package/lib/cache/epochCache.js.map +1 -1
- package/lib/epoch/processPendingDeposits.d.ts.map +1 -1
- package/lib/epoch/processPendingDeposits.js +4 -2
- package/lib/epoch/processPendingDeposits.js.map +1 -1
- package/lib/lightClient/spec/index.d.ts +22 -0
- package/lib/lightClient/spec/index.d.ts.map +1 -0
- package/lib/lightClient/spec/index.js +58 -0
- package/lib/lightClient/spec/index.js.map +1 -0
- package/lib/lightClient/spec/isBetterUpdate.d.ts +23 -0
- package/lib/lightClient/spec/isBetterUpdate.d.ts.map +1 -0
- package/lib/lightClient/spec/isBetterUpdate.js +66 -0
- package/lib/lightClient/spec/isBetterUpdate.js.map +1 -0
- package/lib/lightClient/spec/processLightClientUpdate.d.ts +12 -0
- package/lib/lightClient/spec/processLightClientUpdate.d.ts.map +1 -0
- package/lib/lightClient/spec/processLightClientUpdate.js +80 -0
- package/lib/lightClient/spec/processLightClientUpdate.js.map +1 -0
- package/lib/lightClient/spec/store.d.ts +45 -0
- package/lib/lightClient/spec/store.d.ts.map +1 -0
- package/lib/lightClient/spec/store.js +56 -0
- package/lib/lightClient/spec/store.js.map +1 -0
- package/lib/lightClient/spec/utils.d.ts +47 -0
- package/lib/lightClient/spec/utils.d.ts.map +1 -0
- package/lib/lightClient/spec/utils.js +197 -0
- package/lib/lightClient/spec/utils.js.map +1 -0
- package/lib/lightClient/spec/validateLightClientBootstrap.d.ts +4 -0
- package/lib/lightClient/spec/validateLightClientBootstrap.d.ts.map +1 -0
- package/lib/lightClient/spec/validateLightClientBootstrap.js +22 -0
- package/lib/lightClient/spec/validateLightClientBootstrap.js.map +1 -0
- package/lib/lightClient/spec/validateLightClientUpdate.d.ts +5 -0
- package/lib/lightClient/spec/validateLightClientUpdate.d.ts.map +1 -0
- package/lib/lightClient/spec/validateLightClientUpdate.js +88 -0
- package/lib/lightClient/spec/validateLightClientUpdate.js.map +1 -0
- package/lib/signatureSets/index.d.ts +1 -0
- package/lib/signatureSets/index.d.ts.map +1 -1
- package/lib/signatureSets/index.js +1 -0
- package/lib/signatureSets/index.js.map +1 -1
- package/lib/signatureSets/proposerPreferences.d.ts +4 -0
- package/lib/signatureSets/proposerPreferences.d.ts.map +1 -0
- package/lib/signatureSets/proposerPreferences.js +8 -0
- package/lib/signatureSets/proposerPreferences.js.map +1 -0
- package/lib/slot/upgradeStateToElectra.d.ts.map +1 -1
- package/lib/slot/upgradeStateToElectra.js +2 -2
- package/lib/slot/upgradeStateToElectra.js.map +1 -1
- package/lib/slot/upgradeStateToGloas.d.ts.map +1 -1
- package/lib/slot/upgradeStateToGloas.js +33 -28
- package/lib/slot/upgradeStateToGloas.js.map +1 -1
- package/lib/stateView/beaconStateView.d.ts +14 -5
- package/lib/stateView/beaconStateView.d.ts.map +1 -1
- package/lib/stateView/beaconStateView.js +40 -11
- package/lib/stateView/beaconStateView.js.map +1 -1
- package/lib/stateView/interface.d.ts +7 -5
- package/lib/stateView/interface.d.ts.map +1 -1
- package/lib/stateView/interface.js.map +1 -1
- package/lib/util/epoch.d.ts.map +1 -1
- package/lib/util/epoch.js +6 -4
- package/lib/util/epoch.js.map +1 -1
- package/lib/util/gloas.d.ts +0 -1
- package/lib/util/gloas.d.ts.map +1 -1
- package/lib/util/gloas.js +0 -4
- package/lib/util/gloas.js.map +1 -1
- package/lib/util/index.d.ts +1 -0
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +1 -0
- package/lib/util/index.js.map +1 -1
- package/lib/util/loadState/loadState.js +4 -4
- package/lib/util/loadState/loadState.js.map +1 -1
- package/lib/util/pendingDepositsLookup.d.ts +40 -0
- package/lib/util/pendingDepositsLookup.d.ts.map +1 -0
- package/lib/util/pendingDepositsLookup.js +84 -0
- package/lib/util/pendingDepositsLookup.js.map +1 -0
- package/lib/util/validator.d.ts +14 -2
- package/lib/util/validator.d.ts.map +1 -1
- package/lib/util/validator.js +24 -2
- package/lib/util/validator.js.map +1 -1
- package/package.json +13 -8
- package/src/block/processConsolidationRequest.ts +2 -1
- package/src/block/processDepositRequest.ts +29 -47
- package/src/block/processParentExecutionPayload.ts +7 -6
- package/src/block/processWithdrawals.ts +6 -6
- package/src/cache/epochCache.ts +3 -3
- package/src/epoch/processPendingDeposits.ts +5 -2
- package/src/lightClient/spec/index.ts +101 -0
- package/src/lightClient/spec/isBetterUpdate.ts +94 -0
- package/src/lightClient/spec/processLightClientUpdate.ts +119 -0
- package/src/lightClient/spec/store.ts +106 -0
- package/src/lightClient/spec/utils.ts +317 -0
- package/src/lightClient/spec/validateLightClientBootstrap.ts +39 -0
- package/src/lightClient/spec/validateLightClientUpdate.ts +145 -0
- package/src/signatureSets/index.ts +1 -0
- package/src/signatureSets/proposerPreferences.ts +12 -0
- package/src/slot/upgradeStateToElectra.ts +4 -2
- package/src/slot/upgradeStateToGloas.ts +41 -44
- package/src/stateView/beaconStateView.ts +43 -12
- package/src/stateView/interface.ts +7 -5
- package/src/util/epoch.ts +13 -4
- package/src/util/gloas.ts +0 -5
- package/src/util/index.ts +1 -0
- package/src/util/loadState/loadState.ts +4 -4
- package/src/util/pendingDepositsLookup.ts +105 -0
- package/src/util/validator.ts +42 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { toPubkeyHex } from "@lodestar/utils";
|
|
2
|
+
import { isValidDepositSignature } from "../block/processDeposit.js";
|
|
3
|
+
/**
|
|
4
|
+
* Mutable lookup for the pending-deposit sequence used by builder-routing logic.
|
|
5
|
+
*
|
|
6
|
+
* This is to implement the spec's `is_pending_validator(pending_deposits, pubkey)` lazily:
|
|
7
|
+
* deposits are grouped by pubkey without verifying signatures, and BLS verification is
|
|
8
|
+
* deferred until a builder deposit needs to know whether the same pubkey already has a
|
|
9
|
+
* valid pending validator deposit.
|
|
10
|
+
*
|
|
11
|
+
* Call `add()` whenever a deposit is appended to the represented sequence. A cached `true`
|
|
12
|
+
* result short-circuits all subsequent checks for that pubkey; a cached `false` records
|
|
13
|
+
* how many deposits were already verified, so appending a new deposit only verifies the
|
|
14
|
+
* newly-appended tail rather than re-running BLS on previously-invalid entries.
|
|
15
|
+
*/
|
|
16
|
+
export class PendingDepositsLookup {
|
|
17
|
+
depositsByPubkey;
|
|
18
|
+
validationCache;
|
|
19
|
+
constructor(depositsByPubkey, validationCache) {
|
|
20
|
+
this.depositsByPubkey = depositsByPubkey;
|
|
21
|
+
this.validationCache = validationCache;
|
|
22
|
+
}
|
|
23
|
+
/** Build an empty lookup for a sequence that will be populated incrementally. */
|
|
24
|
+
static buildEmpty() {
|
|
25
|
+
return new PendingDepositsLookup(new Map(), new Map());
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build a pubkey -> pending-deposits lookup from `state.pendingDeposits`.
|
|
29
|
+
* No BLS work is done here; signature verification happens lazily in `hasPendingValidator`.
|
|
30
|
+
*/
|
|
31
|
+
static build(state) {
|
|
32
|
+
const lookup = PendingDepositsLookup.buildEmpty();
|
|
33
|
+
for (const pendingDeposit of state.pendingDeposits.getAllReadonly()) {
|
|
34
|
+
lookup.add(pendingDeposit);
|
|
35
|
+
}
|
|
36
|
+
return lookup;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Append a pending deposit to the represented sequence.
|
|
40
|
+
* Pass `pubkeyHex` if the caller has already computed it.
|
|
41
|
+
*/
|
|
42
|
+
add(pendingDeposit, pubkeyHex) {
|
|
43
|
+
const key = pubkeyHex ?? toPubkeyHex(pendingDeposit.pubkey);
|
|
44
|
+
const existing = this.depositsByPubkey.get(key);
|
|
45
|
+
if (existing) {
|
|
46
|
+
existing.push(pendingDeposit);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.depositsByPubkey.set(key, [pendingDeposit]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Returns true if any pending deposit for `pubkeyHex` has a valid BLS deposit signature.
|
|
54
|
+
* Memoizes the result in `validationCache` so repeated checks for the same pubkey
|
|
55
|
+
* within a block only verify deposits that have not already been checked.
|
|
56
|
+
*/
|
|
57
|
+
hasPendingValidator(config, pubkeyHex) {
|
|
58
|
+
const validation = this.validationCache.get(pubkeyHex);
|
|
59
|
+
if (validation?.hasValidSignature === true) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
const deposits = this.depositsByPubkey.get(pubkeyHex);
|
|
63
|
+
if (deposits === undefined) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
// hasValidSignature is false or undefined; resume from the last validatedCount so
|
|
67
|
+
// previously-checked invalid deposits are not re-verified.
|
|
68
|
+
const startIndex = validation?.validatedCount ?? 0;
|
|
69
|
+
if (startIndex === deposits.length) {
|
|
70
|
+
// Nothing new to check; the cached false result still holds.
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
for (let i = startIndex; i < deposits.length; i++) {
|
|
74
|
+
const deposit = deposits[i];
|
|
75
|
+
if (isValidDepositSignature(config, deposit.pubkey, deposit.withdrawalCredentials, deposit.amount, deposit.signature)) {
|
|
76
|
+
this.validationCache.set(pubkeyHex, { hasValidSignature: true, validatedCount: i + 1 });
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this.validationCache.set(pubkeyHex, { hasValidSignature: false, validatedCount: deposits.length });
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=pendingDepositsLookup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pendingDepositsLookup.js","sourceRoot":"","sources":["../../src/util/pendingDepositsLookup.ts"],"names":[],"mappings":"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"}
|
package/lib/util/validator.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare function isSlashableValidator(validator: phase0.Validator, epoch:
|
|
|
16
16
|
* NAIVE - SLOW CODE 🐢
|
|
17
17
|
*/
|
|
18
18
|
export declare function getActiveValidatorIndices(state: BeaconStateAllForks, epoch: Epoch): Uint32Array;
|
|
19
|
-
export declare function
|
|
19
|
+
export declare function getValidatorActivationChurnLimit(config: ChainForkConfig, fork: ForkSeq, activeValidatorCount: number): number;
|
|
20
20
|
export declare function getChurnLimit(config: ChainForkConfig, activeValidatorCount: number): number;
|
|
21
21
|
/**
|
|
22
22
|
* Get combined churn limit of activation-exit and consolidation
|
|
@@ -24,7 +24,19 @@ export declare function getChurnLimit(config: ChainForkConfig, activeValidatorCo
|
|
|
24
24
|
export declare function getBalanceChurnLimit(totalActiveBalanceIncrements: number, churnLimitQuotient: number, minPerEpochChurnLimit: number): number;
|
|
25
25
|
export declare function getBalanceChurnLimitFromCache(epochCtx: EpochCache): number;
|
|
26
26
|
export declare function getActivationExitChurnLimit(epochCtx: EpochCache): number;
|
|
27
|
-
|
|
27
|
+
/**
|
|
28
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-get_activation_churn_limit
|
|
29
|
+
*/
|
|
30
|
+
export declare function getActivationChurnLimit(epochCtx: EpochCache): number;
|
|
31
|
+
/**
|
|
32
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-get_exit_churn_limit
|
|
33
|
+
*/
|
|
34
|
+
export declare function getExitChurnLimit(epochCtx: EpochCache): number;
|
|
35
|
+
/**
|
|
36
|
+
* Spec (electra): get_consolidation_churn_limit (uses combined balance churn minus activation+exit churn)
|
|
37
|
+
* Spec (gloas): get_consolidation_churn_limit (independent quotient, no MIN floor)
|
|
38
|
+
*/
|
|
39
|
+
export declare function getConsolidationChurnLimit(fork: ForkSeq, epochCtx: EpochCache): number;
|
|
28
40
|
export declare function getMaxEffectiveBalance(withdrawalCredentials: Uint8Array): number;
|
|
29
41
|
/**
|
|
30
42
|
* Check if validator is partially withdrawable.
|
|
@@ -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,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;
|
|
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;AAGD,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,OAAO,EACb,oBAAoB,EAAE,MAAM,GAC3B,MAAM,CAKR;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;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAOpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAM9D;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,GAAG,MAAM,CAUtF;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
|
@@ -29,7 +29,8 @@ export function getActiveValidatorIndices(state, epoch) {
|
|
|
29
29
|
}
|
|
30
30
|
return new Uint32Array(indices);
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
// Deneb fork upgrade only
|
|
33
|
+
export function getValidatorActivationChurnLimit(config, fork, activeValidatorCount) {
|
|
33
34
|
if (fork >= ForkSeq.deneb) {
|
|
34
35
|
return Math.min(config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT, getChurnLimit(config, activeValidatorCount));
|
|
35
36
|
}
|
|
@@ -52,7 +53,28 @@ export function getBalanceChurnLimitFromCache(epochCtx) {
|
|
|
52
53
|
export function getActivationExitChurnLimit(epochCtx) {
|
|
53
54
|
return Math.min(epochCtx.config.MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT, getBalanceChurnLimitFromCache(epochCtx));
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
+
/**
|
|
57
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-get_activation_churn_limit
|
|
58
|
+
*/
|
|
59
|
+
export function getActivationChurnLimit(epochCtx) {
|
|
60
|
+
const churn = getBalanceChurnLimit(epochCtx.totalActiveBalanceIncrements, epochCtx.config.CHURN_LIMIT_QUOTIENT_GLOAS, epochCtx.config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA);
|
|
61
|
+
return Math.min(epochCtx.config.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT_GLOAS, churn);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-get_exit_churn_limit
|
|
65
|
+
*/
|
|
66
|
+
export function getExitChurnLimit(epochCtx) {
|
|
67
|
+
return getBalanceChurnLimit(epochCtx.totalActiveBalanceIncrements, epochCtx.config.CHURN_LIMIT_QUOTIENT_GLOAS, epochCtx.config.MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Spec (electra): get_consolidation_churn_limit (uses combined balance churn minus activation+exit churn)
|
|
71
|
+
* Spec (gloas): get_consolidation_churn_limit (independent quotient, no MIN floor)
|
|
72
|
+
*/
|
|
73
|
+
export function getConsolidationChurnLimit(fork, epochCtx) {
|
|
74
|
+
if (fork >= ForkSeq.gloas) {
|
|
75
|
+
// No MIN floor — pass 0 so getBalanceChurnLimit's max(churn, min) is a no-op.
|
|
76
|
+
return getBalanceChurnLimit(epochCtx.totalActiveBalanceIncrements, epochCtx.config.CONSOLIDATION_CHURN_LIMIT_QUOTIENT, 0);
|
|
77
|
+
}
|
|
56
78
|
return getBalanceChurnLimitFromCache(epochCtx) - getActivationExitChurnLimit(epochCtx);
|
|
57
79
|
}
|
|
58
80
|
export function getMaxEffectiveBalance(withdrawalCredentials) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/util/validator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,2BAA2B,EAC3B,OAAO,EACP,qBAAqB,EACrB,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEvC,OAAO,EAAC,2BAA2B,EAAC,MAAM,cAAc,CAAC;AACzD,OAAO,EAAC,kCAAkC,EAAE,gCAAgC,EAAC,MAAM,cAAc,CAAC;AAElG;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAA2B,EAAE,KAAY,EAAW;IACpF,OAAO,SAAS,CAAC,eAAe,IAAI,KAAK,IAAI,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC;AAAA,CAC1E;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAA2B,EAAE,KAAY,EAAW;IACvF,OAAO,CAAC,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,eAAe,IAAI,KAAK,IAAI,KAAK,GAAG,SAAS,CAAC,iBAAiB,CAAC;AAAA,CACxG;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAA0B,EAAE,KAAY,EAAe;IAC/F,MAAM,OAAO,GAAqB,EAAE,CAAC;IAErC,MAAM,aAAa,GAAG,KAAK,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC;IAC9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,IAAI,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;AAAA,CACjC;AAED,MAAM,UAAU,
|
|
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.43.0-dev.
|
|
14
|
+
"version": "1.43.0-dev.c98da75ec7",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -34,6 +34,11 @@
|
|
|
34
34
|
"types": "./lib/slot/index.d.ts",
|
|
35
35
|
"import": "./lib/slot/index.js"
|
|
36
36
|
},
|
|
37
|
+
"./light-client": {
|
|
38
|
+
"bun": "./src/lightClient/spec/index.ts",
|
|
39
|
+
"types": "./lib/lightClient/spec/index.d.ts",
|
|
40
|
+
"import": "./lib/lightClient/spec/index.js"
|
|
41
|
+
},
|
|
37
42
|
"./test-utils": {
|
|
38
43
|
"bun": "./src/testUtils/index.ts",
|
|
39
44
|
"types": "./lib/testUtils/index.d.ts",
|
|
@@ -62,19 +67,19 @@
|
|
|
62
67
|
"dependencies": {
|
|
63
68
|
"@chainsafe/as-sha256": "^1.2.0",
|
|
64
69
|
"@chainsafe/blst": "^2.2.0",
|
|
65
|
-
"@chainsafe/persistent-merkle-tree": "^1.2.
|
|
70
|
+
"@chainsafe/persistent-merkle-tree": "^1.2.5",
|
|
66
71
|
"@chainsafe/persistent-ts": "^1.0.0",
|
|
67
72
|
"@chainsafe/pubkey-index-map": "^3.0.0",
|
|
68
73
|
"@chainsafe/ssz": "^1.4.0",
|
|
69
74
|
"@chainsafe/swap-or-not-shuffle": "^1.2.1",
|
|
70
|
-
"@lodestar/config": "^1.43.0-dev.
|
|
71
|
-
"@lodestar/params": "^1.43.0-dev.
|
|
72
|
-
"@lodestar/types": "^1.43.0-dev.
|
|
73
|
-
"@lodestar/utils": "^1.43.0-dev.
|
|
75
|
+
"@lodestar/config": "^1.43.0-dev.c98da75ec7",
|
|
76
|
+
"@lodestar/params": "^1.43.0-dev.c98da75ec7",
|
|
77
|
+
"@lodestar/types": "^1.43.0-dev.c98da75ec7",
|
|
78
|
+
"@lodestar/utils": "^1.43.0-dev.c98da75ec7",
|
|
74
79
|
"@vekexasia/bigint-buffer2": "^1.1.1"
|
|
75
80
|
},
|
|
76
81
|
"devDependencies": {
|
|
77
|
-
"@lodestar/api": "^1.43.0-dev.
|
|
82
|
+
"@lodestar/api": "^1.43.0-dev.c98da75ec7"
|
|
78
83
|
},
|
|
79
84
|
"keywords": [
|
|
80
85
|
"ethereum",
|
|
@@ -82,5 +87,5 @@
|
|
|
82
87
|
"beacon",
|
|
83
88
|
"blockchain"
|
|
84
89
|
],
|
|
85
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "d44b10862beae5c59469c81b1aed99df3871dbe9"
|
|
86
91
|
}
|
|
@@ -46,7 +46,8 @@ export function processConsolidationRequest(
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// If there is too little available consolidation churn limit, consolidation requests are ignored
|
|
49
|
-
|
|
49
|
+
const fork = state.config.getForkSeq(state.slot);
|
|
50
|
+
if (getConsolidationChurnLimit(fork, state.epochCtx) <= MIN_ACTIVATION_BALANCE) {
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
52
53
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {BeaconConfig} from "@lodestar/config";
|
|
2
1
|
import {FAR_FUTURE_EPOCH, ForkSeq, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
|
|
3
|
-
import {BLSPubkey, Bytes32,
|
|
2
|
+
import {BLSPubkey, Bytes32, UintNum64, electra, ssz} from "@lodestar/types";
|
|
4
3
|
import {toPubkeyHex} from "@lodestar/utils";
|
|
5
4
|
import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
6
5
|
import {findBuilderIndexByPubkey, isBuilderWithdrawalCredential} from "../util/gloas.js";
|
|
7
6
|
import {computeEpochAtSlot, isValidatorKnown} from "../util/index.js";
|
|
7
|
+
import {PendingDepositsLookup} from "../util/pendingDepositsLookup.js";
|
|
8
8
|
import {isValidDepositSignature} from "./processDeposit.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -76,53 +76,60 @@ function addBuilderToRegistry(
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
// TODO GLOAS:
|
|
80
|
-
//
|
|
81
|
-
//
|
|
79
|
+
// TODO GLOAS: the PendingDepositsLookup is currently scoped to a single envelope of
|
|
80
|
+
// deposit-requests. We can track it as ephemeral within EpochCache and transfer to the next block
|
|
81
|
+
// transition to reuse cached signature verifications.
|
|
82
82
|
// See https://github.com/ChainSafe/lodestar/issues/9181
|
|
83
83
|
export function processDepositRequest(
|
|
84
84
|
fork: ForkSeq,
|
|
85
85
|
state: CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
86
86
|
depositRequest: electra.DepositRequest,
|
|
87
|
-
|
|
87
|
+
pendingDepositsLookup?: PendingDepositsLookup
|
|
88
88
|
): void {
|
|
89
89
|
const {pubkey, withdrawalCredentials, amount, signature} = depositRequest;
|
|
90
90
|
|
|
91
|
-
// Check if this is a builder or validator deposit
|
|
92
91
|
if (fork >= ForkSeq.gloas) {
|
|
93
92
|
const stateGloas = state as CachedBeaconStateGloas;
|
|
94
|
-
const
|
|
95
|
-
pendingValidatorPubkeysCache ?? getPendingValidatorPubkeys(state.config, stateGloas);
|
|
93
|
+
const lookup = pendingDepositsLookup ?? PendingDepositsLookup.build(stateGloas);
|
|
96
94
|
const pubkeyHex = toPubkeyHex(pubkey);
|
|
97
95
|
const builderIndex = findBuilderIndexByPubkey(stateGloas, pubkey);
|
|
98
96
|
const validatorIndex = state.epochCtx.getValidatorIndex(pubkey);
|
|
99
97
|
|
|
100
|
-
// Regardless of the withdrawal credentials prefix, if a builder/validator
|
|
101
|
-
// already exists with this pubkey, apply the deposit to their balance
|
|
102
98
|
const isBuilder = builderIndex !== null;
|
|
103
99
|
const isValidator = isValidatorKnown(state, validatorIndex);
|
|
104
|
-
const isPendingValidator = pendingValidatorPubkeys.has(pubkeyHex);
|
|
105
100
|
|
|
106
|
-
if (isBuilder
|
|
107
|
-
//
|
|
101
|
+
if (isBuilder) {
|
|
102
|
+
// Top up an existing builder regardless of withdrawal credential prefix
|
|
108
103
|
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature, state.slot);
|
|
109
104
|
return;
|
|
110
105
|
}
|
|
111
106
|
|
|
112
|
-
//
|
|
113
|
-
// deposit requests for the same pubkey in this envelope must see it as a pending validator
|
|
107
|
+
// Only check the (expensive) "pending validator" condition when needed
|
|
114
108
|
if (
|
|
115
|
-
|
|
109
|
+
isBuilderWithdrawalCredential(withdrawalCredentials) &&
|
|
116
110
|
!isValidator &&
|
|
117
|
-
!
|
|
118
|
-
isValidDepositSignature(state.config, pubkey, withdrawalCredentials, amount, signature)
|
|
111
|
+
!lookup.hasPendingValidator(state.config, pubkeyHex)
|
|
119
112
|
) {
|
|
120
|
-
|
|
113
|
+
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature, state.slot);
|
|
114
|
+
return;
|
|
121
115
|
}
|
|
116
|
+
|
|
117
|
+
const pendingDeposit = ssz.electra.PendingDeposit.toViewDU({
|
|
118
|
+
pubkey,
|
|
119
|
+
withdrawalCredentials,
|
|
120
|
+
amount,
|
|
121
|
+
signature,
|
|
122
|
+
slot: state.slot,
|
|
123
|
+
});
|
|
124
|
+
// Keep the lookup in sync with state.pendingDeposits so later deposit-requests
|
|
125
|
+
// in the same envelope see this deposit
|
|
126
|
+
lookup.add(pendingDeposit, pubkeyHex);
|
|
127
|
+
state.pendingDeposits.push(pendingDeposit);
|
|
128
|
+
return;
|
|
122
129
|
}
|
|
123
130
|
|
|
124
|
-
//
|
|
125
|
-
if (
|
|
131
|
+
// Pre-Gloas (Electra) path
|
|
132
|
+
if (state.depositRequestsStartIndex === UNSET_DEPOSIT_REQUESTS_START_INDEX) {
|
|
126
133
|
state.depositRequestsStartIndex = depositRequest.index;
|
|
127
134
|
}
|
|
128
135
|
|
|
@@ -136,28 +143,3 @@ export function processDepositRequest(
|
|
|
136
143
|
});
|
|
137
144
|
state.pendingDeposits.push(pendingDeposit);
|
|
138
145
|
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Build a set of pubkeys (hex-encoded) from pending deposits that have valid signatures.
|
|
142
|
-
* This is computed once and passed to each processDepositRequest call to avoid
|
|
143
|
-
* repeatedly iterating state.pendingDeposits.
|
|
144
|
-
*
|
|
145
|
-
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.3/specs/gloas/beacon-chain.md#new-is_pending_validator
|
|
146
|
-
*/
|
|
147
|
-
export function getPendingValidatorPubkeys(config: BeaconConfig, state: CachedBeaconStateGloas): Set<PubkeyHex> {
|
|
148
|
-
const result = new Set<PubkeyHex>();
|
|
149
|
-
for (const pendingDeposit of state.pendingDeposits.getAllReadonly()) {
|
|
150
|
-
if (
|
|
151
|
-
isValidDepositSignature(
|
|
152
|
-
config,
|
|
153
|
-
pendingDeposit.pubkey,
|
|
154
|
-
pendingDeposit.withdrawalCredentials,
|
|
155
|
-
pendingDeposit.amount,
|
|
156
|
-
pendingDeposit.signature
|
|
157
|
-
)
|
|
158
|
-
) {
|
|
159
|
-
result.add(toPubkeyHex(pendingDeposit.pubkey));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return result;
|
|
163
|
-
}
|
|
@@ -3,14 +3,15 @@ import {BeaconBlock, electra, ssz} from "@lodestar/types";
|
|
|
3
3
|
import {byteArrayEquals, toRootHex} from "@lodestar/utils";
|
|
4
4
|
import {CachedBeaconStateGloas} from "../types.js";
|
|
5
5
|
import {computeEpochAtSlot} from "../util/epoch.js";
|
|
6
|
+
import {PendingDepositsLookup} from "../util/pendingDepositsLookup.js";
|
|
6
7
|
import {processConsolidationRequest} from "./processConsolidationRequest.js";
|
|
7
|
-
import {
|
|
8
|
+
import {processDepositRequest} from "./processDepositRequest.js";
|
|
8
9
|
import {processWithdrawalRequest} from "./processWithdrawalRequest.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Process parent execution payload effects as the first step of processBlock.
|
|
12
13
|
*
|
|
13
|
-
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.
|
|
14
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-process_parent_execution_payload
|
|
14
15
|
*/
|
|
15
16
|
export function processParentExecutionPayload(state: CachedBeaconStateGloas, block: BeaconBlock<ForkPostGloas>): void {
|
|
16
17
|
const bid = block.body.signedExecutionPayloadBid.message;
|
|
@@ -42,7 +43,7 @@ export function processParentExecutionPayload(state: CachedBeaconStateGloas, blo
|
|
|
42
43
|
* Called from processParentExecutionPayload during block processing, and from the validator during
|
|
43
44
|
* block production before computing withdrawals.
|
|
44
45
|
*
|
|
45
|
-
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.
|
|
46
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-apply_parent_execution_payload
|
|
46
47
|
*/
|
|
47
48
|
export function applyParentExecutionPayload(state: CachedBeaconStateGloas, requests: electra.ExecutionRequests): void {
|
|
48
49
|
const fork = state.config.getForkSeq(state.slot);
|
|
@@ -54,9 +55,9 @@ export function applyParentExecutionPayload(state: CachedBeaconStateGloas, reque
|
|
|
54
55
|
// Process execution requests from parent's payload. The execution
|
|
55
56
|
// requests are processed at state.slot (child's slot), not the parent's slot.
|
|
56
57
|
if (requests.deposits.length > 0) {
|
|
57
|
-
const
|
|
58
|
+
const pendingDepositsLookup = PendingDepositsLookup.build(state);
|
|
58
59
|
for (const deposit of requests.deposits) {
|
|
59
|
-
processDepositRequest(fork, state, deposit,
|
|
60
|
+
processDepositRequest(fork, state, deposit, pendingDepositsLookup);
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
|
|
@@ -94,7 +95,7 @@ export function applyParentExecutionPayload(state: CachedBeaconStateGloas, reque
|
|
|
94
95
|
* Settle a builder payment at the given index: move its withdrawal (if any) to the
|
|
95
96
|
* pending withdrawals list and clear the payment slot.
|
|
96
97
|
*
|
|
97
|
-
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.
|
|
98
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-settle_builder_payment
|
|
98
99
|
*/
|
|
99
100
|
function settleBuilderPayment(state: CachedBeaconStateGloas, paymentIndex: number): void {
|
|
100
101
|
if (paymentIndex >= state.builderPendingPayments.length) {
|
|
@@ -10,13 +10,11 @@ import {
|
|
|
10
10
|
} from "@lodestar/params";
|
|
11
11
|
import {BuilderIndex, ValidatorIndex, capella, ssz} from "@lodestar/types";
|
|
12
12
|
import {byteArrayEquals, toRootHex} from "@lodestar/utils";
|
|
13
|
-
import {ZERO_HASH} from "../constants/index.js";
|
|
14
13
|
import {CachedBeaconStateCapella, CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
15
14
|
import {
|
|
16
15
|
convertBuilderIndexToValidatorIndex,
|
|
17
16
|
convertValidatorIndexToBuilderIndex,
|
|
18
17
|
isBuilderIndex,
|
|
19
|
-
isParentBlockFull,
|
|
20
18
|
} from "../util/gloas.js";
|
|
21
19
|
import {
|
|
22
20
|
decreaseBalance,
|
|
@@ -32,12 +30,14 @@ export function processWithdrawals(
|
|
|
32
30
|
state: CachedBeaconStateCapella | CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
33
31
|
payload?: capella.FullOrBlindedExecutionPayload
|
|
34
32
|
): void {
|
|
35
|
-
// Return early if
|
|
33
|
+
// Return early if the parent block is empty
|
|
36
34
|
if (fork >= ForkSeq.gloas) {
|
|
37
35
|
const stateGloas = state as CachedBeaconStateGloas;
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
const isParentBlockEmpty = !byteArrayEquals(
|
|
37
|
+
stateGloas.latestBlockHash,
|
|
38
|
+
stateGloas.latestExecutionPayloadBid.blockHash
|
|
39
|
+
);
|
|
40
|
+
if (isParentBlockEmpty) {
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
}
|
package/src/cache/epochCache.ts
CHANGED
|
@@ -38,9 +38,9 @@ import {
|
|
|
38
38
|
computeEpochAtSlot,
|
|
39
39
|
computeProposers,
|
|
40
40
|
computeSyncPeriodAtEpoch,
|
|
41
|
-
getActivationChurnLimit,
|
|
42
41
|
getChurnLimit,
|
|
43
42
|
getSeed,
|
|
43
|
+
getValidatorActivationChurnLimit,
|
|
44
44
|
isActiveValidator,
|
|
45
45
|
isAggregatorFromCommitteeLength,
|
|
46
46
|
} from "../util/index.js";
|
|
@@ -478,7 +478,7 @@ export class EpochCache {
|
|
|
478
478
|
// the first block of the epoch process_block() call. So churnLimit must be computed at the end of the before epoch
|
|
479
479
|
// transition and the result is valid until the end of the next epoch transition
|
|
480
480
|
const churnLimit = getChurnLimit(config, currentShuffling.activeIndices.length);
|
|
481
|
-
const activationChurnLimit =
|
|
481
|
+
const activationChurnLimit = getValidatorActivationChurnLimit(
|
|
482
482
|
config,
|
|
483
483
|
config.getForkSeq(state.slot),
|
|
484
484
|
currentShuffling.activeIndices.length
|
|
@@ -652,7 +652,7 @@ export class EpochCache {
|
|
|
652
652
|
// the first block of the epoch process_block() call. So churnLimit must be computed at the end of the before epoch
|
|
653
653
|
// transition and the result is valid until the end of the next epoch transition
|
|
654
654
|
this.churnLimit = getChurnLimit(this.config, this.currentShuffling.activeIndices.length);
|
|
655
|
-
this.activationChurnLimit =
|
|
655
|
+
this.activationChurnLimit = getValidatorActivationChurnLimit(
|
|
656
656
|
this.config,
|
|
657
657
|
this.config.getForkSeq(state.slot),
|
|
658
658
|
this.currentShuffling.activeIndices.length
|
|
@@ -5,7 +5,7 @@ import {CachedBeaconStateElectra, EpochTransitionCache} from "../types.js";
|
|
|
5
5
|
import {increaseBalance} from "../util/balance.js";
|
|
6
6
|
import {hasCompoundingWithdrawalCredential, isValidatorKnown} from "../util/electra.js";
|
|
7
7
|
import {computeStartSlotAtEpoch} from "../util/epoch.js";
|
|
8
|
-
import {getActivationExitChurnLimit} from "../util/validator.js";
|
|
8
|
+
import {getActivationChurnLimit, getActivationExitChurnLimit} from "../util/validator.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Starting from Electra:
|
|
@@ -17,8 +17,11 @@ import {getActivationExitChurnLimit} from "../util/validator.js";
|
|
|
17
17
|
* TODO Electra: Update ssz library to support batch push to `pendingDeposits`
|
|
18
18
|
*/
|
|
19
19
|
export function processPendingDeposits(state: CachedBeaconStateElectra, cache: EpochTransitionCache): void {
|
|
20
|
+
const fork = state.config.getForkSeq(state.slot);
|
|
20
21
|
const nextEpoch = state.epochCtx.epoch + 1;
|
|
21
|
-
const
|
|
22
|
+
const churnLimit =
|
|
23
|
+
fork >= ForkSeq.gloas ? getActivationChurnLimit(state.epochCtx) : getActivationExitChurnLimit(state.epochCtx);
|
|
24
|
+
const availableForProcessing = state.depositBalanceToConsume + BigInt(churnLimit);
|
|
22
25
|
let processedAmount = 0;
|
|
23
26
|
let nextDepositIndex = 0;
|
|
24
27
|
const depositsToPostpone = [];
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
2
|
+
import {UPDATE_TIMEOUT} from "@lodestar/params";
|
|
3
|
+
import {
|
|
4
|
+
LightClientBootstrap,
|
|
5
|
+
LightClientFinalityUpdate,
|
|
6
|
+
LightClientOptimisticUpdate,
|
|
7
|
+
LightClientUpdate,
|
|
8
|
+
Slot,
|
|
9
|
+
} from "@lodestar/types";
|
|
10
|
+
import {computeSyncPeriodAtSlot} from "../../util/epoch.js";
|
|
11
|
+
import {
|
|
12
|
+
type ProcessUpdateOpts,
|
|
13
|
+
getSyncCommitteeAtPeriod,
|
|
14
|
+
processLightClientUpdate,
|
|
15
|
+
} from "./processLightClientUpdate.js";
|
|
16
|
+
import {type ILightClientStore, LightClientStore, type LightClientStoreEvents} from "./store.js";
|
|
17
|
+
import {ZERO_HEADER, ZERO_SYNC_COMMITTEE, getZeroFinalityBranch, getZeroSyncCommitteeBranch} from "./utils.js";
|
|
18
|
+
|
|
19
|
+
export type {LightClientUpdateSummary} from "./isBetterUpdate.js";
|
|
20
|
+
export {isBetterUpdate, toLightClientUpdateSummary} from "./isBetterUpdate.js";
|
|
21
|
+
export {
|
|
22
|
+
type ProcessUpdateOpts,
|
|
23
|
+
getSyncCommitteeAtPeriod,
|
|
24
|
+
isSafeLightClientUpdate,
|
|
25
|
+
processLightClientUpdate,
|
|
26
|
+
} from "./processLightClientUpdate.js";
|
|
27
|
+
export {
|
|
28
|
+
type ILightClientStore,
|
|
29
|
+
LightClientStore,
|
|
30
|
+
type LightClientStoreEvents,
|
|
31
|
+
type LightClientUpdateWithSummary,
|
|
32
|
+
type SyncCommitteeFast,
|
|
33
|
+
} from "./store.js";
|
|
34
|
+
export {
|
|
35
|
+
getSafetyThreshold,
|
|
36
|
+
isFinalityUpdate,
|
|
37
|
+
isSyncCommitteeUpdate,
|
|
38
|
+
isValidLightClientHeader,
|
|
39
|
+
normalizeMerkleBranch,
|
|
40
|
+
upgradeLightClientFinalityUpdate,
|
|
41
|
+
upgradeLightClientHeader,
|
|
42
|
+
upgradeLightClientOptimisticUpdate,
|
|
43
|
+
upgradeLightClientStore,
|
|
44
|
+
upgradeLightClientUpdate,
|
|
45
|
+
} from "./utils.js";
|
|
46
|
+
export {validateLightClientBootstrap} from "./validateLightClientBootstrap.js";
|
|
47
|
+
export {validateLightClientUpdate} from "./validateLightClientUpdate.js";
|
|
48
|
+
|
|
49
|
+
export class LightclientSpec {
|
|
50
|
+
readonly store: ILightClientStore;
|
|
51
|
+
readonly config: BeaconConfig;
|
|
52
|
+
|
|
53
|
+
constructor(
|
|
54
|
+
config: BeaconConfig,
|
|
55
|
+
private readonly opts: ProcessUpdateOpts & LightClientStoreEvents,
|
|
56
|
+
bootstrap: LightClientBootstrap
|
|
57
|
+
) {
|
|
58
|
+
this.store = new LightClientStore(config, bootstrap, opts);
|
|
59
|
+
this.config = config;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
onUpdate(currentSlot: Slot, update: LightClientUpdate): void {
|
|
63
|
+
processLightClientUpdate(this.config, this.store, currentSlot, this.opts, update);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
onFinalityUpdate(currentSlot: Slot, finalityUpdate: LightClientFinalityUpdate): void {
|
|
67
|
+
this.onUpdate(currentSlot, {
|
|
68
|
+
attestedHeader: finalityUpdate.attestedHeader,
|
|
69
|
+
nextSyncCommittee: ZERO_SYNC_COMMITTEE,
|
|
70
|
+
nextSyncCommitteeBranch: getZeroSyncCommitteeBranch(this.config.getForkName(finalityUpdate.signatureSlot)),
|
|
71
|
+
finalizedHeader: finalityUpdate.finalizedHeader,
|
|
72
|
+
finalityBranch: finalityUpdate.finalityBranch,
|
|
73
|
+
syncAggregate: finalityUpdate.syncAggregate,
|
|
74
|
+
signatureSlot: finalityUpdate.signatureSlot,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
onOptimisticUpdate(currentSlot: Slot, optimisticUpdate: LightClientOptimisticUpdate): void {
|
|
79
|
+
this.onUpdate(currentSlot, {
|
|
80
|
+
attestedHeader: optimisticUpdate.attestedHeader,
|
|
81
|
+
nextSyncCommittee: ZERO_SYNC_COMMITTEE,
|
|
82
|
+
nextSyncCommitteeBranch: getZeroSyncCommitteeBranch(this.config.getForkName(optimisticUpdate.signatureSlot)),
|
|
83
|
+
finalizedHeader: {beacon: ZERO_HEADER},
|
|
84
|
+
finalityBranch: getZeroFinalityBranch(this.config.getForkName(optimisticUpdate.signatureSlot)),
|
|
85
|
+
syncAggregate: optimisticUpdate.syncAggregate,
|
|
86
|
+
signatureSlot: optimisticUpdate.signatureSlot,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
forceUpdate(currentSlot: Slot): void {
|
|
91
|
+
for (const bestValidUpdate of this.store.bestValidUpdates.values()) {
|
|
92
|
+
if (currentSlot > bestValidUpdate.update.finalizedHeader.beacon.slot + UPDATE_TIMEOUT) {
|
|
93
|
+
const updatePeriod = computeSyncPeriodAtSlot(bestValidUpdate.update.signatureSlot);
|
|
94
|
+
// Simulate process_light_client_store_force_update() by forcing to apply a bestValidUpdate
|
|
95
|
+
// https://github.com/ethereum/consensus-specs/blob/a57e15636013eeba3610ff3ade41781dba1bb0cd/specs/altair/light-client/sync-protocol.md?plain=1#L394
|
|
96
|
+
// Call for `updatePeriod + 1` to force the update at `update.signatureSlot` to be applied
|
|
97
|
+
getSyncCommitteeAtPeriod(this.store, updatePeriod + 1, this.opts);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|