mirror of
https://github.com/vacp2p/linea-monorepo.git
synced 2026-01-09 04:08:01 -05:00
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:
1
e2e/env-setup/custom.d.ts
vendored
1
e2e/env-setup/custom.d.ts
vendored
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[],
|
||||
|
||||
Reference in New Issue
Block a user