@lodestar/state-transition 1.49.0-dev.fbb58f7280 → 1.49.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/block/processAttestationPhase0.d.ts +1 -1
- package/lib/block/processAttestationPhase0.js +1 -1
- package/lib/cache/epochTransitionCache.d.ts +2 -7
- package/lib/cache/epochTransitionCache.d.ts.map +1 -1
- package/lib/cache/epochTransitionCache.js +10 -7
- package/lib/cache/epochTransitionCache.js.map +1 -1
- package/lib/epoch/processSlashings.d.ts.map +1 -1
- package/lib/epoch/processSlashings.js +2 -1
- package/lib/epoch/processSlashings.js.map +1 -1
- package/lib/metrics.d.ts +4 -4
- package/lib/metrics.d.ts.map +1 -1
- package/lib/metrics.js +5 -6
- package/lib/metrics.js.map +1 -1
- package/lib/stateTransition.d.ts +2 -3
- package/lib/stateTransition.d.ts.map +1 -1
- package/lib/stateTransition.js +8 -10
- package/lib/stateTransition.js.map +1 -1
- package/lib/stateView/beaconStateView.d.ts +1 -2
- package/lib/stateView/beaconStateView.d.ts.map +1 -1
- package/lib/stateView/beaconStateView.js +3 -3
- package/lib/stateView/beaconStateView.js.map +1 -1
- package/lib/stateView/computeNewStateRoot.d.ts +2 -2
- package/lib/stateView/computeNewStateRoot.d.ts.map +1 -1
- package/lib/stateView/computeNewStateRoot.js +4 -7
- package/lib/stateView/computeNewStateRoot.js.map +1 -1
- package/lib/stateView/interface.d.ts +2 -2
- package/lib/stateView/interface.d.ts.map +1 -1
- package/lib/stateView/interface.js.map +1 -1
- package/lib/stateView/nativeBeaconStateView.d.ts +1 -2
- package/lib/stateView/nativeBeaconStateView.d.ts.map +1 -1
- package/lib/stateView/nativeBeaconStateView.js +3 -3
- package/lib/stateView/nativeBeaconStateView.js.map +1 -1
- package/lib/testUtils/index.d.ts +0 -1
- package/lib/testUtils/index.d.ts.map +1 -1
- package/lib/testUtils/index.js +0 -1
- package/lib/testUtils/index.js.map +1 -1
- package/lib/util/epochShuffling.d.ts +0 -1
- package/lib/util/epochShuffling.d.ts.map +1 -1
- package/lib/util/epochShuffling.js +1 -15
- package/lib/util/epochShuffling.js.map +1 -1
- package/lib/util/seed.js +1 -2
- package/lib/util/seed.js.map +1 -1
- package/package.json +7 -8
- package/src/block/processAttestationPhase0.ts +1 -1
- package/src/cache/epochTransitionCache.ts +11 -18
- package/src/epoch/processSlashings.ts +3 -2
- package/src/metrics.ts +6 -7
- package/src/stateTransition.ts +8 -12
- package/src/stateView/beaconStateView.ts +3 -8
- package/src/stateView/computeNewStateRoot.ts +5 -10
- package/src/stateView/interface.ts +2 -6
- package/src/stateView/nativeBeaconStateView.ts +3 -8
- package/src/testUtils/index.ts +0 -1
- package/src/util/epochShuffling.ts +1 -19
- package/src/util/seed.ts +4 -4
- package/lib/testUtils/infura.d.ts +0 -3
- package/lib/testUtils/infura.d.ts.map +0 -1
- package/lib/testUtils/infura.js +0 -8
- package/lib/testUtils/infura.js.map +0 -1
- package/lib/testUtils/testFileCache.d.ts +0 -17
- package/lib/testUtils/testFileCache.d.ts.map +0 -1
- package/lib/testUtils/testFileCache.js +0 -99
- package/lib/testUtils/testFileCache.js.map +0 -1
- package/src/testUtils/infura.ts +0 -10
- package/src/testUtils/testFileCache.ts +0 -130
package/src/stateTransition.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {toRootHex} from "@lodestar/utils";
|
|
|
4
4
|
import {BlockExternalData, DataAvailabilityStatus, ExecutionPayloadStatus} from "./block/externalData.js";
|
|
5
5
|
import {processBlock} from "./block/index.js";
|
|
6
6
|
import {ProcessBlockOpts} from "./block/types.js";
|
|
7
|
-
import {EpochTransitionCache,
|
|
7
|
+
import {EpochTransitionCache, beforeProcessEpoch} from "./cache/epochTransitionCache.js";
|
|
8
8
|
import {EpochTransitionStep, processEpoch} from "./epoch/index.js";
|
|
9
9
|
import {BeaconStateTransitionMetrics, onPostStateMetrics, onStateCloneMetrics} from "./metrics.js";
|
|
10
10
|
import {verifyProposerSignature} from "./signatureSets/index.js";
|
|
@@ -36,7 +36,6 @@ import {computeEpochAtSlot} from "./util/index.js";
|
|
|
36
36
|
|
|
37
37
|
// NOTE DENEB: Mandatory BlockExternalData to decide if block is available or not
|
|
38
38
|
export type StateTransitionOpts = BlockExternalData &
|
|
39
|
-
EpochTransitionCacheOpts &
|
|
40
39
|
ProcessBlockOpts & {
|
|
41
40
|
verifyStateRoot?: boolean;
|
|
42
41
|
verifyProposer?: boolean;
|
|
@@ -110,7 +109,7 @@ export function stateTransition(
|
|
|
110
109
|
|
|
111
110
|
// Process slots (including those with no blocks) since block.
|
|
112
111
|
// Includes state upgrades
|
|
113
|
-
postState = processSlotsWithTransientCache(postState, blockSlot,
|
|
112
|
+
postState = processSlotsWithTransientCache(postState, blockSlot, {metrics, validatorMonitor});
|
|
114
113
|
|
|
115
114
|
// Verify proposer signature only
|
|
116
115
|
if (verifyProposer && !verifyProposerSignature(postState.config, signedBlock)) {
|
|
@@ -137,12 +136,10 @@ export function stateTransition(
|
|
|
137
136
|
}
|
|
138
137
|
|
|
139
138
|
// Verify state root
|
|
139
|
+
// Only spec tests enable verifyStateRoot. beacon-node always passes false and computes the root at the
|
|
140
|
+
// call site, where it is timed per source, so there is nothing to record here.
|
|
140
141
|
if (verifyStateRoot) {
|
|
141
|
-
const hashTreeRootTimer = metrics?.stateHashTreeRootTime.startTimer({
|
|
142
|
-
source: StateHashTreeRootSource.stateTransition,
|
|
143
|
-
});
|
|
144
142
|
const stateRoot = postState.hashTreeRoot();
|
|
145
|
-
hashTreeRootTimer?.();
|
|
146
143
|
|
|
147
144
|
if (!ssz.Root.equals(block.stateRoot, stateRoot)) {
|
|
148
145
|
throw new Error(
|
|
@@ -164,11 +161,11 @@ export function stateTransition(
|
|
|
164
161
|
export function processSlots(
|
|
165
162
|
state: CachedBeaconStateAllForks,
|
|
166
163
|
slot: Slot,
|
|
167
|
-
|
|
164
|
+
opts?: {dontTransferCache?: boolean},
|
|
168
165
|
{metrics, validatorMonitor}: StateTransitionModules = {}
|
|
169
166
|
): CachedBeaconStateAllForks {
|
|
170
167
|
// .clone() before mutating state in state transition
|
|
171
|
-
let postState = state.clone(
|
|
168
|
+
let postState = state.clone(opts?.dontTransferCache);
|
|
172
169
|
|
|
173
170
|
if (metrics) {
|
|
174
171
|
onStateCloneMetrics(postState, metrics, StateCloneSource.processSlots);
|
|
@@ -177,7 +174,7 @@ export function processSlots(
|
|
|
177
174
|
// State is already a ViewDU, which won't commit changes. Equivalent to .setStateCachesAsTransient()
|
|
178
175
|
// postState.setStateCachesAsTransient();
|
|
179
176
|
|
|
180
|
-
postState = processSlotsWithTransientCache(postState, slot,
|
|
177
|
+
postState = processSlotsWithTransientCache(postState, slot, {metrics, validatorMonitor});
|
|
181
178
|
|
|
182
179
|
// Apply changes to state, must do before hashing
|
|
183
180
|
postState.commit();
|
|
@@ -210,7 +207,6 @@ export function processSlots(
|
|
|
210
207
|
function processSlotsWithTransientCache(
|
|
211
208
|
postState: CachedBeaconStateAllForks,
|
|
212
209
|
slot: Slot,
|
|
213
|
-
epochTransitionCacheOpts?: EpochTransitionCacheOpts,
|
|
214
210
|
{metrics, validatorMonitor}: StateTransitionModules = {}
|
|
215
211
|
): CachedBeaconStateAllForks {
|
|
216
212
|
const {config} = postState;
|
|
@@ -231,7 +227,7 @@ function processSlotsWithTransientCache(
|
|
|
231
227
|
let epochTransitionCache: EpochTransitionCache;
|
|
232
228
|
{
|
|
233
229
|
const timer = metrics?.epochTransitionStepTime.startTimer({step: EpochTransitionStep.beforeProcessEpoch});
|
|
234
|
-
epochTransitionCache = beforeProcessEpoch(postState,
|
|
230
|
+
epochTransitionCache = beforeProcessEpoch(postState, metrics);
|
|
235
231
|
timer?.();
|
|
236
232
|
}
|
|
237
233
|
|
|
@@ -33,7 +33,6 @@ import {applyParentExecutionPayload} from "../block/processParentExecutionPayloa
|
|
|
33
33
|
import {VoluntaryExitValidity, getVoluntaryExitValidity} from "../block/processVoluntaryExit.js";
|
|
34
34
|
import {getExpectedWithdrawals} from "../block/processWithdrawals.js";
|
|
35
35
|
import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
|
|
36
|
-
import {EpochTransitionCacheOpts} from "../cache/epochTransitionCache.js";
|
|
37
36
|
import {RewardCache} from "../cache/rewardCache.js";
|
|
38
37
|
import {
|
|
39
38
|
CachedBeaconStateAllForks,
|
|
@@ -851,7 +850,7 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
|
|
|
851
850
|
const postState = new BeaconStateView(
|
|
852
851
|
stateTransition(this.cachedState, block, computeNewStateRootStateTransitionOpts, modules)
|
|
853
852
|
);
|
|
854
|
-
return getComputeNewStateRootResult(postState
|
|
853
|
+
return getComputeNewStateRootResult(postState);
|
|
855
854
|
}
|
|
856
855
|
|
|
857
856
|
stateTransition(
|
|
@@ -863,12 +862,8 @@ export class BeaconStateView implements IBeaconStateViewLatestFork {
|
|
|
863
862
|
return new BeaconStateView(newState);
|
|
864
863
|
}
|
|
865
864
|
|
|
866
|
-
processSlots(
|
|
867
|
-
slot
|
|
868
|
-
epochTransitionCacheOpts?: EpochTransitionCacheOpts & {dontTransferCache?: boolean},
|
|
869
|
-
modules?: StateTransitionModules
|
|
870
|
-
): IBeaconStateView {
|
|
871
|
-
const newState = processSlots(this.cachedState, slot, epochTransitionCacheOpts, modules);
|
|
865
|
+
processSlots(slot: Slot, opts?: {dontTransferCache?: boolean}, modules?: StateTransitionModules): IBeaconStateView {
|
|
866
|
+
const newState = processSlots(this.cachedState, slot, opts, modules);
|
|
872
867
|
return new BeaconStateView(newState);
|
|
873
868
|
}
|
|
874
869
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {DataAvailabilityStatus, ExecutionPayloadStatus} from "../block/externalData.js";
|
|
2
|
-
import {
|
|
2
|
+
import {StateTransitionOpts} from "../stateTransition.js";
|
|
3
3
|
import {ComputeNewStateRootResult, IBeaconStateView} from "./interface.js";
|
|
4
4
|
|
|
5
5
|
/** State transition options for computing the state root of a locally produced block. */
|
|
@@ -18,18 +18,13 @@ export const computeNewStateRootStateTransitionOpts: StateTransitionOpts = {
|
|
|
18
18
|
dontTransferCache: true,
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
export function getComputeNewStateRootResult(
|
|
22
|
-
postState: IBeaconStateView,
|
|
23
|
-
{metrics}: StateTransitionModules
|
|
24
|
-
): ComputeNewStateRootResult {
|
|
21
|
+
export function getComputeNewStateRootResult(postState: IBeaconStateView): ComputeNewStateRootResult {
|
|
25
22
|
const {attestations, syncAggregate, slashing} = postState.proposerRewards;
|
|
26
23
|
const proposerReward = BigInt(attestations + syncAggregate + slashing);
|
|
27
24
|
|
|
28
|
-
const
|
|
29
|
-
source: StateHashTreeRootSource.computeNewStateRoot,
|
|
30
|
-
});
|
|
25
|
+
const start = Date.now();
|
|
31
26
|
const newStateRoot = postState.hashTreeRoot();
|
|
32
|
-
|
|
27
|
+
const hashTreeRootTime = (Date.now() - start) / 1000;
|
|
33
28
|
|
|
34
|
-
return {newStateRoot, proposerReward, postState};
|
|
29
|
+
return {newStateRoot, proposerReward, postState, hashTreeRootTime};
|
|
35
30
|
}
|
|
@@ -48,7 +48,6 @@ import {
|
|
|
48
48
|
import {Checkpoint, Fork} from "@lodestar/types/phase0";
|
|
49
49
|
import {VoluntaryExitValidity} from "../block/processVoluntaryExit.js";
|
|
50
50
|
import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
|
|
51
|
-
import {EpochTransitionCacheOpts} from "../cache/epochTransitionCache.js";
|
|
52
51
|
import {RewardCache} from "../cache/rewardCache.js";
|
|
53
52
|
import {SyncCommitteeCache} from "../cache/syncCommitteeCache.js";
|
|
54
53
|
import {SyncCommitteeWitness} from "../lightClient/types.js";
|
|
@@ -68,6 +67,7 @@ export type ComputeNewStateRootResult = {
|
|
|
68
67
|
newStateRoot: Root;
|
|
69
68
|
proposerReward: Gwei;
|
|
70
69
|
postState: IBeaconStateView;
|
|
70
|
+
hashTreeRootTime: number;
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
/**
|
|
@@ -184,11 +184,7 @@ export interface IBeaconStateView {
|
|
|
184
184
|
options: StateTransitionOpts,
|
|
185
185
|
modules: StateTransitionModules
|
|
186
186
|
): IBeaconStateView;
|
|
187
|
-
processSlots(
|
|
188
|
-
slot: Slot,
|
|
189
|
-
epochTransitionCacheOpts?: EpochTransitionCacheOpts & {dontTransferCache?: boolean},
|
|
190
|
-
modules?: StateTransitionModules
|
|
191
|
-
): IBeaconStateView;
|
|
187
|
+
processSlots(slot: Slot, opts?: {dontTransferCache?: boolean}, modules?: StateTransitionModules): IBeaconStateView;
|
|
192
188
|
}
|
|
193
189
|
|
|
194
190
|
/** Altair+ state fields — use isStatePostAltair() guard */
|
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
import {Checkpoint, Fork} from "@lodestar/types/phase0";
|
|
30
30
|
import {VoluntaryExitValidity} from "../block/processVoluntaryExit.js";
|
|
31
31
|
import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js";
|
|
32
|
-
import {EpochTransitionCacheOpts} from "../cache/epochTransitionCache.js";
|
|
33
32
|
import {RewardCache} from "../cache/rewardCache.js";
|
|
34
33
|
import {SyncCommitteeCache} from "../cache/syncCommitteeCache.js";
|
|
35
34
|
import {SyncCommitteeWitness} from "../lightClient/types.js";
|
|
@@ -652,7 +651,7 @@ export class NativeBeaconStateView implements IBeaconStateViewLatestFork {
|
|
|
652
651
|
const postState = new NativeBeaconStateView(
|
|
653
652
|
this.binding.stateTransition(input.block, computeNewStateRootStateTransitionOpts, modules)
|
|
654
653
|
);
|
|
655
|
-
return getComputeNewStateRootResult(postState
|
|
654
|
+
return getComputeNewStateRootResult(postState);
|
|
656
655
|
}
|
|
657
656
|
|
|
658
657
|
stateTransition(
|
|
@@ -663,12 +662,8 @@ export class NativeBeaconStateView implements IBeaconStateViewLatestFork {
|
|
|
663
662
|
return new NativeBeaconStateView(this.binding.stateTransition(signedBlock, options, modules));
|
|
664
663
|
}
|
|
665
664
|
|
|
666
|
-
processSlots(
|
|
667
|
-
slot
|
|
668
|
-
epochTransitionCacheOpts?: EpochTransitionCacheOpts & {dontTransferCache?: boolean},
|
|
669
|
-
modules?: StateTransitionModules
|
|
670
|
-
): IBeaconStateView {
|
|
671
|
-
return new NativeBeaconStateView(this.binding.processSlots(slot, epochTransitionCacheOpts, modules));
|
|
665
|
+
processSlots(slot: Slot, opts?: {dontTransferCache?: boolean}, modules?: StateTransitionModules): IBeaconStateView {
|
|
666
|
+
return new NativeBeaconStateView(this.binding.processSlots(slot, opts, modules));
|
|
672
667
|
}
|
|
673
668
|
|
|
674
669
|
// ─── altair ──────────────────────────────────────────────────────────────
|
package/src/testUtils/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {unshuffleList} from "@chainsafe/lodestar-z/shuffle";
|
|
2
2
|
import {BeaconConfig} from "@lodestar/config";
|
|
3
3
|
import {
|
|
4
4
|
DOMAIN_BEACON_ATTESTER,
|
|
@@ -105,24 +105,6 @@ export function computeEpochShuffling(
|
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
export async function computeEpochShufflingAsync(
|
|
109
|
-
// TODO: (@matthewkeil) remove state/epoch and pass in seed to clean this up
|
|
110
|
-
state: BeaconStateAllForks,
|
|
111
|
-
activeIndices: Uint32Array,
|
|
112
|
-
epoch: Epoch
|
|
113
|
-
): Promise<EpochShuffling> {
|
|
114
|
-
const seed = getSeed(state, epoch, DOMAIN_BEACON_ATTESTER);
|
|
115
|
-
const shuffling = await asyncUnshuffleList(activeIndices, seed, SHUFFLE_ROUND_COUNT);
|
|
116
|
-
const committees = buildCommitteesFromShuffling(shuffling);
|
|
117
|
-
return {
|
|
118
|
-
epoch,
|
|
119
|
-
activeIndices,
|
|
120
|
-
shuffling,
|
|
121
|
-
committees,
|
|
122
|
-
committeesPerSlot: committees[0].length,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
108
|
export function calculateDecisionRoot(state: BeaconStateAllForks, epoch: Epoch): RootHex {
|
|
127
109
|
const pivotSlot = Math.max(GENESIS_SLOT, computeStartSlotAtEpoch(epoch - 1) - 1);
|
|
128
110
|
return toRootHex(getBlockRootAtSlot(state, pivotSlot));
|
package/src/util/seed.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {digest} from "@chainsafe/as-sha256";
|
|
2
|
-
import {computePtcIndicesForEpoch} from "@chainsafe/lodestar-z/shuffle";
|
|
3
2
|
import {
|
|
3
|
+
computePtcIndicesForEpoch,
|
|
4
4
|
computeProposerIndex as nativeComputeProposerIndex,
|
|
5
5
|
computeSyncCommitteeIndices as nativeComputeSyncCommitteeIndices,
|
|
6
|
-
} from "@chainsafe/
|
|
6
|
+
} from "@chainsafe/lodestar-z/shuffle";
|
|
7
7
|
import {
|
|
8
8
|
DOMAIN_BEACON_PROPOSER,
|
|
9
9
|
DOMAIN_PTC_ATTESTER,
|
|
@@ -118,7 +118,7 @@ export function computeProposerIndex(
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
let maxEffectiveBalance: number;
|
|
121
|
-
let randByteCount:
|
|
121
|
+
let randByteCount: 1 | 2;
|
|
122
122
|
if (fork >= ForkSeq.electra) {
|
|
123
123
|
maxEffectiveBalance = MAX_EFFECTIVE_BALANCE_ELECTRA;
|
|
124
124
|
randByteCount = 2;
|
|
@@ -245,7 +245,7 @@ export function getNextSyncCommitteeIndices(
|
|
|
245
245
|
effectiveBalanceIncrements: EffectiveBalanceIncrements
|
|
246
246
|
): Uint32Array {
|
|
247
247
|
let maxEffectiveBalance: number;
|
|
248
|
-
let randByteCount:
|
|
248
|
+
let randByteCount: 1 | 2;
|
|
249
249
|
|
|
250
250
|
if (fork >= ForkSeq.electra) {
|
|
251
251
|
maxEffectiveBalance = MAX_EFFECTIVE_BALANCE_ELECTRA;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"infura.d.ts","sourceRoot":"","sources":["../../src/testUtils/infura.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,2BAA2B,CAAC;AAEtD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAO/D"}
|
package/lib/testUtils/infura.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export function getInfuraBeaconUrl(network) {
|
|
2
|
-
const INFURA_ETH2_CREDENTIALS = process.env.INFURA_ETH2_CREDENTIALS;
|
|
3
|
-
if (!INFURA_ETH2_CREDENTIALS) {
|
|
4
|
-
throw Error("Must set ENV INFURA_ETH2_CREDENTIALS");
|
|
5
|
-
}
|
|
6
|
-
return `https://${INFURA_ETH2_CREDENTIALS}@eth2-beacon-${network}.infura.io`;
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=infura.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"infura.js","sourceRoot":"","sources":["../../src/testUtils/infura.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,OAAoB;IACrD,MAAM,uBAAuB,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IACpE,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC7B,MAAM,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,WAAW,uBAAuB,gBAAgB,OAAO,YAAY,CAAC;AAC/E,CAAC"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ChainForkConfig } from "@lodestar/config";
|
|
2
|
-
import { NetworkName } from "@lodestar/config/networks";
|
|
3
|
-
import { SignedBeaconBlock } from "@lodestar/types";
|
|
4
|
-
import { CachedBeaconStateAllForks } from "../index.js";
|
|
5
|
-
/**
|
|
6
|
-
* Create a network config from known network params
|
|
7
|
-
*/
|
|
8
|
-
export declare function getNetworkConfig(network: NetworkName): ChainForkConfig;
|
|
9
|
-
/**
|
|
10
|
-
* Download a state from Infura. Caches states in local fs by network and slot to only download once.
|
|
11
|
-
*/
|
|
12
|
-
export declare function getNetworkCachedState(network: NetworkName, slot: number, timeout?: number): Promise<CachedBeaconStateAllForks>;
|
|
13
|
-
/**
|
|
14
|
-
* Download a state from Infura. Caches states in local fs by network and slot to only download once.
|
|
15
|
-
*/
|
|
16
|
-
export declare function getNetworkCachedBlock(network: NetworkName, slot: number, timeout?: number): Promise<SignedBeaconBlock>;
|
|
17
|
-
//# sourceMappingURL=testFileCache.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"testFileCache.d.ts","sourceRoot":"","sources":["../../src/testUtils/testFileCache.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,eAAe,EAAwB,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAC,WAAW,EAAsB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAC,iBAAiB,EAAC,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAC,yBAAyB,EAAC,MAAM,aAAa,CAAC;AAYtD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,eAAe,CAGtE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,yBAAyB,CAAC,CA4BpC;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,iBAAiB,CAAC,CAyB5B"}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { pubkeyCache } from "@chainsafe/lodestar-z/pubkeys";
|
|
4
|
-
import { getClient } from "@lodestar/api";
|
|
5
|
-
import { createChainForkConfig } from "@lodestar/config";
|
|
6
|
-
import { networksChainConfig } from "@lodestar/config/networks";
|
|
7
|
-
import { fetch } from "@lodestar/utils";
|
|
8
|
-
import { testCachePath } from "./cache.js";
|
|
9
|
-
import { getInfuraBeaconUrl } from "./infura.js";
|
|
10
|
-
import { createCachedBeaconStateTest } from "./state.js";
|
|
11
|
-
/**
|
|
12
|
-
* Full link example:
|
|
13
|
-
* ```
|
|
14
|
-
* https://github.com/dapplion/ethereum-consensus-test-data/releases/download/v0.1.0/block_mainnet_3766821.ssz
|
|
15
|
-
* ``` */
|
|
16
|
-
const TEST_FILES_BASE_URL = "https://github.com/dapplion/ethereum-consensus-test-data/releases/download/v0.1.0";
|
|
17
|
-
/**
|
|
18
|
-
* Create a network config from known network params
|
|
19
|
-
*/
|
|
20
|
-
export function getNetworkConfig(network) {
|
|
21
|
-
const configNetwork = networksChainConfig[network];
|
|
22
|
-
return createChainForkConfig(configNetwork);
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Download a state from Infura. Caches states in local fs by network and slot to only download once.
|
|
26
|
-
*/
|
|
27
|
-
export async function getNetworkCachedState(network, slot, timeout) {
|
|
28
|
-
const config = getNetworkConfig(network);
|
|
29
|
-
const fileId = `state_${network}_${slot}.ssz`;
|
|
30
|
-
const filepath = path.join(testCachePath, fileId);
|
|
31
|
-
if (fs.existsSync(filepath)) {
|
|
32
|
-
const stateSsz = fs.readFileSync(filepath);
|
|
33
|
-
pubkeyCache.reset();
|
|
34
|
-
return createCachedBeaconStateTest(config.getForkTypes(slot).BeaconState.deserializeToViewDU(stateSsz), config);
|
|
35
|
-
}
|
|
36
|
-
const stateSsz = await tryEach([
|
|
37
|
-
() => downloadTestFile(fileId),
|
|
38
|
-
() => {
|
|
39
|
-
const client = getClient({ baseUrl: getInfuraBeaconUrl(network), globalInit: { timeoutMs: timeout ?? 300_000 } }, { config });
|
|
40
|
-
return client.debug.getStateV2({ stateId: slot }).then((r) => {
|
|
41
|
-
return r.ssz();
|
|
42
|
-
});
|
|
43
|
-
},
|
|
44
|
-
]);
|
|
45
|
-
fs.writeFileSync(filepath, stateSsz);
|
|
46
|
-
pubkeyCache.reset();
|
|
47
|
-
return createCachedBeaconStateTest(config.getForkTypes(slot).BeaconState.deserializeToViewDU(stateSsz), config);
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Download a state from Infura. Caches states in local fs by network and slot to only download once.
|
|
51
|
-
*/
|
|
52
|
-
export async function getNetworkCachedBlock(network, slot, timeout) {
|
|
53
|
-
const config = getNetworkConfig(network);
|
|
54
|
-
const fileId = `block_${network}_${slot}.ssz`;
|
|
55
|
-
const filepath = path.join(testCachePath, fileId);
|
|
56
|
-
if (fs.existsSync(filepath)) {
|
|
57
|
-
const blockSsz = fs.readFileSync(filepath);
|
|
58
|
-
return config.getForkTypes(slot).SignedBeaconBlock.deserialize(blockSsz);
|
|
59
|
-
}
|
|
60
|
-
const blockSsz = await tryEach([
|
|
61
|
-
() => downloadTestFile(fileId),
|
|
62
|
-
async () => {
|
|
63
|
-
const client = getClient({ baseUrl: getInfuraBeaconUrl(network), globalInit: { timeoutMs: timeout ?? 300_000 } }, { config });
|
|
64
|
-
return (await client.beacon.getBlockV2({ blockId: slot })).ssz();
|
|
65
|
-
},
|
|
66
|
-
]);
|
|
67
|
-
fs.writeFileSync(filepath, blockSsz);
|
|
68
|
-
return config.getForkTypes(slot).SignedBeaconBlock.deserialize(blockSsz);
|
|
69
|
-
}
|
|
70
|
-
async function downloadTestFile(fileId) {
|
|
71
|
-
const fileUrl = `${TEST_FILES_BASE_URL}/${fileId}`;
|
|
72
|
-
// biome-ignore lint/suspicious/noConsole: We explicity need to log to console
|
|
73
|
-
console.log(`Downloading file ${fileUrl}`);
|
|
74
|
-
try {
|
|
75
|
-
const res = await fetch(fileUrl);
|
|
76
|
-
if (!res.ok) {
|
|
77
|
-
throw new Error(`Error downloading ${fileUrl}: ${res.status} ${res.statusText}`);
|
|
78
|
-
}
|
|
79
|
-
return new Uint8Array(await res.arrayBuffer());
|
|
80
|
-
}
|
|
81
|
-
catch (e) {
|
|
82
|
-
const error = e;
|
|
83
|
-
error.message = `Error downloading ${fileUrl}: ${error.message}`;
|
|
84
|
-
throw error;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
async function tryEach(promises) {
|
|
88
|
-
const errors = [];
|
|
89
|
-
for (let i = 0; i < promises.length; i++) {
|
|
90
|
-
try {
|
|
91
|
-
return await promises[i]();
|
|
92
|
-
}
|
|
93
|
-
catch (e) {
|
|
94
|
-
errors.push(e);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
throw Error(errors.map((e, i) => `Error[${i}] ${e.message}`).join("\n"));
|
|
98
|
-
}
|
|
99
|
-
//# sourceMappingURL=testFileCache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"testFileCache.js","sourceRoot":"","sources":["../../src/testUtils/testFileCache.ts"],"names":[],"mappings":"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"}
|
package/src/testUtils/infura.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import {NetworkName} from "@lodestar/config/networks";
|
|
2
|
-
|
|
3
|
-
export function getInfuraBeaconUrl(network: NetworkName): string {
|
|
4
|
-
const INFURA_ETH2_CREDENTIALS = process.env.INFURA_ETH2_CREDENTIALS;
|
|
5
|
-
if (!INFURA_ETH2_CREDENTIALS) {
|
|
6
|
-
throw Error("Must set ENV INFURA_ETH2_CREDENTIALS");
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
return `https://${INFURA_ETH2_CREDENTIALS}@eth2-beacon-${network}.infura.io`;
|
|
10
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import {pubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
|
|
4
|
-
import {getClient} from "@lodestar/api";
|
|
5
|
-
import {ChainForkConfig, createChainForkConfig} from "@lodestar/config";
|
|
6
|
-
import {NetworkName, networksChainConfig} from "@lodestar/config/networks";
|
|
7
|
-
import {SignedBeaconBlock} from "@lodestar/types";
|
|
8
|
-
import {fetch} from "@lodestar/utils";
|
|
9
|
-
import {CachedBeaconStateAllForks} from "../index.js";
|
|
10
|
-
import {testCachePath} from "./cache.js";
|
|
11
|
-
import {getInfuraBeaconUrl} from "./infura.js";
|
|
12
|
-
import {createCachedBeaconStateTest} from "./state.js";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Full link example:
|
|
16
|
-
* ```
|
|
17
|
-
* https://github.com/dapplion/ethereum-consensus-test-data/releases/download/v0.1.0/block_mainnet_3766821.ssz
|
|
18
|
-
* ``` */
|
|
19
|
-
const TEST_FILES_BASE_URL = "https://github.com/dapplion/ethereum-consensus-test-data/releases/download/v0.1.0";
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Create a network config from known network params
|
|
23
|
-
*/
|
|
24
|
-
export function getNetworkConfig(network: NetworkName): ChainForkConfig {
|
|
25
|
-
const configNetwork = networksChainConfig[network];
|
|
26
|
-
return createChainForkConfig(configNetwork);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Download a state from Infura. Caches states in local fs by network and slot to only download once.
|
|
31
|
-
*/
|
|
32
|
-
export async function getNetworkCachedState(
|
|
33
|
-
network: NetworkName,
|
|
34
|
-
slot: number,
|
|
35
|
-
timeout?: number
|
|
36
|
-
): Promise<CachedBeaconStateAllForks> {
|
|
37
|
-
const config = getNetworkConfig(network);
|
|
38
|
-
const fileId = `state_${network}_${slot}.ssz`;
|
|
39
|
-
|
|
40
|
-
const filepath = path.join(testCachePath, fileId);
|
|
41
|
-
|
|
42
|
-
if (fs.existsSync(filepath)) {
|
|
43
|
-
const stateSsz = fs.readFileSync(filepath);
|
|
44
|
-
pubkeyCache.reset();
|
|
45
|
-
return createCachedBeaconStateTest(config.getForkTypes(slot).BeaconState.deserializeToViewDU(stateSsz), config);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const stateSsz = await tryEach([
|
|
49
|
-
() => downloadTestFile(fileId),
|
|
50
|
-
() => {
|
|
51
|
-
const client = getClient(
|
|
52
|
-
{baseUrl: getInfuraBeaconUrl(network), globalInit: {timeoutMs: timeout ?? 300_000}},
|
|
53
|
-
{config}
|
|
54
|
-
);
|
|
55
|
-
return client.debug.getStateV2({stateId: slot}).then((r) => {
|
|
56
|
-
return r.ssz();
|
|
57
|
-
});
|
|
58
|
-
},
|
|
59
|
-
]);
|
|
60
|
-
|
|
61
|
-
fs.writeFileSync(filepath, stateSsz);
|
|
62
|
-
pubkeyCache.reset();
|
|
63
|
-
return createCachedBeaconStateTest(config.getForkTypes(slot).BeaconState.deserializeToViewDU(stateSsz), config);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Download a state from Infura. Caches states in local fs by network and slot to only download once.
|
|
68
|
-
*/
|
|
69
|
-
export async function getNetworkCachedBlock(
|
|
70
|
-
network: NetworkName,
|
|
71
|
-
slot: number,
|
|
72
|
-
timeout?: number
|
|
73
|
-
): Promise<SignedBeaconBlock> {
|
|
74
|
-
const config = getNetworkConfig(network);
|
|
75
|
-
const fileId = `block_${network}_${slot}.ssz`;
|
|
76
|
-
|
|
77
|
-
const filepath = path.join(testCachePath, fileId);
|
|
78
|
-
|
|
79
|
-
if (fs.existsSync(filepath)) {
|
|
80
|
-
const blockSsz = fs.readFileSync(filepath);
|
|
81
|
-
return config.getForkTypes(slot).SignedBeaconBlock.deserialize(blockSsz);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const blockSsz = await tryEach([
|
|
85
|
-
() => downloadTestFile(fileId),
|
|
86
|
-
async () => {
|
|
87
|
-
const client = getClient(
|
|
88
|
-
{baseUrl: getInfuraBeaconUrl(network), globalInit: {timeoutMs: timeout ?? 300_000}},
|
|
89
|
-
{config}
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
return (await client.beacon.getBlockV2({blockId: slot})).ssz();
|
|
93
|
-
},
|
|
94
|
-
]);
|
|
95
|
-
|
|
96
|
-
fs.writeFileSync(filepath, blockSsz);
|
|
97
|
-
return config.getForkTypes(slot).SignedBeaconBlock.deserialize(blockSsz);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async function downloadTestFile(fileId: string): Promise<Uint8Array> {
|
|
101
|
-
const fileUrl = `${TEST_FILES_BASE_URL}/${fileId}`;
|
|
102
|
-
// biome-ignore lint/suspicious/noConsole: We explicity need to log to console
|
|
103
|
-
console.log(`Downloading file ${fileUrl}`);
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
const res = await fetch(fileUrl);
|
|
107
|
-
if (!res.ok) {
|
|
108
|
-
throw new Error(`Error downloading ${fileUrl}: ${res.status} ${res.statusText}`);
|
|
109
|
-
}
|
|
110
|
-
return new Uint8Array(await res.arrayBuffer());
|
|
111
|
-
} catch (e) {
|
|
112
|
-
const error = e as Error;
|
|
113
|
-
error.message = `Error downloading ${fileUrl}: ${error.message}`;
|
|
114
|
-
throw error;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async function tryEach<T>(promises: (() => Promise<T>)[]): Promise<T> {
|
|
119
|
-
const errors: Error[] = [];
|
|
120
|
-
|
|
121
|
-
for (let i = 0; i < promises.length; i++) {
|
|
122
|
-
try {
|
|
123
|
-
return await promises[i]();
|
|
124
|
-
} catch (e) {
|
|
125
|
-
errors.push(e as Error);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
throw Error(errors.map((e, i) => `Error[${i}] ${e.message}`).join("\n"));
|
|
130
|
-
}
|