@lodestar/state-transition 1.12.0-dev.f77b774be2 → 1.12.0-rc.1
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/processExecutionPayload.d.ts +1 -2
- package/lib/block/processExecutionPayload.js +1 -30
- package/lib/block/processExecutionPayload.js.map +1 -1
- package/lib/cache/epochCache.d.ts +7 -1
- package/lib/cache/epochCache.js +26 -12
- package/lib/cache/epochCache.js.map +1 -1
- package/lib/cache/pubkeyCache.js +1 -1
- package/lib/cache/stateCache.d.ts +7 -0
- package/lib/cache/stateCache.js +30 -2
- package/lib/cache/stateCache.js.map +1 -1
- package/lib/cache/types.d.ts +3 -1
- package/lib/epoch/processRegistryUpdates.js +1 -1
- package/lib/epoch/processRegistryUpdates.js.map +1 -1
- package/lib/index.d.ts +8 -9
- package/lib/index.js +1 -2
- package/lib/index.js.map +1 -1
- package/lib/stateTransition.js +1 -1
- package/lib/stateTransition.js.map +1 -1
- package/lib/types.d.ts +3 -3
- package/lib/util/blindedBlock.d.ts +19 -1
- package/lib/util/blindedBlock.js +84 -1
- package/lib/util/blindedBlock.js.map +1 -1
- package/lib/util/epochShuffling.d.ts +2 -1
- package/lib/util/epochShuffling.js +7 -0
- package/lib/util/epochShuffling.js.map +1 -1
- package/lib/util/execution.d.ts +2 -0
- package/lib/util/execution.js +29 -0
- package/lib/util/execution.js.map +1 -1
- package/lib/util/loadState/findModifiedInactivityScores.d.ts +8 -0
- package/lib/util/loadState/findModifiedInactivityScores.js +27 -0
- package/lib/util/loadState/findModifiedInactivityScores.js.map +1 -0
- package/lib/util/loadState/findModifiedValidators.d.ts +10 -0
- package/lib/util/loadState/findModifiedValidators.js +26 -0
- package/lib/util/loadState/findModifiedValidators.js.map +1 -0
- package/lib/util/loadState/loadState.d.ts +17 -0
- package/lib/util/loadState/loadState.js +145 -0
- package/lib/util/loadState/loadState.js.map +1 -0
- package/lib/util/loadState/loadValidator.d.ts +9 -0
- package/lib/util/loadState/loadValidator.js +35 -0
- package/lib/util/loadState/loadValidator.js.map +1 -0
- package/lib/util/sszBytes.d.ts +24 -0
- package/lib/util/sszBytes.js +44 -0
- package/lib/util/sszBytes.js.map +1 -0
- package/lib/util/validator.d.ts +2 -0
- package/lib/util/validator.js +9 -0
- package/lib/util/validator.js.map +1 -1
- package/package.json +9 -8
package/lib/util/blindedBlock.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ForkSeq } from "@lodestar/params";
|
|
2
|
+
import { ssz, isBlindedBeaconBlock, isBlindedBlobSidecar, isSignedBlindedBlockContents, isExecutionPayloadAndBlobsBundle, } from "@lodestar/types";
|
|
3
|
+
import { executionPayloadToPayloadHeader } from "./execution.js";
|
|
2
4
|
export function blindedOrFullBlockHashTreeRoot(config, blindedOrFull) {
|
|
3
5
|
return isBlindedBeaconBlock(blindedOrFull)
|
|
4
6
|
? // Blinded
|
|
@@ -27,4 +29,85 @@ export function blindedOrFullBlockToHeader(config, blindedOrFull) {
|
|
|
27
29
|
bodyRoot,
|
|
28
30
|
};
|
|
29
31
|
}
|
|
32
|
+
export function beaconBlockToBlinded(config, block) {
|
|
33
|
+
const fork = config.getForkName(block.slot);
|
|
34
|
+
const executionPayloadHeader = executionPayloadToPayloadHeader(ForkSeq[fork], block.body.executionPayload);
|
|
35
|
+
const blindedBlock = { ...block, body: { ...block.body, executionPayloadHeader } };
|
|
36
|
+
return blindedBlock;
|
|
37
|
+
}
|
|
38
|
+
export function blobSidecarsToBlinded(blobSidecars) {
|
|
39
|
+
return blobSidecars.map((blobSidecar) => {
|
|
40
|
+
const blobRoot = ssz.deneb.Blob.hashTreeRoot(blobSidecar.blob);
|
|
41
|
+
return { ...blobSidecar, blobRoot };
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
export function signedBlindedBlockToFull(signedBlindedBlock, executionPayload) {
|
|
45
|
+
const signedBlock = {
|
|
46
|
+
...signedBlindedBlock,
|
|
47
|
+
message: {
|
|
48
|
+
...signedBlindedBlock.message,
|
|
49
|
+
body: {
|
|
50
|
+
...signedBlindedBlock.message.body,
|
|
51
|
+
// state transition doesn't handle null value for executionPayload in pre-bellatrix blocks
|
|
52
|
+
executionPayload: executionPayload ?? undefined,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
// state transition can't seem to handle executionPayloadHeader presense in merge block
|
|
57
|
+
// so just delete the extra field we don't require
|
|
58
|
+
delete signedBlock.message.body
|
|
59
|
+
.executionPayloadHeader;
|
|
60
|
+
return signedBlock;
|
|
61
|
+
}
|
|
62
|
+
export function signedBlindedBlobSidecarsToFull(signedBlindedBlobSidecars, blobs) {
|
|
63
|
+
const signedBlobSidecars = signedBlindedBlobSidecars.map((signedBlindedBlobSidecar, index) => {
|
|
64
|
+
const signedBlobSidecar = {
|
|
65
|
+
...signedBlindedBlobSidecar,
|
|
66
|
+
message: { ...signedBlindedBlobSidecar.message, blob: blobs[index] },
|
|
67
|
+
};
|
|
68
|
+
delete signedBlobSidecar.message.blobRoot;
|
|
69
|
+
return signedBlobSidecar;
|
|
70
|
+
});
|
|
71
|
+
return signedBlobSidecars;
|
|
72
|
+
}
|
|
73
|
+
export function parseSignedBlindedBlockOrContents(signedBlindedBlockOrContents) {
|
|
74
|
+
if (isSignedBlindedBlockContents(signedBlindedBlockOrContents)) {
|
|
75
|
+
const signedBlindedBlock = signedBlindedBlockOrContents.signedBlindedBlock;
|
|
76
|
+
const signedBlindedBlobSidecars = signedBlindedBlockOrContents.signedBlindedBlobSidecars;
|
|
77
|
+
return { signedBlindedBlock, signedBlindedBlobSidecars };
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return { signedBlindedBlock: signedBlindedBlockOrContents, signedBlindedBlobSidecars: null };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function parseExecutionPayloadAndBlobsBundle(data) {
|
|
84
|
+
if (isExecutionPayloadAndBlobsBundle(data)) {
|
|
85
|
+
return data;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
return {
|
|
89
|
+
executionPayload: data,
|
|
90
|
+
blobsBundle: null,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export function reconstructFullBlockOrContents({ signedBlindedBlock, signedBlindedBlobSidecars }, { executionPayload, blobs }) {
|
|
95
|
+
const signedBlock = signedBlindedBlockToFull(signedBlindedBlock, executionPayload);
|
|
96
|
+
if (signedBlindedBlobSidecars !== null) {
|
|
97
|
+
if (executionPayload === null) {
|
|
98
|
+
throw Error("Missing locally produced executionPayload for deneb+ publishBlindedBlock");
|
|
99
|
+
}
|
|
100
|
+
if (blobs === null) {
|
|
101
|
+
throw Error("Missing blobs from the local execution cache");
|
|
102
|
+
}
|
|
103
|
+
if (blobs.length !== signedBlindedBlobSidecars.length) {
|
|
104
|
+
throw Error(`Length mismatch signedBlindedBlobSidecars=${signedBlindedBlobSidecars.length} blobs=${blobs.length}`);
|
|
105
|
+
}
|
|
106
|
+
const signedBlobSidecars = signedBlindedBlobSidecarsToFull(signedBlindedBlobSidecars, blobs);
|
|
107
|
+
return { signedBlock, signedBlobSidecars };
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
return signedBlock;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
30
113
|
//# sourceMappingURL=blindedBlock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blindedBlock.js","sourceRoot":"","sources":["../../src/util/blindedBlock.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"blindedBlock.js","sourceRoot":"","sources":["../../src/util/blindedBlock.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,OAAO,EAAC,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAKL,GAAG,EACH,oBAAoB,EACpB,oBAAoB,EACpB,4BAA4B,EAC5B,gCAAgC,GACjC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAC,+BAA+B,EAAC,MAAM,gBAAgB,CAAC;AAO/D,MAAM,UAAU,8BAA8B,CAC5C,MAAuB,EACvB,aAAgD;IAEhD,OAAO,oBAAoB,CAAC,aAAa,CAAC;QACxC,CAAC,CAAC,UAAU;YACV,MAAM,CAAC,mBAAmB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,aAAa,CAAC;QACxF,CAAC,CAAC,OAAO;YACP,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,oCAAoC,CAClD,MAAuB,EACvB,aAAgD;IAEhD,OAAO,oBAAoB,CAAC,aAAa,CAAC;QACxC,CAAC,CAAC,UAAU;YACV,MAAM,CAAC,iBAAiB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,kBAAkB,CAAC,YAAY,CAAC,aAAa,CAAC;QAC7F,CAAC,CAAC,OAAO;YACP,MAAM,CAAC,iBAAiB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,MAAuB,EACvB,aAAgD;IAEhD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,aAAa,CAAC;QAClD,CAAC,CAAC,UAAU;YACV,MAAM,CAAC,mBAAmB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC;QACjG,CAAC,CAAC,OAAO;YACP,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAE7F,OAAO;QACL,IAAI,EAAE,aAAa,CAAC,IAAI;QACxB,aAAa,EAAE,aAAa,CAAC,aAAa;QAC1C,UAAU,EAAE,aAAa,CAAC,UAAU;QACpC,SAAS,EAAE,aAAa,CAAC,SAAS;QAClC,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,MAAuB,EACvB,KAAgD;IAEhD,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,sBAAsB,GAAG,+BAA+B,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC3G,MAAM,YAAY,GAAG,EAAC,GAAG,KAAK,EAAE,IAAI,EAAE,EAAC,GAAG,KAAK,CAAC,IAAI,EAAE,sBAAsB,EAAC,EAAgC,CAAC;IAC9G,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,YAAgC;IACpE,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE;QACtC,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC/D,OAAO,EAAC,GAAG,WAAW,EAAE,QAAQ,EAA6B,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,kBAAqD,EACrD,gBAAkD;IAElD,MAAM,WAAW,GAAG;QAClB,GAAG,kBAAkB;QACrB,OAAO,EAAE;YACP,GAAG,kBAAkB,CAAC,OAAO;YAC7B,IAAI,EAAE;gBACJ,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI;gBAClC,0FAA0F;gBAC1F,gBAAgB,EAAE,gBAAgB,IAAI,SAAS;aAChD;SACF;KAC4B,CAAC;IAEhC,uFAAuF;IACvF,kDAAkD;IAClD,OAAQ,WAAW,CAAC,OAAO,CAAC,IAAmE;SAC5F,sBAAsB,CAAC;IAC1B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,yBAA0D,EAC1D,KAAkB;IAElB,MAAM,kBAAkB,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC,wBAAwB,EAAE,KAAK,EAAE,EAAE;QAC3F,MAAM,iBAAiB,GAAG;YACxB,GAAG,wBAAwB;YAC3B,OAAO,EAAE,EAAC,GAAG,wBAAwB,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,EAAC;SACnE,CAAC;QACF,OAAQ,iBAAiB,CAAC,OAA0C,CAAC,QAAQ,CAAC;QAC9E,OAAO,iBAAiB,CAAC;IAC3B,CAAC,CAAC,CAAC;IACH,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,iCAAiC,CAC/C,4BAAyE;IAEzE,IAAI,4BAA4B,CAAC,4BAA4B,CAAC,EAAE;QAC9D,MAAM,kBAAkB,GAAG,4BAA4B,CAAC,kBAAkB,CAAC;QAC3E,MAAM,yBAAyB,GAAG,4BAA4B,CAAC,yBAAyB,CAAC;QACzF,OAAO,EAAC,kBAAkB,EAAE,yBAAyB,EAAC,CAAC;KACxD;SAAM;QACL,OAAO,EAAC,kBAAkB,EAAE,4BAA4B,EAAE,yBAAyB,EAAE,IAAI,EAAC,CAAC;KAC5F;AACH,CAAC;AAED,MAAM,UAAU,mCAAmC,CACjD,IAAyE;IAEzE,IAAI,gCAAgC,CAAC,IAAI,CAAC,EAAE;QAC1C,OAAO,IAAI,CAAC;KACb;SAAM;QACL,OAAO;YACL,gBAAgB,EAAE,IAAI;YACtB,WAAW,EAAE,IAAI;SAClB,CAAC;KACH;AACH,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,EAAC,kBAAkB,EAAE,yBAAyB,EAAqC,EACnF,EAAC,gBAAgB,EAAE,KAAK,EAAkF;IAE1G,MAAM,WAAW,GAAG,wBAAwB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IAEnF,IAAI,yBAAyB,KAAK,IAAI,EAAE;QACtC,IAAI,gBAAgB,KAAK,IAAI,EAAE;YAC7B,MAAM,KAAK,CAAC,0EAA0E,CAAC,CAAC;SACzF;QAED,IAAI,KAAK,KAAK,IAAI,EAAE;YAClB,MAAM,KAAK,CAAC,8CAA8C,CAAC,CAAC;SAC7D;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,yBAAyB,CAAC,MAAM,EAAE;YACrD,MAAM,KAAK,CACT,6CAA6C,yBAAyB,CAAC,MAAM,UAAU,KAAK,CAAC,MAAM,EAAE,CACtG,CAAC;SACH;QACD,MAAM,kBAAkB,GAAG,+BAA+B,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAE7F,OAAO,EAAC,WAAW,EAAE,kBAAkB,EAAyC,CAAC;KAClF;SAAM;QACL,OAAO,WAAmD,CAAC;KAC5D;AACH,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Epoch, ValidatorIndex } from "@lodestar/types";
|
|
1
|
+
import { Epoch, RootHex, ValidatorIndex } from "@lodestar/types";
|
|
2
2
|
import { BeaconStateAllForks } from "../types.js";
|
|
3
3
|
/**
|
|
4
4
|
* Readonly interface for EpochShuffling.
|
|
@@ -36,4 +36,5 @@ export type EpochShuffling = {
|
|
|
36
36
|
};
|
|
37
37
|
export declare function computeCommitteeCount(activeValidatorCount: number): number;
|
|
38
38
|
export declare function computeEpochShuffling(state: BeaconStateAllForks, activeIndices: ValidatorIndex[], epoch: Epoch): EpochShuffling;
|
|
39
|
+
export declare function getShufflingDecisionBlock(state: BeaconStateAllForks, epoch: Epoch): RootHex;
|
|
39
40
|
//# sourceMappingURL=epochShuffling.d.ts.map
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { toHexString } from "@chainsafe/ssz";
|
|
1
2
|
import { intDiv } from "@lodestar/utils";
|
|
2
3
|
import { DOMAIN_BEACON_ATTESTER, MAX_COMMITTEES_PER_SLOT, SLOTS_PER_EPOCH, TARGET_COMMITTEE_SIZE, } from "@lodestar/params";
|
|
3
4
|
import { getSeed } from "./seed.js";
|
|
4
5
|
import { unshuffleList } from "./shuffle.js";
|
|
6
|
+
import { computeStartSlotAtEpoch } from "./epoch.js";
|
|
7
|
+
import { getBlockRootAtSlot } from "./blockRoot.js";
|
|
5
8
|
export function computeCommitteeCount(activeValidatorCount) {
|
|
6
9
|
const validatorsPerSlot = intDiv(activeValidatorCount, SLOTS_PER_EPOCH);
|
|
7
10
|
const committeesPerSlot = intDiv(validatorsPerSlot, TARGET_COMMITTEE_SIZE);
|
|
@@ -37,4 +40,8 @@ export function computeEpochShuffling(state, activeIndices, epoch) {
|
|
|
37
40
|
committeesPerSlot,
|
|
38
41
|
};
|
|
39
42
|
}
|
|
43
|
+
export function getShufflingDecisionBlock(state, epoch) {
|
|
44
|
+
const pivotSlot = computeStartSlotAtEpoch(epoch - 1) - 1;
|
|
45
|
+
return toHexString(getBlockRootAtSlot(state, pivotSlot));
|
|
46
|
+
}
|
|
40
47
|
//# sourceMappingURL=epochShuffling.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"epochShuffling.js","sourceRoot":"","sources":["../../src/util/epochShuffling.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"epochShuffling.js","sourceRoot":"","sources":["../../src/util/epochShuffling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAC,MAAM,EAAC,MAAM,iBAAiB,CAAC;AACvC,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,OAAO,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAC,uBAAuB,EAAC,MAAM,YAAY,CAAC;AACnD,OAAO,EAAC,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AA0ClD,MAAM,UAAU,qBAAqB,CAAC,oBAA4B;IAChE,MAAM,iBAAiB,GAAG,MAAM,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;IACxE,MAAM,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,CAAC;IAC3E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,uBAAuB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAA0B,EAC1B,aAA+B,EAC/B,KAAY;IAEZ,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,sBAAsB,CAAC,CAAC;IAE3D,OAAO;IACP,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC;IACxC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAE/B,MAAM,oBAAoB,GAAG,aAAa,CAAC,MAAM,CAAC;IAClD,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,oBAAoB,CAAC,CAAC;IAEtE,MAAM,cAAc,GAAG,iBAAiB,GAAG,eAAe,CAAC;IAE3D,MAAM,UAAU,GAAyB,EAAE,CAAC;IAC5C,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,eAAe,EAAE,IAAI,EAAE,EAAE;QACjD,MAAM,cAAc,GAAuB,EAAE,CAAC;QAC9C,KAAK,IAAI,cAAc,GAAG,CAAC,EAAE,cAAc,GAAG,iBAAiB,EAAE,cAAc,EAAE,EAAE;YACjF,MAAM,KAAK,GAAG,IAAI,GAAG,iBAAiB,GAAG,cAAc,CAAC;YACxD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,oBAAoB,GAAG,KAAK,CAAC,GAAG,cAAc,CAAC,CAAC;YAChF,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,oBAAoB,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC;YACpF,IAAI,CAAC,CAAC,WAAW,IAAI,SAAS,CAAC,EAAE;gBAC/B,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,mCAAmC,SAAS,EAAE,CAAC,CAAC;aACtG;YACD,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;SAC9D;QACD,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;KACjC;IAED,OAAO;QACL,KAAK;QACL,aAAa;QACb,SAAS;QACT,UAAU;QACV,iBAAiB;KAClB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAA0B,EAAE,KAAY;IAChF,MAAM,SAAS,GAAG,uBAAuB,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACzD,OAAO,WAAW,CAAC,kBAAkB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
package/lib/util/execution.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { allForks, bellatrix, capella } from "@lodestar/types";
|
|
2
|
+
import { ForkSeq } from "@lodestar/params";
|
|
2
3
|
import { BeaconStateCapella, BeaconStateAllForks, BeaconStateExecutions, CachedBeaconStateAllForks, CachedBeaconStateExecutions } from "../types.js";
|
|
3
4
|
/**
|
|
4
5
|
* Execution enabled = merge is done.
|
|
@@ -28,4 +29,5 @@ export declare function getFullOrBlindedPayloadFromBody(body: allForks.FullOrBli
|
|
|
28
29
|
export declare function isExecutionPayload(payload: allForks.FullOrBlindedExecutionPayload): payload is allForks.ExecutionPayload;
|
|
29
30
|
export declare function isCapellaPayload(payload: allForks.FullOrBlindedExecutionPayload): payload is capella.FullOrBlindedExecutionPayload;
|
|
30
31
|
export declare function isCapellaPayloadHeader(payload: capella.FullOrBlindedExecutionPayload): payload is capella.ExecutionPayloadHeader;
|
|
32
|
+
export declare function executionPayloadToPayloadHeader(fork: ForkSeq, payload: allForks.ExecutionPayload): allForks.ExecutionPayloadHeader;
|
|
31
33
|
//# sourceMappingURL=execution.d.ts.map
|
package/lib/util/execution.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isBlindedBeaconBlockBody, ssz } from "@lodestar/types";
|
|
2
|
+
import { ForkSeq } from "@lodestar/params";
|
|
2
3
|
/**
|
|
3
4
|
* Execution enabled = merge is done.
|
|
4
5
|
* When (A) state has execution data OR (B) block has execution data
|
|
@@ -85,4 +86,32 @@ export function isCapellaPayload(payload) {
|
|
|
85
86
|
export function isCapellaPayloadHeader(payload) {
|
|
86
87
|
return payload.withdrawalsRoot !== undefined;
|
|
87
88
|
}
|
|
89
|
+
export function executionPayloadToPayloadHeader(fork, payload) {
|
|
90
|
+
const transactionsRoot = ssz.bellatrix.Transactions.hashTreeRoot(payload.transactions);
|
|
91
|
+
const bellatrixPayloadFields = {
|
|
92
|
+
parentHash: payload.parentHash,
|
|
93
|
+
feeRecipient: payload.feeRecipient,
|
|
94
|
+
stateRoot: payload.stateRoot,
|
|
95
|
+
receiptsRoot: payload.receiptsRoot,
|
|
96
|
+
logsBloom: payload.logsBloom,
|
|
97
|
+
prevRandao: payload.prevRandao,
|
|
98
|
+
blockNumber: payload.blockNumber,
|
|
99
|
+
gasLimit: payload.gasLimit,
|
|
100
|
+
gasUsed: payload.gasUsed,
|
|
101
|
+
timestamp: payload.timestamp,
|
|
102
|
+
extraData: payload.extraData,
|
|
103
|
+
baseFeePerGas: payload.baseFeePerGas,
|
|
104
|
+
blockHash: payload.blockHash,
|
|
105
|
+
transactionsRoot,
|
|
106
|
+
};
|
|
107
|
+
if (fork >= ForkSeq.capella) {
|
|
108
|
+
bellatrixPayloadFields.withdrawalsRoot = ssz.capella.Withdrawals.hashTreeRoot(payload.withdrawals);
|
|
109
|
+
}
|
|
110
|
+
if (fork >= ForkSeq.deneb) {
|
|
111
|
+
// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/beacon-chain.md#process_execution_payload
|
|
112
|
+
bellatrixPayloadFields.blobGasUsed = payload.blobGasUsed;
|
|
113
|
+
bellatrixPayloadFields.excessBlobGas = payload.excessBlobGas;
|
|
114
|
+
}
|
|
115
|
+
return bellatrixPayloadFields;
|
|
116
|
+
}
|
|
88
117
|
//# sourceMappingURL=execution.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/util/execution.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/util/execution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const INACTIVITY_SCORE_SIZE = 8;
|
|
2
|
+
/**
|
|
3
|
+
* As monitored on mainnet, inactivityScores are not changed much and they are mostly 0
|
|
4
|
+
* Using Buffer.compare is the fastest way as noted in `./findModifiedValidators.ts`
|
|
5
|
+
* @returns output parameter modifiedValidators: validator indices that are modified
|
|
6
|
+
*/
|
|
7
|
+
export declare function findModifiedInactivityScores(inactivityScoresBytes: Uint8Array, inactivityScoresBytes2: Uint8Array, modifiedValidators: number[], validatorOffset?: number): void;
|
|
8
|
+
//# sourceMappingURL=findModifiedInactivityScores.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// UintNum64 = 8 bytes
|
|
2
|
+
export const INACTIVITY_SCORE_SIZE = 8;
|
|
3
|
+
/**
|
|
4
|
+
* As monitored on mainnet, inactivityScores are not changed much and they are mostly 0
|
|
5
|
+
* Using Buffer.compare is the fastest way as noted in `./findModifiedValidators.ts`
|
|
6
|
+
* @returns output parameter modifiedValidators: validator indices that are modified
|
|
7
|
+
*/
|
|
8
|
+
export function findModifiedInactivityScores(inactivityScoresBytes, inactivityScoresBytes2, modifiedValidators, validatorOffset = 0) {
|
|
9
|
+
if (inactivityScoresBytes.length !== inactivityScoresBytes2.length) {
|
|
10
|
+
throw new Error("inactivityScoresBytes.length !== inactivityScoresBytes2.length " +
|
|
11
|
+
inactivityScoresBytes.length +
|
|
12
|
+
" vs " +
|
|
13
|
+
inactivityScoresBytes2.length);
|
|
14
|
+
}
|
|
15
|
+
if (Buffer.compare(inactivityScoresBytes, inactivityScoresBytes2) === 0) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (inactivityScoresBytes.length === INACTIVITY_SCORE_SIZE) {
|
|
19
|
+
modifiedValidators.push(validatorOffset);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const numValidator = Math.floor(inactivityScoresBytes.length / INACTIVITY_SCORE_SIZE);
|
|
23
|
+
const halfValidator = Math.floor(numValidator / 2);
|
|
24
|
+
findModifiedInactivityScores(inactivityScoresBytes.subarray(0, halfValidator * INACTIVITY_SCORE_SIZE), inactivityScoresBytes2.subarray(0, halfValidator * INACTIVITY_SCORE_SIZE), modifiedValidators, validatorOffset);
|
|
25
|
+
findModifiedInactivityScores(inactivityScoresBytes.subarray(halfValidator * INACTIVITY_SCORE_SIZE), inactivityScoresBytes2.subarray(halfValidator * INACTIVITY_SCORE_SIZE), modifiedValidators, validatorOffset + halfValidator);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=findModifiedInactivityScores.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findModifiedInactivityScores.js","sourceRoot":"","sources":["../../../src/util/loadState/findModifiedInactivityScores.ts"],"names":[],"mappings":"AAAA,sBAAsB;AACtB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAC1C,qBAAiC,EACjC,sBAAkC,EAClC,kBAA4B,EAC5B,eAAe,GAAG,CAAC;IAEnB,IAAI,qBAAqB,CAAC,MAAM,KAAK,sBAAsB,CAAC,MAAM,EAAE;QAClE,MAAM,IAAI,KAAK,CACb,iEAAiE;YAC/D,qBAAqB,CAAC,MAAM;YAC5B,MAAM;YACN,sBAAsB,CAAC,MAAM,CAChC,CAAC;KACH;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,sBAAsB,CAAC,KAAK,CAAC,EAAE;QACvE,OAAO;KACR;IAED,IAAI,qBAAqB,CAAC,MAAM,KAAK,qBAAqB,EAAE;QAC1D,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACzC,OAAO;KACR;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,MAAM,GAAG,qBAAqB,CAAC,CAAC;IACtF,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;IACnD,4BAA4B,CAC1B,qBAAqB,CAAC,QAAQ,CAAC,CAAC,EAAE,aAAa,GAAG,qBAAqB,CAAC,EACxE,sBAAsB,CAAC,QAAQ,CAAC,CAAC,EAAE,aAAa,GAAG,qBAAqB,CAAC,EACzE,kBAAkB,EAClB,eAAe,CAChB,CAAC;IACF,4BAA4B,CAC1B,qBAAqB,CAAC,QAAQ,CAAC,aAAa,GAAG,qBAAqB,CAAC,EACrE,sBAAsB,CAAC,QAAQ,CAAC,aAAa,GAAG,qBAAqB,CAAC,EACtE,kBAAkB,EAClB,eAAe,GAAG,aAAa,CAChC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find modified validators by comparing two validators bytes using Buffer.compare() recursively
|
|
3
|
+
* - As noted in packages/state-transition/test/perf/util/loadState/findModifiedValidators.test.ts, serializing validators and compare Uint8Array is the fastest way
|
|
4
|
+
* - The performance is quite stable and can afford a lot of difference in validators (the benchmark tested up to 10k but it's not likely we have that difference in mainnet)
|
|
5
|
+
* - Also packages/state-transition/test/perf/misc/byteArrayEquals.test.ts shows that Buffer.compare() is very efficient for large Uint8Array
|
|
6
|
+
*
|
|
7
|
+
* @returns output parameter modifiedValidators: validator indices that are modified
|
|
8
|
+
*/
|
|
9
|
+
export declare function findModifiedValidators(validatorsBytes: Uint8Array, validatorsBytes2: Uint8Array, modifiedValidators: number[], validatorOffset?: number): void;
|
|
10
|
+
//# sourceMappingURL=findModifiedValidators.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { VALIDATOR_BYTES_SIZE } from "../sszBytes.js";
|
|
2
|
+
/**
|
|
3
|
+
* Find modified validators by comparing two validators bytes using Buffer.compare() recursively
|
|
4
|
+
* - As noted in packages/state-transition/test/perf/util/loadState/findModifiedValidators.test.ts, serializing validators and compare Uint8Array is the fastest way
|
|
5
|
+
* - The performance is quite stable and can afford a lot of difference in validators (the benchmark tested up to 10k but it's not likely we have that difference in mainnet)
|
|
6
|
+
* - Also packages/state-transition/test/perf/misc/byteArrayEquals.test.ts shows that Buffer.compare() is very efficient for large Uint8Array
|
|
7
|
+
*
|
|
8
|
+
* @returns output parameter modifiedValidators: validator indices that are modified
|
|
9
|
+
*/
|
|
10
|
+
export function findModifiedValidators(validatorsBytes, validatorsBytes2, modifiedValidators, validatorOffset = 0) {
|
|
11
|
+
if (validatorsBytes.length !== validatorsBytes2.length) {
|
|
12
|
+
throw new Error("validatorsBytes.length !== validatorsBytes2.length " + validatorsBytes.length + " vs " + validatorsBytes2.length);
|
|
13
|
+
}
|
|
14
|
+
if (Buffer.compare(validatorsBytes, validatorsBytes2) === 0) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (validatorsBytes.length === VALIDATOR_BYTES_SIZE) {
|
|
18
|
+
modifiedValidators.push(validatorOffset);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const numValidator = Math.floor(validatorsBytes.length / VALIDATOR_BYTES_SIZE);
|
|
22
|
+
const halfValidator = Math.floor(numValidator / 2);
|
|
23
|
+
findModifiedValidators(validatorsBytes.subarray(0, halfValidator * VALIDATOR_BYTES_SIZE), validatorsBytes2.subarray(0, halfValidator * VALIDATOR_BYTES_SIZE), modifiedValidators, validatorOffset);
|
|
24
|
+
findModifiedValidators(validatorsBytes.subarray(halfValidator * VALIDATOR_BYTES_SIZE), validatorsBytes2.subarray(halfValidator * VALIDATOR_BYTES_SIZE), modifiedValidators, validatorOffset + halfValidator);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=findModifiedValidators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findModifiedValidators.js","sourceRoot":"","sources":["../../../src/util/loadState/findModifiedValidators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,gBAAgB,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,eAA2B,EAC3B,gBAA4B,EAC5B,kBAA4B,EAC5B,eAAe,GAAG,CAAC;IAEnB,IAAI,eAAe,CAAC,MAAM,KAAK,gBAAgB,CAAC,MAAM,EAAE;QACtD,MAAM,IAAI,KAAK,CACb,qDAAqD,GAAG,eAAe,CAAC,MAAM,GAAG,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAClH,CAAC;KACH;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE;QAC3D,OAAO;KACR;IAED,IAAI,eAAe,CAAC,MAAM,KAAK,oBAAoB,EAAE;QACnD,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACzC,OAAO;KACR;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,GAAG,oBAAoB,CAAC,CAAC;IAC/E,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;IACnD,sBAAsB,CACpB,eAAe,CAAC,QAAQ,CAAC,CAAC,EAAE,aAAa,GAAG,oBAAoB,CAAC,EACjE,gBAAgB,CAAC,QAAQ,CAAC,CAAC,EAAE,aAAa,GAAG,oBAAoB,CAAC,EAClE,kBAAkB,EAClB,eAAe,CAChB,CAAC;IACF,sBAAsB,CACpB,eAAe,CAAC,QAAQ,CAAC,aAAa,GAAG,oBAAoB,CAAC,EAC9D,gBAAgB,CAAC,QAAQ,CAAC,aAAa,GAAG,oBAAoB,CAAC,EAC/D,kBAAkB,EAClB,eAAe,GAAG,aAAa,CAChC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ChainForkConfig } from "@lodestar/config";
|
|
2
|
+
import { BeaconStateAllForks } from "../../types.js";
|
|
3
|
+
type MigrateStateOutput = {
|
|
4
|
+
state: BeaconStateAllForks;
|
|
5
|
+
modifiedValidators: number[];
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Load state from bytes given a seed state so that we share the same base tree. This gives some benefits:
|
|
9
|
+
* - Have single base tree across the application
|
|
10
|
+
* - Faster to load state
|
|
11
|
+
* - Less memory usage
|
|
12
|
+
* - Utilize the cached HashObjects in seed state due to a lot of validators are not changed, also the inactivity scores.
|
|
13
|
+
* @returns the new state and modified validators
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadState(config: ChainForkConfig, seedState: BeaconStateAllForks, stateBytes: Uint8Array): MigrateStateOutput;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=loadState.d.ts.map
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { deserializeContainerIgnoreFields, ssz } from "@lodestar/types";
|
|
2
|
+
import { ForkSeq } from "@lodestar/params";
|
|
3
|
+
import { VALIDATOR_BYTES_SIZE, getForkFromStateBytes, getStateTypeFromBytes } from "../sszBytes.js";
|
|
4
|
+
import { findModifiedValidators } from "./findModifiedValidators.js";
|
|
5
|
+
import { findModifiedInactivityScores } from "./findModifiedInactivityScores.js";
|
|
6
|
+
import { loadValidator } from "./loadValidator.js";
|
|
7
|
+
/**
|
|
8
|
+
* Load state from bytes given a seed state so that we share the same base tree. This gives some benefits:
|
|
9
|
+
* - Have single base tree across the application
|
|
10
|
+
* - Faster to load state
|
|
11
|
+
* - Less memory usage
|
|
12
|
+
* - Utilize the cached HashObjects in seed state due to a lot of validators are not changed, also the inactivity scores.
|
|
13
|
+
* @returns the new state and modified validators
|
|
14
|
+
*/
|
|
15
|
+
export function loadState(config, seedState, stateBytes) {
|
|
16
|
+
// casting only to make typescript happy
|
|
17
|
+
const stateType = getStateTypeFromBytes(config, stateBytes);
|
|
18
|
+
const dataView = new DataView(stateBytes.buffer, stateBytes.byteOffset, stateBytes.byteLength);
|
|
19
|
+
const fieldRanges = stateType.getFieldRanges(dataView, 0, stateBytes.length);
|
|
20
|
+
const allFields = Object.keys(stateType.fields);
|
|
21
|
+
const validatorsFieldIndex = allFields.indexOf("validators");
|
|
22
|
+
// start with default view has the same performance to start with seed state
|
|
23
|
+
// and it is not fork dependent
|
|
24
|
+
const migratedState = deserializeContainerIgnoreFields(stateType, stateBytes, ["validators", "inactivityScores"], fieldRanges);
|
|
25
|
+
// validators are rarely changed
|
|
26
|
+
const validatorsRange = fieldRanges[validatorsFieldIndex];
|
|
27
|
+
const modifiedValidators = loadValidators(migratedState, seedState, stateBytes.subarray(validatorsRange.start, validatorsRange.end));
|
|
28
|
+
// inactivityScores are rarely changed
|
|
29
|
+
// this saves ~500ms of hashTreeRoot() time of state
|
|
30
|
+
const fork = getForkFromStateBytes(config, stateBytes);
|
|
31
|
+
const seedFork = config.getForkSeq(seedState.slot);
|
|
32
|
+
if (fork >= ForkSeq.altair && seedFork >= ForkSeq.altair) {
|
|
33
|
+
const inactivityScoresIndex = allFields.indexOf("inactivityScores");
|
|
34
|
+
const inactivityScoresRange = fieldRanges[inactivityScoresIndex];
|
|
35
|
+
loadInactivityScores(migratedState, seedState, stateBytes.subarray(inactivityScoresRange.start, inactivityScoresRange.end));
|
|
36
|
+
}
|
|
37
|
+
migratedState.commit();
|
|
38
|
+
return { state: migratedState, modifiedValidators };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* This value is rarely changed as monitored 3 month state diffs on mainnet as of Sep 2023.
|
|
42
|
+
* Reusing this data helps save hashTreeRoot time of state ~500ms
|
|
43
|
+
*
|
|
44
|
+
* Given the below tree:
|
|
45
|
+
*
|
|
46
|
+
* seedState.inactivityScores ====> ROOT
|
|
47
|
+
* / \
|
|
48
|
+
* Hash01 Hash23
|
|
49
|
+
* / \ / \
|
|
50
|
+
* Sco0 Sco1 Sco2 Sco3
|
|
51
|
+
*
|
|
52
|
+
* if score 3 is modified, the new tree looks like this:
|
|
53
|
+
*
|
|
54
|
+
* migratedState.inactivityScores ====> ROOTa
|
|
55
|
+
* / \
|
|
56
|
+
* Hash01 Hash23a
|
|
57
|
+
* / \ / \
|
|
58
|
+
* Sco0 Sco1 Sco2 Sco3a
|
|
59
|
+
*/
|
|
60
|
+
function loadInactivityScores(migratedState, seedState, inactivityScoresBytes) {
|
|
61
|
+
// migratedState starts with the same inactivityScores to seed state
|
|
62
|
+
migratedState.inactivityScores = seedState.inactivityScores.clone();
|
|
63
|
+
const oldValidator = migratedState.inactivityScores.length;
|
|
64
|
+
// UintNum64 = 8 bytes
|
|
65
|
+
const newValidator = inactivityScoresBytes.length / 8;
|
|
66
|
+
const minValidator = Math.min(oldValidator, newValidator);
|
|
67
|
+
const oldInactivityScores = migratedState.inactivityScores.serialize();
|
|
68
|
+
const isMoreValidator = newValidator >= oldValidator;
|
|
69
|
+
const modifiedValidators = [];
|
|
70
|
+
findModifiedInactivityScores(isMoreValidator ? oldInactivityScores : oldInactivityScores.subarray(0, minValidator * 8), isMoreValidator ? inactivityScoresBytes.subarray(0, minValidator * 8) : inactivityScoresBytes, modifiedValidators);
|
|
71
|
+
for (const validatorIndex of modifiedValidators) {
|
|
72
|
+
migratedState.inactivityScores.set(validatorIndex, ssz.UintNum64.deserialize(inactivityScoresBytes.subarray(validatorIndex * 8, (validatorIndex + 1) * 8)));
|
|
73
|
+
}
|
|
74
|
+
if (isMoreValidator) {
|
|
75
|
+
// add new inactivityScores
|
|
76
|
+
for (let validatorIndex = oldValidator; validatorIndex < newValidator; validatorIndex++) {
|
|
77
|
+
migratedState.inactivityScores.push(ssz.UintNum64.deserialize(inactivityScoresBytes.subarray(validatorIndex * 8, (validatorIndex + 1) * 8)));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
if (newValidator - 1 < 0) {
|
|
82
|
+
migratedState.inactivityScores = ssz.altair.InactivityScores.defaultViewDU();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
migratedState.inactivityScores = migratedState.inactivityScores.sliceTo(newValidator - 1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* As of Sep 2021, common validators of 2 mainnet states are rarely changed. However, the benchmark shows that
|
|
91
|
+
* 10k modified validators is not an issue. (see packages/state-transition/test/perf/util/loadState/findModifiedValidators.test.ts)
|
|
92
|
+
*
|
|
93
|
+
* This method loads validators from bytes given a seed state so that they share the same base tree. This gives some benefits:
|
|
94
|
+
* - Have single base tree across the application
|
|
95
|
+
* - Faster to load state
|
|
96
|
+
* - Less memory usage
|
|
97
|
+
* - Utilize the cached HashObjects in seed state due to a lot of validators are not changed
|
|
98
|
+
*
|
|
99
|
+
* Given the below tree:
|
|
100
|
+
*
|
|
101
|
+
* seedState.validators ====> ROOT
|
|
102
|
+
* / \
|
|
103
|
+
* Hash01 Hash23
|
|
104
|
+
* / \ / \
|
|
105
|
+
* Val0 Val1 Val2 Val3
|
|
106
|
+
*
|
|
107
|
+
* if validator 3 is modified, the new tree looks like this:
|
|
108
|
+
*
|
|
109
|
+
* migratedState.validators ====> ROOTa
|
|
110
|
+
* / \
|
|
111
|
+
* Hash01 Hash23a
|
|
112
|
+
* / \ / \
|
|
113
|
+
* Val0 Val1 Val2 Val3a
|
|
114
|
+
*
|
|
115
|
+
* @param migratedState state to be migrated, the validators are loaded to this state
|
|
116
|
+
* @returns modified validator indices
|
|
117
|
+
*/
|
|
118
|
+
function loadValidators(migratedState, seedState, newValidatorsBytes) {
|
|
119
|
+
const seedValidatorCount = seedState.validators.length;
|
|
120
|
+
const newValidatorCount = Math.floor(newValidatorsBytes.length / VALIDATOR_BYTES_SIZE);
|
|
121
|
+
const isMoreValidator = newValidatorCount >= seedValidatorCount;
|
|
122
|
+
const minValidatorCount = Math.min(seedValidatorCount, newValidatorCount);
|
|
123
|
+
// migrated state starts with the same validators to seed state
|
|
124
|
+
migratedState.validators = seedState.validators.clone();
|
|
125
|
+
const seedValidatorsBytes = seedState.validators.serialize();
|
|
126
|
+
const modifiedValidators = [];
|
|
127
|
+
findModifiedValidators(isMoreValidator ? seedValidatorsBytes : seedValidatorsBytes.subarray(0, minValidatorCount * VALIDATOR_BYTES_SIZE), isMoreValidator ? newValidatorsBytes.subarray(0, minValidatorCount * VALIDATOR_BYTES_SIZE) : newValidatorsBytes, modifiedValidators);
|
|
128
|
+
for (const i of modifiedValidators) {
|
|
129
|
+
const seedValidator = seedState.validators.get(i);
|
|
130
|
+
const newValidatorBytes = newValidatorsBytes.subarray(i * VALIDATOR_BYTES_SIZE, (i + 1) * VALIDATOR_BYTES_SIZE);
|
|
131
|
+
migratedState.validators.set(i, loadValidator(seedValidator, newValidatorBytes));
|
|
132
|
+
}
|
|
133
|
+
if (newValidatorCount >= seedValidatorCount) {
|
|
134
|
+
// add new validators
|
|
135
|
+
for (let validatorIndex = seedValidatorCount; validatorIndex < newValidatorCount; validatorIndex++) {
|
|
136
|
+
migratedState.validators.push(ssz.phase0.Validator.deserializeToViewDU(newValidatorsBytes.subarray(validatorIndex * VALIDATOR_BYTES_SIZE, (validatorIndex + 1) * VALIDATOR_BYTES_SIZE)));
|
|
137
|
+
modifiedValidators.push(validatorIndex);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
migratedState.validators = migratedState.validators.sliceTo(newValidatorCount - 1);
|
|
142
|
+
}
|
|
143
|
+
return modifiedValidators;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=loadState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadState.js","sourceRoot":"","sources":["../../../src/util/loadState/loadState.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CompositeViewDU } from "@chainsafe/ssz";
|
|
2
|
+
import { ssz } from "@lodestar/types";
|
|
3
|
+
/**
|
|
4
|
+
* Load validator from bytes given a seed validator.
|
|
5
|
+
* - Reuse pubkey and withdrawal credentials if possible to save memory
|
|
6
|
+
* - If it's a new validator, deserialize it
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadValidator(seedValidator: CompositeViewDU<typeof ssz.phase0.Validator>, newValidatorBytes: Uint8Array): CompositeViewDU<typeof ssz.phase0.Validator>;
|
|
9
|
+
//# sourceMappingURL=loadValidator.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { deserializeContainerIgnoreFields, ssz } from "@lodestar/types";
|
|
2
|
+
/**
|
|
3
|
+
* Load validator from bytes given a seed validator.
|
|
4
|
+
* - Reuse pubkey and withdrawal credentials if possible to save memory
|
|
5
|
+
* - If it's a new validator, deserialize it
|
|
6
|
+
*/
|
|
7
|
+
export function loadValidator(seedValidator, newValidatorBytes) {
|
|
8
|
+
const ignoredFields = getSameFields(seedValidator, newValidatorBytes);
|
|
9
|
+
if (ignoredFields.length > 0) {
|
|
10
|
+
const newValidatorValue = deserializeContainerIgnoreFields(ssz.phase0.Validator, newValidatorBytes, ignoredFields);
|
|
11
|
+
for (const field of ignoredFields) {
|
|
12
|
+
newValidatorValue[field] = seedValidator[field];
|
|
13
|
+
}
|
|
14
|
+
return ssz.phase0.Validator.toViewDU(newValidatorValue);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return ssz.phase0.Validator.deserializeToViewDU(newValidatorBytes);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Return pubkey or withdrawalCredentials or both if they are the same.
|
|
22
|
+
*/
|
|
23
|
+
function getSameFields(validator, validatorBytes) {
|
|
24
|
+
const ignoredFields = [];
|
|
25
|
+
const pubkey = validatorBytes.subarray(0, 48);
|
|
26
|
+
if (Buffer.compare(pubkey, validator.pubkey) === 0) {
|
|
27
|
+
ignoredFields.push("pubkey");
|
|
28
|
+
}
|
|
29
|
+
const withdrawalCredentials = validatorBytes.subarray(48, 80);
|
|
30
|
+
if (Buffer.compare(withdrawalCredentials, validator.withdrawalCredentials) === 0) {
|
|
31
|
+
ignoredFields.push("withdrawalCredentials");
|
|
32
|
+
}
|
|
33
|
+
return ignoredFields;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=loadValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadValidator.js","sourceRoot":"","sources":["../../../src/util/loadState/loadValidator.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,gCAAgC,EAAE,GAAG,EAAC,MAAM,iBAAiB,CAAC;AAEtE;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,aAA2D,EAC3D,iBAA6B;IAE7B,MAAM,aAAa,GAAG,aAAa,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IACtE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE;QAC5B,MAAM,iBAAiB,GAAG,gCAAgC,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,iBAAiB,EAAE,aAAa,CAAC,CAAC;QACnH,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE;YACjC,iBAAiB,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;SACjD;QACD,OAAO,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;KACzD;SAAM;QACL,OAAO,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;KACpE;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CACpB,SAAuD,EACvD,cAA0B;IAE1B,MAAM,aAAa,GAA2C,EAAE,CAAC;IACjE,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9C,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QAClD,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;KAC9B;IAED,MAAM,qBAAqB,GAAG,cAAc,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,SAAS,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE;QAChF,aAAa,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;KAC7C;IAED,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ChainForkConfig } from "@lodestar/config";
|
|
3
|
+
import { ForkSeq } from "@lodestar/params";
|
|
4
|
+
import { Slot, allForks } from "@lodestar/types";
|
|
5
|
+
/**
|
|
6
|
+
* 48 + 32 + 8 + 1 + 8 + 8 + 8 + 8 = 121
|
|
7
|
+
* ```
|
|
8
|
+
* class Validator(Container):
|
|
9
|
+
pubkey: BLSPubkey [fixed - 48 bytes]
|
|
10
|
+
withdrawal_credentials: Bytes32 [fixed - 32 bytes]
|
|
11
|
+
effective_balance: Gwei [fixed - 8 bytes]
|
|
12
|
+
slashed: boolean [fixed - 1 byte]
|
|
13
|
+
# Status epochs
|
|
14
|
+
activation_eligibility_epoch: Epoch [fixed - 8 bytes]
|
|
15
|
+
activation_epoch: Epoch [fixed - 8 bytes]
|
|
16
|
+
exit_epoch: Epoch [fixed - 8 bytes]
|
|
17
|
+
withdrawable_epoch: Epoch [fixed - 8 bytes]
|
|
18
|
+
```
|
|
19
|
+
*/
|
|
20
|
+
export declare const VALIDATOR_BYTES_SIZE = 121;
|
|
21
|
+
export declare function getForkFromStateBytes(config: ChainForkConfig, bytes: Buffer | Uint8Array): ForkSeq;
|
|
22
|
+
export declare function getStateTypeFromBytes(config: ChainForkConfig, bytes: Buffer | Uint8Array): allForks.AllForksSSZTypes["BeaconState"];
|
|
23
|
+
export declare function getStateSlotFromBytes(bytes: Uint8Array): Slot;
|
|
24
|
+
//# sourceMappingURL=sszBytes.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { bytesToInt } from "@lodestar/utils";
|
|
2
|
+
/**
|
|
3
|
+
* Slot uint64
|
|
4
|
+
*/
|
|
5
|
+
const SLOT_BYTE_COUNT = 8;
|
|
6
|
+
/**
|
|
7
|
+
* 48 + 32 + 8 + 1 + 8 + 8 + 8 + 8 = 121
|
|
8
|
+
* ```
|
|
9
|
+
* class Validator(Container):
|
|
10
|
+
pubkey: BLSPubkey [fixed - 48 bytes]
|
|
11
|
+
withdrawal_credentials: Bytes32 [fixed - 32 bytes]
|
|
12
|
+
effective_balance: Gwei [fixed - 8 bytes]
|
|
13
|
+
slashed: boolean [fixed - 1 byte]
|
|
14
|
+
# Status epochs
|
|
15
|
+
activation_eligibility_epoch: Epoch [fixed - 8 bytes]
|
|
16
|
+
activation_epoch: Epoch [fixed - 8 bytes]
|
|
17
|
+
exit_epoch: Epoch [fixed - 8 bytes]
|
|
18
|
+
withdrawable_epoch: Epoch [fixed - 8 bytes]
|
|
19
|
+
```
|
|
20
|
+
*/
|
|
21
|
+
export const VALIDATOR_BYTES_SIZE = 121;
|
|
22
|
+
/**
|
|
23
|
+
* 8 + 32 = 40
|
|
24
|
+
* ```
|
|
25
|
+
* class BeaconState(Container):
|
|
26
|
+
* genesis_time: uint64 [fixed - 8 bytes]
|
|
27
|
+
* genesis_validators_root: Root [fixed - 32 bytes]
|
|
28
|
+
* slot: Slot [fixed - 8 bytes]
|
|
29
|
+
* ...
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
const SLOT_BYTES_POSITION_IN_STATE = 40;
|
|
33
|
+
export function getForkFromStateBytes(config, bytes) {
|
|
34
|
+
const slot = bytesToInt(bytes.subarray(SLOT_BYTES_POSITION_IN_STATE, SLOT_BYTES_POSITION_IN_STATE + SLOT_BYTE_COUNT));
|
|
35
|
+
return config.getForkSeq(slot);
|
|
36
|
+
}
|
|
37
|
+
export function getStateTypeFromBytes(config, bytes) {
|
|
38
|
+
const slot = getStateSlotFromBytes(bytes);
|
|
39
|
+
return config.getForkTypes(slot).BeaconState;
|
|
40
|
+
}
|
|
41
|
+
export function getStateSlotFromBytes(bytes) {
|
|
42
|
+
return bytesToInt(bytes.subarray(SLOT_BYTES_POSITION_IN_STATE, SLOT_BYTES_POSITION_IN_STATE + SLOT_BYTE_COUNT));
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=sszBytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sszBytes.js","sourceRoot":"","sources":["../../src/util/sszBytes.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAE3C;;GAEG;AACH,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAExC;;;;;;;;;GASG;AACH,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAExC,MAAM,UAAU,qBAAqB,CAAC,MAAuB,EAAE,KAA0B;IACvF,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,4BAA4B,EAAE,4BAA4B,GAAG,eAAe,CAAC,CAAC,CAAC;IACtH,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,MAAuB,EACvB,KAA0B;IAE1B,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAiB;IACrD,OAAO,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,4BAA4B,EAAE,4BAA4B,GAAG,eAAe,CAAC,CAAC,CAAC;AAClH,CAAC"}
|
package/lib/util/validator.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Epoch, phase0, ValidatorIndex } from "@lodestar/types";
|
|
2
2
|
import { ChainForkConfig } from "@lodestar/config";
|
|
3
|
+
import { ForkSeq } from "@lodestar/params";
|
|
3
4
|
import { BeaconStateAllForks } from "../types.js";
|
|
4
5
|
/**
|
|
5
6
|
* Check if [[validator]] is active
|
|
@@ -15,5 +16,6 @@ export declare function isSlashableValidator(validator: phase0.Validator, epoch:
|
|
|
15
16
|
* NAIVE - SLOW CODE 🐢
|
|
16
17
|
*/
|
|
17
18
|
export declare function getActiveValidatorIndices(state: BeaconStateAllForks, epoch: Epoch): ValidatorIndex[];
|
|
19
|
+
export declare function getActivationChurnLimit(config: ChainForkConfig, fork: ForkSeq, activeValidatorCount: number): number;
|
|
18
20
|
export declare function getChurnLimit(config: ChainForkConfig, activeValidatorCount: number): number;
|
|
19
21
|
//# sourceMappingURL=validator.d.ts.map
|