@lodestar/state-transition 1.43.0-dev.4451fec75a → 1.43.0-dev.4fe6b362c9
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/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.map +1 -1
- package/lib/block/processParentExecutionPayload.js +4 -3
- package/lib/block/processParentExecutionPayload.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/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/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/shuffling.d.ts +6 -5
- package/lib/util/shuffling.d.ts.map +1 -1
- package/lib/util/shuffling.js +13 -15
- package/lib/util/shuffling.js.map +1 -1
- package/package.json +7 -7
- package/src/block/processDepositRequest.ts +29 -47
- package/src/block/processParentExecutionPayload.ts +4 -3
- package/src/slot/upgradeStateToGloas.ts +41 -44
- package/src/util/index.ts +1 -0
- package/src/util/pendingDepositsLookup.ts +105 -0
- package/src/util/shuffling.ts +17 -15
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import { BeaconConfig } from "@lodestar/config";
|
|
2
1
|
import { ForkSeq } from "@lodestar/params";
|
|
3
|
-
import { BLSPubkey, Bytes32,
|
|
2
|
+
import { BLSPubkey, Bytes32, UintNum64, electra } from "@lodestar/types";
|
|
4
3
|
import { CachedBeaconStateElectra, CachedBeaconStateGloas } from "../types.js";
|
|
4
|
+
import { PendingDepositsLookup } from "../util/pendingDepositsLookup.js";
|
|
5
5
|
/**
|
|
6
6
|
* Apply a deposit for a builder. Either increases balance for existing builder or adds new builder to registry.
|
|
7
7
|
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-apply_deposit_for_builder
|
|
8
8
|
*/
|
|
9
9
|
export declare function applyDepositForBuilder(state: CachedBeaconStateGloas, pubkey: BLSPubkey, withdrawalCredentials: Bytes32, amount: UintNum64, signature: Bytes32, slot: UintNum64): void;
|
|
10
|
-
export declare function processDepositRequest(fork: ForkSeq, state: CachedBeaconStateElectra | CachedBeaconStateGloas, depositRequest: electra.DepositRequest,
|
|
11
|
-
/**
|
|
12
|
-
* Build a set of pubkeys (hex-encoded) from pending deposits that have valid signatures.
|
|
13
|
-
* This is computed once and passed to each processDepositRequest call to avoid
|
|
14
|
-
* repeatedly iterating state.pendingDeposits.
|
|
15
|
-
*
|
|
16
|
-
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.3/specs/gloas/beacon-chain.md#new-is_pending_validator
|
|
17
|
-
*/
|
|
18
|
-
export declare function getPendingValidatorPubkeys(config: BeaconConfig, state: CachedBeaconStateGloas): Set<PubkeyHex>;
|
|
10
|
+
export declare function processDepositRequest(fork: ForkSeq, state: CachedBeaconStateElectra | CachedBeaconStateGloas, depositRequest: electra.DepositRequest, pendingDepositsLookup?: PendingDepositsLookup): void;
|
|
19
11
|
//# sourceMappingURL=processDepositRequest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processDepositRequest.d.ts","sourceRoot":"","sources":["../../src/block/processDepositRequest.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"processDepositRequest.d.ts","sourceRoot":"","sources":["../../src/block/processDepositRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,OAAO,EAAqC,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAM,MAAM,iBAAiB,CAAC;AAE5E,OAAO,EAAC,wBAAwB,EAAE,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAG7E,OAAO,EAAC,qBAAqB,EAAC,MAAM,kCAAkC,CAAC;AAGvE;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,sBAAsB,EAC7B,MAAM,EAAE,SAAS,EACjB,qBAAqB,EAAE,OAAO,EAC9B,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,OAAO,EAClB,IAAI,EAAE,SAAS,GACd,IAAI,CAaN;AAiDD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,wBAAwB,GAAG,sBAAsB,EACxD,cAAc,EAAE,OAAO,CAAC,cAAc,EACtC,qBAAqB,CAAC,EAAE,qBAAqB,GAC5C,IAAI,CAyDN"}
|
|
@@ -3,6 +3,7 @@ import { ssz } from "@lodestar/types";
|
|
|
3
3
|
import { toPubkeyHex } from "@lodestar/utils";
|
|
4
4
|
import { findBuilderIndexByPubkey, isBuilderWithdrawalCredential } from "../util/gloas.js";
|
|
5
5
|
import { computeEpochAtSlot, isValidatorKnown } from "../util/index.js";
|
|
6
|
+
import { PendingDepositsLookup } from "../util/pendingDepositsLookup.js";
|
|
6
7
|
import { isValidDepositSignature } from "./processDeposit.js";
|
|
7
8
|
/**
|
|
8
9
|
* Apply a deposit for a builder. Either increases balance for existing builder or adds new builder to registry.
|
|
@@ -56,40 +57,47 @@ function addBuilderToRegistry(state, pubkey, withdrawalCredentials, amount, slot
|
|
|
56
57
|
state.builders.push(newBuilder);
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
|
-
// TODO GLOAS:
|
|
60
|
-
//
|
|
61
|
-
//
|
|
60
|
+
// TODO GLOAS: the PendingDepositsLookup is currently scoped to a single envelope of
|
|
61
|
+
// deposit-requests. We can track it as ephemeral within EpochCache and transfer to the next block
|
|
62
|
+
// transition to reuse cached signature verifications.
|
|
62
63
|
// See https://github.com/ChainSafe/lodestar/issues/9181
|
|
63
|
-
export function processDepositRequest(fork, state, depositRequest,
|
|
64
|
+
export function processDepositRequest(fork, state, depositRequest, pendingDepositsLookup) {
|
|
64
65
|
const { pubkey, withdrawalCredentials, amount, signature } = depositRequest;
|
|
65
|
-
// Check if this is a builder or validator deposit
|
|
66
66
|
if (fork >= ForkSeq.gloas) {
|
|
67
67
|
const stateGloas = state;
|
|
68
|
-
const
|
|
68
|
+
const lookup = pendingDepositsLookup ?? PendingDepositsLookup.build(stateGloas);
|
|
69
69
|
const pubkeyHex = toPubkeyHex(pubkey);
|
|
70
70
|
const builderIndex = findBuilderIndexByPubkey(stateGloas, pubkey);
|
|
71
71
|
const validatorIndex = state.epochCtx.getValidatorIndex(pubkey);
|
|
72
|
-
// Regardless of the withdrawal credentials prefix, if a builder/validator
|
|
73
|
-
// already exists with this pubkey, apply the deposit to their balance
|
|
74
72
|
const isBuilder = builderIndex !== null;
|
|
75
73
|
const isValidator = isValidatorKnown(state, validatorIndex);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// Apply builder deposits immediately
|
|
74
|
+
if (isBuilder) {
|
|
75
|
+
// Top up an existing builder regardless of withdrawal credential prefix
|
|
79
76
|
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature, state.slot);
|
|
80
77
|
return;
|
|
81
78
|
}
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
if (pendingValidatorPubkeysCache &&
|
|
79
|
+
// Only check the (expensive) "pending validator" condition when needed
|
|
80
|
+
if (isBuilderWithdrawalCredential(withdrawalCredentials) &&
|
|
85
81
|
!isValidator &&
|
|
86
|
-
!
|
|
87
|
-
|
|
88
|
-
|
|
82
|
+
!lookup.hasPendingValidator(state.config, pubkeyHex)) {
|
|
83
|
+
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature, state.slot);
|
|
84
|
+
return;
|
|
89
85
|
}
|
|
86
|
+
const pendingDeposit = ssz.electra.PendingDeposit.toViewDU({
|
|
87
|
+
pubkey,
|
|
88
|
+
withdrawalCredentials,
|
|
89
|
+
amount,
|
|
90
|
+
signature,
|
|
91
|
+
slot: state.slot,
|
|
92
|
+
});
|
|
93
|
+
// Keep the lookup in sync with state.pendingDeposits so later deposit-requests
|
|
94
|
+
// in the same envelope see this deposit
|
|
95
|
+
lookup.add(pendingDeposit, pubkeyHex);
|
|
96
|
+
state.pendingDeposits.push(pendingDeposit);
|
|
97
|
+
return;
|
|
90
98
|
}
|
|
91
|
-
//
|
|
92
|
-
if (
|
|
99
|
+
// Pre-Gloas (Electra) path
|
|
100
|
+
if (state.depositRequestsStartIndex === UNSET_DEPOSIT_REQUESTS_START_INDEX) {
|
|
93
101
|
state.depositRequestsStartIndex = depositRequest.index;
|
|
94
102
|
}
|
|
95
103
|
// Add validator deposits to the queue
|
|
@@ -102,20 +110,4 @@ export function processDepositRequest(fork, state, depositRequest, pendingValida
|
|
|
102
110
|
});
|
|
103
111
|
state.pendingDeposits.push(pendingDeposit);
|
|
104
112
|
}
|
|
105
|
-
/**
|
|
106
|
-
* Build a set of pubkeys (hex-encoded) from pending deposits that have valid signatures.
|
|
107
|
-
* This is computed once and passed to each processDepositRequest call to avoid
|
|
108
|
-
* repeatedly iterating state.pendingDeposits.
|
|
109
|
-
*
|
|
110
|
-
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.3/specs/gloas/beacon-chain.md#new-is_pending_validator
|
|
111
|
-
*/
|
|
112
|
-
export function getPendingValidatorPubkeys(config, state) {
|
|
113
|
-
const result = new Set();
|
|
114
|
-
for (const pendingDeposit of state.pendingDeposits.getAllReadonly()) {
|
|
115
|
-
if (isValidDepositSignature(config, pendingDeposit.pubkey, pendingDeposit.withdrawalCredentials, pendingDeposit.amount, pendingDeposit.signature)) {
|
|
116
|
-
result.add(toPubkeyHex(pendingDeposit.pubkey));
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return result;
|
|
120
|
-
}
|
|
121
113
|
//# sourceMappingURL=processDepositRequest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processDepositRequest.js","sourceRoot":"","sources":["../../src/block/processDepositRequest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"processDepositRequest.js","sourceRoot":"","sources":["../../src/block/processDepositRequest.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processParentExecutionPayload.d.ts","sourceRoot":"","sources":["../../src/block/processParentExecutionPayload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAA6C,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAC,WAAW,EAAE,OAAO,EAAM,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAC,sBAAsB,EAAC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"processParentExecutionPayload.d.ts","sourceRoot":"","sources":["../../src/block/processParentExecutionPayload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAA6C,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAC,WAAW,EAAE,OAAO,EAAM,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAC,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAOnD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAAE,WAAW,CAAC,aAAa,CAAC,GAAG,IAAI,CAqBpH;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,sBAAsB,EAAE,QAAQ,EAAE,OAAO,CAAC,iBAAiB,GAAG,IAAI,CA4CpH"}
|
|
@@ -2,8 +2,9 @@ import { SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT } from "@lodestar/params";
|
|
|
2
2
|
import { ssz } from "@lodestar/types";
|
|
3
3
|
import { byteArrayEquals, toRootHex } from "@lodestar/utils";
|
|
4
4
|
import { computeEpochAtSlot } from "../util/epoch.js";
|
|
5
|
+
import { PendingDepositsLookup } from "../util/pendingDepositsLookup.js";
|
|
5
6
|
import { processConsolidationRequest } from "./processConsolidationRequest.js";
|
|
6
|
-
import {
|
|
7
|
+
import { processDepositRequest } from "./processDepositRequest.js";
|
|
7
8
|
import { processWithdrawalRequest } from "./processWithdrawalRequest.js";
|
|
8
9
|
/**
|
|
9
10
|
* Process parent execution payload effects as the first step of processBlock.
|
|
@@ -45,9 +46,9 @@ export function applyParentExecutionPayload(state, requests) {
|
|
|
45
46
|
// Process execution requests from parent's payload. The execution
|
|
46
47
|
// requests are processed at state.slot (child's slot), not the parent's slot.
|
|
47
48
|
if (requests.deposits.length > 0) {
|
|
48
|
-
const
|
|
49
|
+
const pendingDepositsLookup = PendingDepositsLookup.build(state);
|
|
49
50
|
for (const deposit of requests.deposits) {
|
|
50
|
-
processDepositRequest(fork, state, deposit,
|
|
51
|
+
processDepositRequest(fork, state, deposit, pendingDepositsLookup);
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
for (const withdrawal of requests.withdrawals) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processParentExecutionPayload.js","sourceRoot":"","sources":["../../src/block/processParentExecutionPayload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,eAAe,EAAE,yBAAyB,EAAC,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAuB,GAAG,EAAC,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAC,eAAe,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAC,kBAAkB,EAAC,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAC,2BAA2B,EAAC,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"processParentExecutionPayload.js","sourceRoot":"","sources":["../../src/block/processParentExecutionPayload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,eAAe,EAAE,yBAAyB,EAAC,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAuB,GAAG,EAAC,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAC,eAAe,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAC,kBAAkB,EAAC,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAC,qBAAqB,EAAC,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAC,2BAA2B,EAAC,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAC,qBAAqB,EAAC,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAC,wBAAwB,EAAC,MAAM,+BAA+B,CAAC;AAEvE;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAAC,KAA6B,EAAE,KAAiC,EAAQ;IACpH,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,OAAO,CAAC;IACzD,MAAM,SAAS,GAAG,KAAK,CAAC,yBAAyB,CAAC;IAClD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC;IAEpD,MAAM,iBAAiB,GAAG,eAAe,CAAC,GAAG,CAAC,eAAe,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpF,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,qDAAqD;QACrD,4BAA4B,CAAC,QAAQ,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IAED,qEAAqE;IACrE,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1E,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,SAAS,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CACb,kDAAkD,SAAS,CAAC,YAAY,CAAC,aAAa,SAAS,CAAC,SAAS,CAAC,qBAAqB,CAAC,EAAE,CACnI,CAAC;IACJ,CAAC;IAED,2BAA2B,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAAA,CAC9C;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAA6B,EAAE,QAAmC,EAAQ;IACpH,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,KAAK,CAAC,yBAAyB,CAAC;IAClD,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC;IAClC,MAAM,WAAW,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEpD,kEAAkE;IAClE,8EAA8E;IAC9E,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,qBAAqB,GAAG,qBAAqB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjE,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACxC,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,qBAAqB,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,KAAK,MAAM,UAAU,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC9C,wBAAwB,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,MAAM,aAAa,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QACpD,2BAA2B,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IACpD,CAAC;IAED,6BAA6B;IAC7B,IAAI,WAAW,KAAK,YAAY,EAAE,CAAC;QACjC,oBAAoB,CAAC,KAAK,EAAE,eAAe,GAAG,CAAC,UAAU,GAAG,eAAe,CAAC,CAAC,CAAC;IAChF,CAAC;SAAM,IAAI,WAAW,KAAK,YAAY,GAAG,CAAC,EAAE,CAAC;QAC5C,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,eAAe,CAAC,CAAC;IAC5D,CAAC;SAAM,IAAI,SAAS,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;QAC/B,mFAAmF;QACnF,4DAA4D;QAC5D,KAAK,CAAC,yBAAyB,CAAC,IAAI,CAClC,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,QAAQ,CAAC;YAC1C,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,MAAM,EAAE,SAAS,CAAC,KAAK;YACvB,YAAY,EAAE,SAAS,CAAC,YAAY;SACrC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,4BAA4B,CAAC,GAAG,CAAC,UAAU,GAAG,yBAAyB,EAAE,IAAI,CAAC,CAAC;IACrF,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC,SAAS,CAAC;AAAA,CAC7C;AAED;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,KAA6B,EAAE,YAAoB,EAAQ;IACvF,IAAI,YAAY,IAAI,KAAK,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,8CAA8C,YAAY,UAAU,KAAK,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAC1G,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,KAAK,EAAE,CAAC;IACvE,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3D,CAAC;IACD,KAAK,CAAC,sBAAsB,CAAC,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,aAAa,EAAE,CAAC,CAAC;AAAA,CACjG;AAED,SAAS,4BAA4B,CAAC,QAAmC,EAAQ;IAC/E,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChH,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACxF,CAAC;AAAA,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgradeStateToGloas.d.ts","sourceRoot":"","sources":["../../src/slot/upgradeStateToGloas.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"upgradeStateToGloas.d.ts","sourceRoot":"","sources":["../../src/slot/upgradeStateToGloas.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,qBAAqB,EAAE,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAK1E;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,GAAG,sBAAsB,CAuE5F"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { SLOTS_PER_HISTORICAL_ROOT } from "@lodestar/params";
|
|
2
2
|
import { ssz } from "@lodestar/types";
|
|
3
|
-
import {
|
|
4
|
-
import { isValidDepositSignature } from "../block/processDeposit.js";
|
|
3
|
+
import { toPubkeyHex } from "@lodestar/utils";
|
|
5
4
|
import { applyDepositForBuilder } from "../block/processDepositRequest.js";
|
|
6
5
|
import { getCachedBeaconState } from "../cache/stateCache.js";
|
|
7
6
|
import { initializePtcWindow, isBuilderWithdrawalCredential } from "../util/gloas.js";
|
|
8
7
|
import { isValidatorKnown } from "../util/index.js";
|
|
8
|
+
import { PendingDepositsLookup } from "../util/pendingDepositsLookup.js";
|
|
9
9
|
/**
|
|
10
10
|
* Upgrade a state from Fulu to Gloas.
|
|
11
11
|
*/
|
|
@@ -76,42 +76,47 @@ export function upgradeStateToGloas(stateFulu) {
|
|
|
76
76
|
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.2/specs/gloas/fork.md#new-onboard_builders_from_pending_deposits
|
|
77
77
|
*/
|
|
78
78
|
function onboardBuildersFromPendingDeposits(state) {
|
|
79
|
-
// Track pubkeys of new validators to keep their deposits pending
|
|
80
|
-
const validatorPubkeys = new Set();
|
|
81
79
|
// Track pubkeys of new builders added when applying deposits
|
|
82
80
|
const builderPubkeys = new Set();
|
|
83
|
-
const
|
|
81
|
+
const pendingDeposits = ssz.electra.PendingDeposits.defaultViewDU();
|
|
82
|
+
const pendingDepositsLookup = PendingDepositsLookup.buildEmpty();
|
|
84
83
|
for (let i = 0; i < state.pendingDeposits.length; i++) {
|
|
85
84
|
const deposit = state.pendingDeposits.getReadonly(i);
|
|
86
85
|
const validatorIndex = state.epochCtx.getValidatorIndex(deposit.pubkey);
|
|
87
|
-
const pubkeyHex =
|
|
88
|
-
// Deposits for existing validators stay in pending queue
|
|
89
|
-
if (isValidatorKnown(state, validatorIndex)
|
|
90
|
-
|
|
86
|
+
const pubkeyHex = toPubkeyHex(deposit.pubkey);
|
|
87
|
+
// Deposits for existing validators stay in the pending queue
|
|
88
|
+
if (isValidatorKnown(state, validatorIndex)) {
|
|
89
|
+
pendingDeposits.push(deposit);
|
|
90
|
+
pendingDepositsLookup.add(deposit, pubkeyHex);
|
|
91
91
|
continue;
|
|
92
92
|
}
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
//
|
|
101
|
-
if (!
|
|
102
|
-
|
|
93
|
+
// `applyDepositForBuilder` can mutate the state and add a builder to the registry, so
|
|
94
|
+
// the set of builder pubkeys must be recomputed each iteration. `builderPubkeys` stands
|
|
95
|
+
// in for the spec's `[b.pubkey for b in state.builders]`: `state.builders` starts empty
|
|
96
|
+
// at the fork, so every builder is one added in a previous iteration of this loop.
|
|
97
|
+
if (!builderPubkeys.has(pubkeyHex)) {
|
|
98
|
+
// Deposits for non-builders stay in the pending queue. If there is a valid pending
|
|
99
|
+
// deposit for a new validator with this pubkey, keep this deposit in the pending
|
|
100
|
+
// queue to be applied to that validator later.
|
|
101
|
+
if (!isBuilderWithdrawalCredential(deposit.withdrawalCredentials)) {
|
|
102
|
+
pendingDeposits.push(deposit);
|
|
103
|
+
pendingDepositsLookup.add(deposit, pubkeyHex);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (pendingDepositsLookup.hasPendingValidator(state.config, pubkeyHex)) {
|
|
107
|
+
pendingDeposits.push(deposit);
|
|
108
|
+
pendingDepositsLookup.add(deposit, pubkeyHex);
|
|
109
|
+
continue;
|
|
103
110
|
}
|
|
104
|
-
continue;
|
|
105
111
|
}
|
|
106
|
-
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
remainingPendingDeposits.push(deposit);
|
|
112
|
+
const buildersLenBefore = state.builders.length;
|
|
113
|
+
// TODO GLOAS: handle 20k 1ETH deposits on time
|
|
114
|
+
// there is a note in the spec https://github.com/ethereum/consensus-specs/pull/5227
|
|
115
|
+
applyDepositForBuilder(state, deposit.pubkey, deposit.withdrawalCredentials, deposit.amount, deposit.signature, deposit.slot);
|
|
116
|
+
if (state.builders.length > buildersLenBefore) {
|
|
117
|
+
builderPubkeys.add(pubkeyHex);
|
|
113
118
|
}
|
|
114
119
|
}
|
|
115
|
-
state.pendingDeposits =
|
|
120
|
+
state.pendingDeposits = pendingDeposits;
|
|
116
121
|
}
|
|
117
122
|
//# sourceMappingURL=upgradeStateToGloas.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgradeStateToGloas.js","sourceRoot":"","sources":["../../src/slot/upgradeStateToGloas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,yBAAyB,EAAC,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAC,GAAG,EAAC,MAAM,iBAAiB,CAAC;AACpC,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"upgradeStateToGloas.js","sourceRoot":"","sources":["../../src/slot/upgradeStateToGloas.ts"],"names":[],"mappings":"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"}
|
package/lib/util/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from "./genesis.js";
|
|
|
18
18
|
export * from "./gloas.js";
|
|
19
19
|
export * from "./interop.js";
|
|
20
20
|
export * from "./loadState/index.js";
|
|
21
|
+
export * from "./pendingDepositsLookup.js";
|
|
21
22
|
export * from "./rootCache.js";
|
|
22
23
|
export * from "./seed.js";
|
|
23
24
|
export * from "./shuffling.js";
|
package/lib/util/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC"}
|
package/lib/util/index.js
CHANGED
|
@@ -18,6 +18,7 @@ export * from "./genesis.js";
|
|
|
18
18
|
export * from "./gloas.js";
|
|
19
19
|
export * from "./interop.js";
|
|
20
20
|
export * from "./loadState/index.js";
|
|
21
|
+
export * from "./pendingDepositsLookup.js";
|
|
21
22
|
export * from "./rootCache.js";
|
|
22
23
|
export * from "./seed.js";
|
|
23
24
|
export * from "./shuffling.js";
|
package/lib/util/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { BeaconConfig } from "@lodestar/config";
|
|
2
|
+
import { PubkeyHex, electra } from "@lodestar/types";
|
|
3
|
+
import { CachedBeaconStateGloas } from "../types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Mutable lookup for the pending-deposit sequence used by builder-routing logic.
|
|
6
|
+
*
|
|
7
|
+
* This is to implement the spec's `is_pending_validator(pending_deposits, pubkey)` lazily:
|
|
8
|
+
* deposits are grouped by pubkey without verifying signatures, and BLS verification is
|
|
9
|
+
* deferred until a builder deposit needs to know whether the same pubkey already has a
|
|
10
|
+
* valid pending validator deposit.
|
|
11
|
+
*
|
|
12
|
+
* Call `add()` whenever a deposit is appended to the represented sequence. A cached `true`
|
|
13
|
+
* result short-circuits all subsequent checks for that pubkey; a cached `false` records
|
|
14
|
+
* how many deposits were already verified, so appending a new deposit only verifies the
|
|
15
|
+
* newly-appended tail rather than re-running BLS on previously-invalid entries.
|
|
16
|
+
*/
|
|
17
|
+
export declare class PendingDepositsLookup {
|
|
18
|
+
private readonly depositsByPubkey;
|
|
19
|
+
private readonly validationCache;
|
|
20
|
+
private constructor();
|
|
21
|
+
/** Build an empty lookup for a sequence that will be populated incrementally. */
|
|
22
|
+
static buildEmpty(): PendingDepositsLookup;
|
|
23
|
+
/**
|
|
24
|
+
* Build a pubkey -> pending-deposits lookup from `state.pendingDeposits`.
|
|
25
|
+
* No BLS work is done here; signature verification happens lazily in `hasPendingValidator`.
|
|
26
|
+
*/
|
|
27
|
+
static build(state: CachedBeaconStateGloas): PendingDepositsLookup;
|
|
28
|
+
/**
|
|
29
|
+
* Append a pending deposit to the represented sequence.
|
|
30
|
+
* Pass `pubkeyHex` if the caller has already computed it.
|
|
31
|
+
*/
|
|
32
|
+
add(pendingDeposit: electra.PendingDeposit, pubkeyHex?: PubkeyHex): void;
|
|
33
|
+
/**
|
|
34
|
+
* Returns true if any pending deposit for `pubkeyHex` has a valid BLS deposit signature.
|
|
35
|
+
* Memoizes the result in `validationCache` so repeated checks for the same pubkey
|
|
36
|
+
* within a block only verify deposits that have not already been checked.
|
|
37
|
+
*/
|
|
38
|
+
hasPendingValidator(config: BeaconConfig, pubkeyHex: PubkeyHex): boolean;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=pendingDepositsLookup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pendingDepositsLookup.d.ts","sourceRoot":"","sources":["../../src/util/pendingDepositsLookup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAC,SAAS,EAAE,OAAO,EAAC,MAAM,iBAAiB,CAAC;AAGnD,OAAO,EAAC,sBAAsB,EAAC,MAAM,aAAa,CAAC;AAOnD;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAFlC,OAAO,eAGH;IAEJ,iFAAiF;IACjF,MAAM,CAAC,UAAU,IAAI,qBAAqB,CAEzC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,qBAAqB,CAMjE;IAED;;;OAGG;IACH,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAQvE;IAED;;;;OAIG;IACH,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAqCvE;CACF"}
|
|
@@ -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/shuffling.d.ts
CHANGED
|
@@ -5,13 +5,14 @@ import { CachedBeaconStateAllForks } from "../cache/stateCache.js";
|
|
|
5
5
|
import { IBeaconStateView } from "../stateView/interface.js";
|
|
6
6
|
import { EpochShuffling } from "./epochShuffling.js";
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Block root that decided the proposer shuffling for `proposalEpoch` (keys that shuffling).
|
|
9
|
+
* Computed for the requested epoch, not `state.epoch`, so it is correct when `state` is one
|
|
10
|
+
* epoch off the requested epoch (e.g. serving next-epoch duties from the current state).
|
|
10
11
|
*
|
|
11
|
-
* Returns `null`
|
|
12
|
-
*
|
|
12
|
+
* Returns `null` when the genesis block decides its own shuffling (caller falls back to the
|
|
13
|
+
* genesis block root).
|
|
13
14
|
*/
|
|
14
|
-
export declare function proposerShufflingDecisionRoot(fork: ForkName, state: IBeaconStateView): Root | null;
|
|
15
|
+
export declare function proposerShufflingDecisionRoot(fork: ForkName, state: IBeaconStateView, proposalEpoch: Epoch): Root | null;
|
|
15
16
|
/**
|
|
16
17
|
* Returns the block root which decided the attester shuffling for the given `requestedEpoch`.
|
|
17
18
|
* This root can be used to key that attester shuffling.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shuffling.d.ts","sourceRoot":"","sources":["../../src/util/shuffling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,OAAO,EAAkC,MAAM,kBAAkB,CAAC;AACpF,OAAO,EACL,WAAW,EACX,cAAc,EACd,KAAK,EACL,kBAAkB,EAClB,IAAI,EACJ,IAAI,EACJ,cAAc,EAEf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAC,yBAAyB,EAAC,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAC,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAEnD
|
|
1
|
+
{"version":3,"file":"shuffling.d.ts","sourceRoot":"","sources":["../../src/util/shuffling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,OAAO,EAAkC,MAAM,kBAAkB,CAAC;AACpF,OAAO,EACL,WAAW,EACX,cAAc,EACd,KAAK,EACL,kBAAkB,EAClB,IAAI,EACJ,IAAI,EACJ,cAAc,EAEf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAC,yBAAyB,EAAC,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAC,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAG3D,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,gBAAgB,EACvB,aAAa,EAAE,KAAK,GACnB,IAAI,GAAG,IAAI,CAMb;AAUD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,yBAAyB,EAAE,cAAc,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,CAMlH;AAsCD,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;IAChC,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,wBAAgB,6BAA6B,CAC3C,cAAc,EAAE,cAAc,EAC9B,yBAAyB,EAAE,cAAc,EAAE,GAC1C,GAAG,CAAC,cAAc,EAAE,YAAY,CAAC,CAyBnC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,GACvB,kBAAkB,CAWpB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,GAAG,MAAM,EAAE,CA6BrH;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,GAAG,WAAW,CAEjH;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,cAAc,EAAE,GACxB,WAAW,EAAE,CAoBf;AAED,oBAAY,kBAAkB;IAC5B,4BAA4B,iDAAiD;CAC9E;AAED,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,kBAAkB,CAAC,4BAA4B,CAAC;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,qBAAa,cAAe,SAAQ,aAAa,CAAC,kBAAkB,CAAC;CAAG"}
|
package/lib/util/shuffling.js
CHANGED
|
@@ -3,28 +3,26 @@ import { LodestarError } from "@lodestar/utils";
|
|
|
3
3
|
import { getBlockRootAtSlot } from "./blockRoot.js";
|
|
4
4
|
import { computeStartSlotAtEpoch } from "./epoch.js";
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Block root that decided the proposer shuffling for `proposalEpoch` (keys that shuffling).
|
|
7
|
+
* Computed for the requested epoch, not `state.epoch`, so it is correct when `state` is one
|
|
8
|
+
* epoch off the requested epoch (e.g. serving next-epoch duties from the current state).
|
|
8
9
|
*
|
|
9
|
-
* Returns `null`
|
|
10
|
-
*
|
|
10
|
+
* Returns `null` when the genesis block decides its own shuffling (caller falls back to the
|
|
11
|
+
* genesis block root).
|
|
11
12
|
*/
|
|
12
|
-
export function proposerShufflingDecisionRoot(fork, state) {
|
|
13
|
-
const decisionSlot = proposerShufflingDecisionSlot(fork,
|
|
13
|
+
export function proposerShufflingDecisionRoot(fork, state, proposalEpoch) {
|
|
14
|
+
const decisionSlot = proposerShufflingDecisionSlot(fork, proposalEpoch);
|
|
14
15
|
if (state.slot === decisionSlot) {
|
|
15
16
|
return null;
|
|
16
17
|
}
|
|
17
18
|
return state.getBlockRootAtSlot(decisionSlot);
|
|
18
19
|
}
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const epoch = isForkPostFulu(fork) ? state.epoch - 1 : state.epoch;
|
|
26
|
-
const startSlot = computeStartSlotAtEpoch(epoch);
|
|
27
|
-
return Math.max(startSlot - 1, 0);
|
|
20
|
+
/** Slot whose block root keys the proposer shuffling for `proposalEpoch`. */
|
|
21
|
+
function proposerShufflingDecisionSlot(fork, proposalEpoch) {
|
|
22
|
+
// Post-Fulu the shuffling is decided one epoch earlier (deterministic proposer lookahead,
|
|
23
|
+
// MIN_SEED_LOOKAHEAD = 1); pre-Fulu it is the last block before `proposalEpoch`.
|
|
24
|
+
const decisionEpoch = isForkPostFulu(fork) ? proposalEpoch - 1 : proposalEpoch;
|
|
25
|
+
return Math.max(computeStartSlotAtEpoch(decisionEpoch) - 1, 0);
|
|
28
26
|
}
|
|
29
27
|
/**
|
|
30
28
|
* Returns the block root which decided the attester shuffling for the given `requestedEpoch`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shuffling.js","sourceRoot":"","sources":["../../src/util/shuffling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,OAAO,EAAE,eAAe,EAAE,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAWpF,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAG9C,OAAO,EAAC,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAC,uBAAuB,EAAC,MAAM,YAAY,CAAC;AAGnD
|
|
1
|
+
{"version":3,"file":"shuffling.js","sourceRoot":"","sources":["../../src/util/shuffling.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.4fe6b362c9",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -72,14 +72,14 @@
|
|
|
72
72
|
"@chainsafe/pubkey-index-map": "^3.0.0",
|
|
73
73
|
"@chainsafe/ssz": "^1.4.0",
|
|
74
74
|
"@chainsafe/swap-or-not-shuffle": "^1.2.1",
|
|
75
|
-
"@lodestar/config": "^1.43.0-dev.
|
|
76
|
-
"@lodestar/params": "^1.43.0-dev.
|
|
77
|
-
"@lodestar/types": "^1.43.0-dev.
|
|
78
|
-
"@lodestar/utils": "^1.43.0-dev.
|
|
75
|
+
"@lodestar/config": "^1.43.0-dev.4fe6b362c9",
|
|
76
|
+
"@lodestar/params": "^1.43.0-dev.4fe6b362c9",
|
|
77
|
+
"@lodestar/types": "^1.43.0-dev.4fe6b362c9",
|
|
78
|
+
"@lodestar/utils": "^1.43.0-dev.4fe6b362c9",
|
|
79
79
|
"@vekexasia/bigint-buffer2": "^1.1.1"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@lodestar/api": "^1.43.0-dev.
|
|
82
|
+
"@lodestar/api": "^1.43.0-dev.4fe6b362c9"
|
|
83
83
|
},
|
|
84
84
|
"keywords": [
|
|
85
85
|
"ethereum",
|
|
@@ -87,5 +87,5 @@
|
|
|
87
87
|
"beacon",
|
|
88
88
|
"blockchain"
|
|
89
89
|
],
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "3a8e096d928384196d421eb6e3cf5724df94d540"
|
|
91
91
|
}
|
|
@@ -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,8 +3,9 @@ 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
|
/**
|
|
@@ -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
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
|
|
2
2
|
import {ssz} from "@lodestar/types";
|
|
3
|
-
import {
|
|
4
|
-
import {isValidDepositSignature} from "../block/processDeposit.js";
|
|
3
|
+
import {toPubkeyHex} from "@lodestar/utils";
|
|
5
4
|
import {applyDepositForBuilder} from "../block/processDepositRequest.js";
|
|
6
5
|
import {getCachedBeaconState} from "../cache/stateCache.js";
|
|
7
6
|
import {CachedBeaconStateFulu, CachedBeaconStateGloas} from "../types.js";
|
|
8
7
|
import {initializePtcWindow, isBuilderWithdrawalCredential} from "../util/gloas.js";
|
|
9
8
|
import {isValidatorKnown} from "../util/index.js";
|
|
9
|
+
import {PendingDepositsLookup} from "../util/pendingDepositsLookup.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Upgrade a state from Fulu to Gloas.
|
|
@@ -89,63 +89,60 @@ export function upgradeStateToGloas(stateFulu: CachedBeaconStateFulu): CachedBea
|
|
|
89
89
|
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.2/specs/gloas/fork.md#new-onboard_builders_from_pending_deposits
|
|
90
90
|
*/
|
|
91
91
|
function onboardBuildersFromPendingDeposits(state: CachedBeaconStateGloas): void {
|
|
92
|
-
// Track pubkeys of new validators to keep their deposits pending
|
|
93
|
-
const validatorPubkeys = new Set<string>();
|
|
94
|
-
|
|
95
92
|
// Track pubkeys of new builders added when applying deposits
|
|
96
93
|
const builderPubkeys = new Set<string>();
|
|
97
94
|
|
|
98
|
-
const
|
|
95
|
+
const pendingDeposits = ssz.electra.PendingDeposits.defaultViewDU();
|
|
96
|
+
const pendingDepositsLookup = PendingDepositsLookup.buildEmpty();
|
|
97
|
+
|
|
99
98
|
for (let i = 0; i < state.pendingDeposits.length; i++) {
|
|
100
99
|
const deposit = state.pendingDeposits.getReadonly(i);
|
|
101
100
|
|
|
102
101
|
const validatorIndex = state.epochCtx.getValidatorIndex(deposit.pubkey);
|
|
103
|
-
const pubkeyHex =
|
|
102
|
+
const pubkeyHex = toPubkeyHex(deposit.pubkey);
|
|
104
103
|
|
|
105
|
-
// Deposits for existing validators stay in pending queue
|
|
106
|
-
if (isValidatorKnown(state, validatorIndex)
|
|
107
|
-
|
|
104
|
+
// Deposits for existing validators stay in the pending queue
|
|
105
|
+
if (isValidatorKnown(state, validatorIndex)) {
|
|
106
|
+
pendingDeposits.push(deposit);
|
|
107
|
+
pendingDepositsLookup.add(deposit, pubkeyHex);
|
|
108
108
|
continue;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
deposit
|
|
121
|
-
deposit
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
111
|
+
// `applyDepositForBuilder` can mutate the state and add a builder to the registry, so
|
|
112
|
+
// the set of builder pubkeys must be recomputed each iteration. `builderPubkeys` stands
|
|
113
|
+
// in for the spec's `[b.pubkey for b in state.builders]`: `state.builders` starts empty
|
|
114
|
+
// at the fork, so every builder is one added in a previous iteration of this loop.
|
|
115
|
+
if (!builderPubkeys.has(pubkeyHex)) {
|
|
116
|
+
// Deposits for non-builders stay in the pending queue. If there is a valid pending
|
|
117
|
+
// deposit for a new validator with this pubkey, keep this deposit in the pending
|
|
118
|
+
// queue to be applied to that validator later.
|
|
119
|
+
if (!isBuilderWithdrawalCredential(deposit.withdrawalCredentials)) {
|
|
120
|
+
pendingDeposits.push(deposit);
|
|
121
|
+
pendingDepositsLookup.add(deposit, pubkeyHex);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (pendingDepositsLookup.hasPendingValidator(state.config, pubkeyHex)) {
|
|
125
|
+
pendingDeposits.push(deposit);
|
|
126
|
+
pendingDepositsLookup.add(deposit, pubkeyHex);
|
|
127
|
+
continue;
|
|
128
128
|
}
|
|
129
|
-
continue;
|
|
130
129
|
}
|
|
131
130
|
|
|
132
|
-
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
validatorPubkeys.add(pubkeyHex);
|
|
146
|
-
remainingPendingDeposits.push(deposit);
|
|
131
|
+
const buildersLenBefore = state.builders.length;
|
|
132
|
+
// TODO GLOAS: handle 20k 1ETH deposits on time
|
|
133
|
+
// there is a note in the spec https://github.com/ethereum/consensus-specs/pull/5227
|
|
134
|
+
applyDepositForBuilder(
|
|
135
|
+
state,
|
|
136
|
+
deposit.pubkey,
|
|
137
|
+
deposit.withdrawalCredentials,
|
|
138
|
+
deposit.amount,
|
|
139
|
+
deposit.signature,
|
|
140
|
+
deposit.slot
|
|
141
|
+
);
|
|
142
|
+
if (state.builders.length > buildersLenBefore) {
|
|
143
|
+
builderPubkeys.add(pubkeyHex);
|
|
147
144
|
}
|
|
148
145
|
}
|
|
149
146
|
|
|
150
|
-
state.pendingDeposits =
|
|
147
|
+
state.pendingDeposits = pendingDeposits;
|
|
151
148
|
}
|
package/src/util/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from "./genesis.js";
|
|
|
18
18
|
export * from "./gloas.js";
|
|
19
19
|
export * from "./interop.js";
|
|
20
20
|
export * from "./loadState/index.js";
|
|
21
|
+
export * from "./pendingDepositsLookup.js";
|
|
21
22
|
export * from "./rootCache.js";
|
|
22
23
|
export * from "./seed.js";
|
|
23
24
|
export * from "./shuffling.js";
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
2
|
+
import {PubkeyHex, electra} from "@lodestar/types";
|
|
3
|
+
import {toPubkeyHex} from "@lodestar/utils";
|
|
4
|
+
import {isValidDepositSignature} from "../block/processDeposit.js";
|
|
5
|
+
import {CachedBeaconStateGloas} from "../types.js";
|
|
6
|
+
|
|
7
|
+
type PendingDepositsValidation = {
|
|
8
|
+
hasValidSignature: boolean;
|
|
9
|
+
validatedCount: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Mutable lookup for the pending-deposit sequence used by builder-routing logic.
|
|
14
|
+
*
|
|
15
|
+
* This is to implement the spec's `is_pending_validator(pending_deposits, pubkey)` lazily:
|
|
16
|
+
* deposits are grouped by pubkey without verifying signatures, and BLS verification is
|
|
17
|
+
* deferred until a builder deposit needs to know whether the same pubkey already has a
|
|
18
|
+
* valid pending validator deposit.
|
|
19
|
+
*
|
|
20
|
+
* Call `add()` whenever a deposit is appended to the represented sequence. A cached `true`
|
|
21
|
+
* result short-circuits all subsequent checks for that pubkey; a cached `false` records
|
|
22
|
+
* how many deposits were already verified, so appending a new deposit only verifies the
|
|
23
|
+
* newly-appended tail rather than re-running BLS on previously-invalid entries.
|
|
24
|
+
*/
|
|
25
|
+
export class PendingDepositsLookup {
|
|
26
|
+
private constructor(
|
|
27
|
+
private readonly depositsByPubkey: Map<PubkeyHex, electra.PendingDeposit[]>,
|
|
28
|
+
private readonly validationCache: Map<PubkeyHex, PendingDepositsValidation>
|
|
29
|
+
) {}
|
|
30
|
+
|
|
31
|
+
/** Build an empty lookup for a sequence that will be populated incrementally. */
|
|
32
|
+
static buildEmpty(): PendingDepositsLookup {
|
|
33
|
+
return new PendingDepositsLookup(new Map(), new Map());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Build a pubkey -> pending-deposits lookup from `state.pendingDeposits`.
|
|
38
|
+
* No BLS work is done here; signature verification happens lazily in `hasPendingValidator`.
|
|
39
|
+
*/
|
|
40
|
+
static build(state: CachedBeaconStateGloas): PendingDepositsLookup {
|
|
41
|
+
const lookup = PendingDepositsLookup.buildEmpty();
|
|
42
|
+
for (const pendingDeposit of state.pendingDeposits.getAllReadonly()) {
|
|
43
|
+
lookup.add(pendingDeposit);
|
|
44
|
+
}
|
|
45
|
+
return lookup;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Append a pending deposit to the represented sequence.
|
|
50
|
+
* Pass `pubkeyHex` if the caller has already computed it.
|
|
51
|
+
*/
|
|
52
|
+
add(pendingDeposit: electra.PendingDeposit, pubkeyHex?: PubkeyHex): void {
|
|
53
|
+
const key = pubkeyHex ?? toPubkeyHex(pendingDeposit.pubkey);
|
|
54
|
+
const existing = this.depositsByPubkey.get(key);
|
|
55
|
+
if (existing) {
|
|
56
|
+
existing.push(pendingDeposit);
|
|
57
|
+
} else {
|
|
58
|
+
this.depositsByPubkey.set(key, [pendingDeposit]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Returns true if any pending deposit for `pubkeyHex` has a valid BLS deposit signature.
|
|
64
|
+
* Memoizes the result in `validationCache` so repeated checks for the same pubkey
|
|
65
|
+
* within a block only verify deposits that have not already been checked.
|
|
66
|
+
*/
|
|
67
|
+
hasPendingValidator(config: BeaconConfig, pubkeyHex: PubkeyHex): boolean {
|
|
68
|
+
const validation = this.validationCache.get(pubkeyHex);
|
|
69
|
+
if (validation?.hasValidSignature === true) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const deposits = this.depositsByPubkey.get(pubkeyHex);
|
|
74
|
+
if (deposits === undefined) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// hasValidSignature is false or undefined; resume from the last validatedCount so
|
|
79
|
+
// previously-checked invalid deposits are not re-verified.
|
|
80
|
+
const startIndex = validation?.validatedCount ?? 0;
|
|
81
|
+
if (startIndex === deposits.length) {
|
|
82
|
+
// Nothing new to check; the cached false result still holds.
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
for (let i = startIndex; i < deposits.length; i++) {
|
|
87
|
+
const deposit = deposits[i];
|
|
88
|
+
if (
|
|
89
|
+
isValidDepositSignature(
|
|
90
|
+
config,
|
|
91
|
+
deposit.pubkey,
|
|
92
|
+
deposit.withdrawalCredentials,
|
|
93
|
+
deposit.amount,
|
|
94
|
+
deposit.signature
|
|
95
|
+
)
|
|
96
|
+
) {
|
|
97
|
+
this.validationCache.set(pubkeyHex, {hasValidSignature: true, validatedCount: i + 1});
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.validationCache.set(pubkeyHex, {hasValidSignature: false, validatedCount: deposits.length});
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
package/src/util/shuffling.ts
CHANGED
|
@@ -17,29 +17,31 @@ import {computeStartSlotAtEpoch} from "./epoch.js";
|
|
|
17
17
|
import {EpochShuffling} from "./epochShuffling.js";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
20
|
+
* Block root that decided the proposer shuffling for `proposalEpoch` (keys that shuffling).
|
|
21
|
+
* Computed for the requested epoch, not `state.epoch`, so it is correct when `state` is one
|
|
22
|
+
* epoch off the requested epoch (e.g. serving next-epoch duties from the current state).
|
|
22
23
|
*
|
|
23
|
-
* Returns `null`
|
|
24
|
-
*
|
|
24
|
+
* Returns `null` when the genesis block decides its own shuffling (caller falls back to the
|
|
25
|
+
* genesis block root).
|
|
25
26
|
*/
|
|
26
|
-
export function proposerShufflingDecisionRoot(
|
|
27
|
-
|
|
27
|
+
export function proposerShufflingDecisionRoot(
|
|
28
|
+
fork: ForkName,
|
|
29
|
+
state: IBeaconStateView,
|
|
30
|
+
proposalEpoch: Epoch
|
|
31
|
+
): Root | null {
|
|
32
|
+
const decisionSlot = proposerShufflingDecisionSlot(fork, proposalEpoch);
|
|
28
33
|
if (state.slot === decisionSlot) {
|
|
29
34
|
return null;
|
|
30
35
|
}
|
|
31
36
|
return state.getBlockRootAtSlot(decisionSlot);
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const epoch = isForkPostFulu(fork) ? state.epoch - 1 : state.epoch;
|
|
41
|
-
const startSlot = computeStartSlotAtEpoch(epoch);
|
|
42
|
-
return Math.max(startSlot - 1, 0);
|
|
39
|
+
/** Slot whose block root keys the proposer shuffling for `proposalEpoch`. */
|
|
40
|
+
function proposerShufflingDecisionSlot(fork: ForkName, proposalEpoch: Epoch): Slot {
|
|
41
|
+
// Post-Fulu the shuffling is decided one epoch earlier (deterministic proposer lookahead,
|
|
42
|
+
// MIN_SEED_LOOKAHEAD = 1); pre-Fulu it is the last block before `proposalEpoch`.
|
|
43
|
+
const decisionEpoch = isForkPostFulu(fork) ? proposalEpoch - 1 : proposalEpoch;
|
|
44
|
+
return Math.max(computeStartSlotAtEpoch(decisionEpoch) - 1, 0);
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
/**
|