diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 64d40541..428a1c9a 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -226,10 +226,25 @@ jobs: test-integration-anvil: name: Test (Integration Anvil) runs-on: ubuntu-latest + env: + NITRO_CONTRACTS_IMAGE_REF: v3.2.0-2f747c7 steps: - name: Checkout uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build nitro contracts image + uses: docker/build-push-action@v6 + with: + context: ./nitro-contracts + file: ./nitro-contracts/Dockerfile + tags: chain-sdk-nitro-contracts:${{ env.NITRO_CONTRACTS_IMAGE_REF }} + load: true + cache-from: type=gha,scope=chain-sdk-nitro-contracts-${{ env.NITRO_CONTRACTS_IMAGE_REF }} + cache-to: type=gha,mode=max,scope=chain-sdk-nitro-contracts-${{ env.NITRO_CONTRACTS_IMAGE_REF }} + - name: Setup pnpm uses: pnpm/action-setup@v4 with: diff --git a/nitro-contracts/Dockerfile b/nitro-contracts/Dockerfile index 4a0df925..eaa45522 100644 --- a/nitro-contracts/Dockerfile +++ b/nitro-contracts/Dockerfile @@ -1,13 +1,37 @@ FROM ghcr.io/foundry-rs/foundry:v1.3.1 AS foundry -FROM node:20-bullseye-slim +FROM node:20-bullseye-slim AS builder + +ARG NITRO_CONTRACTS_REPO_URL=https://github.com/OffchainLabs/nitro-contracts.git +ARG NITRO_CONTRACTS_GIT_COMMIT=2f747c722d98d5fd662bfda08cd86aa534b22be2 COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge +RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* + WORKDIR /workspace -COPY . /workspace + +RUN git init . \ + && git remote add origin "${NITRO_CONTRACTS_REPO_URL}" \ + && git fetch --depth 1 origin "${NITRO_CONTRACTS_GIT_COMMIT}" \ + && git checkout --detach FETCH_HEAD \ + && git submodule update --init --recursive --depth 1 + RUN cp scripts/config.example.ts scripts/config.ts -RUN yarn install +RUN yarn install --frozen-lockfile RUN yarn build:all +FROM node:20-bullseye-slim + +WORKDIR /workspace +COPY --from=builder /workspace/package.json /workspace/package.json +COPY --from=builder /workspace/yarn.lock /workspace/yarn.lock +COPY --from=builder /workspace/hardhat.config.ts /workspace/hardhat.config.ts +COPY --from=builder /workspace/tsconfig.json /workspace/tsconfig.json +COPY --from=builder /workspace/scripts /workspace/scripts +COPY --from=builder /workspace/test/contract /workspace/test/contract +COPY --from=builder /workspace/build /workspace/build +COPY --from=builder /workspace/out /workspace/out +COPY --from=builder /workspace/node_modules /workspace/node_modules + ENTRYPOINT ["yarn"] diff --git a/src/integrationTestHelpers/anvilHarness.ts b/src/integrationTestHelpers/anvilHarness.ts index 7140401d..9717444f 100644 --- a/src/integrationTestHelpers/anvilHarness.ts +++ b/src/integrationTestHelpers/anvilHarness.ts @@ -30,9 +30,9 @@ import { cleanupCurrentHarnessResources, cleanupStaleHarnessContainers, cleanupStaleHarnessNetworks, - createSourceDockerNetwork, - startSourceL1AnvilContainer, - startSourceL2NitroContainer, + createDockerNetwork, + startL1AnvilContainer, + startL2NitroContainer, waitForRpc, } from './dockerHelpers'; import { @@ -105,7 +105,7 @@ export async function setupAnvilTestStack(): Promise { runtimeDir = mkdtempSync(join(tmpdir(), 'chain-sdk-int-test')); prepareNitroRuntimeDir(runtimeDir); dockerNetworkName = `chain-sdk-int-test-net-${Date.now()}`; - createSourceDockerNetwork(dockerNetworkName); + createDockerNetwork(dockerNetworkName); const l2ChainId = testConstants.DEFAULT_L2_CHAIN_ID; const l1RpcPort = testConstants.DEFAULT_L1_RPC_PORT; @@ -143,7 +143,7 @@ export async function setupAnvilTestStack(): Promise { l1ContainerName = `chain-sdk-int-test-l1-${Date.now()}`; console.log('Starting L1 Anvil node...'); - startSourceL1AnvilContainer({ + startL1AnvilContainer({ containerName: l1ContainerName, networkName: dockerNetworkName, l1RpcPort, @@ -225,16 +225,17 @@ export async function setupAnvilTestStack(): Promise { if (l2ChainConfig.arbitrum.DataAvailabilityCommittee) { delete l2NodeConfig.node?.['data-availability']?.['rpc-aggregator']; } + l2NodeConfig.node!['batch-poster']!.enable = false; l2NodeConfig.node!.staker!.enable = false; - const nodeConfigPath = join(runtimeDir, 'source-l2-node-config.json'); + const nodeConfigPath = join(runtimeDir, 'l2-node-config.json'); writeFileSync(nodeConfigPath, JSON.stringify(l2NodeConfig, null, 2), { mode: 0o644 }); // Starting L2 node (Nitro) console.log('Starting L2 Nitro node...'); l2ContainerName = `chain-sdk-int-test-l2-${Date.now()}`; - startSourceL2NitroContainer({ + startL2NitroContainer({ containerName: l2ContainerName, networkName: dockerNetworkName, l2RpcPort, diff --git a/src/integrationTestHelpers/anvilHarnessHelpers.ts b/src/integrationTestHelpers/anvilHarnessHelpers.ts index ebfb2b6e..b780c328 100644 --- a/src/integrationTestHelpers/anvilHarnessHelpers.ts +++ b/src/integrationTestHelpers/anvilHarnessHelpers.ts @@ -94,7 +94,10 @@ function getRollupCreatorDockerArgs( '-e', 'IGNORE_MAX_DATA_SIZE_WARNING=true', nitroContractsImage, - 'deploy-factory', + 'hardhat', + 'run', + '--no-compile', + 'scripts/deployment.ts', '--network', 'custom', ]; diff --git a/src/integrationTestHelpers/constants.ts b/src/integrationTestHelpers/constants.ts index 25f93f75..a6c24619 100644 --- a/src/integrationTestHelpers/constants.ts +++ b/src/integrationTestHelpers/constants.ts @@ -4,9 +4,7 @@ import { ethers } from 'ethers'; export const testConstants = { DEFAULT_ANVIL_IMAGE: 'ghcr.io/foundry-rs/foundry:v1.3.1', DEFAULT_NITRO_IMAGE: 'offchainlabs/nitro-node:v3.9.5-66e42c4', - DEFAULT_NITRO_CONTRACTS_REF: 'v3.2.0', - DEFAULT_NITRO_CONTRACTS_REPO_URL: 'https://github.com/OffchainLabs/nitro-contracts.git', - DEFAULT_NITRO_CONTRACTS_BRANCH: 'feat/add-polling-interval', + DEFAULT_NITRO_CONTRACTS_REF: 'v3.2.0-2f747c7', DEFAULT_L2_CHAIN_ID: 421_337, DEFAULT_L1_RPC_PORT: 9645, DEFAULT_L2_RPC_PORT: 8747, diff --git a/src/integrationTestHelpers/dockerHelpers.ts b/src/integrationTestHelpers/dockerHelpers.ts index 8dc79eb2..55d239e7 100644 --- a/src/integrationTestHelpers/dockerHelpers.ts +++ b/src/integrationTestHelpers/dockerHelpers.ts @@ -1,14 +1,11 @@ import { execFile, execFileSync } from 'node:child_process'; -import { mkdtempSync, rmSync } from 'node:fs'; -import { tmpdir } from 'node:os'; +import { rmSync } from 'node:fs'; import { join } from 'node:path'; import { createPublicClient, http } from 'viem'; import { testConstants } from './constants'; -const cachedNitroContractsImageByTag: Record = {}; - function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } @@ -47,43 +44,19 @@ export function getNitroContractsImage(): string { const imageTag = `chain-sdk-nitro-contracts:${sanitizeDockerTagPart( testConstants.DEFAULT_NITRO_CONTRACTS_REF, )}`; - const cachedImage = cachedNitroContractsImageByTag[imageTag]; - if (cachedImage) { - return cachedImage; - } try { docker(['image', 'inspect', imageTag]); } catch { - const tempDir = mkdtempSync(join(tmpdir(), 'chain-sdk-nitro-contracts-')); - const repoDir = join(tempDir, 'repo'); + const nitroContractsDir = join(process.cwd(), 'nitro-contracts'); const dockerfilePath = join(process.cwd(), 'nitro-contracts', 'Dockerfile'); - - try { - runCommand('git', [ - 'clone', - '--recurse-submodules', - '--shallow-submodules', - '--depth', - '1', - '--branch', - testConstants.DEFAULT_NITRO_CONTRACTS_BRANCH, - '--single-branch', - testConstants.DEFAULT_NITRO_CONTRACTS_REPO_URL, - repoDir, - ]); - - docker(['build', '-f', dockerfilePath, '-t', imageTag, repoDir]); - } finally { - rmSync(tempDir, { recursive: true, force: true }); - } + docker(['build', '-f', dockerfilePath, '-t', imageTag, nitroContractsDir]); } - cachedNitroContractsImageByTag[imageTag] = imageTag; return imageTag; } -export function createSourceDockerNetwork(networkName: string) { +export function createDockerNetwork(networkName: string) { docker(['network', 'create', networkName]); } @@ -237,7 +210,7 @@ export function cleanupStaleHarnessNetworks() { } } -export function startSourceL1AnvilContainer(params: { +export function startL1AnvilContainer(params: { containerName: string; networkName: string; l1RpcPort: number; @@ -275,7 +248,7 @@ export function startSourceL1AnvilContainer(params: { ]); } -export function startSourceL2NitroContainer(params: { +export function startL2NitroContainer(params: { containerName: string; networkName: string; l2RpcPort: number; @@ -295,7 +268,7 @@ export function startSourceL2NitroContainer(params: { `${params.runtimeDir}:/runtime`, params.nitroImage, '--conf.file', - '/runtime/source-l2-node-config.json', + '/runtime/l2-node-config.json', '--persistent.chain', '/runtime/nitro-data', '--ensure-rollup-deployment=false',