Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: move syncing logic to helper functions #6638

Merged
merged 1 commit into from
Apr 5, 2024
Merged
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
56 changes: 4 additions & 52 deletions packages/cli/test/sim/deneb.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/* eslint-disable @typescript-eslint/naming-convention */
import path from "node:path";
import {ApiError} from "@lodestar/api";
import {activePreset} from "@lodestar/params";
import {toHex, toHexString} from "@lodestar/utils";
import {SimulationEnvironment} from "../utils/simulation/SimulationEnvironment.js";
import {nodeAssertion} from "../utils/simulation/assertions/nodeAssertion.js";
import {AssertionMatch, BeaconClient, ExecutionClient} from "../utils/simulation/interfaces.js";
import {defineSimTestConfig, logFilesDir} from "../utils/simulation/utils/index.js";
import {connectAllNodes, connectNewNode, waitForNodeSync, waitForSlot} from "../utils/simulation/utils/network.js";
import {connectAllNodes, waitForSlot} from "../utils/simulation/utils/network.js";
import {assertRangeSync, assertCheckpointSync} from "../utils/simulation/utils/syncing.js";

const altairForkEpoch = 2;
const bellatrixForkEpoch = 4;
Expand Down Expand Up @@ -50,54 +49,7 @@ await waitForSlot(env.clock.getLastSlotOfEpoch(bellatrixForkEpoch) + activePrese
env,
});

// Range Sync
// ========================================================
const headForRangeSync = await env.nodes[0].beacon.api.beacon.getBlockHeader("head");
ApiError.assert(headForRangeSync);
const rangeSync = await env.createNodePair({
id: "range-sync-node",
beacon: BeaconClient.Lodestar,
execution: ExecutionClient.Geth,
keysCount: 0,
});

// Checkpoint sync involves Weak Subjectivity Checkpoint
// ========================================================
const res = await env.nodes[0].beacon.api.beacon.getStateFinalityCheckpoints("head");
ApiError.assert(res);
const headForCheckpointSync = res.response.data.finalized;
const checkpointSync = await env.createNodePair({
id: "checkpoint-sync-node",
beacon: {
type: BeaconClient.Lodestar,
options: {clientOptions: {wssCheckpoint: `${toHex(headForCheckpointSync.root)}:${headForCheckpointSync.epoch}`}},
},
execution: ExecutionClient.Geth,
keysCount: 0,
});

await rangeSync.execution.job.start();
await rangeSync.beacon.job.start();
await connectNewNode(rangeSync, env.nodes);

await checkpointSync.execution.job.start();
await checkpointSync.beacon.job.start();
await connectNewNode(checkpointSync, env.nodes);

await Promise.all([
await waitForNodeSync(env, rangeSync, {
head: toHexString(headForRangeSync.response.data.root),
slot: headForRangeSync.response.data.header.message.slot,
}),
await waitForNodeSync(env, checkpointSync, {
head: toHexString(headForCheckpointSync.root),
slot: env.clock.getLastSlotOfEpoch(headForCheckpointSync.epoch),
}),
]);

await rangeSync.beacon.job.stop();
await rangeSync.execution.job.stop();
await checkpointSync.beacon.job.stop();
await checkpointSync.execution.job.stop();
await assertRangeSync(env);
await assertCheckpointSync(env);

await env.stop();
160 changes: 5 additions & 155 deletions packages/cli/test/sim/multi_fork.test.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
/* eslint-disable @typescript-eslint/naming-convention */
import path from "node:path";
import {sleep, toHex, toHexString} from "@lodestar/utils";
import {ApiError, routes} from "@lodestar/api";
import {AssertionMatch, BeaconClient, ExecutionClient, ValidatorClient} from "../utils/simulation/interfaces.js";
import {SimulationEnvironment} from "../utils/simulation/SimulationEnvironment.js";
import {defineSimTestConfig, logFilesDir} from "../utils/simulation/utils/index.js";
import {
connectAllNodes,
connectNewCLNode,
connectNewELNode,
connectNewNode,
waitForHead,
waitForNodeSync,
waitForSlot,
} from "../utils/simulation/utils/network.js";
import {connectAllNodes, waitForSlot} from "../utils/simulation/utils/network.js";
import {nodeAssertion} from "../utils/simulation/assertions/nodeAssertion.js";
import {mergeAssertion} from "../utils/simulation/assertions/mergeAssertion.js";
import {createForkAssertion} from "../utils/simulation/assertions/forkAssertion.js";
import {createAccountBalanceAssertion} from "../utils/simulation/assertions/accountBalanceAssertion.js";
import {createExecutionHeadAssertion} from "../utils/simulation/assertions/executionHeadAssertion.js";
import {createWithdrawalAssertions} from "../utils/simulation/assertions/withdrawalsAssertion.js";
import {assertCheckpointSync, assertRangeSync, assertUnknownBlockSync} from "../utils/simulation/utils/syncing.js";

const altairForkEpoch = 2;
const bellatrixForkEpoch = 4;
Expand Down Expand Up @@ -174,149 +165,8 @@ await waitForSlot(env.clock.getLastSlotOfEpoch(lastForkEpoch + 1), env.nodes, {
env,
});

// Range Sync
// ========================================================
const headForRangeSync = await env.nodes[0].beacon.api.beacon.getBlockHeader("head");
ApiError.assert(headForRangeSync);
const rangeSync = await env.createNodePair({
id: "range-sync-node",
beacon: BeaconClient.Lodestar,
execution: ExecutionClient.Geth,
keysCount: 0,
});

// Checkpoint sync involves Weak Subjectivity Checkpoint
// ========================================================
const res = await env.nodes[0].beacon.api.beacon.getStateFinalityCheckpoints("head");
ApiError.assert(res);
const headForCheckpointSync = res.response.data.finalized;
const checkpointSync = await env.createNodePair({
id: "checkpoint-sync-node",
beacon: {
type: BeaconClient.Lodestar,
options: {clientOptions: {wssCheckpoint: `${toHex(headForCheckpointSync.root)}:${headForCheckpointSync.epoch}`}},
},
execution: ExecutionClient.Geth,
keysCount: 0,
});

// TODO: A workaround for this issue for sim tests only
// 1. Start the execution node and let it connect to network
// 2. Wait for few seconds
// 3. And later start the beacon node and connect to network
// 4. With this delay the execution node would be synced before the beacon node starts
// https://github.com/ChainSafe/lodestar/issues/6435
// Revert to following code once the issue is fixed
// await rangeSync.execution.job.start();
// await rangeSync.beacon.job.start();
// await connectNewNode(rangeSync, env.nodes);
await rangeSync.execution.job.start();
await connectNewELNode(
rangeSync.execution,
env.nodes.map((node) => node.execution)
);
await sleep(4000);
await rangeSync.beacon.job.start();
await connectNewCLNode(
rangeSync.beacon,
env.nodes.map((node) => node.beacon)
);

await checkpointSync.execution.job.start();
await checkpointSync.beacon.job.start();
await connectNewNode(checkpointSync, env.nodes);

await Promise.all([
await waitForNodeSync(env, rangeSync, {
head: toHexString(headForRangeSync.response.data.root),
slot: headForRangeSync.response.data.header.message.slot,
}),
await waitForNodeSync(env, checkpointSync, {
head: toHexString(headForCheckpointSync.root),
slot: env.clock.getLastSlotOfEpoch(headForCheckpointSync.epoch),
}),
]);

await rangeSync.beacon.job.stop();
await rangeSync.execution.job.stop();
await checkpointSync.beacon.job.stop();
await checkpointSync.execution.job.stop();

// Unknown block sync
// ========================================================
const headForUnknownBlockSync = await env.nodes[0].beacon.api.beacon.getBlockV2("head");
ApiError.assert(headForUnknownBlockSync);
const blobsForUnknownBlockSync = await env.nodes[0].beacon.api.beacon.getBlobSidecars(
headForUnknownBlockSync.response.data.message.slot
);
ApiError.assert(blobsForUnknownBlockSync);
const unknownBlockSync = await env.createNodePair({
id: "unknown-block-sync-node",
beacon: {
type: BeaconClient.Lodestar,
options: {
clientOptions: {
"network.allowPublishToZeroPeers": true,
"sync.disableRangeSync": true,
/*
Initiation of the 'unknownBlockSync' node occurs when other nodes are several epochs ahead.
The effectiveness of the 'unknown block sync' is contingent on the gap being at most 'slotImportTolerance * 2'.
The default 'slotImportTolerance' value is one epoch; thus, if the gap exceeds 2 epochs,
the 'unknown block sync' won't function properly. Moreover, the 'unknownBlockSync' requires some startup time,
contributing to the overall gap. For stability in our CI, we've opted to set a higher limit on this constraint.
*/
"sync.slotImportTolerance": headForUnknownBlockSync.response.data.message.slot,
},
},
},
execution: ExecutionClient.Geth,
keysCount: 0,
});
await unknownBlockSync.execution.job.start();
await unknownBlockSync.beacon.job.start();
await connectNewNode(unknownBlockSync, env.nodes);

// Wait for EL node to start and sync
await sleep(5000);

try {
ApiError.assert(
await unknownBlockSync.beacon.api.beacon.publishBlockV2(
{
signedBlock: headForUnknownBlockSync.response.data,
blobs: blobsForUnknownBlockSync.response.data.map((b) => b.blob),
kzgProofs: blobsForUnknownBlockSync.response.data.map((b) => b.kzgProof),
},
{
broadcastValidation: routes.beacon.BroadcastValidation.none,
}
)
);

env.tracker.record({
message: "Publishing unknown block should fail",
slot: env.clock.currentSlot,
assertionId: "unknownBlockParent",
});
} catch (error) {
if (!(error as Error).message.includes("BLOCK_ERROR_PARENT_UNKNOWN")) {
env.tracker.record({
message: `Publishing unknown block should return "BLOCK_ERROR_PARENT_UNKNOWN" got "${(error as Error).message}"`,
slot: env.clock.currentSlot,
assertionId: "unknownBlockParent",
});
}
}
await waitForHead(env, unknownBlockSync, {
head: toHexString(
env.forkConfig
.getForkTypes(headForUnknownBlockSync.response.data.message.slot)
.BeaconBlock.hashTreeRoot(headForUnknownBlockSync.response.data.message)
),
slot: headForUnknownBlockSync.response.data.message.slot,
});

await unknownBlockSync.beacon.job.stop();
await unknownBlockSync.execution.job.stop();
await assertRangeSync(env);
await assertCheckpointSync(env);
await assertUnknownBlockSync(env);

await env.stop();
Loading
Loading