@lodestar/beacon-node 1.43.0-dev.6641fd750e → 1.43.0-dev.ade910fc78
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/api/impl/lodestar/attesterSlashing.d.ts +8 -0
- package/lib/api/impl/lodestar/attesterSlashing.d.ts.map +1 -0
- package/lib/api/impl/lodestar/attesterSlashing.js +29 -0
- package/lib/api/impl/lodestar/attesterSlashing.js.map +1 -0
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +36 -1
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/chain/blocks/importBlock.js +4 -4
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +3 -7
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +0 -1
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/queued.d.ts +2 -3
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +7 -32
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +7 -26
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/stateCache/datastore/db.d.ts +5 -4
- package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/db.js +10 -32
- package/lib/chain/stateCache/datastore/db.js.map +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/file.js +5 -5
- package/lib/chain/stateCache/datastore/file.js.map +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -7
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +0 -8
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +19 -30
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +118 -209
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +12 -13
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +2 -729
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/lodestar/attesterSlashing.ts +43 -0
- package/src/api/impl/lodestar/index.ts +48 -2
- package/src/chain/blocks/importBlock.ts +4 -4
- package/src/chain/chain.ts +3 -15
- package/src/chain/regen/interface.ts +0 -1
- package/src/chain/regen/queued.ts +8 -36
- package/src/chain/regen/regen.ts +8 -28
- package/src/chain/stateCache/datastore/db.ts +10 -33
- package/src/chain/stateCache/datastore/file.ts +5 -6
- package/src/chain/stateCache/datastore/types.ts +2 -3
- package/src/chain/stateCache/fifoBlockStateCache.ts +1 -10
- package/src/chain/stateCache/persistentCheckpointsCache.ts +142 -240
- package/src/chain/stateCache/types.ts +10 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topic.d.ts","sourceRoot":"","sources":["../../../src/network/gossip/topic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAEL,QAAQ,EAMT,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,WAAW,EAAE,iBAAiB,EAAmB,MAAM,iBAAiB,CAAC;AAEjF,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAiB,WAAW,EAAE,kBAAkB,EAAE,UAAU,EAAE,oBAAoB,EAAC,MAAM,gBAAgB,CAAC;AAEjH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC;CACzC;AAED,qBAAa,gBAAiB,YAAW,iBAAiB;IAG5C,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAF9C,OAAO,CAAC,gBAAgB,CAA4C;IAEpE,YAA6B,iBAAiB,EAAE,iBAAiB,EAAI;IAErE,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAQtC;IAED,8DAA8D;IAC9D,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEvD;IAED,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAInD;CACF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,CAKrG;AA8BD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW
|
|
1
|
+
{"version":3,"file":"topic.d.ts","sourceRoot":"","sources":["../../../src/network/gossip/topic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAEL,QAAQ,EAMT,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,WAAW,EAAE,iBAAiB,EAAmB,MAAM,iBAAiB,CAAC;AAEjF,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAiB,WAAW,EAAE,kBAAkB,EAAE,UAAU,EAAE,oBAAoB,EAAC,MAAM,gBAAgB,CAAC;AAEjH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC;CACzC;AAED,qBAAa,gBAAiB,YAAW,iBAAiB;IAG5C,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAF9C,OAAO,CAAC,gBAAgB,CAA4C;IAEpE,YAA6B,iBAAiB,EAAE,iBAAiB,EAAI;IAErE,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAQtC;IAED,8DAA8D;IAC9D,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEvD;IAED,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAInD;CACF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,CAKrG;AA8BD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAyClD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,cAAc,EAAE,UAAU,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAOnH;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,GAAG,WAAW,CAMjG;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,GAAG,iBAAiB,CAS7G;AAMD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAyD9G;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE;IAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAAC,wBAAwB,CAAC,EAAE,OAAO,CAAA;CAAC,GACxE,kBAAkB,CAAC,MAAM,kBAAkB,CAAC,EAAE,CA2DhD;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,aAAa,EAAE,aAAa,GAC3B,kBAAkB,CAAC,MAAM,kBAAkB,CAAC,EAAE,CAShD;AAgBD,eAAO,MAAM,sCAAsC,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAiB9E,CAAC"}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/ChainSafe/lodestar/issues"
|
|
13
13
|
},
|
|
14
|
-
"version": "1.43.0-dev.
|
|
14
|
+
"version": "1.43.0-dev.ade910fc78",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -135,18 +135,18 @@
|
|
|
135
135
|
"@libp2p/peer-id": "^6.0.4",
|
|
136
136
|
"@libp2p/prometheus-metrics": "^5.0.14",
|
|
137
137
|
"@libp2p/tcp": "^11.0.13",
|
|
138
|
-
"@lodestar/api": "^1.43.0-dev.
|
|
139
|
-
"@lodestar/config": "^1.43.0-dev.
|
|
140
|
-
"@lodestar/db": "^1.43.0-dev.
|
|
141
|
-
"@lodestar/fork-choice": "^1.43.0-dev.
|
|
142
|
-
"@lodestar/light-client": "^1.43.0-dev.
|
|
143
|
-
"@lodestar/logger": "^1.43.0-dev.
|
|
144
|
-
"@lodestar/params": "^1.43.0-dev.
|
|
145
|
-
"@lodestar/reqresp": "^1.43.0-dev.
|
|
146
|
-
"@lodestar/state-transition": "^1.43.0-dev.
|
|
147
|
-
"@lodestar/types": "^1.43.0-dev.
|
|
148
|
-
"@lodestar/utils": "^1.43.0-dev.
|
|
149
|
-
"@lodestar/validator": "^1.43.0-dev.
|
|
138
|
+
"@lodestar/api": "^1.43.0-dev.ade910fc78",
|
|
139
|
+
"@lodestar/config": "^1.43.0-dev.ade910fc78",
|
|
140
|
+
"@lodestar/db": "^1.43.0-dev.ade910fc78",
|
|
141
|
+
"@lodestar/fork-choice": "^1.43.0-dev.ade910fc78",
|
|
142
|
+
"@lodestar/light-client": "^1.43.0-dev.ade910fc78",
|
|
143
|
+
"@lodestar/logger": "^1.43.0-dev.ade910fc78",
|
|
144
|
+
"@lodestar/params": "^1.43.0-dev.ade910fc78",
|
|
145
|
+
"@lodestar/reqresp": "^1.43.0-dev.ade910fc78",
|
|
146
|
+
"@lodestar/state-transition": "^1.43.0-dev.ade910fc78",
|
|
147
|
+
"@lodestar/types": "^1.43.0-dev.ade910fc78",
|
|
148
|
+
"@lodestar/utils": "^1.43.0-dev.ade910fc78",
|
|
149
|
+
"@lodestar/validator": "^1.43.0-dev.ade910fc78",
|
|
150
150
|
"@multiformats/multiaddr": "^13.0.1",
|
|
151
151
|
"datastore-core": "^11.0.2",
|
|
152
152
|
"datastore-fs": "^11.0.2",
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
"@libp2p/interface-internal": "^3.0.13",
|
|
170
170
|
"@libp2p/logger": "^6.2.2",
|
|
171
171
|
"@libp2p/utils": "^7.0.13",
|
|
172
|
-
"@lodestar/spec-test-util": "^1.43.0-dev.
|
|
172
|
+
"@lodestar/spec-test-util": "^1.43.0-dev.ade910fc78",
|
|
173
173
|
"@types/js-yaml": "^4.0.5",
|
|
174
174
|
"@types/qs": "^6.9.7",
|
|
175
175
|
"@types/tmp": "^0.2.3",
|
|
@@ -186,5 +186,5 @@
|
|
|
186
186
|
"beacon",
|
|
187
187
|
"blockchain"
|
|
188
188
|
],
|
|
189
|
-
"gitHead": "
|
|
189
|
+
"gitHead": "28e20b48ea4cedefb77526a12286bb0b042a08bb"
|
|
190
190
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {ForkSeq} from "@lodestar/params";
|
|
2
|
+
import {
|
|
3
|
+
getIntersectingIndices,
|
|
4
|
+
isSlashableAttestationData,
|
|
5
|
+
toIndexedAttestationBigint,
|
|
6
|
+
} from "@lodestar/state-transition";
|
|
7
|
+
import {AttesterSlashing, IndexedAttestation} from "@lodestar/types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Find all slashable pairs within a list of IndexedAttestations and
|
|
11
|
+
* construct AttesterSlashing objects for each.
|
|
12
|
+
*/
|
|
13
|
+
export function getAttesterSlashingsFromIndexedAttestations(
|
|
14
|
+
fork: ForkSeq,
|
|
15
|
+
indexedAttestations: IndexedAttestation[]
|
|
16
|
+
): AttesterSlashing[] {
|
|
17
|
+
const slashings: AttesterSlashing[] = [];
|
|
18
|
+
|
|
19
|
+
for (let i = 0; i < indexedAttestations.length; i++) {
|
|
20
|
+
for (let j = i + 1; j < indexedAttestations.length; j++) {
|
|
21
|
+
// Order by source epoch so the surrounding attestation is always first,
|
|
22
|
+
// matching what isSlashableAttestationData expects (one-directional check).
|
|
23
|
+
const [first, second] =
|
|
24
|
+
indexedAttestations[j].data.source.epoch < indexedAttestations[i].data.source.epoch
|
|
25
|
+
? [indexedAttestations[j], indexedAttestations[i]]
|
|
26
|
+
: [indexedAttestations[i], indexedAttestations[j]];
|
|
27
|
+
|
|
28
|
+
if (getIntersectingIndices(first.attestingIndices, second.attestingIndices).length === 0) continue;
|
|
29
|
+
|
|
30
|
+
const firstBigint = toIndexedAttestationBigint(first, fork);
|
|
31
|
+
const secondBigint = toIndexedAttestationBigint(second, fork);
|
|
32
|
+
|
|
33
|
+
if (!isSlashableAttestationData(firstBigint.data, secondBigint.data)) continue;
|
|
34
|
+
|
|
35
|
+
slashings.push({
|
|
36
|
+
attestation1: firstBigint,
|
|
37
|
+
attestation2: secondBigint,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return slashings;
|
|
43
|
+
}
|
|
@@ -3,8 +3,13 @@ import {ApplicationMethods} from "@lodestar/api/server";
|
|
|
3
3
|
import {ChainForkConfig} from "@lodestar/config";
|
|
4
4
|
import {Repository} from "@lodestar/db";
|
|
5
5
|
import {ForkSeq, SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
computeEpochAtSlot,
|
|
8
|
+
computeStartSlotAtEpoch,
|
|
9
|
+
getIndexedAttestation,
|
|
10
|
+
isStatePostCapella,
|
|
11
|
+
} from "@lodestar/state-transition";
|
|
12
|
+
import {Attestation, Epoch, IndexedAttestation, ssz} from "@lodestar/types";
|
|
8
13
|
import {Checkpoint} from "@lodestar/types/phase0";
|
|
9
14
|
import {fromHex, toHex, toRootHex} from "@lodestar/utils";
|
|
10
15
|
import {BeaconChain} from "../../../chain/index.js";
|
|
@@ -16,6 +21,7 @@ import {ProfileThread, profileThread, writeHeapSnapshot} from "../../../util/pro
|
|
|
16
21
|
import {getStateResponseWithRegen} from "../beacon/state/utils.js";
|
|
17
22
|
import {ApiError} from "../errors.js";
|
|
18
23
|
import {ApiModules} from "../types.js";
|
|
24
|
+
import {getAttesterSlashingsFromIndexedAttestations} from "./attesterSlashing.js";
|
|
19
25
|
|
|
20
26
|
export function getLodestarApi({
|
|
21
27
|
chain,
|
|
@@ -273,6 +279,46 @@ export function getLodestarApi({
|
|
|
273
279
|
},
|
|
274
280
|
};
|
|
275
281
|
},
|
|
282
|
+
|
|
283
|
+
async getAttesterSlashingsFromBlocks({signedBlocks}) {
|
|
284
|
+
const attestations = new Map<Epoch, Attestation[]>();
|
|
285
|
+
|
|
286
|
+
for (const block of signedBlocks) {
|
|
287
|
+
const attestationsOfABlock = block.message.body.attestations;
|
|
288
|
+
for (const attestation of attestationsOfABlock) {
|
|
289
|
+
const epoch = computeEpochAtSlot(attestation.data.slot);
|
|
290
|
+
let attestationsPerEpoch = attestations.get(epoch);
|
|
291
|
+
if (!attestationsPerEpoch) {
|
|
292
|
+
attestationsPerEpoch = [];
|
|
293
|
+
attestations.set(epoch, attestationsPerEpoch);
|
|
294
|
+
}
|
|
295
|
+
attestationsPerEpoch.push(attestation);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const indexedAttestations: IndexedAttestation[] = [];
|
|
300
|
+
// Assume all blocks are from the same fork
|
|
301
|
+
const forkSeq = config.getForkSeq(signedBlocks[0].message.slot);
|
|
302
|
+
|
|
303
|
+
for (const [epoch, attestationsPerEpoch] of attestations) {
|
|
304
|
+
const slot = computeStartSlotAtEpoch(epoch);
|
|
305
|
+
const {state} = await getStateResponseWithRegen(chain, slot);
|
|
306
|
+
const stateView = state instanceof Uint8Array ? chain.getHeadState().loadOtherState(state) : state;
|
|
307
|
+
const shuffling = stateView.getShufflingAtEpoch(epoch);
|
|
308
|
+
for (const attestation of attestationsPerEpoch) {
|
|
309
|
+
indexedAttestations.push(getIndexedAttestation(shuffling, forkSeq, attestation));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const result = getAttesterSlashingsFromIndexedAttestations(forkSeq, indexedAttestations);
|
|
314
|
+
|
|
315
|
+
return {
|
|
316
|
+
data: result,
|
|
317
|
+
meta: {
|
|
318
|
+
version: config.getForkName(signedBlocks[0].message.slot),
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
},
|
|
276
322
|
};
|
|
277
323
|
}
|
|
278
324
|
|
|
@@ -48,7 +48,7 @@ import type {BeaconChain} from "../chain.js";
|
|
|
48
48
|
import {ChainEvent, ReorgEventData} from "../emitter.js";
|
|
49
49
|
import {ForkchoiceCaller} from "../forkChoice/index.js";
|
|
50
50
|
import {REPROCESS_MIN_TIME_TO_NEXT_SLOT_SEC} from "../reprocess.js";
|
|
51
|
-
import {
|
|
51
|
+
import {toCheckpointHex} from "../stateCache/persistentCheckpointsCache.js";
|
|
52
52
|
import {isBlockInputBlobs, isBlockInputColumns} from "./blockInput/blockInput.js";
|
|
53
53
|
import {AttestationImportOpt, FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
|
|
54
54
|
import {getCheckpointFromState} from "./utils/checkpoint.js";
|
|
@@ -519,7 +519,7 @@ export async function importBlock(
|
|
|
519
519
|
this.emitter.emit(ChainEvent.checkpoint, cp, checkpointState);
|
|
520
520
|
|
|
521
521
|
// Note: in-lined code from previos handler of ChainEvent.checkpoint
|
|
522
|
-
this.logger.verbose("Checkpoint processed",
|
|
522
|
+
this.logger.verbose("Checkpoint processed", toCheckpointHex(cp));
|
|
523
523
|
|
|
524
524
|
const activeValidatorsCount = checkpointState.activeValidatorCount;
|
|
525
525
|
this.metrics?.currentActiveValidators.set(activeValidatorsCount);
|
|
@@ -537,7 +537,7 @@ export async function importBlock(
|
|
|
537
537
|
const justifiedEpoch = justifiedCheckpoint.epoch;
|
|
538
538
|
const preJustifiedEpoch = parentBlockSummary.justifiedEpoch;
|
|
539
539
|
if (justifiedEpoch > preJustifiedEpoch) {
|
|
540
|
-
this.logger.verbose("Checkpoint justified",
|
|
540
|
+
this.logger.verbose("Checkpoint justified", toCheckpointHex(justifiedCheckpoint));
|
|
541
541
|
this.metrics?.previousJustifiedEpoch.set(checkpointState.previousJustifiedCheckpoint.epoch);
|
|
542
542
|
this.metrics?.currentJustifiedEpoch.set(justifiedCheckpoint.epoch);
|
|
543
543
|
}
|
|
@@ -551,7 +551,7 @@ export async function importBlock(
|
|
|
551
551
|
state: toRootHex(checkpointState.hashTreeRoot()),
|
|
552
552
|
executionOptimistic: false,
|
|
553
553
|
});
|
|
554
|
-
this.logger.verbose("Checkpoint finalized",
|
|
554
|
+
this.logger.verbose("Checkpoint finalized", toCheckpointHex(finalizedCheckpoint));
|
|
555
555
|
this.metrics?.finalizedEpoch.set(finalizedCheckpoint.epoch);
|
|
556
556
|
}
|
|
557
557
|
}
|
package/src/chain/chain.ts
CHANGED
|
@@ -2,14 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import {PrivateKey} from "@libp2p/interface";
|
|
3
3
|
import {Type} from "@chainsafe/ssz";
|
|
4
4
|
import {BeaconConfig} from "@lodestar/config";
|
|
5
|
-
import {
|
|
6
|
-
CheckpointWithPayloadStatus,
|
|
7
|
-
IForkChoice,
|
|
8
|
-
PayloadStatus,
|
|
9
|
-
ProtoBlock,
|
|
10
|
-
UpdateHeadOpt,
|
|
11
|
-
getCheckpointPayloadStatus,
|
|
12
|
-
} from "@lodestar/fork-choice";
|
|
5
|
+
import {CheckpointWithPayloadStatus, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice";
|
|
13
6
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
14
7
|
import {
|
|
15
8
|
BUILDER_INDEX_SELF_BUILD,
|
|
@@ -390,8 +383,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
390
383
|
const {checkpoint} = anchorState.computeAnchorCheckpoint();
|
|
391
384
|
blockStateCache.add(anchorState);
|
|
392
385
|
blockStateCache.setHeadState(anchorState);
|
|
393
|
-
|
|
394
|
-
checkpointStateCache.add(checkpoint, anchorState, payloadPresent);
|
|
386
|
+
checkpointStateCache.add(checkpoint, anchorState);
|
|
395
387
|
|
|
396
388
|
const forkChoice = initializeForkChoice(
|
|
397
389
|
config,
|
|
@@ -685,7 +677,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
685
677
|
|
|
686
678
|
// TODO GLOAS: Need to revisit the design of this api. Currently we just retrieve FULL state of the checkpoint for backwards compatibility.
|
|
687
679
|
// because pre-gloas we always store FULL checkpoint state.
|
|
688
|
-
const persistedKey = checkpointToDatastoreKey(checkpoint
|
|
680
|
+
const persistedKey = checkpointToDatastoreKey(checkpoint);
|
|
689
681
|
return this.cpStateDatastore.read(persistedKey);
|
|
690
682
|
}
|
|
691
683
|
|
|
@@ -1471,10 +1463,6 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1471
1463
|
private onClockEpoch(epoch: Epoch): void {
|
|
1472
1464
|
this.metrics?.clockEpoch.set(epoch);
|
|
1473
1465
|
|
|
1474
|
-
if (epoch === this.config.GLOAS_FORK_EPOCH) {
|
|
1475
|
-
this.regen.upgradeForGloas(epoch);
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
1466
|
this.seenAttesters.prune(epoch);
|
|
1479
1467
|
this.seenAggregators.prune(epoch);
|
|
1480
1468
|
this.seenPayloadAttesters.prune(epoch);
|
|
@@ -54,7 +54,6 @@ export interface IStateRegenerator extends IStateRegeneratorInternal {
|
|
|
54
54
|
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView, payloadPresent: boolean): void;
|
|
55
55
|
updateHeadState(newHead: ProtoBlock, maybeHeadState: IBeaconStateView): void;
|
|
56
56
|
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch, payloadPresent: boolean): number | null;
|
|
57
|
-
upgradeForGloas(epoch: Epoch): void;
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
|
-
import {IForkChoice,
|
|
2
|
+
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
3
3
|
import {IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
|
|
4
4
|
import {BeaconBlock, Epoch, RootHex, Slot, isGloasBeaconBlock, phase0} from "@lodestar/types";
|
|
5
|
-
import {Logger,
|
|
5
|
+
import {Logger, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {Metrics} from "../../metrics/index.js";
|
|
7
7
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
8
8
|
import {BlockStateCache, CheckpointHexPayload, CheckpointStateCache} from "../stateCache/types.js";
|
|
@@ -104,19 +104,9 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
104
104
|
const parentEpoch = computeEpochAtSlot(parentBlock.slot);
|
|
105
105
|
const blockEpoch = computeEpochAtSlot(block.slot);
|
|
106
106
|
|
|
107
|
-
// Convert PayloadStatus to payloadPresent boolean
|
|
108
|
-
if (parentBlock.payloadStatus === PayloadStatus.PENDING) {
|
|
109
|
-
throw new RegenError({
|
|
110
|
-
code: RegenErrorCode.UNEXPECTED_PAYLOAD_STATUS,
|
|
111
|
-
blockRoot: block.parentRoot,
|
|
112
|
-
payloadStatus: parentBlock.payloadStatus,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
const payloadPresent = parentBlock.payloadStatus === PayloadStatus.FULL;
|
|
116
|
-
|
|
117
107
|
// Check the checkpoint cache (if the pre-state is a checkpoint state)
|
|
118
108
|
if (parentEpoch < blockEpoch) {
|
|
119
|
-
const checkpointState = this.checkpointStateCache.getLatest(parentRoot, blockEpoch
|
|
109
|
+
const checkpointState = this.checkpointStateCache.getLatest(parentRoot, blockEpoch);
|
|
120
110
|
if (checkpointState && computeEpochAtSlot(checkpointState.slot) === blockEpoch) {
|
|
121
111
|
return checkpointState;
|
|
122
112
|
}
|
|
@@ -150,19 +140,7 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
150
140
|
* Get state closest to head
|
|
151
141
|
*/
|
|
152
142
|
getClosestHeadState(head: ProtoBlock): IBeaconStateView | null {
|
|
153
|
-
|
|
154
|
-
if (head.payloadStatus === PayloadStatus.PENDING) {
|
|
155
|
-
throw new RegenError({
|
|
156
|
-
code: RegenErrorCode.UNEXPECTED_PAYLOAD_STATUS,
|
|
157
|
-
blockRoot: fromHex(head.blockRoot),
|
|
158
|
-
payloadStatus: head.payloadStatus,
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
const payloadPresent = head.payloadStatus === PayloadStatus.FULL;
|
|
162
|
-
return (
|
|
163
|
-
this.checkpointStateCache.getLatest(head.blockRoot, Infinity, payloadPresent) ||
|
|
164
|
-
this.blockStateCache.get(head.stateRoot)
|
|
165
|
-
);
|
|
143
|
+
return this.checkpointStateCache.getLatest(head.blockRoot, Infinity) || this.blockStateCache.get(head.stateRoot);
|
|
166
144
|
}
|
|
167
145
|
|
|
168
146
|
pruneOnCheckpoint(finalizedEpoch: Epoch, justifiedEpoch: Epoch, headStateRoot: RootHex): void {
|
|
@@ -190,9 +168,8 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
190
168
|
this.blockStateCache.add(payloadState);
|
|
191
169
|
}
|
|
192
170
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
this.checkpointStateCache.add(cp, item, payloadPresent);
|
|
171
|
+
addCheckpointState(cp: phase0.Checkpoint, item: IBeaconStateView, _payloadPresent: boolean): void {
|
|
172
|
+
this.checkpointStateCache.add(cp, item);
|
|
196
173
|
}
|
|
197
174
|
|
|
198
175
|
updateHeadState(newHead: ProtoBlock, maybeHeadState: IBeaconStateView): void {
|
|
@@ -228,13 +205,8 @@ export class QueuedStateRegenerator implements IStateRegenerator {
|
|
|
228
205
|
}
|
|
229
206
|
}
|
|
230
207
|
|
|
231
|
-
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch,
|
|
232
|
-
return this.checkpointStateCache.updatePreComputedCheckpoint(rootHex, epoch
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
upgradeForGloas(epoch: Epoch): void {
|
|
236
|
-
this.logger.verbose("Upgrading block state cache for Gloas fork", {epoch});
|
|
237
|
-
this.blockStateCache.upgradeToGloas();
|
|
208
|
+
updatePreComputedCheckpoint(rootHex: RootHex, epoch: Epoch, _payloadPresent: boolean): number | null {
|
|
209
|
+
return this.checkpointStateCache.updatePreComputedCheckpoint(rootHex, epoch);
|
|
238
210
|
}
|
|
239
211
|
|
|
240
212
|
/**
|
package/src/chain/regen/regen.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {IForkChoice,
|
|
3
|
-
import {
|
|
2
|
+
import {IForkChoice, ProtoBlock} from "@lodestar/fork-choice";
|
|
3
|
+
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
4
4
|
import {
|
|
5
5
|
DataAvailabilityStatus,
|
|
6
6
|
ExecutionPayloadStatus,
|
|
@@ -110,19 +110,9 @@ export class StateRegenerator implements IStateRegeneratorInternal {
|
|
|
110
110
|
const {checkpointStateCache} = this.modules;
|
|
111
111
|
const epoch = computeEpochAtSlot(slot);
|
|
112
112
|
|
|
113
|
-
// Convert PayloadStatus to payloadPresent boolean
|
|
114
|
-
if (block.payloadStatus === PayloadStatus.PENDING) {
|
|
115
|
-
throw new RegenError({
|
|
116
|
-
code: RegenErrorCode.UNEXPECTED_PAYLOAD_STATUS,
|
|
117
|
-
blockRoot: fromHex(blockRoot),
|
|
118
|
-
payloadStatus: block.payloadStatus,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
const payloadPresent = block.payloadStatus === PayloadStatus.FULL;
|
|
122
|
-
|
|
123
113
|
const latestCheckpointStateCtx = allowDiskReload
|
|
124
|
-
? await checkpointStateCache.getOrReloadLatest(blockRoot, epoch
|
|
125
|
-
: checkpointStateCache.getLatest(blockRoot, epoch
|
|
114
|
+
? await checkpointStateCache.getOrReloadLatest(blockRoot, epoch)
|
|
115
|
+
: checkpointStateCache.getLatest(blockRoot, epoch);
|
|
126
116
|
|
|
127
117
|
// If a checkpoint state exists with the given checkpoint root, it either is in requested epoch
|
|
128
118
|
// or needs to have empty slots processed until the requested epoch
|
|
@@ -176,18 +166,9 @@ export class StateRegenerator implements IStateRegeneratorInternal {
|
|
|
176
166
|
if (!lastBlockToReplay) continue;
|
|
177
167
|
const epoch = computeEpochAtSlot(lastBlockToReplay.slot - 1);
|
|
178
168
|
|
|
179
|
-
// Convert PayloadStatus to payloadPresent boolean
|
|
180
|
-
if (b.payloadStatus === PayloadStatus.PENDING) {
|
|
181
|
-
throw new RegenError({
|
|
182
|
-
code: RegenErrorCode.INTERNAL_ERROR,
|
|
183
|
-
message: `Unexpected PENDING payloadStatus for ancestor block ${b.blockRoot} at slot ${b.slot}`,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
const payloadPresent = b.payloadStatus === PayloadStatus.FULL;
|
|
187
|
-
|
|
188
169
|
state = allowDiskReload
|
|
189
|
-
? await checkpointStateCache.getOrReloadLatest(b.blockRoot, epoch
|
|
190
|
-
: checkpointStateCache.getLatest(b.blockRoot, epoch
|
|
170
|
+
? await checkpointStateCache.getOrReloadLatest(b.blockRoot, epoch)
|
|
171
|
+
: checkpointStateCache.getLatest(b.blockRoot, epoch);
|
|
191
172
|
if (state) {
|
|
192
173
|
break;
|
|
193
174
|
}
|
|
@@ -375,7 +356,7 @@ export async function processSlotsToNearestCheckpoint(
|
|
|
375
356
|
const postSlot = slot;
|
|
376
357
|
const preEpoch = computeEpochAtSlot(preSlot);
|
|
377
358
|
let postState = preState;
|
|
378
|
-
const {
|
|
359
|
+
const {checkpointStateCache, emitter, metrics, logger} = modules;
|
|
379
360
|
let count = 0;
|
|
380
361
|
|
|
381
362
|
for (
|
|
@@ -402,8 +383,7 @@ export async function processSlotsToNearestCheckpoint(
|
|
|
402
383
|
// processSlots() only does epoch transitions, never processes payloads
|
|
403
384
|
// Pre-Gloas: payloadPresent is always true (execution payload embedded in block)
|
|
404
385
|
// Post-Gloas: result is a block state (payloadPresent=false)
|
|
405
|
-
|
|
406
|
-
checkpointStateCache.add(cp, checkpointState, isPayloadPresent);
|
|
386
|
+
checkpointStateCache.add(cp, checkpointState);
|
|
407
387
|
// consumers should not mutate state ever
|
|
408
388
|
emitter?.emit(ChainEvent.checkpoint, cp, checkpointState);
|
|
409
389
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
2
2
|
import {Epoch, phase0, ssz} from "@lodestar/types";
|
|
3
|
-
import {MapDef
|
|
3
|
+
import {MapDef} from "@lodestar/utils";
|
|
4
4
|
import {IBeaconDb} from "../../../db/interface.js";
|
|
5
5
|
import {
|
|
6
6
|
getLastProcessedSlotFromBeaconStateSerialized,
|
|
@@ -14,8 +14,8 @@ import {CPStateDatastore, DatastoreKey} from "./types.js";
|
|
|
14
14
|
export class DbCPStateDatastore implements CPStateDatastore {
|
|
15
15
|
constructor(private readonly db: IBeaconDb) {}
|
|
16
16
|
|
|
17
|
-
async write(cpKey: phase0.Checkpoint, stateBytes: Uint8Array
|
|
18
|
-
const serializedCheckpoint = checkpointToDatastoreKey(cpKey
|
|
17
|
+
async write(cpKey: phase0.Checkpoint, stateBytes: Uint8Array): Promise<DatastoreKey> {
|
|
18
|
+
const serializedCheckpoint = checkpointToDatastoreKey(cpKey);
|
|
19
19
|
await this.db.checkpointState.putBinary(serializedCheckpoint, stateBytes);
|
|
20
20
|
return serializedCheckpoint;
|
|
21
21
|
}
|
|
@@ -40,30 +40,18 @@ export class DbCPStateDatastore implements CPStateDatastore {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function extractCheckpointBytes(key: DatastoreKey): Uint8Array {
|
|
44
|
-
const fixedSize = ssz.phase0.Checkpoint.minSize;
|
|
45
|
-
return key.subarray(0, fixedSize);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
43
|
export function datastoreKeyToCheckpoint(key: DatastoreKey): phase0.Checkpoint {
|
|
49
|
-
return ssz.phase0.Checkpoint.deserialize(
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function checkpointToDatastoreKey(cp: phase0.Checkpoint, payloadPresent: boolean): DatastoreKey {
|
|
53
|
-
const cpBytes = ssz.phase0.Checkpoint.serialize(cp);
|
|
54
|
-
const key = new Uint8Array(cpBytes.length + 1);
|
|
55
|
-
key.set(cpBytes);
|
|
56
|
-
key[cpBytes.length] = payloadPresent ? 1 : 0;
|
|
57
|
-
return key;
|
|
44
|
+
return ssz.phase0.Checkpoint.deserialize(key);
|
|
58
45
|
}
|
|
59
46
|
|
|
60
|
-
function
|
|
61
|
-
return
|
|
47
|
+
export function checkpointToDatastoreKey(cp: phase0.Checkpoint): DatastoreKey {
|
|
48
|
+
return ssz.phase0.Checkpoint.serialize(cp);
|
|
62
49
|
}
|
|
63
50
|
|
|
64
51
|
/**
|
|
65
|
-
* Get the latest
|
|
66
|
-
* -
|
|
52
|
+
* Get the latest safe checkpoint state the node can use to boot from
|
|
53
|
+
* - it should be the checkpoint state that's unique in its epoch
|
|
54
|
+
* - its last processed block slot should be at epoch boundary or last slot of previous epoch
|
|
67
55
|
* - state slot should be at epoch boundary
|
|
68
56
|
* - state slot should be equal to epoch * SLOTS_PER_EPOCH
|
|
69
57
|
*
|
|
@@ -82,20 +70,9 @@ export async function getLatestSafeDatastoreKey(
|
|
|
82
70
|
|
|
83
71
|
const dataStoreKeyByEpoch: Map<Epoch, DatastoreKey> = new Map();
|
|
84
72
|
for (const [epoch, keys] of checkpointsByEpoch.entries()) {
|
|
73
|
+
// only consider epochs with a single checkpoint to avoid ambiguity from forks
|
|
85
74
|
if (keys.length === 1) {
|
|
86
|
-
// PRCS (skipped slot) or CRCS and no payloadPresent
|
|
87
|
-
// Pre-gloas always fall into this case
|
|
88
75
|
dataStoreKeyByEpoch.set(epoch, keys[0]);
|
|
89
|
-
} else if (keys.length === 2) {
|
|
90
|
-
// CRCS without payload and CRCS with payload
|
|
91
|
-
// ie Two keys for the same checkpoint with different payloadPresent suffix (FULL/EMPTY)
|
|
92
|
-
// TODO GLOAS: Here we pick FULL key, there is a chance that payload is orphaned hence we not be able to sync
|
|
93
|
-
const cp0 = extractCheckpointBytes(keys[0]);
|
|
94
|
-
const cp1 = extractCheckpointBytes(keys[1]);
|
|
95
|
-
if (byteArrayEquals(cp0, cp1)) {
|
|
96
|
-
const fullKey = isPayloadCheckpointState(keys[0]) ? keys[0] : keys[1];
|
|
97
|
-
dataStoreKeyByEpoch.set(epoch, fullKey);
|
|
98
|
-
}
|
|
99
76
|
}
|
|
100
77
|
}
|
|
101
78
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {phase0} from "@lodestar/types";
|
|
2
|
+
import {phase0, ssz} from "@lodestar/types";
|
|
3
3
|
import {fromHex, toHex} from "@lodestar/utils";
|
|
4
4
|
import {ensureDir, readFile, readFileNames, removeFile, writeIfNotExist} from "../../../util/file.js";
|
|
5
|
-
import {
|
|
5
|
+
import {getLatestSafeDatastoreKey} from "./db.js";
|
|
6
6
|
import {CPStateDatastore, DatastoreKey} from "./types.js";
|
|
7
7
|
|
|
8
8
|
const CHECKPOINT_STATES_FOLDER = "checkpoint_states";
|
|
9
|
-
|
|
10
|
-
const CHECKPOINT_FILE_NAME_LENGTH = 84;
|
|
9
|
+
const CHECKPOINT_FILE_NAME_LENGTH = 82;
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Implementation of CPStateDatastore using file system, this is beneficial for debugging.
|
|
@@ -29,8 +28,8 @@ export class FileCPStateDatastore implements CPStateDatastore {
|
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
async write(cpKey: phase0.Checkpoint, stateBytes: Uint8Array
|
|
33
|
-
const serializedCheckpoint =
|
|
31
|
+
async write(cpKey: phase0.Checkpoint, stateBytes: Uint8Array): Promise<DatastoreKey> {
|
|
32
|
+
const serializedCheckpoint = ssz.phase0.Checkpoint.serialize(cpKey);
|
|
34
33
|
const filePath = path.join(this.folderPath, toHex(serializedCheckpoint));
|
|
35
34
|
await writeIfNotExist(filePath, stateBytes);
|
|
36
35
|
return serializedCheckpoint;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import {phase0} from "@lodestar/types";
|
|
2
2
|
|
|
3
|
-
// With db implementation, persistedKey is serialized data of a checkpoint
|
|
4
|
-
// ie a fixed size of `ssz.phase0.Checkpoint.minSize + 1`
|
|
3
|
+
// With db implementation, persistedKey is serialized data of a checkpoint
|
|
5
4
|
export type DatastoreKey = Uint8Array;
|
|
6
5
|
|
|
7
6
|
// Make this generic to support testing
|
|
8
7
|
export interface CPStateDatastore {
|
|
9
|
-
write: (cpKey: phase0.Checkpoint, stateBytes: Uint8Array
|
|
8
|
+
write: (cpKey: phase0.Checkpoint, stateBytes: Uint8Array) => Promise<DatastoreKey>;
|
|
10
9
|
remove: (key: DatastoreKey) => Promise<void>;
|
|
11
10
|
read: (key: DatastoreKey) => Promise<Uint8Array | null>;
|
|
12
11
|
readLatestSafe: () => Promise<Uint8Array | null>;
|
|
@@ -20,11 +20,6 @@ export type FIFOBlockStateCacheOpts = {
|
|
|
20
20
|
* clock slot
|
|
21
21
|
*/
|
|
22
22
|
export const DEFAULT_MAX_BLOCK_STATES = 64;
|
|
23
|
-
/**
|
|
24
|
-
* For Gloas (ePBS), each block can have two states: block state and payload state.
|
|
25
|
-
* Double the cache size to maintain the same effective block depth.
|
|
26
|
-
*/
|
|
27
|
-
export const DEFAULT_MAX_BLOCK_STATES_GLOAS = 128;
|
|
28
23
|
|
|
29
24
|
/**
|
|
30
25
|
* New implementation of BlockStateCache that keeps the most recent n states consistently
|
|
@@ -46,7 +41,7 @@ export const DEFAULT_MAX_BLOCK_STATES_GLOAS = 128;
|
|
|
46
41
|
* The maintained key order would be: 11 -> 13 -> 12 -> 10, and state 10 will be pruned first.
|
|
47
42
|
*/
|
|
48
43
|
export class FIFOBlockStateCache implements BlockStateCache {
|
|
49
|
-
|
|
44
|
+
readonly maxStates: number;
|
|
50
45
|
|
|
51
46
|
private readonly cache: MapTracker<string, IBeaconStateView>;
|
|
52
47
|
/**
|
|
@@ -172,10 +167,6 @@ export class FIFOBlockStateCache implements BlockStateCache {
|
|
|
172
167
|
}
|
|
173
168
|
}
|
|
174
169
|
|
|
175
|
-
upgradeToGloas(): void {
|
|
176
|
-
this.maxStates = DEFAULT_MAX_BLOCK_STATES_GLOAS;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
170
|
/**
|
|
180
171
|
* No need for this implementation
|
|
181
172
|
* This is only to conform to the old api
|