@lodestar/state-transition 1.39.1 → 1.40.0-dev.1020f27ca9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/block/index.d.ts +1 -0
- package/lib/block/index.d.ts.map +1 -1
- package/lib/block/index.js +1 -0
- package/lib/block/index.js.map +1 -1
- package/lib/block/isValidIndexedAttestation.d.ts +4 -5
- package/lib/block/isValidIndexedAttestation.d.ts.map +1 -1
- package/lib/block/isValidIndexedAttestation.js +9 -10
- package/lib/block/isValidIndexedAttestation.js.map +1 -1
- package/lib/block/isValidIndexedPayloadAttestation.d.ts.map +1 -1
- package/lib/block/isValidIndexedPayloadAttestation.js +1 -1
- package/lib/block/isValidIndexedPayloadAttestation.js.map +1 -1
- package/lib/block/processAttestationPhase0.d.ts.map +1 -1
- package/lib/block/processAttestationPhase0.js +1 -1
- package/lib/block/processAttestationPhase0.js.map +1 -1
- package/lib/block/processAttestationsAltair.d.ts.map +1 -1
- package/lib/block/processAttestationsAltair.js +2 -2
- package/lib/block/processAttestationsAltair.js.map +1 -1
- package/lib/block/processAttesterSlashing.d.ts +3 -2
- package/lib/block/processAttesterSlashing.d.ts.map +1 -1
- package/lib/block/processAttesterSlashing.js +3 -3
- package/lib/block/processAttesterSlashing.js.map +1 -1
- package/lib/block/processBlsToExecutionChange.d.ts +3 -1
- package/lib/block/processBlsToExecutionChange.d.ts.map +1 -1
- package/lib/block/processBlsToExecutionChange.js +7 -11
- package/lib/block/processBlsToExecutionChange.js.map +1 -1
- package/lib/block/processConsolidationRequest.d.ts +1 -2
- package/lib/block/processConsolidationRequest.d.ts.map +1 -1
- package/lib/block/processConsolidationRequest.js +2 -2
- package/lib/block/processConsolidationRequest.js.map +1 -1
- package/lib/block/processDepositRequest.d.ts +8 -2
- package/lib/block/processDepositRequest.d.ts.map +1 -1
- package/lib/block/processDepositRequest.js +81 -8
- package/lib/block/processDepositRequest.js.map +1 -1
- package/lib/block/processExecutionPayloadBid.d.ts.map +1 -1
- package/lib/block/processExecutionPayloadBid.js +16 -29
- package/lib/block/processExecutionPayloadBid.js.map +1 -1
- package/lib/block/processExecutionPayloadEnvelope.d.ts.map +1 -1
- package/lib/block/processExecutionPayloadEnvelope.js +26 -25
- package/lib/block/processExecutionPayloadEnvelope.js.map +1 -1
- package/lib/block/processOperations.js +2 -2
- package/lib/block/processOperations.js.map +1 -1
- package/lib/block/processProposerSlashing.d.ts +5 -2
- package/lib/block/processProposerSlashing.d.ts.map +1 -1
- package/lib/block/processProposerSlashing.js +8 -6
- package/lib/block/processProposerSlashing.js.map +1 -1
- package/lib/block/processSyncCommittee.d.ts +1 -2
- package/lib/block/processSyncCommittee.d.ts.map +1 -1
- package/lib/block/processSyncCommittee.js +5 -5
- package/lib/block/processSyncCommittee.js.map +1 -1
- package/lib/block/processVoluntaryExit.d.ts +1 -1
- package/lib/block/processVoluntaryExit.d.ts.map +1 -1
- package/lib/block/processVoluntaryExit.js +45 -3
- package/lib/block/processVoluntaryExit.js.map +1 -1
- package/lib/block/processWithdrawalRequest.js +1 -1
- package/lib/block/processWithdrawalRequest.js.map +1 -1
- package/lib/block/processWithdrawals.d.ts +1 -0
- package/lib/block/processWithdrawals.d.ts.map +1 -1
- package/lib/block/processWithdrawals.js +121 -66
- package/lib/block/processWithdrawals.js.map +1 -1
- package/lib/cache/epochCache.d.ts +8 -28
- package/lib/cache/epochCache.d.ts.map +1 -1
- package/lib/cache/epochCache.js +40 -180
- package/lib/cache/epochCache.js.map +1 -1
- package/lib/cache/epochTransitionCache.d.ts +5 -12
- package/lib/cache/epochTransitionCache.d.ts.map +1 -1
- package/lib/cache/epochTransitionCache.js +4 -14
- package/lib/cache/epochTransitionCache.js.map +1 -1
- package/lib/cache/stateCache.d.ts.map +1 -1
- package/lib/cache/stateCache.js +1 -2
- package/lib/cache/stateCache.js.map +1 -1
- package/lib/epoch/processBuilderPendingPayments.d.ts.map +1 -1
- package/lib/epoch/processBuilderPendingPayments.js +1 -4
- package/lib/epoch/processBuilderPendingPayments.js.map +1 -1
- package/lib/epoch/processProposerLookahead.d.ts.map +1 -1
- package/lib/epoch/processProposerLookahead.js +3 -6
- package/lib/epoch/processProposerLookahead.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/rewards/blockRewards.d.ts +2 -1
- package/lib/rewards/blockRewards.d.ts.map +1 -1
- package/lib/rewards/blockRewards.js +3 -2
- package/lib/rewards/blockRewards.js.map +1 -1
- package/lib/rewards/syncCommitteeRewards.d.ts.map +1 -1
- package/lib/rewards/syncCommitteeRewards.js +10 -11
- package/lib/rewards/syncCommitteeRewards.js.map +1 -1
- package/lib/signatureSets/attesterSlashings.d.ts +3 -4
- package/lib/signatureSets/attesterSlashings.d.ts.map +1 -1
- package/lib/signatureSets/attesterSlashings.js +6 -6
- package/lib/signatureSets/attesterSlashings.js.map +1 -1
- package/lib/signatureSets/blsToExecutionChange.d.ts +4 -5
- package/lib/signatureSets/blsToExecutionChange.d.ts.map +1 -1
- package/lib/signatureSets/blsToExecutionChange.js +2 -2
- package/lib/signatureSets/blsToExecutionChange.js.map +1 -1
- package/lib/signatureSets/executionPayloadBid.d.ts +4 -0
- package/lib/signatureSets/executionPayloadBid.d.ts.map +1 -0
- package/lib/signatureSets/executionPayloadBid.js +8 -0
- package/lib/signatureSets/executionPayloadBid.js.map +1 -0
- package/lib/signatureSets/executionPayloadEnvelope.d.ts +4 -0
- package/lib/signatureSets/executionPayloadEnvelope.d.ts.map +1 -0
- package/lib/signatureSets/executionPayloadEnvelope.js +8 -0
- package/lib/signatureSets/executionPayloadEnvelope.js.map +1 -0
- package/lib/signatureSets/index.d.ts +3 -2
- package/lib/signatureSets/index.d.ts.map +1 -1
- package/lib/signatureSets/index.js +10 -8
- package/lib/signatureSets/index.js.map +1 -1
- package/lib/signatureSets/indexedAttestation.d.ts +3 -4
- package/lib/signatureSets/indexedAttestation.d.ts.map +1 -1
- package/lib/signatureSets/indexedAttestation.js +6 -6
- package/lib/signatureSets/indexedAttestation.js.map +1 -1
- package/lib/signatureSets/indexedPayloadAttestation.d.ts +5 -4
- package/lib/signatureSets/indexedPayloadAttestation.d.ts.map +1 -1
- package/lib/signatureSets/indexedPayloadAttestation.js +3 -3
- package/lib/signatureSets/indexedPayloadAttestation.js.map +1 -1
- package/lib/signatureSets/proposer.d.ts +3 -3
- package/lib/signatureSets/proposer.d.ts.map +1 -1
- package/lib/signatureSets/proposer.js +12 -12
- package/lib/signatureSets/proposer.js.map +1 -1
- package/lib/signatureSets/proposerSlashings.d.ts +2 -3
- package/lib/signatureSets/proposerSlashings.d.ts.map +1 -1
- package/lib/signatureSets/proposerSlashings.js +6 -6
- package/lib/signatureSets/proposerSlashings.js.map +1 -1
- package/lib/signatureSets/randao.d.ts +1 -1
- package/lib/signatureSets/randao.d.ts.map +1 -1
- package/lib/signatureSets/randao.js +4 -4
- package/lib/signatureSets/randao.js.map +1 -1
- package/lib/signatureSets/voluntaryExits.d.ts +2 -2
- package/lib/signatureSets/voluntaryExits.d.ts.map +1 -1
- package/lib/signatureSets/voluntaryExits.js +6 -6
- package/lib/signatureSets/voluntaryExits.js.map +1 -1
- package/lib/types.d.ts +1 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/util/electra.d.ts.map +1 -1
- package/lib/util/electra.js +1 -2
- package/lib/util/electra.js.map +1 -1
- package/lib/util/epochShuffling.d.ts +1 -34
- package/lib/util/epochShuffling.d.ts.map +1 -1
- package/lib/util/epochShuffling.js +1 -1
- package/lib/util/epochShuffling.js.map +1 -1
- package/lib/util/gloas.d.ts +46 -5
- package/lib/util/gloas.d.ts.map +1 -1
- package/lib/util/gloas.js +91 -5
- package/lib/util/gloas.js.map +1 -1
- package/lib/util/index.d.ts +2 -2
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +2 -2
- package/lib/util/index.js.map +1 -1
- package/lib/util/interop.js +1 -1
- package/lib/util/interop.js.map +1 -1
- package/lib/util/shuffling.d.ts +58 -0
- package/lib/util/shuffling.d.ts.map +1 -0
- package/lib/util/shuffling.js +175 -0
- package/lib/util/shuffling.js.map +1 -0
- package/lib/util/signatureSets.d.ts +38 -5
- package/lib/util/signatureSets.d.ts.map +1 -1
- package/lib/util/signatureSets.js +48 -6
- package/lib/util/signatureSets.js.map +1 -1
- package/lib/util/validator.d.ts +6 -1
- package/lib/util/validator.d.ts.map +1 -1
- package/lib/util/validator.js +26 -16
- package/lib/util/validator.js.map +1 -1
- package/package.json +8 -8
- package/src/block/index.ts +1 -0
- package/src/block/isValidIndexedAttestation.ts +18 -12
- package/src/block/isValidIndexedPayloadAttestation.ts +4 -1
- package/src/block/processAttestationPhase0.ts +2 -1
- package/src/block/processAttestationsAltair.ts +2 -8
- package/src/block/processAttesterSlashing.ts +16 -4
- package/src/block/processBlsToExecutionChange.ts +13 -14
- package/src/block/processConsolidationRequest.ts +2 -3
- package/src/block/processDepositRequest.ts +101 -8
- package/src/block/processExecutionPayloadBid.ts +20 -42
- package/src/block/processExecutionPayloadEnvelope.ts +34 -30
- package/src/block/processOperations.ts +2 -2
- package/src/block/processProposerSlashing.ts +22 -12
- package/src/block/processSyncCommittee.ts +3 -6
- package/src/block/processVoluntaryExit.ts +60 -5
- package/src/block/processWithdrawalRequest.ts +1 -1
- package/src/block/processWithdrawals.ts +168 -70
- package/src/cache/epochCache.ts +52 -214
- package/src/cache/epochTransitionCache.ts +9 -34
- package/src/cache/stateCache.ts +1 -2
- package/src/epoch/processBuilderPendingPayments.ts +1 -5
- package/src/epoch/processProposerLookahead.ts +3 -7
- package/src/index.ts +0 -2
- package/src/rewards/blockRewards.ts +6 -3
- package/src/rewards/syncCommitteeRewards.ts +10 -13
- package/src/signatureSets/attesterSlashings.ts +3 -7
- package/src/signatureSets/blsToExecutionChange.ts +5 -6
- package/src/signatureSets/executionPayloadBid.ts +14 -0
- package/src/signatureSets/executionPayloadEnvelope.ts +13 -0
- package/src/signatureSets/index.ts +8 -9
- package/src/signatureSets/indexedAttestation.ts +2 -7
- package/src/signatureSets/indexedPayloadAttestation.ts +9 -7
- package/src/signatureSets/proposer.ts +8 -12
- package/src/signatureSets/proposerSlashings.ts +4 -7
- package/src/signatureSets/randao.ts +4 -8
- package/src/signatureSets/voluntaryExits.ts +5 -10
- package/src/types.ts +1 -0
- package/src/util/electra.ts +1 -4
- package/src/util/epochShuffling.ts +2 -43
- package/src/util/gloas.ts +116 -10
- package/src/util/index.ts +2 -2
- package/src/util/interop.ts +1 -1
- package/src/util/shuffling.ts +234 -0
- package/src/util/signatureSets.ts +84 -8
- package/src/util/validator.ts +31 -16
- package/lib/util/calculateCommitteeAssignments.d.ts +0 -12
- package/lib/util/calculateCommitteeAssignments.d.ts.map +0 -1
- package/lib/util/calculateCommitteeAssignments.js +0 -26
- package/lib/util/calculateCommitteeAssignments.js.map +0 -1
- package/lib/util/shufflingDecisionRoot.d.ts +0 -20
- package/lib/util/shufflingDecisionRoot.d.ts.map +0 -1
- package/lib/util/shufflingDecisionRoot.js +0 -76
- package/lib/util/shufflingDecisionRoot.js.map +0 -1
- package/src/util/calculateCommitteeAssignments.ts +0 -43
- package/src/util/shufflingDecisionRoot.ts +0 -81
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.
|
|
14
|
+
"version": "1.40.0-dev.1020f27ca9",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -62,14 +62,14 @@
|
|
|
62
62
|
"@chainsafe/pubkey-index-map": "^3.0.0",
|
|
63
63
|
"@chainsafe/ssz": "^1.2.2",
|
|
64
64
|
"@chainsafe/swap-or-not-shuffle": "^1.2.1",
|
|
65
|
-
"@lodestar/config": "^1.
|
|
66
|
-
"@lodestar/params": "^1.
|
|
67
|
-
"@lodestar/types": "^1.
|
|
68
|
-
"@lodestar/utils": "^1.
|
|
69
|
-
"bigint-
|
|
65
|
+
"@lodestar/config": "^1.40.0-dev.1020f27ca9",
|
|
66
|
+
"@lodestar/params": "^1.40.0-dev.1020f27ca9",
|
|
67
|
+
"@lodestar/types": "^1.40.0-dev.1020f27ca9",
|
|
68
|
+
"@lodestar/utils": "^1.40.0-dev.1020f27ca9",
|
|
69
|
+
"@vekexasia/bigint-buffer2": "^1.0.4"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@lodestar/api": "^1.
|
|
72
|
+
"@lodestar/api": "^1.40.0-dev.1020f27ca9"
|
|
73
73
|
},
|
|
74
74
|
"keywords": [
|
|
75
75
|
"ethereum",
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"beacon",
|
|
78
78
|
"blockchain"
|
|
79
79
|
],
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "48125446bbfccfe4301299cece757d92692a1a2a"
|
|
81
81
|
}
|
package/src/block/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ export {
|
|
|
38
38
|
export * from "./externalData.js";
|
|
39
39
|
export * from "./initiateValidatorExit.js";
|
|
40
40
|
export * from "./isValidIndexedAttestation.js";
|
|
41
|
+
export * from "./processDepositRequest.js";
|
|
41
42
|
export * from "./processOperations.js";
|
|
42
43
|
|
|
43
44
|
export function processBlock(
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import {BeaconConfig} from "@lodestar/config";
|
|
2
2
|
import {ForkSeq, MAX_COMMITTEES_PER_SLOT, MAX_VALIDATORS_PER_COMMITTEE} from "@lodestar/params";
|
|
3
|
-
import {IndexedAttestation, IndexedAttestationBigint} from "@lodestar/types";
|
|
3
|
+
import {IndexedAttestation, IndexedAttestationBigint, Slot} from "@lodestar/types";
|
|
4
4
|
import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
|
|
5
5
|
import {getIndexedAttestationBigintSignatureSet, getIndexedAttestationSignatureSet} from "../signatureSets/index.js";
|
|
6
|
-
import {CachedBeaconStateAllForks} from "../types.js";
|
|
7
6
|
import {verifySignatureSet} from "../util/index.js";
|
|
8
7
|
|
|
9
8
|
/**
|
|
@@ -12,16 +11,17 @@ import {verifySignatureSet} from "../util/index.js";
|
|
|
12
11
|
export function isValidIndexedAttestation(
|
|
13
12
|
config: BeaconConfig,
|
|
14
13
|
index2pubkey: Index2PubkeyCache,
|
|
15
|
-
|
|
14
|
+
stateSlot: Slot,
|
|
15
|
+
validatorsLen: number,
|
|
16
16
|
indexedAttestation: IndexedAttestation,
|
|
17
17
|
verifySignature: boolean
|
|
18
18
|
): boolean {
|
|
19
|
-
if (!isValidIndexedAttestationIndices(
|
|
19
|
+
if (!isValidIndexedAttestationIndices(config, stateSlot, validatorsLen, indexedAttestation.attestingIndices)) {
|
|
20
20
|
return false;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
if (verifySignature) {
|
|
24
|
-
return verifySignatureSet(getIndexedAttestationSignatureSet(config,
|
|
24
|
+
return verifySignatureSet(getIndexedAttestationSignatureSet(config, stateSlot, indexedAttestation), index2pubkey);
|
|
25
25
|
}
|
|
26
26
|
return true;
|
|
27
27
|
}
|
|
@@ -29,17 +29,19 @@ export function isValidIndexedAttestation(
|
|
|
29
29
|
export function isValidIndexedAttestationBigint(
|
|
30
30
|
config: BeaconConfig,
|
|
31
31
|
index2pubkey: Index2PubkeyCache,
|
|
32
|
-
|
|
32
|
+
stateSlot: Slot,
|
|
33
|
+
validatorsLen: number,
|
|
33
34
|
indexedAttestation: IndexedAttestationBigint,
|
|
34
35
|
verifySignature: boolean
|
|
35
36
|
): boolean {
|
|
36
|
-
if (!isValidIndexedAttestationIndices(
|
|
37
|
+
if (!isValidIndexedAttestationIndices(config, stateSlot, validatorsLen, indexedAttestation.attestingIndices)) {
|
|
37
38
|
return false;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
if (verifySignature) {
|
|
41
42
|
return verifySignatureSet(
|
|
42
|
-
getIndexedAttestationBigintSignatureSet(config,
|
|
43
|
+
getIndexedAttestationBigintSignatureSet(config, stateSlot, indexedAttestation),
|
|
44
|
+
index2pubkey
|
|
43
45
|
);
|
|
44
46
|
}
|
|
45
47
|
return true;
|
|
@@ -48,10 +50,15 @@ export function isValidIndexedAttestationBigint(
|
|
|
48
50
|
/**
|
|
49
51
|
* Check if `indexedAttestation` has sorted and unique indices and a valid aggregate signature.
|
|
50
52
|
*/
|
|
51
|
-
export function isValidIndexedAttestationIndices(
|
|
53
|
+
export function isValidIndexedAttestationIndices(
|
|
54
|
+
config: BeaconConfig,
|
|
55
|
+
stateSlot: Slot,
|
|
56
|
+
validatorsLen: number,
|
|
57
|
+
indices: number[]
|
|
58
|
+
): boolean {
|
|
52
59
|
// verify max number of indices
|
|
53
60
|
const maxIndices =
|
|
54
|
-
|
|
61
|
+
config.getForkSeq(stateSlot) >= ForkSeq.electra
|
|
55
62
|
? MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT
|
|
56
63
|
: MAX_VALIDATORS_PER_COMMITTEE;
|
|
57
64
|
if (!(indices.length > 0 && indices.length <= maxIndices)) {
|
|
@@ -68,9 +75,8 @@ export function isValidIndexedAttestationIndices(state: CachedBeaconStateAllFork
|
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
// check if indices are out of bounds, by checking the highest index (since it is sorted)
|
|
71
|
-
// TODO - SLOW CODE - Does this .length check the tree and is expensive?
|
|
72
78
|
const lastIndex = indices.at(-1);
|
|
73
|
-
if (lastIndex && lastIndex >=
|
|
79
|
+
if (lastIndex && lastIndex >= validatorsLen) {
|
|
74
80
|
return false;
|
|
75
81
|
}
|
|
76
82
|
|
|
@@ -16,7 +16,10 @@ export function isValidIndexedPayloadAttestation(
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
if (verifySignature) {
|
|
19
|
-
return verifySignatureSet(
|
|
19
|
+
return verifySignatureSet(
|
|
20
|
+
getIndexedPayloadAttestationSignatureSet(state, indexedPayloadAttestation),
|
|
21
|
+
state.epochCtx.index2pubkey
|
|
22
|
+
);
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
return true;
|
|
@@ -64,14 +64,8 @@ export function processAttestationsAltair(
|
|
|
64
64
|
// TODO: Why should we verify an indexed attestation that we just created? If it's just for the signature
|
|
65
65
|
// we can verify only that and nothing else.
|
|
66
66
|
if (verifySignature) {
|
|
67
|
-
const sigSet = getAttestationWithIndicesSignatureSet(
|
|
68
|
-
|
|
69
|
-
epochCtx.index2pubkey,
|
|
70
|
-
state.slot,
|
|
71
|
-
attestation,
|
|
72
|
-
attestingIndices
|
|
73
|
-
);
|
|
74
|
-
if (!verifySignatureSet(sigSet)) {
|
|
67
|
+
const sigSet = getAttestationWithIndicesSignatureSet(state.config, state.slot, attestation, attestingIndices);
|
|
68
|
+
if (!verifySignatureSet(sigSet, state.epochCtx.index2pubkey)) {
|
|
75
69
|
throw new Error("Attestation signature is not valid");
|
|
76
70
|
}
|
|
77
71
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
1
2
|
import {ForkSeq} from "@lodestar/params";
|
|
2
|
-
import {AttesterSlashing} from "@lodestar/types";
|
|
3
|
+
import {AttesterSlashing, Slot} from "@lodestar/types";
|
|
3
4
|
import {Index2PubkeyCache} from "../cache/pubkeyCache.js";
|
|
4
5
|
import {CachedBeaconStateAllForks} from "../types.js";
|
|
5
6
|
import {getAttesterSlashableIndices, isSlashableAttestationData, isSlashableValidator} from "../util/index.js";
|
|
@@ -19,7 +20,14 @@ export function processAttesterSlashing(
|
|
|
19
20
|
verifySignatures = true
|
|
20
21
|
): void {
|
|
21
22
|
const {epochCtx} = state;
|
|
22
|
-
assertValidAttesterSlashing(
|
|
23
|
+
assertValidAttesterSlashing(
|
|
24
|
+
state.config,
|
|
25
|
+
epochCtx.index2pubkey,
|
|
26
|
+
state.slot,
|
|
27
|
+
state.validators.length,
|
|
28
|
+
attesterSlashing,
|
|
29
|
+
verifySignatures
|
|
30
|
+
);
|
|
23
31
|
|
|
24
32
|
const intersectingIndices = getAttesterSlashableIndices(attesterSlashing);
|
|
25
33
|
|
|
@@ -39,8 +47,10 @@ export function processAttesterSlashing(
|
|
|
39
47
|
}
|
|
40
48
|
|
|
41
49
|
export function assertValidAttesterSlashing(
|
|
50
|
+
config: BeaconConfig,
|
|
42
51
|
index2pubkey: Index2PubkeyCache,
|
|
43
|
-
|
|
52
|
+
stateSlot: Slot,
|
|
53
|
+
validatorsLen: number,
|
|
44
54
|
attesterSlashing: AttesterSlashing,
|
|
45
55
|
verifySignatures = true
|
|
46
56
|
): void {
|
|
@@ -55,7 +65,9 @@ export function assertValidAttesterSlashing(
|
|
|
55
65
|
// be higher than the clock and the slashing would still be valid. Same applies to attestation data index, which
|
|
56
66
|
// can be any arbitrary value. Must use bigint variants to hash correctly to all possible values
|
|
57
67
|
for (const [i, attestation] of [attestation1, attestation2].entries()) {
|
|
58
|
-
if (
|
|
68
|
+
if (
|
|
69
|
+
!isValidIndexedAttestationBigint(config, index2pubkey, stateSlot, validatorsLen, attestation, verifySignatures)
|
|
70
|
+
) {
|
|
59
71
|
throw new Error(`AttesterSlashing attestation${i} is invalid`);
|
|
60
72
|
}
|
|
61
73
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {digest} from "@chainsafe/as-sha256";
|
|
2
2
|
import {byteArrayEquals} from "@chainsafe/ssz";
|
|
3
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
3
4
|
import {BLS_WITHDRAWAL_PREFIX, ETH1_ADDRESS_WITHDRAWAL_PREFIX} from "@lodestar/params";
|
|
4
5
|
import {capella} from "@lodestar/types";
|
|
6
|
+
import {Validator} from "@lodestar/types/phase0";
|
|
5
7
|
import {toHex} from "@lodestar/utils";
|
|
6
8
|
import {verifyBlsToExecutionChangeSignature} from "../signatureSets/index.js";
|
|
7
9
|
import {CachedBeaconStateCapella} from "../types.js";
|
|
@@ -12,12 +14,18 @@ export function processBlsToExecutionChange(
|
|
|
12
14
|
): void {
|
|
13
15
|
const addressChange = signedBlsToExecutionChange.message;
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
if (addressChange.validatorIndex >= state.validators.length) {
|
|
18
|
+
throw Error(
|
|
19
|
+
`withdrawalValidatorIndex ${addressChange.validatorIndex} >= state.validators len ${state.validators.length}`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const validator = state.validators.get(addressChange.validatorIndex);
|
|
24
|
+
const validation = isValidBlsToExecutionChange(state.config, validator, signedBlsToExecutionChange, true);
|
|
16
25
|
if (!validation.valid) {
|
|
17
26
|
throw validation.error;
|
|
18
27
|
}
|
|
19
28
|
|
|
20
|
-
const validator = state.validators.get(addressChange.validatorIndex);
|
|
21
29
|
const newWithdrawalCredentials = new Uint8Array(32);
|
|
22
30
|
newWithdrawalCredentials[0] = ETH1_ADDRESS_WITHDRAWAL_PREFIX;
|
|
23
31
|
newWithdrawalCredentials.set(addressChange.toExecutionAddress, 12);
|
|
@@ -27,22 +35,13 @@ export function processBlsToExecutionChange(
|
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
export function isValidBlsToExecutionChange(
|
|
30
|
-
|
|
38
|
+
config: BeaconConfig,
|
|
39
|
+
validator: Validator,
|
|
31
40
|
signedBLSToExecutionChange: capella.SignedBLSToExecutionChange,
|
|
32
41
|
verifySignature = true
|
|
33
42
|
): {valid: true} | {valid: false; error: Error} {
|
|
34
43
|
const addressChange = signedBLSToExecutionChange.message;
|
|
35
44
|
|
|
36
|
-
if (addressChange.validatorIndex >= state.validators.length) {
|
|
37
|
-
return {
|
|
38
|
-
valid: false,
|
|
39
|
-
error: Error(
|
|
40
|
-
`withdrawalValidatorIndex ${addressChange.validatorIndex} > state.validators len ${state.validators.length}`
|
|
41
|
-
),
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const validator = state.validators.getReadonly(addressChange.validatorIndex);
|
|
46
45
|
const {withdrawalCredentials} = validator;
|
|
47
46
|
if (withdrawalCredentials[0] !== BLS_WITHDRAWAL_PREFIX) {
|
|
48
47
|
return {
|
|
@@ -65,7 +64,7 @@ export function isValidBlsToExecutionChange(
|
|
|
65
64
|
};
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
if (verifySignature && !verifyBlsToExecutionChangeSignature(
|
|
67
|
+
if (verifySignature && !verifyBlsToExecutionChangeSignature(config, signedBLSToExecutionChange)) {
|
|
69
68
|
return {
|
|
70
69
|
valid: false,
|
|
71
70
|
error: Error(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {FAR_FUTURE_EPOCH,
|
|
1
|
+
import {FAR_FUTURE_EPOCH, MIN_ACTIVATION_BALANCE, PENDING_CONSOLIDATIONS_LIMIT} from "@lodestar/params";
|
|
2
2
|
import {electra, ssz} from "@lodestar/types";
|
|
3
3
|
import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
4
4
|
import {hasEth1WithdrawalCredential} from "../util/capella.js";
|
|
@@ -13,7 +13,6 @@ import {getConsolidationChurnLimit, getPendingBalanceToWithdraw, isActiveValidat
|
|
|
13
13
|
|
|
14
14
|
// TODO Electra: Clean up necessary as there is a lot of overlap with isValidSwitchToCompoundRequest
|
|
15
15
|
export function processConsolidationRequest(
|
|
16
|
-
fork: ForkSeq,
|
|
17
16
|
state: CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
18
17
|
consolidationRequest: electra.ConsolidationRequest
|
|
19
18
|
): void {
|
|
@@ -83,7 +82,7 @@ export function processConsolidationRequest(
|
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
// Verify the source has no pending withdrawals in the queue
|
|
86
|
-
if (getPendingBalanceToWithdraw(
|
|
85
|
+
if (getPendingBalanceToWithdraw(state, sourceIndex) > 0) {
|
|
87
86
|
return;
|
|
88
87
|
}
|
|
89
88
|
|
|
@@ -1,21 +1,114 @@
|
|
|
1
|
-
import {UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
|
|
2
|
-
import {electra, ssz} from "@lodestar/types";
|
|
1
|
+
import {FAR_FUTURE_EPOCH, ForkSeq, UNSET_DEPOSIT_REQUESTS_START_INDEX} from "@lodestar/params";
|
|
2
|
+
import {BLSPubkey, Bytes32, UintNum64, electra, ssz} from "@lodestar/types";
|
|
3
3
|
import {CachedBeaconStateElectra, CachedBeaconStateGloas} from "../types.js";
|
|
4
|
+
import {findBuilderIndexByPubkey, isBuilderWithdrawalCredential} from "../util/gloas.js";
|
|
5
|
+
import {computeEpochAtSlot, isValidatorKnown} from "../util/index.js";
|
|
6
|
+
import {isValidDepositSignature} from "./processDeposit.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Apply a deposit for a builder. Either increases balance for existing builder or adds new builder to registry.
|
|
10
|
+
* Spec: https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.1/specs/gloas/beacon-chain.md#new-apply_deposit_for_builder
|
|
11
|
+
*/
|
|
12
|
+
export function applyDepositForBuilder(
|
|
13
|
+
state: CachedBeaconStateGloas,
|
|
14
|
+
pubkey: BLSPubkey,
|
|
15
|
+
withdrawalCredentials: Bytes32,
|
|
16
|
+
amount: UintNum64,
|
|
17
|
+
signature: Bytes32
|
|
18
|
+
): void {
|
|
19
|
+
const builderIndex = findBuilderIndexByPubkey(state, pubkey);
|
|
20
|
+
|
|
21
|
+
if (builderIndex !== null) {
|
|
22
|
+
// Existing builder - increase balance
|
|
23
|
+
const builder = state.builders.get(builderIndex);
|
|
24
|
+
builder.balance += amount;
|
|
25
|
+
} else {
|
|
26
|
+
// New builder - verify signature and add to registry
|
|
27
|
+
if (isValidDepositSignature(state.config, pubkey, withdrawalCredentials, amount, signature)) {
|
|
28
|
+
addBuilderToRegistry(state, pubkey, withdrawalCredentials, amount);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Add a new builder to the builders registry.
|
|
35
|
+
* Reuses slots from exited and fully withdrawn builders if available.
|
|
36
|
+
*/
|
|
37
|
+
function addBuilderToRegistry(
|
|
38
|
+
state: CachedBeaconStateGloas,
|
|
39
|
+
pubkey: BLSPubkey,
|
|
40
|
+
withdrawalCredentials: Bytes32,
|
|
41
|
+
amount: UintNum64
|
|
42
|
+
): void {
|
|
43
|
+
const currentEpoch = computeEpochAtSlot(state.slot);
|
|
44
|
+
|
|
45
|
+
// Try to find a reusable slot from an exited builder with zero balance
|
|
46
|
+
let builderIndex = state.builders.length;
|
|
47
|
+
for (let i = 0; i < state.builders.length; i++) {
|
|
48
|
+
const builder = state.builders.getReadonly(i);
|
|
49
|
+
if (builder.withdrawableEpoch <= currentEpoch && builder.balance === 0) {
|
|
50
|
+
builderIndex = i;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Create new builder
|
|
56
|
+
const newBuilder = ssz.gloas.Builder.toViewDU({
|
|
57
|
+
pubkey,
|
|
58
|
+
version: withdrawalCredentials[0],
|
|
59
|
+
executionAddress: withdrawalCredentials.subarray(12),
|
|
60
|
+
balance: amount,
|
|
61
|
+
depositEpoch: currentEpoch,
|
|
62
|
+
withdrawableEpoch: FAR_FUTURE_EPOCH,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (builderIndex < state.builders.length) {
|
|
66
|
+
// Reuse existing slot
|
|
67
|
+
state.builders.set(builderIndex, newBuilder);
|
|
68
|
+
} else {
|
|
69
|
+
// Append to end
|
|
70
|
+
state.builders.push(newBuilder);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
4
73
|
|
|
5
74
|
export function processDepositRequest(
|
|
75
|
+
fork: ForkSeq,
|
|
6
76
|
state: CachedBeaconStateElectra | CachedBeaconStateGloas,
|
|
7
77
|
depositRequest: electra.DepositRequest
|
|
8
78
|
): void {
|
|
9
|
-
|
|
79
|
+
const {pubkey, withdrawalCredentials, amount, signature} = depositRequest;
|
|
80
|
+
|
|
81
|
+
// Check if this is a builder or validator deposit
|
|
82
|
+
if (fork >= ForkSeq.gloas) {
|
|
83
|
+
const stateGloas = state as CachedBeaconStateGloas;
|
|
84
|
+
const builderIndex = findBuilderIndexByPubkey(stateGloas, pubkey);
|
|
85
|
+
const validatorIndex = state.epochCtx.getValidatorIndex(pubkey);
|
|
86
|
+
|
|
87
|
+
// Regardless of the withdrawal credentials prefix, if a builder/validator
|
|
88
|
+
// already exists with this pubkey, apply the deposit to their balance
|
|
89
|
+
const isBuilder = builderIndex !== null;
|
|
90
|
+
const isValidator = isValidatorKnown(state, validatorIndex);
|
|
91
|
+
const isBuilderPrefix = isBuilderWithdrawalCredential(withdrawalCredentials);
|
|
92
|
+
|
|
93
|
+
// Route to builder if it's an existing builder OR has builder prefix and is not a validator
|
|
94
|
+
if (isBuilder || (isBuilderPrefix && !isValidator)) {
|
|
95
|
+
// Apply builder deposits immediately
|
|
96
|
+
applyDepositForBuilder(stateGloas, pubkey, withdrawalCredentials, amount, signature);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Only set deposit_requests_start_index in Electra fork, not Gloas
|
|
102
|
+
if (fork < ForkSeq.gloas && state.depositRequestsStartIndex === UNSET_DEPOSIT_REQUESTS_START_INDEX) {
|
|
10
103
|
state.depositRequestsStartIndex = depositRequest.index;
|
|
11
104
|
}
|
|
12
105
|
|
|
13
|
-
//
|
|
106
|
+
// Add validator deposits to the queue
|
|
14
107
|
const pendingDeposit = ssz.electra.PendingDeposit.toViewDU({
|
|
15
|
-
pubkey
|
|
16
|
-
withdrawalCredentials
|
|
17
|
-
amount
|
|
18
|
-
signature
|
|
108
|
+
pubkey,
|
|
109
|
+
withdrawalCredentials,
|
|
110
|
+
amount,
|
|
111
|
+
signature,
|
|
19
112
|
slot: state.slot,
|
|
20
113
|
});
|
|
21
114
|
state.pendingDeposits.push(pendingDeposit);
|
|
@@ -1,68 +1,48 @@
|
|
|
1
1
|
import {PublicKey, Signature, verify} from "@chainsafe/blst";
|
|
2
2
|
import {byteArrayEquals} from "@chainsafe/ssz";
|
|
3
|
-
import {
|
|
4
|
-
DOMAIN_BEACON_BUILDER,
|
|
5
|
-
FAR_FUTURE_EPOCH,
|
|
6
|
-
ForkPostGloas,
|
|
7
|
-
MIN_ACTIVATION_BALANCE,
|
|
8
|
-
SLOTS_PER_EPOCH,
|
|
9
|
-
} from "@lodestar/params";
|
|
3
|
+
import {BUILDER_INDEX_SELF_BUILD, ForkPostGloas, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
10
4
|
import {BeaconBlock, gloas, ssz} from "@lodestar/types";
|
|
11
5
|
import {toHex, toRootHex} from "@lodestar/utils";
|
|
12
6
|
import {G2_POINT_AT_INFINITY} from "../constants/constants.ts";
|
|
7
|
+
import {getExecutionPayloadBidSigningRoot} from "../signatureSets/executionPayloadBid.js";
|
|
13
8
|
import {CachedBeaconStateGloas} from "../types.ts";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
9
|
+
import {canBuilderCoverBid, isActiveBuilder} from "../util/gloas.ts";
|
|
10
|
+
import {getCurrentEpoch, getRandaoMix} from "../util/index.ts";
|
|
16
11
|
|
|
17
12
|
export function processExecutionPayloadBid(state: CachedBeaconStateGloas, block: BeaconBlock<ForkPostGloas>): void {
|
|
18
13
|
const signedBid = block.body.signedExecutionPayloadBid;
|
|
19
14
|
const bid = signedBid.message;
|
|
20
15
|
const {builderIndex, value: amount} = bid;
|
|
21
|
-
const builder = state.validators.getReadonly(builderIndex);
|
|
22
16
|
|
|
23
17
|
// For self-builds, amount must be zero regardless of withdrawal credential prefix
|
|
24
|
-
if (builderIndex ===
|
|
18
|
+
if (builderIndex === BUILDER_INDEX_SELF_BUILD) {
|
|
25
19
|
if (amount !== 0) {
|
|
26
20
|
throw Error(`Invalid execution payload bid: self-build with non-zero amount ${amount}`);
|
|
27
21
|
}
|
|
28
22
|
if (!byteArrayEquals(signedBid.signature, G2_POINT_AT_INFINITY)) {
|
|
29
23
|
throw Error("Invalid execution payload bid: self-build with non-zero signature");
|
|
30
24
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
}
|
|
26
|
+
// Non-self builds require active builder with valid signature
|
|
27
|
+
else {
|
|
28
|
+
const builder = state.builders.getReadonly(builderIndex);
|
|
29
|
+
|
|
30
|
+
// Verify that the builder is active
|
|
31
|
+
if (!isActiveBuilder(builder, state.finalizedCheckpoint.epoch)) {
|
|
32
|
+
throw Error(`Invalid execution payload bid: builder ${builderIndex} is not active`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Verify that the builder has funds to cover the bid
|
|
36
|
+
if (!canBuilderCoverBid(state, builderIndex, amount)) {
|
|
37
|
+
throw Error(`Invalid execution payload bid: builder ${builderIndex} has insufficient balance`);
|
|
35
38
|
}
|
|
36
39
|
|
|
40
|
+
// Verify that the bid signature is valid
|
|
37
41
|
if (!verifyExecutionPayloadBidSignature(state, builder.pubkey, signedBid)) {
|
|
38
42
|
throw Error(`Invalid execution payload bid: invalid signature for builder ${builderIndex}`);
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
|
|
42
|
-
if (!isActiveValidator(builder, getCurrentEpoch(state))) {
|
|
43
|
-
throw Error(`Invalid execution payload bid: builder ${builderIndex} is not active`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (builder.slashed) {
|
|
47
|
-
throw Error(`Invalid execution payload bid: builder ${builderIndex} is slashed`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const pendingPayments = state.builderPendingPayments
|
|
51
|
-
.getAllReadonly()
|
|
52
|
-
.filter((payment) => payment.withdrawal.builderIndex === builderIndex)
|
|
53
|
-
.reduce((acc, payment) => acc + payment.withdrawal.amount, 0);
|
|
54
|
-
const pendingWithdrawals = state.builderPendingWithdrawals
|
|
55
|
-
.getAllReadonly()
|
|
56
|
-
.filter((withdrawal) => withdrawal.builderIndex === builderIndex)
|
|
57
|
-
.reduce((acc, withdrawal) => acc + withdrawal.amount, 0);
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
amount !== 0 &&
|
|
61
|
-
state.balances.get(builderIndex) < amount + pendingPayments + pendingWithdrawals + MIN_ACTIVATION_BALANCE
|
|
62
|
-
) {
|
|
63
|
-
throw Error("Insufficient builder balance");
|
|
64
|
-
}
|
|
65
|
-
|
|
66
46
|
if (bid.slot !== block.slot) {
|
|
67
47
|
throw Error(`Bid slot ${bid.slot} does not match block slot ${block.slot}`);
|
|
68
48
|
}
|
|
@@ -91,7 +71,6 @@ export function processExecutionPayloadBid(state: CachedBeaconStateGloas, block:
|
|
|
91
71
|
feeRecipient: bid.feeRecipient,
|
|
92
72
|
amount,
|
|
93
73
|
builderIndex,
|
|
94
|
-
withdrawableEpoch: FAR_FUTURE_EPOCH,
|
|
95
74
|
}),
|
|
96
75
|
});
|
|
97
76
|
|
|
@@ -106,8 +85,7 @@ function verifyExecutionPayloadBidSignature(
|
|
|
106
85
|
pubkey: Uint8Array,
|
|
107
86
|
signedBid: gloas.SignedExecutionPayloadBid
|
|
108
87
|
): boolean {
|
|
109
|
-
const
|
|
110
|
-
const signingRoot = computeSigningRoot(ssz.gloas.ExecutionPayloadBid, signedBid.message, domain);
|
|
88
|
+
const signingRoot = getExecutionPayloadBidSigningRoot(state.config, state.slot, signedBid.message);
|
|
111
89
|
|
|
112
90
|
try {
|
|
113
91
|
const publicKey = PublicKey.fromBytes(pubkey);
|