@lodestar/state-transition 1.44.0-rc.2 → 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/block/index.d.ts +2 -0
- package/lib/block/index.d.ts.map +1 -1
- package/lib/block/index.js +3 -1
- package/lib/block/index.js.map +1 -1
- package/lib/block/processBuilderDepositRequest.d.ts +10 -0
- package/lib/block/processBuilderDepositRequest.d.ts.map +1 -0
- package/lib/block/processBuilderDepositRequest.js +27 -0
- package/lib/block/processBuilderDepositRequest.js.map +1 -0
- package/lib/block/processBuilderExitRequest.d.ts +13 -0
- package/lib/block/processBuilderExitRequest.d.ts.map +1 -0
- package/lib/block/processBuilderExitRequest.js +29 -0
- package/lib/block/processBuilderExitRequest.js.map +1 -0
- package/lib/block/processDepositRequest.d.ts +2 -8
- package/lib/block/processDepositRequest.d.ts.map +1 -1
- package/lib/block/processDepositRequest.js +2 -98
- package/lib/block/processDepositRequest.js.map +1 -1
- package/lib/block/processExecutionPayloadBid.d.ts +2 -3
- package/lib/block/processExecutionPayloadBid.d.ts.map +1 -1
- package/lib/block/processExecutionPayloadBid.js +16 -8
- package/lib/block/processExecutionPayloadBid.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 +16 -8
- package/lib/block/processParentExecutionPayload.js.map +1 -1
- package/lib/block/processProposerSlashing.d.ts.map +1 -1
- package/lib/block/processProposerSlashing.js +9 -1
- package/lib/block/processProposerSlashing.js.map +1 -1
- package/lib/block/processVoluntaryExit.d.ts +1 -1
- package/lib/block/processVoluntaryExit.d.ts.map +1 -1
- package/lib/block/processVoluntaryExit.js +1 -35
- package/lib/block/processVoluntaryExit.js.map +1 -1
- package/lib/slot/upgradeStateToGloas.js +34 -28
- package/lib/slot/upgradeStateToGloas.js.map +1 -1
- package/lib/stateView/beaconStateView.d.ts +1 -1
- package/lib/stateView/beaconStateView.d.ts.map +1 -1
- package/lib/stateView/beaconStateView.js.map +1 -1
- package/lib/stateView/interface.d.ts +1 -1
- package/lib/stateView/interface.d.ts.map +1 -1
- package/lib/stateView/nativeBeaconStateView.d.ts +1 -1
- package/lib/stateView/nativeBeaconStateView.d.ts.map +1 -1
- package/lib/stateView/nativeBeaconStateView.js.map +1 -1
- package/lib/util/gloas.d.ts +17 -0
- package/lib/util/gloas.d.ts.map +1 -1
- package/lib/util/gloas.js +59 -1
- package/lib/util/gloas.js.map +1 -1
- package/package.json +7 -7
- package/src/block/index.ts +6 -1
- package/src/block/processBuilderDepositRequest.ts +43 -0
- package/src/block/processBuilderExitRequest.ts +39 -0
- package/src/block/processDepositRequest.ts +3 -124
- package/src/block/processExecutionPayloadBid.ts +24 -9
- package/src/block/processParentExecutionPayload.ts +23 -11
- package/src/block/processProposerSlashing.ts +9 -4
- package/src/block/processVoluntaryExit.ts +2 -61
- package/src/slot/upgradeStateToGloas.ts +48 -32
- package/src/stateView/beaconStateView.ts +1 -1
- package/src/stateView/interface.ts +1 -1
- package/src/stateView/nativeBeaconStateView.ts +1 -1
- package/src/util/gloas.ts +76 -1
package/lib/util/gloas.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PublicKey, Signature, verify } from "@chainsafe/blst";
|
|
2
|
+
import { BUILDER_INDEX_FLAG, BUILDER_PAYMENT_THRESHOLD_DENOMINATOR, BUILDER_PAYMENT_THRESHOLD_NUMERATOR, BUILDER_WITHDRAWAL_PREFIX, DOMAIN_BUILDER_DEPOSIT, EFFECTIVE_BALANCE_INCREMENT, FAR_FUTURE_EPOCH, MIN_DEPOSIT_AMOUNT, MIN_SEED_LOOKAHEAD, PTC_SIZE, SLOTS_PER_EPOCH, } from "@lodestar/params";
|
|
3
|
+
import { ssz } from "@lodestar/types";
|
|
2
4
|
import { byteArrayEquals } from "@lodestar/utils";
|
|
5
|
+
import { ZERO_HASH } from "../constants/index.js";
|
|
3
6
|
import { getBlockRootAtSlot } from "./blockRoot.js";
|
|
7
|
+
import { computeDomain } from "./domain.js";
|
|
4
8
|
import { computeEpochAtSlot } from "./epoch.js";
|
|
5
9
|
import { computeEpochShuffling } from "./epochShuffling.js";
|
|
6
10
|
import { computePayloadTimelinessCommitteesForEpoch } from "./seed.js";
|
|
11
|
+
import { computeSigningRoot } from "./signingRoot.js";
|
|
7
12
|
import { getActiveValidatorIndices } from "./validator.js";
|
|
8
13
|
export function isBuilderWithdrawalCredential(withdrawalCredentials) {
|
|
9
14
|
return withdrawalCredentials[0] === BUILDER_WITHDRAWAL_PREFIX;
|
|
@@ -171,4 +176,57 @@ export function getPtcWindowEpochCacheData(state) {
|
|
|
171
176
|
nextPayloadTimelinessCommittees: toUint32Arrays(nextPtcWindow),
|
|
172
177
|
};
|
|
173
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Add a new builder to the builders registry. Reuses slots from exited and fully withdrawn
|
|
181
|
+
* builders when available, otherwise appends.
|
|
182
|
+
*
|
|
183
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md#new-add_builder_to_registry
|
|
184
|
+
*/
|
|
185
|
+
export function addBuilderToRegistry(state, pubkey, version, executionAddress, amount, slot) {
|
|
186
|
+
const currentEpoch = computeEpochAtSlot(state.slot);
|
|
187
|
+
const depositEpoch = computeEpochAtSlot(slot);
|
|
188
|
+
let builderIndex = state.builders.length;
|
|
189
|
+
for (let i = 0; i < state.builders.length; i++) {
|
|
190
|
+
const builder = state.builders.getReadonly(i);
|
|
191
|
+
if (builder.withdrawableEpoch <= currentEpoch && builder.balance === 0) {
|
|
192
|
+
builderIndex = i;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const newBuilder = ssz.gloas.Builder.toViewDU({
|
|
197
|
+
pubkey,
|
|
198
|
+
version,
|
|
199
|
+
executionAddress,
|
|
200
|
+
balance: amount,
|
|
201
|
+
depositEpoch,
|
|
202
|
+
withdrawableEpoch: FAR_FUTURE_EPOCH,
|
|
203
|
+
});
|
|
204
|
+
if (builderIndex < state.builders.length) {
|
|
205
|
+
state.builders.set(builderIndex, newBuilder);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
state.builders.push(newBuilder);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Verify the proof of possession on a builder deposit request.
|
|
213
|
+
*
|
|
214
|
+
* The dedicated `DOMAIN_BUILDER_DEPOSIT` (vs the validator `DOMAIN_DEPOSIT`) prevents replay
|
|
215
|
+
* of validator deposit signatures against the builder deposit contract and vice versa.
|
|
216
|
+
*
|
|
217
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md#new-is_valid_builder_deposit_signature
|
|
218
|
+
*/
|
|
219
|
+
export function isValidBuilderDepositSignature(config, pubkey, withdrawalCredentials, amount, signature) {
|
|
220
|
+
const depositMessage = { pubkey, withdrawalCredentials, amount };
|
|
221
|
+
const domain = computeDomain(DOMAIN_BUILDER_DEPOSIT, config.GENESIS_FORK_VERSION, ZERO_HASH);
|
|
222
|
+
const signingRoot = computeSigningRoot(ssz.phase0.DepositMessage, depositMessage, domain);
|
|
223
|
+
try {
|
|
224
|
+
const publicKey = PublicKey.fromBytes(pubkey, true);
|
|
225
|
+
const sig = Signature.fromBytes(signature, true);
|
|
226
|
+
return verify(signingRoot, publicKey, sig);
|
|
227
|
+
}
|
|
228
|
+
catch (_e) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
174
232
|
//# sourceMappingURL=gloas.js.map
|
package/lib/util/gloas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gloas.js","sourceRoot":"","sources":["../../src/util/gloas.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,qCAAqC,EACrC,mCAAmC,EACnC,yBAAyB,EACzB,2BAA2B,EAC3B,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,eAAe,GAChB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"gloas.js","sourceRoot":"","sources":["../../src/util/gloas.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.44.0
|
|
14
|
+
"version": "1.44.0",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -71,14 +71,14 @@
|
|
|
71
71
|
"@chainsafe/pubkey-index-map": "^3.0.0",
|
|
72
72
|
"@chainsafe/ssz": "^1.4.0",
|
|
73
73
|
"@chainsafe/swap-or-not-shuffle": "^1.2.1",
|
|
74
|
-
"@lodestar/config": "^1.44.0
|
|
75
|
-
"@lodestar/params": "^1.44.0
|
|
76
|
-
"@lodestar/types": "^1.44.0
|
|
77
|
-
"@lodestar/utils": "^1.44.0
|
|
74
|
+
"@lodestar/config": "^1.44.0",
|
|
75
|
+
"@lodestar/params": "^1.44.0",
|
|
76
|
+
"@lodestar/types": "^1.44.0",
|
|
77
|
+
"@lodestar/utils": "^1.44.0",
|
|
78
78
|
"@vekexasia/bigint-buffer2": "^1.1.1"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@lodestar/api": "^1.44.0
|
|
81
|
+
"@lodestar/api": "^1.44.0"
|
|
82
82
|
},
|
|
83
83
|
"keywords": [
|
|
84
84
|
"ethereum",
|
|
@@ -86,5 +86,5 @@
|
|
|
86
86
|
"beacon",
|
|
87
87
|
"blockchain"
|
|
88
88
|
],
|
|
89
|
-
"gitHead": "
|
|
89
|
+
"gitHead": "e3d733b7b5107122ff90fc89021a9ab404198c39"
|
|
90
90
|
}
|
package/src/block/index.ts
CHANGED
|
@@ -38,6 +38,8 @@ export {
|
|
|
38
38
|
export * from "./externalData.js";
|
|
39
39
|
export * from "./initiateValidatorExit.js";
|
|
40
40
|
export * from "./isValidIndexedAttestation.js";
|
|
41
|
+
export * from "./processBuilderDepositRequest.js";
|
|
42
|
+
export * from "./processBuilderExitRequest.js";
|
|
41
43
|
export * from "./processDepositRequest.js";
|
|
42
44
|
export * from "./processOperations.js";
|
|
43
45
|
|
|
@@ -85,7 +87,10 @@ export function processBlock(
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
if (fork >= ForkSeq.gloas) {
|
|
88
|
-
processExecutionPayloadBid(
|
|
90
|
+
processExecutionPayloadBid(
|
|
91
|
+
state as CachedBeaconStateGloas,
|
|
92
|
+
(block as BeaconBlock<ForkPostGloas>).body.signedExecutionPayloadBid
|
|
93
|
+
);
|
|
89
94
|
}
|
|
90
95
|
|
|
91
96
|
processRandao(state, block, verifySignatures);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {FAR_FUTURE_EPOCH} from "@lodestar/params";
|
|
2
|
+
import {gloas} from "@lodestar/types";
|
|
3
|
+
import {CachedBeaconStateGloas} from "../types.js";
|
|
4
|
+
import {computeEpochAtSlot} from "../util/epoch.js";
|
|
5
|
+
import {addBuilderToRegistry, findBuilderIndexByPubkey, isValidBuilderDepositSignature} from "../util/gloas.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Process a builder deposit request from the execution layer: register a new builder
|
|
9
|
+
* (proof-of-possession gated) or top up an existing builder's balance.
|
|
10
|
+
*
|
|
11
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md#new-process_builder_deposit_request
|
|
12
|
+
*/
|
|
13
|
+
export function processBuilderDepositRequest(
|
|
14
|
+
state: CachedBeaconStateGloas,
|
|
15
|
+
request: gloas.BuilderDepositRequest
|
|
16
|
+
): void {
|
|
17
|
+
const {pubkey, withdrawalCredentials, amount, signature} = request;
|
|
18
|
+
const builderIndex = findBuilderIndexByPubkey(state, pubkey);
|
|
19
|
+
|
|
20
|
+
if (builderIndex === null) {
|
|
21
|
+
if (isValidBuilderDepositSignature(state.config, pubkey, withdrawalCredentials, amount, signature)) {
|
|
22
|
+
addBuilderToRegistry(
|
|
23
|
+
state,
|
|
24
|
+
pubkey,
|
|
25
|
+
withdrawalCredentials[0],
|
|
26
|
+
withdrawalCredentials.subarray(12),
|
|
27
|
+
amount,
|
|
28
|
+
state.slot
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const builder = state.builders.get(builderIndex);
|
|
35
|
+
|
|
36
|
+
// Increase balance by deposit amount
|
|
37
|
+
builder.balance += amount;
|
|
38
|
+
|
|
39
|
+
// If exited, reset the withdrawable epoch
|
|
40
|
+
if (builder.withdrawableEpoch !== FAR_FUTURE_EPOCH) {
|
|
41
|
+
builder.withdrawableEpoch = computeEpochAtSlot(state.slot) + state.config.MIN_BUILDER_WITHDRAWABILITY_DELAY;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {gloas} from "@lodestar/types";
|
|
2
|
+
import {byteArrayEquals} from "@lodestar/utils";
|
|
3
|
+
import {CachedBeaconStateGloas} from "../types.js";
|
|
4
|
+
import {
|
|
5
|
+
findBuilderIndexByPubkey,
|
|
6
|
+
getPendingBalanceToWithdrawForBuilder,
|
|
7
|
+
initiateBuilderExit,
|
|
8
|
+
isActiveBuilder,
|
|
9
|
+
} from "../util/gloas.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Apply a builder exit request. Authorizes the exit via `source_address` (the builder's
|
|
13
|
+
* execution_address), not the BLS key — mirroring EIP-7002's 0x01 credential exit.
|
|
14
|
+
*
|
|
15
|
+
* Drops the request silently if any precondition fails; the EL has already dequeued it
|
|
16
|
+
* deterministically, so the fee is forfeited but `requests_hash` agreement is unaffected.
|
|
17
|
+
*
|
|
18
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md#new-process_builder_exit_request
|
|
19
|
+
*/
|
|
20
|
+
export function processBuilderExitRequest(state: CachedBeaconStateGloas, request: gloas.BuilderExitRequest): void {
|
|
21
|
+
const builderIndex = findBuilderIndexByPubkey(state, request.pubkey);
|
|
22
|
+
if (builderIndex === null) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const builder = state.builders.getReadonly(builderIndex);
|
|
27
|
+
|
|
28
|
+
if (!isActiveBuilder(builder, state.finalizedCheckpoint.epoch)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (!byteArrayEquals(builder.executionAddress, request.sourceAddress)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (getPendingBalanceToWithdrawForBuilder(state, builderIndex) !== 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
initiateBuilderExit(state, builderIndex);
|
|
39
|
+
}
|
|
@@ -1,135 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {toPubkeyHex} from "@lodestar/utils";
|
|
1
|
+
import {ForkSeq, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
|
|
2
|
+
import {electra, ssz} from "@lodestar/types";
|
|
4
3
|
import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
5
|
-
import {findBuilderIndexByPubkey, isBuilderWithdrawalCredential} from "../util/gloas.js";
|
|
6
|
-
import {computeEpochAtSlot, isValidatorKnown} from "../util/index.js";
|
|
7
|
-
import {PendingDepositsLookup} from "../util/pendingDepositsLookup.js";
|
|
8
|
-
import {isValidDepositSignature} from "./processDeposit.js";
|
|
9
4
|
|
|
10
|
-
/**
|
|
11
|
-
* Apply a deposit for a builder. Either increases balance for existing builder or adds new builder to registry.
|
|
12
|
-
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-apply_deposit_for_builder
|
|
13
|
-
*/
|
|
14
|
-
export function applyDepositForBuilder(
|
|
15
|
-
state: CachedBeaconStateGloas,
|
|
16
|
-
pubkey: BLSPubkey,
|
|
17
|
-
withdrawalCredentials: Bytes32,
|
|
18
|
-
amount: UintNum64,
|
|
19
|
-
signature: Bytes32,
|
|
20
|
-
slot: UintNum64
|
|
21
|
-
): void {
|
|
22
|
-
const builderIndex = findBuilderIndexByPubkey(state, pubkey);
|
|
23
|
-
|
|
24
|
-
if (builderIndex !== null) {
|
|
25
|
-
// Existing builder - increase balance
|
|
26
|
-
const builder = state.builders.get(builderIndex);
|
|
27
|
-
builder.balance += amount;
|
|
28
|
-
} else {
|
|
29
|
-
// New builder - verify signature and add to registry
|
|
30
|
-
if (isValidDepositSignature(state.config, pubkey, withdrawalCredentials, amount, signature)) {
|
|
31
|
-
addBuilderToRegistry(state, pubkey, withdrawalCredentials, amount, slot);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Add a new builder to the builders registry.
|
|
38
|
-
* Reuses slots from exited and fully withdrawn builders if available.
|
|
39
|
-
*/
|
|
40
|
-
function addBuilderToRegistry(
|
|
41
|
-
state: CachedBeaconStateGloas,
|
|
42
|
-
pubkey: BLSPubkey,
|
|
43
|
-
withdrawalCredentials: Bytes32,
|
|
44
|
-
amount: UintNum64,
|
|
45
|
-
slot: UintNum64
|
|
46
|
-
): void {
|
|
47
|
-
const currentEpoch = computeEpochAtSlot(state.slot);
|
|
48
|
-
const depositEpoch = computeEpochAtSlot(slot);
|
|
49
|
-
|
|
50
|
-
// Try to find a reusable slot from an exited builder with zero balance
|
|
51
|
-
let builderIndex = state.builders.length;
|
|
52
|
-
for (let i = 0; i < state.builders.length; i++) {
|
|
53
|
-
const builder = state.builders.getReadonly(i);
|
|
54
|
-
if (builder.withdrawableEpoch <= currentEpoch && builder.balance === 0) {
|
|
55
|
-
builderIndex = i;
|
|
56
|
-
break;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Create new builder
|
|
61
|
-
const newBuilder = ssz.gloas.Builder.toViewDU({
|
|
62
|
-
pubkey,
|
|
63
|
-
version: withdrawalCredentials[0],
|
|
64
|
-
executionAddress: withdrawalCredentials.subarray(12),
|
|
65
|
-
balance: amount,
|
|
66
|
-
depositEpoch: depositEpoch,
|
|
67
|
-
withdrawableEpoch: FAR_FUTURE_EPOCH,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
if (builderIndex < state.builders.length) {
|
|
71
|
-
// Reuse existing slot
|
|
72
|
-
state.builders.set(builderIndex, newBuilder);
|
|
73
|
-
} else {
|
|
74
|
-
// Append to end
|
|
75
|
-
state.builders.push(newBuilder);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
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
|
-
// See https://github.com/ChainSafe/lodestar/issues/9181
|
|
83
5
|
export function processDepositRequest(
|
|
84
6
|
fork: ForkSeq,
|
|
85
7
|
state: CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
86
|
-
depositRequest: electra.DepositRequest
|
|
87
|
-
pendingDepositsLookup?: PendingDepositsLookup
|
|
8
|
+
depositRequest: electra.DepositRequest
|
|
88
9
|
): void {
|
|
89
10
|
const {pubkey, withdrawalCredentials, amount, signature} = depositRequest;
|
|
90
11
|
|
|
91
|
-
if (fork >= ForkSeq.gloas) {
|
|
92
|
-
const stateGloas = state as CachedBeaconStateGloas;
|
|
93
|
-
const lookup = pendingDepositsLookup ?? PendingDepositsLookup.build(stateGloas);
|
|
94
|
-
const pubkeyHex = toPubkeyHex(pubkey);
|
|
95
|
-
const builderIndex = findBuilderIndexByPubkey(stateGloas, pubkey);
|
|
96
|
-
const validatorIndex = state.epochCtx.getValidatorIndex(pubkey);
|
|
97
|
-
|
|
98
|
-
const isBuilder = builderIndex !== null;
|
|
99
|
-
const isValidator = isValidatorKnown(state, validatorIndex);
|
|
100
|
-
|
|
101
|
-
if (isBuilder) {
|
|
102
|
-
// Top up an existing builder regardless of withdrawal credential prefix
|
|
103
|
-
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature, state.slot);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Only check the (expensive) "pending validator" condition when needed
|
|
108
|
-
if (
|
|
109
|
-
isBuilderWithdrawalCredential(withdrawalCredentials) &&
|
|
110
|
-
!isValidator &&
|
|
111
|
-
!lookup.hasPendingValidator(state.config, pubkeyHex)
|
|
112
|
-
) {
|
|
113
|
-
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature, state.slot);
|
|
114
|
-
return;
|
|
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;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Pre-Gloas (Electra) path
|
|
132
|
-
// depositRequestsStartIndex is only set in Electra, from Fulu the eth1 bridge deposit mechanism was removed.
|
|
133
12
|
if (fork === ForkSeq.electra && state.depositRequestsStartIndex === UNSET_DEPOSIT_REQUESTS_START_INDEX) {
|
|
134
13
|
state.depositRequestsStartIndex = depositRequest.index;
|
|
135
14
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import {PublicKey, Signature, verify} from "@chainsafe/blst";
|
|
2
|
-
import {BUILDER_INDEX_SELF_BUILD,
|
|
3
|
-
import {
|
|
2
|
+
import {BUILDER_INDEX_SELF_BUILD, GENESIS_SLOT, PAYLOAD_BUILDER_VERSION, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
3
|
+
import {gloas, ssz} from "@lodestar/types";
|
|
4
4
|
import {byteArrayEquals, toHex, toRootHex} from "@lodestar/utils";
|
|
5
5
|
import {G2_POINT_AT_INFINITY} from "../constants/constants.js";
|
|
6
6
|
import {getExecutionPayloadBidSigningRoot} from "../signatureSets/executionPayloadBid.js";
|
|
7
7
|
import {CachedBeaconStateGloas} from "../types.js";
|
|
8
8
|
import {canBuilderCoverBid, isActiveBuilder} from "../util/gloas.js";
|
|
9
|
-
import {getCurrentEpoch, getRandaoMix} from "../util/index.js";
|
|
9
|
+
import {getBlockRootAtSlot, getCurrentEpoch, getRandaoMix} from "../util/index.js";
|
|
10
10
|
|
|
11
|
-
export function processExecutionPayloadBid(
|
|
12
|
-
|
|
11
|
+
export function processExecutionPayloadBid(
|
|
12
|
+
state: CachedBeaconStateGloas,
|
|
13
|
+
signedBid: gloas.SignedExecutionPayloadBid
|
|
14
|
+
): void {
|
|
13
15
|
const bid = signedBid.message;
|
|
14
16
|
const {builderIndex, value: amount} = bid;
|
|
15
17
|
|
|
@@ -31,6 +33,13 @@ export function processExecutionPayloadBid(state: CachedBeaconStateGloas, block:
|
|
|
31
33
|
throw Error(`Invalid execution payload bid: builder ${builderIndex} is not active`);
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
// Verify that the builder is a payload builder
|
|
37
|
+
if (builder.version !== PAYLOAD_BUILDER_VERSION) {
|
|
38
|
+
throw Error(
|
|
39
|
+
`Invalid execution payload bid: builder ${builderIndex} version ${builder.version} != ${PAYLOAD_BUILDER_VERSION}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
34
43
|
// Verify that the builder has funds to cover the bid
|
|
35
44
|
if (!canBuilderCoverBid(state, builderIndex, amount)) {
|
|
36
45
|
throw Error(`Invalid execution payload bid: builder ${builderIndex} has insufficient balance`);
|
|
@@ -42,8 +51,12 @@ export function processExecutionPayloadBid(state: CachedBeaconStateGloas, block:
|
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
|
|
45
|
-
if (bid.slot !==
|
|
46
|
-
throw Error(`Bid slot ${bid.slot} does not match
|
|
54
|
+
if (bid.slot !== state.slot) {
|
|
55
|
+
throw Error(`Bid slot ${bid.slot} does not match state slot ${state.slot}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (state.slot <= GENESIS_SLOT) {
|
|
59
|
+
throw Error(`Execution payload bid not allowed at genesis slot ${state.slot}`);
|
|
47
60
|
}
|
|
48
61
|
|
|
49
62
|
if (!byteArrayEquals(bid.parentBlockHash, state.latestBlockHash)) {
|
|
@@ -52,9 +65,10 @@ export function processExecutionPayloadBid(state: CachedBeaconStateGloas, block:
|
|
|
52
65
|
);
|
|
53
66
|
}
|
|
54
67
|
|
|
55
|
-
|
|
68
|
+
const parentBlockRoot = getBlockRootAtSlot(state, state.slot - 1);
|
|
69
|
+
if (!byteArrayEquals(bid.parentBlockRoot, parentBlockRoot)) {
|
|
56
70
|
throw Error(
|
|
57
|
-
`Parent block root ${toRootHex(bid.parentBlockRoot)} of bid does not match
|
|
71
|
+
`Parent block root ${toRootHex(bid.parentBlockRoot)} of bid does not match state's parent block root ${toRootHex(parentBlockRoot)}`
|
|
58
72
|
);
|
|
59
73
|
}
|
|
60
74
|
|
|
@@ -79,6 +93,7 @@ export function processExecutionPayloadBid(state: CachedBeaconStateGloas, block:
|
|
|
79
93
|
amount,
|
|
80
94
|
builderIndex,
|
|
81
95
|
}),
|
|
96
|
+
proposerIndex: state.epochCtx.getBeaconProposer(state.slot),
|
|
82
97
|
});
|
|
83
98
|
|
|
84
99
|
state.builderPendingPayments.set(SLOTS_PER_EPOCH + (bid.slot % SLOTS_PER_EPOCH), pendingPaymentView);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {ForkPostGloas, SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT} from "@lodestar/params";
|
|
2
|
-
import {BeaconBlock,
|
|
2
|
+
import {BeaconBlock, gloas, 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 {
|
|
6
|
+
import {processBuilderDepositRequest} from "./processBuilderDepositRequest.js";
|
|
7
|
+
import {processBuilderExitRequest} from "./processBuilderExitRequest.js";
|
|
7
8
|
import {processConsolidationRequest} from "./processConsolidationRequest.js";
|
|
8
9
|
import {processDepositRequest} from "./processDepositRequest.js";
|
|
9
10
|
import {processWithdrawalRequest} from "./processWithdrawalRequest.js";
|
|
@@ -26,7 +27,7 @@ export function processParentExecutionPayload(state: CachedBeaconStateGloas, blo
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
// Parent was FULL -- verify the bid commitment and apply the payload
|
|
29
|
-
const requestsRoot = ssz.
|
|
30
|
+
const requestsRoot = ssz.gloas.ExecutionRequests.hashTreeRoot(requests);
|
|
30
31
|
if (!byteArrayEquals(requestsRoot, parentBid.executionRequestsRoot)) {
|
|
31
32
|
throw new Error(
|
|
32
33
|
`Parent execution requests root mismatch actual=${toRootHex(requestsRoot)} expected=${toRootHex(parentBid.executionRequestsRoot)}`
|
|
@@ -45,7 +46,7 @@ export function processParentExecutionPayload(state: CachedBeaconStateGloas, blo
|
|
|
45
46
|
*
|
|
46
47
|
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.6/specs/gloas/beacon-chain.md#new-apply_parent_execution_payload
|
|
47
48
|
*/
|
|
48
|
-
export function applyParentExecutionPayload(state: CachedBeaconStateGloas, requests:
|
|
49
|
+
export function applyParentExecutionPayload(state: CachedBeaconStateGloas, requests: gloas.ExecutionRequests): void {
|
|
49
50
|
const fork = state.config.getForkSeq(state.slot);
|
|
50
51
|
const parentBid = state.latestExecutionPayloadBid;
|
|
51
52
|
const parentSlot = parentBid.slot;
|
|
@@ -54,11 +55,8 @@ export function applyParentExecutionPayload(state: CachedBeaconStateGloas, reque
|
|
|
54
55
|
|
|
55
56
|
// Process execution requests from parent's payload. The execution
|
|
56
57
|
// requests are processed at state.slot (child's slot), not the parent's slot.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
for (const deposit of requests.deposits) {
|
|
60
|
-
processDepositRequest(fork, state, deposit, pendingDepositsLookup);
|
|
61
|
-
}
|
|
58
|
+
for (const deposit of requests.deposits) {
|
|
59
|
+
processDepositRequest(fork, state, deposit);
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
for (const withdrawal of requests.withdrawals) {
|
|
@@ -69,6 +67,14 @@ export function applyParentExecutionPayload(state: CachedBeaconStateGloas, reque
|
|
|
69
67
|
processConsolidationRequest(state, consolidation);
|
|
70
68
|
}
|
|
71
69
|
|
|
70
|
+
for (const builderDeposit of requests.builderDeposits) {
|
|
71
|
+
processBuilderDepositRequest(state, builderDeposit);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (const builderExit of requests.builderExits) {
|
|
75
|
+
processBuilderExitRequest(state, builderExit);
|
|
76
|
+
}
|
|
77
|
+
|
|
72
78
|
// Settle the builder payment
|
|
73
79
|
if (parentEpoch === currentEpoch) {
|
|
74
80
|
settleBuilderPayment(state, SLOTS_PER_EPOCH + (parentSlot % SLOTS_PER_EPOCH));
|
|
@@ -110,8 +116,14 @@ function settleBuilderPayment(state: CachedBeaconStateGloas, paymentIndex: numbe
|
|
|
110
116
|
state.builderPendingPayments.set(paymentIndex, ssz.gloas.BuilderPendingPayment.defaultViewDU());
|
|
111
117
|
}
|
|
112
118
|
|
|
113
|
-
function assertEmptyExecutionRequests(requests:
|
|
114
|
-
if (
|
|
119
|
+
function assertEmptyExecutionRequests(requests: gloas.ExecutionRequests): void {
|
|
120
|
+
if (
|
|
121
|
+
requests.deposits.length !== 0 ||
|
|
122
|
+
requests.withdrawals.length !== 0 ||
|
|
123
|
+
requests.consolidations.length !== 0 ||
|
|
124
|
+
requests.builderDeposits.length !== 0 ||
|
|
125
|
+
requests.builderExits.length !== 0
|
|
126
|
+
) {
|
|
115
127
|
throw new Error("Parent execution requests must be empty when parent block is EMPTY");
|
|
116
128
|
}
|
|
117
129
|
}
|
|
@@ -32,6 +32,10 @@ export function processProposerSlashing(
|
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
if (fork >= ForkSeq.gloas) {
|
|
35
|
+
// Remove the BuilderPendingPayment corresponding to this proposal if it is still in the
|
|
36
|
+
// 2-epoch window. Only clear it when the slashed validator is the proposer associated with
|
|
37
|
+
// the payment; otherwise an unrelated same-slot equivocation could grief an honest proposer's
|
|
38
|
+
// payment.
|
|
35
39
|
const slot = Number(proposerSlashing.signedHeader1.message.slot);
|
|
36
40
|
const proposalEpoch = computeEpochAtSlot(slot);
|
|
37
41
|
const currentEpoch = state.epochCtx.epoch;
|
|
@@ -45,10 +49,11 @@ export function processProposerSlashing(
|
|
|
45
49
|
: undefined;
|
|
46
50
|
|
|
47
51
|
if (paymentIndex !== undefined) {
|
|
48
|
-
(state as CachedBeaconStateGloas).builderPendingPayments
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
const builderPendingPayments = (state as CachedBeaconStateGloas).builderPendingPayments;
|
|
53
|
+
const payment = builderPendingPayments.get(paymentIndex);
|
|
54
|
+
if (payment.proposerIndex === proposerSlashing.signedHeader1.message.proposerIndex) {
|
|
55
|
+
builderPendingPayments.set(paymentIndex, ssz.gloas.BuilderPendingPayment.defaultViewDU());
|
|
56
|
+
}
|
|
52
57
|
}
|
|
53
58
|
}
|
|
54
59
|
|
|
@@ -2,14 +2,7 @@ import {FAR_FUTURE_EPOCH, ForkSeq} from "@lodestar/params";
|
|
|
2
2
|
import {phase0} from "@lodestar/types";
|
|
3
3
|
import {verifyVoluntaryExitSignature} from "../signatureSets/index.js";
|
|
4
4
|
import {BeaconStateView} from "../stateView/beaconStateView.js";
|
|
5
|
-
import {CachedBeaconStateAllForks, CachedBeaconStateElectra
|
|
6
|
-
import {
|
|
7
|
-
convertValidatorIndexToBuilderIndex,
|
|
8
|
-
getPendingBalanceToWithdrawForBuilder,
|
|
9
|
-
initiateBuilderExit,
|
|
10
|
-
isActiveBuilder,
|
|
11
|
-
isBuilderIndex,
|
|
12
|
-
} from "../util/gloas.js";
|
|
5
|
+
import {CachedBeaconStateAllForks, CachedBeaconStateElectra} from "../types.js";
|
|
13
6
|
import {getPendingBalanceToWithdraw, isActiveValidator} from "../util/index.js";
|
|
14
7
|
import {initiateValidatorExit} from "./index.js";
|
|
15
8
|
|
|
@@ -24,7 +17,7 @@ export enum VoluntaryExitValidity {
|
|
|
24
17
|
}
|
|
25
18
|
|
|
26
19
|
/**
|
|
27
|
-
* Process a VoluntaryExit operation. Initiates the exit of a validator
|
|
20
|
+
* Process a VoluntaryExit operation. Initiates the exit of a validator.
|
|
28
21
|
*
|
|
29
22
|
* PERF: Work depends on number of VoluntaryExit per block. On regular networks the average is 0 / block.
|
|
30
23
|
*/
|
|
@@ -34,21 +27,11 @@ export function processVoluntaryExit(
|
|
|
34
27
|
signedVoluntaryExit: phase0.SignedVoluntaryExit,
|
|
35
28
|
verifySignature = true
|
|
36
29
|
): void {
|
|
37
|
-
const voluntaryExit = signedVoluntaryExit.message;
|
|
38
|
-
|
|
39
30
|
const validity = getVoluntaryExitValidity(fork, state, signedVoluntaryExit, verifySignature);
|
|
40
31
|
if (validity !== VoluntaryExitValidity.valid) {
|
|
41
32
|
throw Error(`Invalid voluntary exit at forkSeq=${fork} reason=${validity}`);
|
|
42
33
|
}
|
|
43
34
|
|
|
44
|
-
if (fork >= ForkSeq.gloas && isBuilderIndex(voluntaryExit.validatorIndex)) {
|
|
45
|
-
initiateBuilderExit(
|
|
46
|
-
state as CachedBeaconStateGloas,
|
|
47
|
-
convertValidatorIndexToBuilderIndex(voluntaryExit.validatorIndex)
|
|
48
|
-
);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
35
|
const validator = state.validators.get(signedVoluntaryExit.message.validatorIndex);
|
|
53
36
|
initiateValidatorExit(fork, state, validator);
|
|
54
37
|
}
|
|
@@ -67,51 +50,9 @@ export function getVoluntaryExitValidity(
|
|
|
67
50
|
return VoluntaryExitValidity.earlyEpoch;
|
|
68
51
|
}
|
|
69
52
|
|
|
70
|
-
// Check if this is a builder exit
|
|
71
|
-
if (fork >= ForkSeq.gloas && isBuilderIndex(voluntaryExit.validatorIndex)) {
|
|
72
|
-
return getBuilderVoluntaryExitValidity(state as CachedBeaconStateGloas, signedVoluntaryExit, verifySignature);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
53
|
return getValidatorVoluntaryExitValidity(fork, state, signedVoluntaryExit, verifySignature);
|
|
76
54
|
}
|
|
77
55
|
|
|
78
|
-
function getBuilderVoluntaryExitValidity(
|
|
79
|
-
state: CachedBeaconStateGloas,
|
|
80
|
-
signedVoluntaryExit: phase0.SignedVoluntaryExit,
|
|
81
|
-
verifySignature: boolean
|
|
82
|
-
): VoluntaryExitValidity {
|
|
83
|
-
const {config, epochCtx} = state;
|
|
84
|
-
const builderIndex = convertValidatorIndexToBuilderIndex(signedVoluntaryExit.message.validatorIndex);
|
|
85
|
-
|
|
86
|
-
if (builderIndex >= state.builders.length) {
|
|
87
|
-
return VoluntaryExitValidity.inactive;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const builder = state.builders.getReadonly(builderIndex);
|
|
91
|
-
|
|
92
|
-
// Verify the builder is active
|
|
93
|
-
if (!isActiveBuilder(builder, state.finalizedCheckpoint.epoch)) {
|
|
94
|
-
return builder.withdrawableEpoch !== FAR_FUTURE_EPOCH
|
|
95
|
-
? VoluntaryExitValidity.alreadyExited
|
|
96
|
-
: VoluntaryExitValidity.inactive;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Only exit builder if it has no pending withdrawals in the queue
|
|
100
|
-
if (getPendingBalanceToWithdrawForBuilder(state, builderIndex) !== 0) {
|
|
101
|
-
return VoluntaryExitValidity.pendingWithdrawals;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Verify signature
|
|
105
|
-
if (
|
|
106
|
-
verifySignature &&
|
|
107
|
-
!verifyVoluntaryExitSignature(config, epochCtx.pubkeyCache, new BeaconStateView(state), signedVoluntaryExit)
|
|
108
|
-
) {
|
|
109
|
-
return VoluntaryExitValidity.invalidSignature;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return VoluntaryExitValidity.valid;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
56
|
function getValidatorVoluntaryExitValidity(
|
|
116
57
|
fork: ForkSeq,
|
|
117
58
|
state: CachedBeaconStateAllForks,
|