Skip to content

Commit

Permalink
test: move syncing logic to helper functions (#6638)
Browse files Browse the repository at this point in the history
Move syncing logic to helper functions
  • Loading branch information
nazarhussain authored Apr 5, 2024
1 parent 898cd90 commit 91801fa
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 207 deletions.
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

0 comments on commit 91801fa

Please sign in to comment.