Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/beacon-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@
"xxhash-wasm": "1.0.2"
},
"devDependencies": {
"@chainsafe/swap-or-not-shuffle": "^1.2.1",
"@libp2p/interface-internal": "^3.1.12",
"@libp2p/logger": "^6.2.13",
"@libp2p/utils": "^7.4.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/beacon-node/test/spec/presets/shuffling.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import path from "node:path";
import {unshuffleList} from "@chainsafe/swap-or-not-shuffle";
import bindings from "@chainsafe/lodestar-z";
import {ACTIVE_PRESET, SHUFFLE_ROUND_COUNT} from "@lodestar/params";
import {InputType} from "@lodestar/spec-test-util";
import {bnToNum, fromHex} from "@lodestar/utils";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
import {RunnerType, TestRunnerFn} from "../utils/types.js";

const {unshuffleList} = bindings.shuffle;

const shuffling: TestRunnerFn<ShufflingTestCase, string> = () => {
return {
testFunction: (testcase) => {
Expand Down
1 change: 0 additions & 1 deletion packages/state-transition/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
"@chainsafe/lodestar-z": "catalog:",
"@chainsafe/persistent-merkle-tree": "^1.3.1",
"@chainsafe/ssz": "^1.6.3",
"@chainsafe/swap-or-not-shuffle": "^1.2.1",
"@lodestar/config": "workspace:^",
"@lodestar/params": "workspace:^",
"@lodestar/types": "workspace:^",
Expand Down
22 changes: 3 additions & 19 deletions packages/state-transition/src/util/epochShuffling.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {asyncUnshuffleList, unshuffleList} from "@chainsafe/swap-or-not-shuffle";
import bindings from "@chainsafe/lodestar-z";
import {BeaconConfig} from "@lodestar/config";
import {
DOMAIN_BEACON_ATTESTER,
Expand All @@ -16,6 +16,8 @@ import {computeAnchorCheckpoint} from "./computeAnchorCheckpoint.js";
import {computeStartSlotAtEpoch} from "./epoch.js";
import {getSeed} from "./seed.js";

const {unshuffleList} = bindings.shuffle;

/**
* Readonly interface for EpochShuffling.
*/
Expand Down Expand Up @@ -105,24 +107,6 @@ export function computeEpochShuffling(
};
}

export async function computeEpochShufflingAsync(
// TODO: (@matthewkeil) remove state/epoch and pass in seed to clean this up
state: BeaconStateAllForks,
activeIndices: Uint32Array,
epoch: Epoch
): Promise<EpochShuffling> {
const seed = getSeed(state, epoch, DOMAIN_BEACON_ATTESTER);
const shuffling = await asyncUnshuffleList(activeIndices, seed, SHUFFLE_ROUND_COUNT);
const committees = buildCommitteesFromShuffling(shuffling);
return {
epoch,
activeIndices,
shuffling,
committees,
committeesPerSlot: committees[0].length,
};
}

export function calculateDecisionRoot(state: BeaconStateAllForks, epoch: Epoch): RootHex {
const pivotSlot = Math.max(GENESIS_SLOT, computeStartSlotAtEpoch(epoch - 1) - 1);
return toRootHex(getBlockRootAtSlot(state, pivotSlot));
Expand Down
14 changes: 8 additions & 6 deletions packages/state-transition/src/util/seed.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import {digest} from "@chainsafe/as-sha256";
import {
computeProposerIndex as nativeComputeProposerIndex,
computeSyncCommitteeIndices as nativeComputeSyncCommitteeIndices,
} from "@chainsafe/swap-or-not-shuffle";
import bindings from "@chainsafe/lodestar-z";
import {
DOMAIN_BEACON_PROPOSER,
DOMAIN_PTC_ATTESTER,
Expand All @@ -24,6 +21,11 @@ import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js
import {BeaconStateAllForks, CachedBeaconStateAllForks} from "../types.js";
import {computeEpochAtSlot, computeStartSlotAtEpoch} from "./epoch.js";

const {
computeProposerIndex: nativeComputeProposerIndex,
computeSyncCommitteeIndices: nativeComputeSyncCommitteeIndices,
} = bindings.shuffle;

/**
* Compute proposer indices for an epoch
*/
Expand Down Expand Up @@ -117,7 +119,7 @@ export function computeProposerIndex(
}

let maxEffectiveBalance: number;
let randByteCount: number;
let randByteCount: 1 | 2;
if (fork >= ForkSeq.electra) {
maxEffectiveBalance = MAX_EFFECTIVE_BALANCE_ELECTRA;
randByteCount = 2;
Expand Down Expand Up @@ -244,7 +246,7 @@ export function getNextSyncCommitteeIndices(
effectiveBalanceIncrements: EffectiveBalanceIncrements
): Uint32Array {
let maxEffectiveBalance: number;
let randByteCount: number;
let randByteCount: 1 | 2;

if (fork >= ForkSeq.electra) {
maxEffectiveBalance = MAX_EFFECTIVE_BALANCE_ELECTRA;
Expand Down
4 changes: 3 additions & 1 deletion packages/state-transition/test/perf/hashing.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {beforeAll, bench, describe} from "@chainsafe/benchmark";
import {unshuffleList} from "@chainsafe/swap-or-not-shuffle";
import bindings from "@chainsafe/lodestar-z";
import {SHUFFLE_ROUND_COUNT} from "@lodestar/params";
import {ssz} from "@lodestar/types";
import {generatePerfTestCachedStatePhase0, numValidators} from "../../src/testUtils/util.js";

const {unshuffleList} = bindings.shuffle;

// Test cost of hashing state after some modifications

describe("BeaconState hashTreeRoot", () => {
Expand Down
18 changes: 13 additions & 5 deletions packages/state-transition/test/unit/util/shuffling.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {describe, expect, it} from "vitest";
import {SLOTS_PER_EPOCH} from "@lodestar/params";
import {ssz} from "@lodestar/types";
import {computeEpochAtSlot} from "../../../src/index.js";
import {generateState} from "../../../src/testUtils/state.js";
import {computeEpochShuffling, computeEpochShufflingAsync} from "../../../src/util/epochShuffling.js";
import {computeEpochShuffling} from "../../../src/util/epochShuffling.js";

describe("EpochShuffling", () => {
it("async and sync versions should be identical", async () => {
it("should shuffle active indices into a permutation split into committees", () => {
const numberOfValidators = 1000;
const activeIndices = Uint32Array.from(Array.from({length: numberOfValidators}, (_, i) => i));
const state = generateState();
Expand All @@ -24,9 +25,16 @@ describe("EpochShuffling", () => {
);
const epoch = computeEpochAtSlot(state.slot);

const sync = computeEpochShuffling(state, activeIndices, epoch);
const async = await computeEpochShufflingAsync(state, activeIndices, epoch);
const shuffling = computeEpochShuffling(state, activeIndices, epoch);

expect(sync).toStrictEqual(async);
expect(shuffling.epoch).toBe(epoch);
expect(shuffling.activeIndices).toBe(activeIndices);
expect(Array.from(shuffling.shuffling).sort((a, b) => a - b)).toEqual(Array.from(activeIndices));
expect(shuffling.committees.length).toBe(SLOTS_PER_EPOCH);
const committeeSize = shuffling.committees.flat().reduce((sum, c) => sum + c.length, 0);
expect(committeeSize).toBe(numberOfValidators);

// deterministic for the same state and epoch
expect(computeEpochShuffling(state, activeIndices, epoch)).toStrictEqual(shuffling);
});
});
97 changes: 0 additions & 97 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading