Skip to content
Draft
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
78 changes: 43 additions & 35 deletions src/integrationTestHelpers/anvilHarness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,12 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
parentChainBeaconRpcUrl: sepoliaBeaconRpc,
});

if (l2NodeConfig.execution === undefined || l2NodeConfig.execution.sequencer === undefined) {
throw new Error('L2 node config execution is undefined');
}

l2NodeConfig.execution.sequencer['max-block-speed'] = '100ms';

if (
l2NodeConfig.node === undefined ||
l2NodeConfig.node['batch-poster'] === undefined ||
Expand Down Expand Up @@ -558,6 +564,15 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
}),
account: l2BlockAdvancerAccount,
});
const fundL2BlockAdvancerTxHash = await l2WalletClient.sendTransaction({
account: harnessDeployer,
chain: l2BootstrapChain,
to: l2BlockAdvancerAccount.address,
value: parseEther('1'),
});
await l2Client.waitForTransactionReceipt({ hash: fundL2BlockAdvancerTxHash });
startBlockAdvancing(l2BlockAdvancer);
persistentBlockAdvancers.push(l2BlockAdvancer);

console.log('Configuring L2 fee settings...');
await configureL2Fees(l2Client, l2WalletClient, harnessDeployer);
Expand All @@ -584,13 +599,6 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {

console.log('L2 custom gas token deployed\n');

const tx = await l2Signer.sendTransaction({
to: l2BlockAdvancerAccount.address,
value: parseEther('1'),
...testConstants.LOW_L2_FEE_OVERRIDES,
});
await tx.wait();

console.log('Deploying L2 rollup creator...');
const l2RollupCreator = await deployRollupCreator({
rpcUrl: l2RpcUrl,
Expand Down Expand Up @@ -691,6 +699,12 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
parentChainRpcUrl: `http://${l2ContainerName}:${l2RpcPort}`,
});

if (l3NodeConfig.execution === undefined || l3NodeConfig.execution.sequencer === undefined) {
throw new Error('L3 node config execution is undefined');
}

l3NodeConfig.execution.sequencer['max-block-speed'] = '100ms';

if (
l3NodeConfig.node === undefined ||
l3NodeConfig.node['batch-poster'] === undefined ||
Expand Down Expand Up @@ -743,11 +757,13 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
failIfContainerExited: l3ContainerName,
});
console.log('L3 Nitro node is ready\n');

const l3Client = createPublicClient({
chain: l3Chain,
transport: http(l3RpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
});

const l3WalletClient = createWalletClient({
chain: l3Chain,
transport: http(l3RpcUrl),
Expand All @@ -774,6 +790,17 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
});
console.log('Deployer funded on L3\n');

const l3BlockAdvancer = createBlockAdvancer({
publicClient: l3Client,
walletClient: createWalletClient({
chain: l3Chain,
transport: http(l3RpcUrl),
account: l3BlockAdvancerAccount,
pollingInterval: testConstants.POLLING_INTERVAL,
}),
account: l3BlockAdvancerAccount,
});

console.log('Funding block advancer on L3...');
const fundL3BlockAdvancerTxHash = await l3WalletClient.sendTransaction({
account: harnessDeployer,
Expand All @@ -784,6 +811,9 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
await l3Client.waitForTransactionReceipt({ hash: fundL3BlockAdvancerTxHash });
console.log('Block advancer funded on L3\n');

startBlockAdvancing(l3BlockAdvancer);
persistentBlockAdvancers.push(l3BlockAdvancer);

console.log('Deploying L3 token bridge contracts on L2...');
const { tokenBridgeContracts } = await createTokenBridge({
rollupOwner: harnessDeployer.address,
Expand Down Expand Up @@ -820,29 +850,6 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
});
console.log('L3 token bridge contracts deployed on L2\n');

l2BlockAdvancer.publicClient = l2Client;
l2BlockAdvancer.walletClient = createWalletClient({
chain: l2Chain,
transport: http(l2RpcUrl),
account: l2BlockAdvancerAccount,
pollingInterval: testConstants.POLLING_INTERVAL,
});

const l3BlockAdvancer = createBlockAdvancer({
publicClient: l3Client,
walletClient: createWalletClient({
chain: l3Chain,
transport: http(l3RpcUrl),
account: l3BlockAdvancerAccount,
pollingInterval: testConstants.POLLING_INTERVAL,
}),
account: l3BlockAdvancerAccount,
});

startBlockAdvancing(l2BlockAdvancer);
startBlockAdvancing(l3BlockAdvancer);
persistentBlockAdvancers.push(l2BlockAdvancer, l3BlockAdvancer);

initializedEnv = {
l1: {
rpcUrl: l1RpcUrl,
Expand Down Expand Up @@ -896,23 +903,24 @@ export function getInitializedAnvilTestStackEnv(): AnvilTestStack {
return initializedEnv;
}

export function teardownAnvilTestStack() {
export async function teardownAnvilTestStack() {
if (teardownStarted) {
return;
}
teardownStarted = true;

for (const blockAdvancer of persistentBlockAdvancers) {
void blockAdvancer.stop();
}
const blockAdvancers = persistentBlockAdvancers;
persistentBlockAdvancers = [];

await Promise.all(blockAdvancers.map((blockAdvancer) => blockAdvancer.stop()));

if (l1RpcCachingProxy) {
for (const line of l1RpcCachingProxy.getSummaryLines()) {
console.log(line);
}

l1RpcCachingProxy.close();
await l1RpcCachingProxy.close();
l1RpcCachingProxy = undefined;
}

cleanupCurrentHarnessResources({
Expand Down
48 changes: 19 additions & 29 deletions src/integrationTestHelpers/anvilHarnessHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ export function startBlockAdvancing(blockAdvancer: BlockAdvancer): void {
return;
}

const blockAdvanceIntervalMs = 100;
let keepAdvancingBlocks = true;
const state: BlockAdvancingState = {
stopAdvancing() {
Expand All @@ -439,13 +440,18 @@ export function startBlockAdvancing(blockAdvancer: BlockAdvancer): void {
state.done = (async () => {
try {
while (keepAdvancingBlocks) {
const startedAt = Date.now();

try {
await advanceBlock(blockAdvancer);
} catch {
// ignore and keep advancing blocks
}

await sleep(100);
const remainingDelayMs = blockAdvanceIntervalMs - (Date.now() - startedAt);
if (remainingDelayMs > 0) {
await sleep(remainingDelayMs);
}
}
} finally {
if (blockAdvancingStates.get(blockAdvancer) === state) {
Expand All @@ -457,33 +463,18 @@ export function startBlockAdvancing(blockAdvancer: BlockAdvancer): void {
blockAdvancingStates.set(blockAdvancer, state);
}

async function withBlockAdvancing<T>(
blockAdvancer: BlockAdvancer,
fn: () => Promise<T>,
): Promise<T> {
startBlockAdvancing(blockAdvancer);

try {
return await fn();
} finally {
await blockAdvancer.stop();
}
}

export async function deployRollupCreator(params: DeployRollupCreatorParams): Promise<Address> {
const intTestContractsImage = getIntTestContractsImage();
const stdout = await withBlockAdvancing(params.blockAdvancer, () =>
dockerAsync(
getRollupCreatorDockerArgs(
{
rpcUrl: params.rpcUrl.replace(new URL(params.rpcUrl).hostname, 'host.docker.internal'),
deployerPrivateKey: params.deployerPrivateKey,
factoryOwner: params.factoryOwner,
maxDataSize: params.maxDataSize,
chainId: params.chainId,
},
intTestContractsImage,
),
const stdout = await dockerAsync(
getRollupCreatorDockerArgs(
{
rpcUrl: params.rpcUrl.replace(new URL(params.rpcUrl).hostname, 'host.docker.internal'),
deployerPrivateKey: params.deployerPrivateKey,
factoryOwner: params.factoryOwner,
maxDataSize: params.maxDataSize,
chainId: params.chainId,
},
intTestContractsImage,
),
);

Expand All @@ -505,9 +496,8 @@ export async function deployTokenBridgeCreator(
),
);

const stdout = params.blockAdvancer
? await withBlockAdvancing(params.blockAdvancer, deploy)
: await deploy();
const stdout = await deploy();

const address = parseTokenBridgeCreatorAddress(stdout);
const chain = rpcUrlToChain.get(params.rpcUrl);

Expand Down
2 changes: 1 addition & 1 deletion src/integrationTestHelpers/globalSetup.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ export async function setup(project) {
project.provide('anvilTestStack', structuredClone(dehydrateAnvilTestStack(env)));

return async () => {
teardownAnvilTestStack();
await teardownAnvilTestStack();
};
}
15 changes: 13 additions & 2 deletions src/integrationTestHelpers/rpcCachingProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type CacheFile = {

export type RpcCachingProxy = {
proxyUrl: string;
close: () => void;
close: () => Promise<void>;
getSummaryLines: () => string[];
};

Expand Down Expand Up @@ -243,6 +243,17 @@ export async function startRpcCachingProxy(
` cache misses: ${stats.cacheMisses}`,
` upstream HTTP requests: ${stats.upstreamRequests}`,
],
close: () => server.close(),
close: () =>
new Promise((resolve, reject) => {
server.closeAllConnections?.();
server.close((error) => {
if (error) {
reject(error);
return;
}

resolve();
});
}),
};
}
Loading