small e2e CI tweaks (#33)

improve e2e test with dedicated liveness account

Signed-off-by: Pedro Novais <1478752+jpnovais@users.noreply.github.com>
This commit is contained in:
Pedro Novais
2024-10-01 10:20:49 +01:00
committed by GitHub
parent 405d683059
commit 41cec7c602
11 changed files with 76 additions and 76 deletions

View File

@@ -19,6 +19,7 @@ declare global {
var LINEA_ROLLUP_CONTRACT_ADDRESS: string;
var L1_ACCOUNT_0_PRIVATE_KEY: string;
var L2_ACCOUNT_0_PRIVATE_KEY: string;
var L2_ACCOUNT_1_PRIVATE_KEY: string;
var L1_DEPLOYER_ACCOUNT_PRIVATE_KEY: string;
var L2_DEPLOYER_ACCOUNT_PRIVATE_KEY: string;
var TRANSACTION_CALLDATA_LIMIT: number;

View File

@@ -12,6 +12,7 @@ import {
import {
L2_ACCOUNT_0,
L2_ACCOUNT_0_PRIVATE_KEY,
L2_ACCOUNT_1_PRIVATE_KEY,
L1_DEPLOYER_ACCOUNT_PRIVATE_KEY,
L2_DEPLOYER_ACCOUNT_PRIVATE_KEY,
INITIAL_WITHDRAW_LIMIT,
@@ -70,6 +71,7 @@ beforeAll(async () => {
global.lineaRollup = lineaRollup;
global.useLocalSetup = true;
global.L2_ACCOUNT_0_PRIVATE_KEY = L2_ACCOUNT_0_PRIVATE_KEY;
global.L2_ACCOUNT_1_PRIVATE_KEY = L2_ACCOUNT_1_PRIVATE_KEY;
global.L1_DEPLOYER_ACCOUNT_PRIVATE_KEY = L1_DEPLOYER_ACCOUNT_PRIVATE_KEY;
global.L2_DEPLOYER_ACCOUNT_PRIVATE_KEY = L2_DEPLOYER_ACCOUNT_PRIVATE_KEY;
global.TRANSACTION_CALLDATA_LIMIT = TRANSACTION_CALLDATA_LIMIT;

View File

@@ -18,6 +18,7 @@ import {
MESSAGE_SERVICE_ADDRESS,
L1_ACCOUNT_0_PRIVATE_KEY,
L2_ACCOUNT_0_PRIVATE_KEY,
L2_ACCOUNT_1_PRIVATE_KEY,
TRANSACTION_CALLDATA_LIMIT,
OPERATOR_0_PRIVATE_KEY,
SHOMEI_ENDPOINT,
@@ -77,6 +78,7 @@ beforeAll(async () => {
global.chainId = CHAIN_ID;
global.L1_ACCOUNT_0_PRIVATE_KEY = L1_ACCOUNT_0_PRIVATE_KEY;
global.L2_ACCOUNT_0_PRIVATE_KEY = L2_ACCOUNT_0_PRIVATE_KEY;
global.L2_ACCOUNT_1_PRIVATE_KEY = L2_ACCOUNT_1_PRIVATE_KEY;
global.L1_DEPLOYER_ACCOUNT_PRIVATE_KEY = L1_DEPLOYER_ACCOUNT_PRIVATE_KEY;
global.L2_DEPLOYER_ACCOUNT_PRIVATE_KEY = L2_DEPLOYER_ACCOUNT_PRIVATE_KEY;
global.TRANSACTION_CALLDATA_LIMIT = TRANSACTION_CALLDATA_LIMIT;

View File

@@ -1,6 +1,10 @@
import { Wallet, ethers } from "ethers";
import { beforeAll, describe, expect, it } from "@jest/globals";
import { encodeFunctionCall, sendXTransactions, waitForEvents } from "./utils/utils";
import {
encodeFunctionCall,
sendTransactionsToGenerateTrafficWithInterval,
waitForEvents
} from "./utils/utils";
import { getAndIncreaseFeeData } from "./utils/helpers";
import { MESSAGE_SENT_EVENT_SIGNATURE } from "./utils/constants";
@@ -8,10 +12,12 @@ const messagingTestSuite = (title: string) => {
describe(title, () => {
let l1Account: Wallet;
let l2Account0: Wallet;
let l2AccountForLiveness: Wallet;
beforeAll(() => {
l1Account = new Wallet(L1_ACCOUNT_0_PRIVATE_KEY, l1Provider);
l2Account0 = new Wallet(L2_ACCOUNT_0_PRIVATE_KEY, l2Provider);
l2AccountForLiveness = new Wallet(L2_ACCOUNT_1_PRIVATE_KEY, l2Provider);
});
describe("Message Service L1 -> L2", () => {
@@ -46,33 +52,19 @@ const messagingTestSuite = (title: string) => {
const receipt = await tx.wait();
console.log("Moving the L2 chain forward to trigger anchoring...");
const intervalId = await sendTransactionsToGenerateTrafficWithInterval(l2AccountForLiveness);
const [messageSentEvent] = receipt.logs.filter((log) => log.topics[0] === MESSAGE_SENT_EVENT_SIGNATURE);
const messageHash = messageSentEvent.topics[3];
console.log(`L1 message sent: messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
//Extra transactions to trigger anchoring
console.log("Moving the L2 chain forward to trigger anchoring...");
const [maxPriorityFeePerGas2, maxFeePerGas2] = getAndIncreaseFeeData(await l2Provider.getFeeData());
await sendXTransactions(
l2Account0,
{
to: "0x8D97689C9818892B700e27F316cc3E41e17fBeb9",
value: ethers.utils.parseEther("0.0001"),
maxPriorityFeePerGas: maxPriorityFeePerGas2,
maxFeePerGas: maxFeePerGas2,
},
5,
);
console.log("Waiting for MessageClaimed event on L2.");
const [messageClaimedEvent] = await waitForEvents(
l2MessageService,
l2MessageService.filters.MessageClaimed(messageHash),
1_000,
);
clearInterval(intervalId);
console.log(`Message claimed on L2: ${JSON.stringify(messageClaimedEvent)}`);
expect(messageClaimedEvent).toBeDefined();
},
@@ -116,24 +108,14 @@ const messagingTestSuite = (title: string) => {
console.log(`L2 message sent: messageHash=${messageHash} transaction=${JSON.stringify(tx)}`);
console.log("Moving the L2 chain forward to trigger conflation...");
const [maxPriorityFeePerGas2, maxFeePerGas2] = getAndIncreaseFeeData(await l2Provider.getFeeData());
await sendXTransactions(
l2Account0,
{
to: "0x8D97689C9818892B700e27F316cc3E41e17fBeb9",
value: ethers.utils.parseEther("0.0001"),
maxPriorityFeePerGas: maxPriorityFeePerGas2,
maxFeePerGas: maxFeePerGas2,
},
10,
);
const intervalId = await sendTransactionsToGenerateTrafficWithInterval(l2AccountForLiveness);
console.log("Waiting for MessageClaimed event on L1.");
const [messageClaimedEvent] = await waitForEvents(
lineaRollup,
lineaRollup.filters.MessageClaimed(messageHash),
1_000,
lineaRollup.filters.MessageClaimed(messageHash)
);
clearInterval(intervalId);
console.log(`Message claimed on L1: ${JSON.stringify(messageClaimedEvent)}`);
expect(messageClaimedEvent).toBeDefined();

View File

@@ -1,25 +1,32 @@
import { describe, expect, it } from "@jest/globals";
import {describe, expect, it} from "@jest/globals";
import {
getEvents,
execDockerCommand,
sendXTransactions,
waitForEvents,
getMessageSentEventFromLogs,
sendMessage,
sendTransactionsToGenerateTrafficWithInterval,
} from "./utils/utils";
import { getAndIncreaseFeeData } from "./utils/helpers";
import { Wallet, ethers } from "ethers";
// import { MessageEvent } from "./utils/types";
import {getAndIncreaseFeeData} from "./utils/helpers";
import {Wallet, ethers} from "ethers";
const coordinatorRestartTestSuite = (title: string) => {
describe(title, () => {
it("When the coordinator restarts it should resume blob submission and finalization", async () => {
const l2Account0 = new Wallet(L2_ACCOUNT_0_PRIVATE_KEY, l2Provider);
const l2AccountForLiveness = new Wallet(L2_ACCOUNT_1_PRIVATE_KEY, l2Provider);
console.log("Moving the L2 chain forward to trigger conflation...");
const intervalId = await sendTransactionsToGenerateTrafficWithInterval(l2AccountForLiveness);
// await for a finalization to happen on L1
await Promise.all([
waitForEvents(lineaRollup, lineaRollup.filters.DataSubmittedV2(), 0, "latest"),
waitForEvents(lineaRollup, lineaRollup.filters.DataFinalized(), 0, "latest"),
]);
await execDockerCommand("stop", "coordinator");
const currentBlockNumberBeforeRestart = await l1Provider.getBlockNumber();
const [dataSubmittedEventsBeforeRestart, dataFinalizedEventsBeforeRestart] = await Promise.all([
getEvents(lineaRollup, lineaRollup.filters.DataSubmittedV2(), 0, currentBlockNumberBeforeRestart),
getEvents(lineaRollup, lineaRollup.filters.DataFinalized(), 0, currentBlockNumberBeforeRestart),
@@ -27,24 +34,14 @@ const coordinatorRestartTestSuite = (title: string) => {
const lastDataSubmittedEventBeforeRestart = dataSubmittedEventsBeforeRestart.slice(-1)[0];
const lastDataFinalizedEventsBeforeRestart = dataFinalizedEventsBeforeRestart.slice(-1)[0];
// Just some sanity checks
// Check that the coordinator has submitted and finalized data before the restart
expect(lastDataSubmittedEventBeforeRestart.args.endBlock.toNumber()).toBeGreaterThan(0)
expect(lastDataFinalizedEventsBeforeRestart.args.lastBlockFinalized.toNumber()).toBeGreaterThan(0)
await execDockerCommand("start", "coordinator");
const currentBlockNumberAfterRestart = await l1Provider.getBlockNumber();
console.log("Moving the L2 chain forward to trigger conflation...");
const [maxPriorityFeePerGas, maxFeePerGas] = getAndIncreaseFeeData(await l2Provider.getFeeData());
await sendXTransactions(
l2Account0,
{
to: "0x8D97689C9818892B700e27F316cc3E41e17fBeb9",
value: ethers.utils.parseEther("0.0001"),
maxPriorityFeePerGas,
maxFeePerGas,
},
20,
);
console.log("Waiting for DataSubmittedV2 event after coordinator restart...");
const [dataSubmittedV2EventAfterRestart] = await waitForEvents(
lineaRollup,
@@ -68,14 +65,16 @@ const coordinatorRestartTestSuite = (title: string) => {
},
);
console.log(`New DataFinalized event found: event=${JSON.stringify(dataFinalizedEventAfterRestart)}`);
clearInterval(intervalId)
expect(dataFinalizedEventAfterRestart.args.lastBlockFinalized.toNumber()).toBeGreaterThan(
lastDataFinalizedEventsBeforeRestart.args.lastBlockFinalized.toNumber(),
);
}, 300_000);
it("When the coordinator restarts it should resume anchoring", async () => {
const l1MessageSender = new Wallet(L1_ACCOUNT_0_PRIVATE_KEY, l1Provider);
const l2MessageSender = new Wallet(L2_ACCOUNT_0_PRIVATE_KEY, l2Provider);
const l2AccountForLiveness = new Wallet(L2_ACCOUNT_1_PRIVATE_KEY, l2Provider);
// Send Messages L1 -> L2
const messageFee = ethers.utils.parseEther("0.0001");
@@ -112,7 +111,7 @@ const coordinatorRestartTestSuite = (title: string) => {
// Wait for L2 Anchoring
const lastNewL1MessageNumber = l1Messages.slice(-1)[0].messageNumber;
console.log("Waiting for the anchoring using rolling hash...");
console.log(`Waiting L1->L2 anchoring messageNumber=${lastNewL1MessageNumber}`);
await waitForEvents(l2MessageService, l2MessageService.filters.RollingHashUpdated(lastNewL1MessageNumber), 1_000);
// Restart Coordinator
@@ -144,22 +143,14 @@ const coordinatorRestartTestSuite = (title: string) => {
console.log("Moving the L2 chain forward to trigger anchoring...");
// Using 5 messages to give the coordinator time to restart
const [maxPriorityFeePerGas, maxFeePerGas] = getAndIncreaseFeeData(await l2Provider.getFeeData());
await sendXTransactions(
l2MessageSender,
{
to: "0x8D97689C9818892B700e27F316cc3E41e17fBeb9",
value: ethers.utils.parseEther("0.0001"),
maxPriorityFeePerGas,
maxFeePerGas,
},
5,
);
const intervalId = await sendTransactionsToGenerateTrafficWithInterval(l2AccountForLiveness);
// Wait for messages to be anchored on L2
const lastNewL1MessageNumberAfterRestart = l1MessagesAfterRestart.slice(-1)[0].messageNumber;
console.log("Waiting for the anchoring using rolling hash after coordinator restart...");
console.log(
`Waiting L1->L2 anchoring after coordinator restart messageNumber=${lastNewL1MessageNumberAfterRestart}`
);
const [rollingHashUpdatedEventAfterRestart] = await waitForEvents(
l2MessageService,
l2MessageService.filters.RollingHashUpdated(lastNewL1MessageNumberAfterRestart),
@@ -171,6 +162,8 @@ const coordinatorRestartTestSuite = (title: string) => {
l2MessageService.lastAnchoredL1MessageNumber(),
]);
clearInterval(intervalId)
expect(lastNewMessageRollingHashAfterRestart).toEqual(rollingHashUpdatedEventAfterRestart.args.rollingHash);
expect(lastAnchoredL1MessageNumberAfterRestart).toEqual(lastNewL1MessageNumberAfterRestart);
}, 300_000);

View File

@@ -29,6 +29,7 @@ export const L1_ACCOUNT_0_PRIVATE_KEY = "0x47e179ec197488593b187f80a00eb0da91f1b
export const L2_ACCOUNT_0 = "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73";
// WARNING: FOR LOCAL DEV ONLY - DO NOT REUSE THESE KEYS ELSEWHERE
export const L2_ACCOUNT_0_PRIVATE_KEY = "0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63";
export const L2_ACCOUNT_1_PRIVATE_KEY = "0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3";
export const OPERATOR_0 = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8";
// WARNING: FOR LOCAL DEV ONLY - DO NOT REUSE THESE KEYS ELSEWHERE
@@ -56,4 +57,4 @@ export const SHOMEI_ENDPOINT = new URL("http://localhost:8998");
export const SHOMEI_FRONTEND_ENDPOINT = new URL("http://localhost:8889");
export const SEQUENCER_ENDPOINT = new URL("http://localhost:8545")
export const CONTRACT_GAS_OPTIMIZATION_SWITCH_BLOCK = 12;
export const CONTRACT_GAS_OPTIMIZATION_SWITCH_BLOCK = 12;

View File

@@ -1,7 +1,7 @@
import { BlockTag } from "@ethersproject/providers";
import * as fs from "fs";
import assert from "assert";
import { Contract, ContractReceipt, PayableOverrides, Wallet, ethers } from "ethers";
import {Contract, ContractReceipt, PayableOverrides, Wallet, ethers} from "ethers";
import path from "path";
import { exec } from "child_process";
import { L2MessageService, LineaRollup } from "../typechain";
@@ -92,7 +92,7 @@ export async function getEvents<TContract extends LineaRollup | L2MessageService
export async function waitForEvents<TContract extends LineaRollup | L2MessageService, TEvent extends TypedEvent>(
contract: TContract,
eventFilter: TypedEventFilter<TEvent>,
pollingInterval: number,
pollingInterval: number = 500,
fromBlock?: BlockTag,
toBlock?: BlockTag,
criteria?: (events: TEvent[]) => Promise<TEvent[]>,
@@ -170,6 +170,24 @@ export async function sendXTransactions(
}
}
export async function sendTransactionsToGenerateTrafficWithInterval(
signer: Wallet,
pollingInterval: number = 1000,
) {
const [maxPriorityFeePerGas, maxFeePerGas] = getAndIncreaseFeeData(await signer.provider.getFeeData());
const transactionRequest = {
to: signer.address,
value: ethers.utils.parseEther("0.000001"),
maxPriorityFeePerGas: maxPriorityFeePerGas,
maxFeePerGas: maxFeePerGas,
}
return setInterval(async function () {
const tx = await signer.sendTransaction(transactionRequest);
await tx.wait();
}, pollingInterval);
}
export function getMessageSentEventFromLogs<T extends Contract>(
contract: T,
receipts: ContractReceipt[],