diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2172e08cfb2a..1bfad2a8a4db 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,48 +1,10 @@ -# Legacy codebases -/batch-submitter @ethereum-optimism/legacy-reviewers -/bss-core @ethereum-optimism/legacy-reviewers -/gas-oracle @ethereum-optimism/legacy-reviewers -/integration-tests @ethereum-optimism/legacy-reviewers -/l2geth @ethereum-optimism/legacy-reviewers -/l2geth-exporter @ethereum-optimism/legacy-reviewers -/packages/actor-tests @ethereum-optimism/legacy-reviewers -/packages/common-ts @ethereum-optimism/typescript-reviewers -/packages/contracts @ethereum-optimism/contract-reviewers -/packages/contracts-bedrock @ethereum-optimism/contract-reviewers -/packages/contracts-periphery @ethereum-optimism/contract-reviewers -/packages/core-utils @ethereum-optimism/legacy-reviewers -/packages/data-transport-layer @ethereum-optimism/legacy-reviewers -/packages/chain-mon @smartcontracts -/packages/fault-detector @ethereum-optimism/legacy-reviewers -/packages/hardhat-deploy-config @ethereum-optimism/legacy-reviewers -/packages/message-relayer @ethereum-optimism/legacy-reviewers -/packages/migration-data @ethereum-optimism/legacy-reviewers -/packages/replica-healthcheck @ethereum-optimism/legacy-reviewers -/packages/sdk @ethereum-optimism/ecopod -/packages/atst @ethereum-optimism/ecopod - -# Bedrock codebases -/bedrock-devnet @ethereum-optimism/go-reviewers -/op-batcher @ethereum-optimism/go-reviewers -/op-chain-ops @ethereum-optimism/go-reviewers -/op-e2e @ethereum-optimism/go-reviewers -/op-node @ethereum-optimism/go-reviewers -/op-node/rollup @protolambda @trianglesphere -/op-proposer @ethereum-optimism/go-reviewers -/op-program @ethereum-optimism/go-reviewers -/op-service @ethereum-optimism/go-reviewers -/ops-bedrock @ethereum-optimism/go-reviewers - - -# Ops -/.circleci @ethereum-optimism/infra-reviewers -/.github @ethereum-optimism/infra-reviewers -/ops @ethereum-optimism/infra-reviewers -/op-signer @ethereum-optimism/infra-reviewers - -# Misc -/proxyd @ethereum-optimism/infra-reviewers -/indexer @ethereum-optimism/infra-reviewers -/infra @ethereum-optimism/infra-reviewers -/specs @ethereum-optimism/contract-reviewers @ethereum-optimism/go-reviewers -/endpoint-monitor @ethereum-optimism/infra-reviewers +# CODEOWNERS: https://help.github.com/articles/about-codeowners/ + +# Everything goes through the following "global owners" by default. +# Unless a later match takes precedence, these three will be +# requested for review when someone opens a PR. +# Note that the last matching pattern takes precedence, so +# global owners are only requested if there isn't a more specific +# codeowner specified below. For this reason, the global codeowners +# are often repeated in package-level definitions. +* @tuxcanfly @jcstein @Ferret-san diff --git a/.github/auto_request_review.yml b/.github/auto_request_review.yml new file mode 100644 index 000000000000..6257b8a6f8cb --- /dev/null +++ b/.github/auto_request_review.yml @@ -0,0 +1,18 @@ +reviewers: + defaults: + - code-owners + groups: + code-owners: + - tuxcanfly + - jcstein + - Ferret-san + celestia: + - team:celestia +files: + '**': + - code-owners +options: + ignore_draft: true + ignored_keywords: + - WIP + number_of_reviewers: 3 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000000..542de477686a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,25 @@ +version: 2 +updates: + # Check for updates on our docker image and for celestia-node + - package-ecosystem: docker + directory: "/ops-bedrock" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies + # Check for updates on celestia packages + - package-ecosystem: gomod + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 + labels: + - dependencies diff --git a/.github/labeler.yml b/.github/labeler.yml deleted file mode 100644 index 2a7b8f5dfb6d..000000000000 --- a/.github/labeler.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -C-Protocol-Critical: - - 'packages/data-transport-layer/**/*.ts' - - 'packages/contracts/**/*.sol' - - 'l2geth/**/*.go' diff --git a/.github/mergify.yml b/.github/mergify.yml deleted file mode 100644 index 76296581af90..000000000000 --- a/.github/mergify.yml +++ /dev/null @@ -1,137 +0,0 @@ -queue_rules: - - name: default - conditions: [] - -pull_request_rules: - - name: Automatic merge on approval - conditions: - - and: - - "#review-threads-unresolved=0" - - "#approved-reviews-by>=1" - - "#changes-requested-reviews-by=0" - - "label!=do-not-merge" - - "label!=multiple-reviewers" - - "label!=mergify-ignore" - - "base=develop" - - or: - - and: - - "label!=SR-Risk" - - "label!=C-Protocol-Critical" - - and: - - "label=SR-Risk" - - "approved-reviews-by=maurelian" - - and: - - "label=C-Protocol-Critical" - - or: - - "approved-reviews-by=tynes" - - "approved-reviews-by=smartcontracts" - actions: - queue: - name: default - method: merge - merge_bot_account: OptimismBot - - name: Add merge train label - conditions: - - "queue-position >= 0" - actions: - comment: - message: | - This PR has been added to the merge queue, and will be merged soon. - label: - add: - - on-merge-train - - name: Remove merge train label - conditions: - - "queue-position = -1" - actions: - label: - remove: - - on-merge-train - - name: Handle security critical PRs - conditions: - - "label=SR-Risk" - actions: - request_reviews: - users: - - "maurelian" - comment: - message: | - Hey there @{{author}}! You flagged this PR as security critical. To make review easier, please add a comment describing - - 1. The risks present in this PR. - 2. The mitigations you have added to try and reduce those risks. - - name: Request protocol critical reviewers - conditions: - - label=C-Protocol-Critical - actions: - request_reviews: - users: - - tynes - - smartcontracts - random_count: 1 - - name: Ask to resolve conflict - conditions: - - conflict - actions: - comment: - message: Hey @{{author}}! This PR has merge conflicts. Please fix them before continuing review. - label: - add: - - conflict - - name: Remove conflicts label when conflicts gone - conditions: - - -conflict - actions: - label: - remove: - - conflict - - name: Notify author when added to merge queue - conditions: - - "check-pending=Queue: Embarked in merge train" - actions: - comment: - message: | - This PR is next in line to be merged, and will be merged as soon as checks pass. - - name: Notify author on queue failure - conditions: - - 'check-failure=Queue: Embarked in merge train' - actions: - comment: - message: > - Hey @{{ author }}, this pull request failed to merge and has been - dequeued from the merge train. If you believe your PR failed in - the merge train because of a flaky test, requeue it by commenting - with `@mergifyio requeue`. - - More details can be found on the `Queue: Embarked in merge train` - check-run. - - name: Add indexer tag and ecopod reviewers - conditions: - - 'files~=^indexer/' - actions: - label: - add: - - indexer - request_reviews: - users: - - roninjin10 - - name: Add sdk tag and ecopod reviewers - conditions: - - 'files~=^packages/sdk/' - actions: - label: - add: - - sdk - request_reviews: - users: - - roninjin10 - - name: Add common-ts tag and ecopod reviewers - conditions: - - 'files~=^packages/common-ts/' - actions: - label: - add: - - common-ts - request_reviews: - users: - - roninjin10 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000000..a99ea3e7fcfe --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: CI +on: + push: + branches: + - main + # Trigger on version tags + tags: + - 'v[0-9]+\.[0-9]+\.[0-9]+-OP_v[0-9]+\.[0-9]+\.[0-9]+-CN_v[0-9]+\.[0-9]+\.[0-9]+' + - 'v[0-9]+\.[0-9]+\.[0-9]+-OP_v[0-9]+\.[0-9]+\.[0-9]+-CN_v[0-9]+\.[0-9]+\.[0-9]+-rc(?:[0-9]+|\.[0-9]+)' + pull_request: + workflow_dispatch: + # Inputs the workflow accepts. + inputs: + version: + # Friendly description to be shown in the UI instead of 'name' + description: "Semver type of new version (major / minor / patch)" + # Input has to be provided for the workflow to run + required: true + type: choice + options: + - patch + - minor + - major + +jobs: + test: + uses: ./.github/workflows/test.yml + with: + GO_VERSION: '1.20' diff --git a/.github/workflows/close-stale.yml b/.github/workflows/close-stale.yml deleted file mode 100644 index d36e8d6c6b4d..000000000000 --- a/.github/workflows/close-stale.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: 'Close stale issues and PRs' -on: - schedule: - - cron: '30 1 * * *' - -jobs: - stale: - runs-on: ubuntu-latest - steps: - - uses: actions/stale@v4 - with: - stale-pr-message: 'This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days.' - exempt-pr-labels: exempt-stale - days-before-issue-stale: 999 - days-before-pr-stale: 14 - days-before-close: 5 - repo-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/devnet.yml b/.github/workflows/devnet.yml new file mode 100644 index 000000000000..51577b39c9ba --- /dev/null +++ b/.github/workflows/devnet.yml @@ -0,0 +1,10 @@ +# devnet.yml +name: 'Celestia Devnet' +description: 'Launch a local celestia devnet' +runs: + using: 'docker' + image: 'ghcr.io/rollkit/local-celestia-devnet:v0.9.5' + ports: + - 26650:26657 + - 26659:26659 + options: --platform linux/amd64 diff --git a/.github/workflows/housekeeping.yml b/.github/workflows/housekeeping.yml new file mode 100644 index 000000000000..5a7ccd14ecbc --- /dev/null +++ b/.github/workflows/housekeeping.yml @@ -0,0 +1,75 @@ +name: Housekeeping + +on: + issues: + types: [opened] + pull_request_target: + types: [opened] + +jobs: + project: + # ignore dependabot PRs + if: ${{ github.actor != 'dependabot[bot]' }} + name: Add issues and PRs to project and add grooming label + uses: celestiaorg/.github/.github/workflows/reusable_housekeeping.yml@v0.1.1 + secrets: inherit + permissions: + issues: write + pull-requests: write + with: + run-labels: true + labels-to-add: "needs-grooming" + run-projects: true + project-url: https://github.com/orgs/celestiaorg/projects/32 + + auto-add-reviewer: + name: Auto add reviewer to PR + if: github.event.pull_request + uses: celestiaorg/.github/.github/workflows/reusable_housekeeping.yml@v0.1.1 + secrets: inherit + permissions: + issues: write + pull-requests: write + with: + run-auto-request-review: true + + auto-add-assignee: + # ignore dependabot PRs + if: ${{ github.actor != 'dependabot[bot]' }} + name: Assign issue and PR to creator + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: Set issue url and creator login + if: ${{ github.event.issue }} + run: | + echo "ISSUE=${{ github.event.issue.html_url }}" >> $GITHUB_ENV + echo "CREATOR=${{ github.event.issue.user.login }}" >> $GITHUB_ENV + - name: Set pull_request url and creator login + if: ${{ github.event.pull_request }} + # yamllint disable rule:line-length + run: | + echo "PR=${{ github.event.pull_request.html_url }}" >> $GITHUB_ENV + echo "CREATOR=${{ github.event.pull_request.user.login }}" >> $GITHUB_ENV + # yamllint enable rule:line-length + - name: Assign issue to creator (issue) + if: ${{ github.event.issue }} + run: gh issue edit ${{ env.ISSUE }} --add-assignee ${{ env.CREATOR }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Assign issue to creator (PR) + if: ${{ github.event.pull_request }} + run: gh pr edit ${{ env.PR }} --add-assignee ${{ env.CREATOR }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + required-labels: + runs-on: ubuntu-latest + steps: + - uses: mheap/github-action-required-labels@v4 + with: + mode: minimum + count: 1 + labels: "T:enhancement, T:documentation, T:code-hygiene, T:bug, T:adr, T:sdk, T:testing, T:question, T:dependencies, T:spec-and-docs, T:da-integration, T:dev-usability-and-ux" # yamllint disable-line rule:line-length diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml deleted file mode 100644 index f689dfbc359a..000000000000 --- a/.github/workflows/labeler.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -name: "Pull Request Labeler" -on: - - pull_request_target - -jobs: - pr-labeler: - runs-on: ubuntu-latest - steps: - - uses: actions/labeler@main - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" - configuration-path: .github/labeler.yml diff --git a/.github/workflows/publish-canary.yml b/.github/workflows/publish-canary.yml deleted file mode 100644 index 3d690f424ccf..000000000000 --- a/.github/workflows/publish-canary.yml +++ /dev/null @@ -1,587 +0,0 @@ -name: Publish Packages (canary) - -on: - # enable users to manually trigger with workflow_dispatch - workflow_dispatch: - inputs: - customImageName: - description: 'Custom Docker Image Tag (keep empty for git hash)' - required: false - default: '0.0.0-rc-0' - -jobs: - canary-publish: - name: Publish Packages (canary) - runs-on: ubuntu-latest - # map the step outputs to job outputs - outputs: - l2geth: ${{ steps.packages.outputs.l2geth }} - message-relayer: ${{ steps.packages.outputs.message-relayer }} - fault-detector: ${{ steps.packages.outputs.fault-detector }} - balance-mon: ${{ steps.packages.outputs.balance-mon }} - drippie-mon: ${{ steps.packages.outputs.drippie-mon }} - wd-mon: ${{ steps.packages.outputs.wd-mon }} - data-transport-layer: ${{ steps.packages.outputs.data-transport-layer }} - contracts: ${{ steps.packages.outputs.contracts }} - contracts-bedrock: ${{ steps.packages.outputs.contracts-bedrock }} - gas-oracle: ${{ steps.packages.outputs.gas-oracle }} - replica-healthcheck: ${{ steps.packages.outputs.replica-healthcheck }} - hardhat-node: ${{ steps.packages.outputs.hardhat-node }} - canary-docker-tag: ${{ steps.docker-image-name.outputs.canary-docker-tag }} - op-exporter: ${{ steps.packages.outputs.op-exporter }} - l2geth-exporter: ${{ steps.packages.outputs.l2geth-exporter }} - batch-submitter-service: ${{ steps.packages.outputs.batch-submitter-service }} - endpoint-monitor: ${{ steps.packages.outputs.l2geth-exporter }} - - steps: - - name: Check out source code - uses: actions/checkout@v2 - with: - # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits - fetch-depth: 0 - - - name: Setup Node.js 16.x - uses: actions/setup-node@master - with: - node-version: 16.x - - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Install Dependencies - run: yarn --frozen-lockfile - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly - - - name: Build - run: yarn build - - - name: Setup Canary Snapshot - run: yarn changeset version --snapshot - - - name: Publish To NPM - uses: changesets/action@v1 - id: changesets - with: - createGithubReleases: false - publish: yarn changeset publish --tag canary - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - # Conditional on the release being executed, we unbundle the publishedPackages to specific - # job outputs - - name: Get version tags from each published version - id: packages - run: | - node ops/scripts/ci-versions.js ${{ toJSON(steps.changesets.outputs.publishedPackages) }} - - - name: Docker Image Name - id: docker-image-name - run: | - if [ ${CUSTOM_IMAGE_NAME} == '' ] - then - echo "::set-output name=canary-docker-tag::${GITHUB_SHA::8}" - else - echo "::set-output name=canary-docker-tag::prerelease-${CUSTOM_IMAGE_NAME}" - fi - env: - CUSTOM_IMAGE_NAME: ${{ github.event.inputs.customImageName }} - - l2geth: - name: Publish L2Geth Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.l2geth != '' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Publish L2Geth - uses: docker/build-push-action@v2 - with: - context: . - file: ./l2geth/Dockerfile - push: true - tags: ethereumoptimism/l2geth:${{ needs.canary-publish.outputs.canary-docker-tag }} - - gas-oracle: - name: Publish Gas Oracle ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.gas-oracle != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./gas-oracle/Dockerfile - push: true - tags: ethereumoptimism/gas-oracle:${{ needs.canary-publish.outputs.canary-docker-tag }} - - hardhat-node: - name: Publish Hardhat Node ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.hardhat-node != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: ./ops/docker/hardhat - file: ./ops/docker/hardhat/Dockerfile - push: true - tags: ethereumoptimism/hardhat-node:${{ needs.canary-publish.outputs.canary-docker-tag }} - - message-relayer: - name: Publish Message Relayer Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.message-relayer != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: message-relayer - push: true - tags: ethereumoptimism/message-relayer:${{ needs.canary-publish.outputs.canary-docker-tag }} - - fault-detector: - name: Publish Fault Detector Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.fault-detector != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: fault-detector - push: true - tags: ethereumoptimism/fault-detector:${{ needs.canary-publish.outputs.canary-docker-tag }} - - balance-mon: - name: Publish Balance Monitor Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.balance-mon != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: balance-mon - push: true - tags: ethereumoptimism/balance-mon:${{ needs.canary-publish.outputs.canary-docker-tag }} - - drippie-mon: - name: Publish Drippie Monitor Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.drippie-mon != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: drippie-mon - push: true - tags: ethereumoptimism/drippie-mon:${{ needs.canary-publish.outputs.canary-docker-tag }} - - wd-mon: - name: Publish Withdrawal Monitor Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.wd-mon != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: wd-mon - push: true - tags: ethereumoptimism/wd-mon:${{ needs.canary-publish.outputs.canary-docker-tag }} - - data-transport-layer: - name: Publish Data Transport Layer Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.data-transport-layer != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: data-transport-layer - push: true - tags: ethereumoptimism/data-transport-layer:${{ needs.canary-publish.outputs.canary-docker-tag }} - - contracts: - name: Publish Deployer Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.contracts != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: deployer - push: true - tags: ethereumoptimism/deployer:${{ needs.canary-publish.outputs.canary-docker-tag }} - - contracts-bedrock: - name: Publish deployer-bedrock Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.contracts-bedrock != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: deployer-bedrock - push: true - tags: ethereumoptimism/deployer-bedrock:${{ needs.canary-publish.outputs.canary-docker-tag }} - - integration_tests: - name: Publish Integration tests ${{ needs.canary-publish.outputs.integration-tests }} - needs: canary-publish - if: needs.canary-publish.outputs.integration-tests != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: integration-tests - push: true - tags: ethereumoptimism/integration-tests:${{ needs.canary-publish.outputs.canary-docker-tag }} - - replica-healthcheck: - name: Publish Replica Healthcheck Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.replica-healthcheck != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: replica-healthcheck - push: true - tags: ethereumoptimism/replica-healthcheck:${{ needs.canary-publish.outputs.canary-docker-tag }} - - op-exporter: - name: Publish op-exporter Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.op-exporter != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set build args - id: build_args - run: | - echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)" - echo ::set-output name=GITVERSION::$(jq -r .version ./op-exporter/package.json) - echo ::set-output name=GITCOMMIT::"$GITHUB_SHA" - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./op-exporter/Dockerfile= - push: true - tags: ethereumoptimism/op-exporter:${{ needs.canary-publish.outputs.op-exporter }} - build-args: | - GITDATE=${{ steps.build_args.outputs.GITDATE }} - GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }} - GITVERSION=${{ steps.build_args.outputs.GITVERSION }} - - l2geth-exporter: - name: Publish l2geth-exporter Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.l2geth-exporter != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set build args - id: build_args - run: | - echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)" - echo ::set-output name=GITVERSION::$(jq -r .version ./l2geth-exporter/package.json) - echo ::set-output name=GITCOMMIT::"$GITHUB_SHA" - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./l2geth-exporter/Dockerfile - push: true - tags: ethereumoptimism/l2geth-exporter:${{ needs.canary-publish.outputs.l2geth-exporter }} - build-args: | - GITDATE=${{ steps.build_args.outputs.GITDATE }} - GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }} - GITVERSION=${{ steps.build_args.outputs.GITVERSION }} - - batch-submitter-service: - name: Publish batch-submitter-service Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.batch-submitter-service != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./batch-submitter/Dockerfile - push: true - tags: ethereumoptimism/batch-submitter-service:${{ needs.canary-publish.outputs.batch-submitter-service }} - - endpoint-monitor: - name: Publish endpoint-monitor Version ${{ needs.canary-publish.outputs.canary-docker-tag }} - needs: canary-publish - if: needs.canary-publish.outputs.endpoint-monitor != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set build args - id: build_args - run: | - echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)" - echo ::set-output name=GITVERSION::$(jq -r .version ./endpoint-monitor/package.json) - echo ::set-output name=GITCOMMIT::"$GITHUB_SHA" - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./endpoint-monitor/Dockerfile - push: true - tags: ethereumoptimism/endpoint-monitor:${{ needs.canary-publish.outputs.endpoint-monitor }} - build-args: | - GITDATE=${{ steps.build_args.outputs.GITDATE }} - GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }} - GITVERSION=${{ steps.build_args.outputs.GITVERSION }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 4722ce592391..000000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,619 +0,0 @@ -name: Release - -on: - push: - branches: - - master - -jobs: - release: - name: Release - runs-on: ubuntu-latest - # map the step outputs to job outputs - outputs: - l2geth: ${{ steps.packages.outputs.l2geth }} - message-relayer: ${{ steps.packages.outputs.message-relayer }} - fault-detector: ${{ steps.packages.outputs.fault-detector }} - balance-mon: ${{ steps.packages.outputs.drippie-mon }} - drippie-mon: ${{ steps.packages.outputs.drippie-mon }} - wd-mon: ${{ steps.packages.outputs.wd-mon }} - data-transport-layer: ${{ steps.packages.outputs.data-transport-layer }} - contracts: ${{ steps.packages.outputs.contracts }} - contracts-bedrock: ${{ steps.packages.outputs.contracts-bedrock }} - balance-monitor: ${{ steps.packages.outputs.balance-monitor }} - gas-oracle: ${{ steps.packages.outputs.gas-oracle }} - replica-healthcheck: ${{ steps.packages.outputs.replica-healthcheck }} - hardhat-node: ${{ steps.packages.outputs.hardhat-node }} - op-exporter: ${{ steps.packages.outputs.op-exporter }} - l2geth-exporter: ${{ steps.packages.outputs.l2geth-exporter }} - batch-submitter-service: ${{ steps.packages.outputs.batch-submitter-service }} - foundry: ${{ steps.packages.outputs.foundry }} - endpoint-monitor: ${{ steps.packages.outputs.endpoint-monitor }} - - steps: - - name: Checkout Repo - uses: actions/checkout@master - with: - # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits - fetch-depth: 0 - - - name: Setup Node.js 16.x - uses: actions/setup-node@master - with: - node-version: 16.x - - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - - uses: actions/cache@v2 - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Install Dependencies - run: yarn --frozen-lockfile - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly - - - name: Publish To NPM or Create Release Pull Request - uses: changesets/action@v1 - id: changesets - with: - createGithubReleases: false - publish: yarn release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - # Conditional on the release being executed, we unbundle the publishedPackages to specific - # job outputs - - name: Get version tags from each published version - id: packages - if: steps.changesets.outputs.published == 'true' - run: | - node ops/scripts/ci-versions.js ${{ toJSON(steps.changesets.outputs.publishedPackages) }} - - l2geth: - name: Publish L2Geth Version ${{ needs.release.outputs.l2geth }} - needs: release - if: needs.release.outputs.l2geth != '' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Publish L2Geth - uses: docker/build-push-action@v2 - with: - context: . - file: ./l2geth/Dockerfile - push: true - tags: ethereumoptimism/l2geth:${{ needs.release.outputs.l2geth }},ethereumoptimism/l2geth:latest - - gas-oracle: - name: Publish Gas Oracle Version ${{ needs.release.outputs.gas-oracle }} - needs: release - if: needs.release.outputs.gas-oracle != '' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Publish Gas Oracle - uses: docker/build-push-action@v2 - with: - context: . - file: ./gas-oracle/Dockerfile - push: true - tags: ethereumoptimism/gas-oracle:${{ needs.release.outputs.gas-oracle }},ethereumoptimism/gas-oracle:latest - - hardhat-node: - name: Publish Hardhat Node ${{ needs.release.outputs.hardhat-node }} - needs: release - if: needs.release.outputs.hardhat-node != '' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Publish Hardhat Node - uses: docker/build-push-action@v2 - with: - context: ./ops/docker/hardhat - file: ./ops/docker/hardhat/Dockerfile - push: true - tags: ethereumoptimism/hardhat-node:${{ needs.release.outputs.hardhat-node }},ethereumoptimism/hardhat-node:latest - - foundry: - name: Publish foundry ${{ needs.release.outputs.foundry }} - needs: release - if: needs.release.outputs.foundry != '' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Publish foundry - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/foundry/Dockerfile - push: true - tags: ethereumoptimism/foundry:${{ needs.release.outputs.foundry }},ethereumoptimism/foundry:latest - - l2geth-exporter: - name: Publish l2geth-exporter Version ${{ needs.release.outputs.l2geth-exporter}} - needs: release - if: needs.release.outputs.l2geth-exporter != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set build args - id: build_args - run: | - echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)" - echo ::set-output name=GITVERSION::$(jq -r .version ./l2geth-exporter/package.json) - echo ::set-output name=GITCOMMIT::"$GITHUB_SHA" - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./l2geth-exporter/Dockerfile - push: true - tags: ethereumoptimism/l2geth-exporter:${{ needs.release.outputs.l2geth-exporter }},ethereumoptimism/l2geth-exporter:latest - build-args: | - GITDATE=${{ steps.build_args.outputs.GITDATE }} - GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }} - GITVERSION=${{ steps.build_args.outputs.GITVERSION }} - - op-exporter: - name: Publish op-exporter Version ${{ needs.release.outputs.op-exporter}} - needs: release - if: needs.release.outputs.op-exporter != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set build args - id: build_args - run: | - echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)" - echo ::set-output name=GITVERSION::$(jq -r .version ./op-exporter/package.json) - echo ::set-output name=GITCOMMIT::"$GITHUB_SHA" - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./op-exporter/Dockerfile - push: true - tags: ethereumoptimism/op-exporter:${{ needs.release.outputs.op-exporter }},ethereumoptimism/op-exporter:latest - build-args: | - GITDATE=${{ steps.build_args.outputs.GITDATE }} - GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }} - GITVERSION=${{ steps.build_args.outputs.GITVERSION }} - - message-relayer: - name: Publish Message Relayer Version ${{ needs.release.outputs.message-relayer }} - needs: release - if: needs.release.outputs.message-relayer != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: message-relayer - push: true - tags: ethereumoptimism/message-relayer:${{ needs.release.outputs.message-relayer }},ethereumoptimism/message-relayer:latest - - fault-detector: - name: Publish Fault Detector Version ${{ needs.release.outputs.fault-detector }} - needs: release - if: needs.release.outputs.fault-detector != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: fault-detector - push: true - tags: ethereumoptimism/fault-detector:${{ needs.release.outputs.fault-detector }},ethereumoptimism/fault-detector:latest - - wd-mon: - name: Publish Withdrawal Monitor Version ${{ needs.release.outputs.wd-mon }} - needs: release - if: needs.release.outputs.wd-mon != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: wd-mon - push: true - tags: ethereumoptimism/wd-mon:${{ needs.release.outputs.wd-mon }},ethereumoptimism/wd-mon:latest - - balance-mon: - name: Publish Balance Monitor Version ${{ needs.release.outputs.balance-mon }} - needs: release - if: needs.release.outputs.balance-mon != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: balance-mon - push: true - tags: ethereumoptimism/balance-mon:${{ needs.release.outputs.balance-mon }},ethereumoptimism/balance-mon:latest - - drippie-mon: - name: Publish Drippie Monitor Version ${{ needs.release.outputs.drippie-mon }} - needs: release - if: needs.release.outputs.drippie-mon != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: drippie-mon - push: true - tags: ethereumoptimism/drippie-mon:${{ needs.release.outputs.drippie-mon }},ethereumoptimism/drippie-mon:latest - - data-transport-layer: - name: Publish Data Transport Layer Version ${{ needs.release.outputs.data-transport-layer }} - needs: release - if: needs.release.outputs.data-transport-layer != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: data-transport-layer - push: true - tags: ethereumoptimism/data-transport-layer:${{ needs.release.outputs.data-transport-layer }},ethereumoptimism/data-transport-layer:latest - - contracts: - name: Publish Deployer Version ${{ needs.release.outputs.contracts }} - needs: release - if: needs.release.outputs.contracts != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: deployer - push: true - tags: ethereumoptimism/deployer:${{ needs.release.outputs.contracts }},ethereumoptimism/deployer:latest - - contracts-bedrock: - name: Publish deployer-bedrock Version ${{ needs.release.outputs.contracts-bedrock }} - needs: release - if: needs.release.outputs.contracts != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: deployer-bedrock - push: true - tags: ethereumoptimism/deployer-bedrock:${{ needs.release.outputs.contracts-bedrock }},ethereumoptimism/deployer-bedrock:latest - - balance-monitor: - name: Publish balance-monitor Version ${{ needs.release.outputs.balance-monitor }} - needs: release - if: needs.release.outputs.balance-monitor != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: balance-monitor - push: true - tags: ethereumoptimism/balance-monitor:${{ needs.release.outputs.balance-monitor }},ethereumoptimism/balance-monitor:latest - - integration_tests: - name: Publish Integration tests ${{ needs.release.outputs.integration-tests }} - needs: release - if: needs.release.outputs.integration-tests != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: integration-tests - push: true - tags: ethereumoptimism/integration-tests:${{ needs.release.outputs.integration-tests }},ethereumoptimism/integration-tests:latest - - replica-healthcheck: - name: Publish Replica Healthcheck Version ${{ needs.release.outputs.replica-healthcheck }} - needs: release - if: needs.release.outputs.replica-healthcheck != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./ops/docker/Dockerfile.packages - target: replica-healthcheck - push: true - tags: ethereumoptimism/replica-healthcheck:${{ needs.release.outputs.replica-healthcheck }},ethereumoptimism/replica-healthcheck:latest - - batch-submitter-service: - name: Publish batch-submitter-service Version ${{ needs.release.outputs.batch-submitter-service }} - needs: release - if: needs.release.outputs.batch-submitter-service != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./batch-submitter/Dockerfile - push: true - tags: ethereumoptimism/batch-submitter-service:${{ needs.release.outputs.batch-submitter-service }},ethereumoptimism/batch-submitter-service:latest - - endpoint-monitor: - name: Publish endpoint-monitor Version ${{ needs.release.outputs.endpoint-monitor}} - needs: release - if: needs.release.outputs.endpoint-monitor != '' - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} - password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} - - - name: Set build args - id: build_args - run: | - echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)" - echo ::set-output name=GITVERSION::$(jq -r .version ./endpoint-monitor/package.json) - echo ::set-output name=GITCOMMIT::"$GITHUB_SHA" - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./endpoint-monitor/Dockerfile - push: true - tags: ethereumoptimism/endpoint-monitor:${{ needs.release.outputs.endpoint-monitor }},ethereumoptimism/endpoint-monitor:latest - build-args: | - GITDATE=${{ steps.build_args.outputs.GITDATE }} - GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }} - GITVERSION=${{ steps.build_args.outputs.GITVERSION }} diff --git a/.github/workflows/tag-service.yml b/.github/workflows/tag-service.yml deleted file mode 100644 index d7a24fb1d099..000000000000 --- a/.github/workflows/tag-service.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Tag Service - -on: - workflow_dispatch: - inputs: - bump: - description: 'How much to bump the version by' - required: true - type: choice - options: - - major - - minor - - patch - - prerelease - - finalize-prerelease - service: - description: 'Which service to release' - required: true - type: choice - options: - - op-node - - op-batcher - - op-proposer - - proxyd - - indexer - prerelease: - description: Increment major/minor/patch as prerelease? - required: false - type: boolean - default: false - -jobs: - release: - runs-on: ubuntu-latest - environment: op-stack-production - - steps: - - uses: actions/checkout@v2 - - name: Fetch tags - run: git fetch --tags origin - - name: Setup Python 3.10 - uses: actions/setup-python@v4 - with: - python-version: "3.10" - - name: Install deps - run: pip install -r requirements.txt - working-directory: ops/tag-service - - run: ops/tag-service/tag-service.py --bump="$BUMP" --service="$SERVICE" - env: - INPUT_GITHUB_TOKEN: ${{ github.token }} - BUMP: ${{ github.event.inputs.bump }} - SERVICE: ${{ github.event.inputs.service }} - if: ${{ github.event.inputs.prerelease == 'false' }} - - run: ops/tag-service/tag-service.py --bump="$BUMP" --service="$SERVICE" --pre-release - env: - INPUT_GITHUB_TOKEN: ${{ github.token }} - BUMP: ${{ github.event.inputs.bump }} - SERVICE: ${{ github.event.inputs.service }} - if: ${{ github.event.inputs.prerelease == 'true' }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000000..507e7b761b73 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,28 @@ +name: Tests +on: + workflow_call: + inputs: + GO_VERSION: + description: 'Go version to use' + type: string + required: true + +jobs: + integration_test: + name: Run Integration Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: set up go + uses: actions/setup-go@v4 + with: + go-version: ${{ inputs.GO_VERSION }} + + - name: Integration Tests + run: | + cd op-e2e + docker run --platform linux/amd64 -p 26650:26657 -p 26659:26659 ghcr.io/rollkit/local-celestia-devnet:v0.9.5 & sleep 15 + make test + docker stop $(docker ps -q --filter ancestor=ghcr.io/rollkit/local-celestia-devnet:v0.9.5) + cd .. diff --git a/Makefile b/Makefile index fb6ba7049db5..c9ddb9805e53 100644 --- a/Makefile +++ b/Makefile @@ -65,26 +65,46 @@ devnet-up: @bash ./ops-bedrock/devnet-up.sh .PHONY: devnet-up +testnet-up: + @bash ./ops-bedrock/testnet-up.sh +.PHONY: testnet-up + devnet-up-deploy: PYTHONPATH=./bedrock-devnet python3 ./bedrock-devnet/main.py --monorepo-dir=. .PHONY: devnet-up-deploy devnet-down: - @(cd ./ops-bedrock && GENESIS_TIMESTAMP=$(shell date +%s) docker-compose stop) + @(cd ./ops-bedrock && GENESIS_TIMESTAMP=$(shell date +%s) docker-compose -f docker-compose-devnet.yml stop) .PHONY: devnet-down +testnet-down: + @(cd ./ops-bedrock && GENESIS_TIMESTAMP=$(shell date +%s) docker-compose -f docker-compose-testnet.yml stop) +.PHONY: testnet-down + devnet-clean: rm -rf ./packages/contracts-bedrock/deployments/devnetL1 rm -rf ./.devnet - cd ./ops-bedrock && docker-compose down + cd ./ops-bedrock && docker-compose -f docker-compose-devnet.yml down docker image ls 'ops-bedrock*' --format='{{.Repository}}' | xargs -r docker rmi docker volume ls --filter name=ops-bedrock --format='{{.Name}}' | xargs -r docker volume rm .PHONY: devnet-clean +testnet-clean: + rm -rf ./packages/contracts-bedrock/deployments/devnetL1 + rm -rf ./.devnet + cd ./ops-bedrock && docker-compose -f docker-compose-testnet.yml down + docker image ls 'ops-bedrock*' --format='{{.Repository}}' | xargs -r docker rmi + docker volume ls --filter name=ops-bedrock --format='{{.Name}}' | xargs -r docker volume rm +.PHONY: testnet-clean + devnet-logs: - @(cd ./ops-bedrock && docker-compose logs -f) + @(cd ./ops-bedrock && docker-compose -f docker-compose-devnet.yml logs -f) .PHONY: devnet-logs +testnet-logs: + @(cd ./ops-bedrock && docker-compose -f docker-compose-testnet.yml logs -f) + .PHONY: testnet-logs + test-unit: make -C ./op-node test make -C ./op-proposer test diff --git a/README.md b/README.md index 767fce6e619a..f80278262734 100644 --- a/README.md +++ b/README.md @@ -3,50 +3,96 @@

Optimism +

Optimism is a low-cost and lightning-fast Ethereum L2 blockchain, built with the OP Stack.


-

Optimism is a low-cost and lightning-fast Ethereum L2 blockchain.

+

+

+ Celestia +

Celestia is a modular consensus and data network, built to enable anyone to easily deploy their own blockchain with minimal overhead.


-## What is Optimism? +## Celestia + OP Stack tutorial + +If you're looking to run the OP Stack + Celestia setup for this repository, please visit the [Optimism & Celestia guides and tutorials](https://docs.celestia.org/developers/intro-to-op-stack/) to get started. + +## What are Optimism and the OP Stack? Optimism is a low-cost and lightning-fast Ethereum L2 blockchain, **but it's also so much more than that**. -Optimism is the technical foundation for [the Optimism Collective](https://app.optimism.io/announcement), a band of communities, companies, and citizens united by a mutually beneficial pact to adhere to the axiom of **impact=profit** — the principle that positive impact to the collective should be rewarded with profit to the individual. -We're trying to solve some of the most critical coordination failures facing the crypto ecosystem today. -**We're particularly focused on creating a sustainable funding stream for the public goods and infrastructure upon which the ecosystem so heavily relies but has so far been unable to adequately reward.** -We'd love for you to check out [The Optimistic Vision](https://www.optimism.io/vision) to understand more about why we do what we do. +The OP Stack powers Optimism, an Ethereum L2 blockchain, and forms the technical foundation for the [the Optimism Collective](https://app.optimism.io/announcement)—a group committed to the **impact=profit** principle. This principle rewards individuals for their positive contributions to the collective. + +Optimism addresses critical coordination failures in the crypto ecosystem, such as funding public goods and infrastructure. The OP Stack focuses on creating a shared, open-source system for developing new L2 blockchains within the proposed Superchain ecosystem, promoting collaboration and preventing redundant efforts. + +As Optimism evolves, the OP Stack will adapt, encompassing components ranging from blockchain infrastructure to governance systems. This software suite aims to simplify L2 blockchain creation while supporting the growth and development of the Optimism ecosystem. + +## What is Celestia? + +Celestia is a modular consensus and data network, built to enable anyone to easily deploy their own blockchain with minimal overhead. + +Celestia is a minimal blockchain that only orders and publishes transactions and does not execute them. By decoupling the consensus and application execution layers, Celestia modularizes the blockchain technology stack and unlocks new possibilities for decentralized application builders. Lean more at [Celestia.org](https://celestia.org). ## Documentation -If you want to build on top of Optimism, take a look at the extensive documentation on the [Optimism Community Hub](http://community.optimism.io/). -If you want to build Optimism, check out the [Protocol Specs](./specs/). +If you want to build on top of Celestia, take a look at the documentation at [docs.celestia.org](https://docs.celestia.org). + +If you want to learn more about the OP Stack, check out the documentation at [stack.optimism.io](https://stack.optimism.io/). ## Community +### Optimism + General discussion happens most frequently on the [Optimism discord](https://discord.gg/optimism). Governance discussion can also be found on the [Optimism Governance Forum](https://gov.optimism.io/). -## Contributing +### Celestia + +General discussion happens most frequently on the [Celestia discord](https://discord.com/invite/YsnTPcSfWQ). +Other discussions can be found on the [Celestia forum](https://forum.celestia.org). + + + +## e2e testing + +This repository has updated end-to-end tests in the `op-e2e` package to work with +Celestia as the data availability (DA) layer. + +Currently, the tests assume a working [Celestia devnet](https://github.com/rollkit/local-celestia-devnet) running locally: + +```bash +docker run --platform linux/amd64 -p 26650:26657 -p 26659:26659 ghcr.io/rollkit/local-celestia-devnet:v0.9.5 +``` -## Security Policy and Vulnerability Reporting +The e2e tests can be triggered with: -Please refer to our canonical [Security Policy](https://github.com/ethereum-optimism/.github/blob/master/SECURITY.md) document for detailed information about how to report vulnerabilities in this codebase. -Bounty hunters are encouraged to check out [our Immunefi bug bounty program](https://immunefi.com/bounty/optimism/). -We offer up to $2,000,042 for in-scope critical vulnerabilities and [we pay our maximum bug bounty rewards](https://medium.com/ethereum-optimism/disclosure-fixing-a-critical-bug-in-optimisms-geth-fork-a836ebdf7c94). +```bash +cd $HOME/optimism +cd op-e2e +make test +``` -## The Bedrock Upgrade +## Bridging -Optimism is currently preparing for [its next major upgrade called Bedrock](https://dev.optimism.io/introducing-optimism-bedrock/). -Bedrock significantly revamps how Optimism works under the hood and will help make Optimism the fastest, cheapest, and most reliable rollup yet. -You can find detailed specifications for the Bedrock upgrade within the [specs folder](./specs) in this repository. +If you have the OP Stack + Celestia setup running, you can test out bridging from the L1 +to the L2. -Please note that a significant number of packages and folders within this repository are part of the Bedrock upgrade and are NOT currently running in production. -Refer to the Directory Structure section below to understand which packages are currently running in production and which are intended for use as part of the Bedrock upgrade. +To do this, first navigate to the `packages/contracts-bedrock` directory and create a +`.env` file with the following contents: + +```bash +L1_PROVIDER_URL=http://localhost:8545 +L2_PROVIDER_URL=http://localhost:9545 +PRIVATE_KEY=bf7604d9d3a1c7748642b1b7b05c2bd219c9faa91458b370f85e5a40f3b03af7 +``` + +Then, run the following from the same directory: + +```bash +npx hardhat deposit --network devnetL1 --l1-provider-url http://localhost:8545 --l2-provider-url http://localhost:9545 --amount-eth --to
+``` ## Directory Structure @@ -86,7 +132,7 @@ Refer to the Directory Structure section below to understand which packages are ├── ops-bedrock: Bedrock devnet work └── specs: Specs of the rollup starting at the Bedrock upgrade - + diff --git a/bedrock-devnet/devnet/__init__.py b/bedrock-devnet/devnet/__init__.py index f9a6c494301e..a81aa1bd733f 100644 --- a/bedrock-devnet/devnet/__init__.py +++ b/bedrock-devnet/devnet/__init__.py @@ -111,6 +111,10 @@ def main(): }) wait_up(9545) + log.info('Bringing up DA') + run_command(['docker-compose', 'up', '-d', 'da'], cwd=ops_bedrock_dir, env={ + 'PWD': ops_bedrock_dir, + }) log.info('Bringing up everything else.') run_command(['docker-compose', 'up', '-d', 'op-node', 'op-proposer', 'op-batcher'], cwd=ops_bedrock_dir, env={ 'PWD': ops_bedrock_dir, diff --git a/docs/op-stack/src/assets/docs/understand/Celestia-logo-color-color.svg b/docs/op-stack/src/assets/docs/understand/Celestia-logo-color-color.svg new file mode 100644 index 000000000000..6d22cb408925 --- /dev/null +++ b/docs/op-stack/src/assets/docs/understand/Celestia-logo-color-color.svg @@ -0,0 +1 @@ +Celestia-logo-color-black \ No newline at end of file diff --git a/go.mod b/go.mod index 1c672dd091b0..dda40320e21f 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( github.com/btcsuite/btcd v0.23.3 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 + github.com/celestiaorg/go-cnc v0.3.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 github.com/docker/docker v20.10.24+incompatible github.com/docker/go-connections v0.4.0 @@ -29,7 +30,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/prometheus/client_golang v1.14.0 github.com/schollz/progressbar/v3 v3.13.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.2 github.com/urfave/cli v1.22.9 github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa golang.org/x/crypto v0.6.0 @@ -72,6 +73,7 @@ require ( github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect @@ -125,7 +127,6 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/pointerstructure v1.2.1 // indirect github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c // indirect - github.com/morikuni/aec v1.0.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect @@ -137,7 +138,7 @@ require ( github.com/multiformats/go-varint v0.0.7 // indirect github.com/onsi/ginkgo/v2 v2.8.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect diff --git a/go.sum b/go.sum index d80b907b8057..bc6d4a1f5335 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= +github.com/celestiaorg/go-cnc v0.3.0 h1:eAVPNHGpx+2sBO7NZyQ1+VW8rzf6W4FQDlSq6aqSTsM= +github.com/celestiaorg/go-cnc v0.3.0/go.mod h1:zYzvHudSd1iNPuHBMyvZ1YvWou5aT9JXgtch9Tkaf70= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= @@ -241,6 +243,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= +github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -579,7 +583,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -641,8 +644,8 @@ github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9 github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -787,8 +790,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= @@ -955,6 +958,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index 37d879263f1d..6f290b7cf3b8 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -2,6 +2,7 @@ package batcher import ( "context" + "encoding/hex" "errors" "fmt" "io" @@ -45,6 +46,17 @@ type BatchSubmitter struct { // NewBatchSubmitterFromCLIConfig initializes the BatchSubmitter, gathering any resources // that will be needed during operation. func NewBatchSubmitterFromCLIConfig(cfg CLIConfig, l log.Logger, m metrics.Metricer) (*BatchSubmitter, error) { + var nid [8]byte + + if cfg.TxMgrConfig.NamespaceId == "" { + return nil, errors.New("namespace id cannot be blank") + } + namespaceId, err := hex.DecodeString(cfg.TxMgrConfig.NamespaceId) + if err != nil { + return nil, err + } + copy(nid[:], namespaceId) + ctx := context.Background() // Connect to L1 and L2 providers. Perform these last since they are the @@ -99,12 +111,12 @@ func NewBatchSubmitterFromCLIConfig(cfg CLIConfig, l log.Logger, m metrics.Metri return nil, err } - return NewBatchSubmitter(ctx, batcherCfg, l, m) + return NewBatchSubmitter(ctx, nid, batcherCfg, l, m) } // NewBatchSubmitter initializes the BatchSubmitter, gathering any resources // that will be needed during operation. -func NewBatchSubmitter(ctx context.Context, cfg Config, l log.Logger, m metrics.Metricer) (*BatchSubmitter, error) { +func NewBatchSubmitter(ctx context.Context, nid [8]byte, cfg Config, l log.Logger, m metrics.Metricer) (*BatchSubmitter, error) { balance, err := cfg.L1Client.BalanceAt(ctx, cfg.TxManager.From(), nil) if err != nil { return nil, err diff --git a/op-batcher/flags/flags.go b/op-batcher/flags/flags.go index 006017ef8bcd..37e225180fbe 100644 --- a/op-batcher/flags/flags.go +++ b/op-batcher/flags/flags.go @@ -33,6 +33,12 @@ var ( Usage: "HTTP provider URL for Rollup node", EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ROLLUP_RPC"), } + DaRpcFlag = cli.StringFlag{ + Name: "da-rpc", + Usage: "HTTP provider URL for DA node", + Required: true, + EnvVar: opservice.PrefixEnvVar(envVarPrefix, "DA_RPC"), + } SubSafetyMarginFlag = cli.Uint64Flag{ Name: "sub-safety-margin", Usage: "The batcher tx submission safety margin (in #L1-blocks) to subtract " + @@ -91,6 +97,7 @@ var requiredFlags = []cli.Flag{ L1EthRpcFlag, L2EthRpcFlag, RollupRpcFlag, + DaRpcFlag, SubSafetyMarginFlag, PollIntervalFlag, } diff --git a/op-celestia/go.mod b/op-celestia/go.mod new file mode 100644 index 000000000000..7c93d7dd595e --- /dev/null +++ b/op-celestia/go.mod @@ -0,0 +1,11 @@ +module github.com/ethereum-optimism/optimism/op-celestia + +go 1.19 + +require github.com/celestiaorg/go-cnc v0.3.0 + +require ( + github.com/go-resty/resty/v2 v2.7.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 // indirect +) diff --git a/op-celestia/go.sum b/op-celestia/go.sum new file mode 100644 index 000000000000..4ca6d4fd8472 --- /dev/null +++ b/op-celestia/go.sum @@ -0,0 +1,42 @@ +github.com/celestiaorg/go-cnc v0.3.0 h1:eAVPNHGpx+2sBO7NZyQ1+VW8rzf6W4FQDlSq6aqSTsM= +github.com/celestiaorg/go-cnc v0.3.0/go.mod h1:zYzvHudSd1iNPuHBMyvZ1YvWou5aT9JXgtch9Tkaf70= +github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= +github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 h1:Yqz/iviulwKwAREEeUd3nbBFn0XuyJqkoft2IlrvOhc= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/op-celestia/main.go b/op-celestia/main.go new file mode 100644 index 000000000000..e328c45f9755 --- /dev/null +++ b/op-celestia/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "bytes" + "context" + "encoding/binary" + "encoding/hex" + "fmt" + "os" + "time" + + "github.com/celestiaorg/go-cnc" +) + +func main() { + data, _ := hex.DecodeString(os.Args[1]) + buf := bytes.NewBuffer(data) + var height int64 + err := binary.Read(buf, binary.BigEndian, &height) + if err != nil { + panic(err) + } + var index uint32 + err = binary.Read(buf, binary.BigEndian, &index) + if err != nil { + panic(err) + } + fmt.Printf("celestia block height: %v; tx index: %v\n", height, index) + fmt.Println("-----------------------------------------") + client, err := cnc.NewClient("http://localhost:26659", cnc.WithTimeout(30*time.Second)) + if err != nil { + panic(err) + } + namespaceId, _ := hex.DecodeString("e8e5f679bf7116cbe5f679ef") + var nid [8]byte + copy(nid[:], namespaceId) + namespacedData, err := client.NamespacedData(context.Background(), nid, uint64(height)) + if err != nil { + panic(err) + } + fmt.Printf("optimism block data on celestia: %x\n", namespacedData) +} diff --git a/op-e2e/actions/l2_verifier.go b/op-e2e/actions/l2_verifier.go index d1293ecc7c6f..99b2a9bdb49e 100644 --- a/op-e2e/actions/l2_verifier.go +++ b/op-e2e/actions/l2_verifier.go @@ -57,7 +57,9 @@ type L2API interface { func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, eng L2API, cfg *rollup.Config) *L2Verifier { metrics := &testutils.TestDerivationMetrics{} - pipeline := derive.NewDerivationPipeline(log, cfg, l1, eng, metrics) + daCfg, err := rollup.NewDAConfig("http://localhost:26659", "e8e5f679bf7116cb") + require.NoError(t, err) + pipeline := derive.NewDerivationPipeline(log, cfg, daCfg, l1, eng, metrics) pipeline.Reset() rollupNode := &L2Verifier{ diff --git a/op-e2e/setup.go b/op-e2e/setup.go index 6e99c0bb54be..c3e7a2c9a799 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -57,6 +57,7 @@ func newTxMgrConfig(l1Addr string, privKey *ecdsa.PrivateKey) txmgr.CLIConfig { ReceiptQueryInterval: 50 * time.Millisecond, NetworkTimeout: 2 * time.Second, TxNotInMempoolTimeout: 2 * time.Minute, + NamespaceId: "e8e5f679bf7116cb", } } @@ -532,6 +533,13 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { c.Rollup.LogDescription(cfg.Loggers[name], chaincfg.L2ChainIDToNetworkName) + daCfg, err := rollup.NewDAConfig("http://127.0.0.1:26659", "e8e5f679bf7116cb") + if err != nil { + return nil, err + } + + c.DAConfig = *daCfg + node, err := rollupNode.New(context.Background(), &c, cfg.Loggers[name], snapLog, "", metrics.NewMetrics("")) if err != nil { didErrAfterStart = true diff --git a/op-node/flags/flags.go b/op-node/flags/flags.go index ded27af0b72e..4672761da1fe 100644 --- a/op-node/flags/flags.go +++ b/op-node/flags/flags.go @@ -38,6 +38,18 @@ var ( Usage: "Rollup chain parameters", EnvVar: prefixEnvVar("ROLLUP_CONFIG"), } + DaRPC = cli.StringFlag{ + Name: "da-rpc", + Usage: "Data Availability RPC", + Value: "http://da:26659", + EnvVar: prefixEnvVar("DA_RPC"), + } + NamespaceId = cli.StringFlag{ + Name: "namespace-id", + Usage: "Namespace ID for DA node", + Value: "e8e5f679bf7116cb", + EnvVar: prefixEnvVar("NAMESPACE_ID"), + } Network = cli.StringFlag{ Name: "network", Usage: fmt.Sprintf("Predefined network selection. Available networks: %s", strings.Join(chaincfg.AvailableNetworks(), ", ")), @@ -218,6 +230,8 @@ var requiredFlags = []cli.Flag{ var optionalFlags = []cli.Flag{ RollupConfig, + DaRPC, + NamespaceId, Network, L1TrustRPC, L1RPCProviderKind, diff --git a/op-node/node/config.go b/op-node/node/config.go index 37533a868aa0..f85e1f61a474 100644 --- a/op-node/node/config.go +++ b/op-node/node/config.go @@ -21,6 +21,8 @@ type Config struct { Rollup rollup.Config + DAConfig rollup.DAConfig + // P2PSigner will be used for signing off on published content // if the node is sequencing and if the p2p stack is enabled P2PSigner p2p.SignerSetup diff --git a/op-node/node/node.go b/op-node/node/node.go index 0dd4b89144e9..3c30178e9fc5 100644 --- a/op-node/node/node.go +++ b/op-node/node/node.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/metrics" "github.com/ethereum-optimism/optimism/op-node/p2p" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/sources" ) @@ -39,6 +40,7 @@ type OpNode struct { p2pSigner p2p.Signer // p2p gogssip application messages will be signed with this signer tracer Tracer // tracer to get events for testing/debugging runCfg *RuntimeConfig // runtime configurables + daCfg *rollup.DAConfig // some resources cannot be stopped directly, like the p2p gossipsub router (not our design), // and depend on this ctx to be closed. @@ -74,7 +76,15 @@ func New(ctx context.Context, cfg *Config, log log.Logger, snapshotLog log.Logge return n, nil } +func (n *OpNode) initDA(ctx context.Context, cfg *Config) error { + n.daCfg = &cfg.DAConfig + return nil +} + func (n *OpNode) init(ctx context.Context, cfg *Config, snapshotLog log.Logger) error { + if err := n.initDA(ctx, cfg); err != nil { + return err + } if err := n.initTracer(ctx, cfg); err != nil { return err } @@ -199,7 +209,7 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config, snapshotLog log.Logger return err } - n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, n, n, n.log, snapshotLog, n.metrics) + n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.daCfg, n.l2Source, n.l1Source, n, n, n.log, snapshotLog, n.metrics) return nil } diff --git a/op-node/rollup/da_config.go b/op-node/rollup/da_config.go new file mode 100644 index 000000000000..1d67fc046f38 --- /dev/null +++ b/op-node/rollup/da_config.go @@ -0,0 +1,33 @@ +package rollup + +import ( + "encoding/hex" + "time" + + "github.com/celestiaorg/go-cnc" +) + +type DAConfig struct { + Rpc string + NamespaceId [8]byte + Client *cnc.Client +} + +func NewDAConfig(rpc string, namespaceId string) (*DAConfig, error) { + var nid [8]byte + n, err := hex.DecodeString(namespaceId) + if err != nil { + return &DAConfig{}, err + } + copy(nid[:], n) + daClient, err := cnc.NewClient(rpc, cnc.WithTimeout(30*time.Second)) + if err != nil { + return &DAConfig{}, err + } + + return &DAConfig{ + NamespaceId: nid, + Rpc: rpc, + Client: daClient, + }, nil +} diff --git a/op-node/rollup/derive/calldata_source.go b/op-node/rollup/derive/calldata_source.go index 52314420a8de..98a796931d05 100644 --- a/op-node/rollup/derive/calldata_source.go +++ b/op-node/rollup/derive/calldata_source.go @@ -1,7 +1,10 @@ package derive import ( + "bytes" "context" + "encoding/binary" + "encoding/hex" "errors" "fmt" "io" @@ -29,16 +32,17 @@ type L1TransactionFetcher interface { type DataSourceFactory struct { log log.Logger cfg *rollup.Config + daCfg *rollup.DAConfig fetcher L1TransactionFetcher } -func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, fetcher L1TransactionFetcher) *DataSourceFactory { - return &DataSourceFactory{log: log, cfg: cfg, fetcher: fetcher} +func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, daCfg *rollup.DAConfig, fetcher L1TransactionFetcher) *DataSourceFactory { + return &DataSourceFactory{log: log, cfg: cfg, daCfg: daCfg, fetcher: fetcher} } // OpenData returns a DataIter. This struct implements the `Next` function. func (ds *DataSourceFactory) OpenData(ctx context.Context, id eth.BlockID, batcherAddr common.Address) DataIter { - return NewDataSource(ctx, ds.log, ds.cfg, ds.fetcher, id, batcherAddr) + return NewDataSource(ctx, ds.log, ds.cfg, ds.daCfg, ds.fetcher, id, batcherAddr) } // DataSource is a fault tolerant approach to fetching data. @@ -51,6 +55,7 @@ type DataSource struct { // Required to re-attempt fetching id eth.BlockID cfg *rollup.Config // TODO: `DataFromEVMTransactions` should probably not take the full config + daCfg *rollup.DAConfig fetcher L1TransactionFetcher log log.Logger @@ -59,7 +64,7 @@ type DataSource struct { // NewDataSource creates a new calldata source. It suppresses errors in fetching the L1 block if they occur. // If there is an error, it will attempt to fetch the result on the next call to `Next`. -func NewDataSource(ctx context.Context, log log.Logger, cfg *rollup.Config, fetcher L1TransactionFetcher, block eth.BlockID, batcherAddr common.Address) DataIter { +func NewDataSource(ctx context.Context, log log.Logger, cfg *rollup.Config, daCfg *rollup.DAConfig, fetcher L1TransactionFetcher, block eth.BlockID, batcherAddr common.Address) DataIter { _, txs, err := fetcher.InfoAndTxsByHash(ctx, block.Hash) if err != nil { return &DataSource{ @@ -71,9 +76,20 @@ func NewDataSource(ctx context.Context, log log.Logger, cfg *rollup.Config, fetc batcherAddr: batcherAddr, } } else { + data, err := DataFromEVMTransactions(cfg, daCfg, batcherAddr, txs, log.New("origin", block)) + if err != nil { + return &DataSource{ + open: false, + id: block, + cfg: cfg, + fetcher: fetcher, + log: log, + batcherAddr: batcherAddr, + } + } return &DataSource{ open: true, - data: DataFromEVMTransactions(cfg, batcherAddr, txs, log.New("origin", block)), + data: data, } } } @@ -85,7 +101,10 @@ func (ds *DataSource) Next(ctx context.Context) (eth.Data, error) { if !ds.open { if _, txs, err := ds.fetcher.InfoAndTxsByHash(ctx, ds.id.Hash); err == nil { ds.open = true - ds.data = DataFromEVMTransactions(ds.cfg, ds.batcherAddr, txs, log.New("origin", ds.id)) + ds.data, err = DataFromEVMTransactions(ds.cfg, ds.daCfg, ds.batcherAddr, txs, log.New("origin", ds.id)) + if err != nil { + return nil, NewTemporaryError(fmt.Errorf("failed to open calldata source: %w", err)) + } } else if errors.Is(err, ethereum.NotFound) { return nil, NewResetError(fmt.Errorf("failed to open calldata source: %w", err)) } else { @@ -104,7 +123,7 @@ func (ds *DataSource) Next(ctx context.Context) (eth.Data, error) { // DataFromEVMTransactions filters all of the transactions and returns the calldata from transactions // that are sent to the batch inbox address from the batch sender address. // This will return an empty array if no valid transactions are found. -func DataFromEVMTransactions(config *rollup.Config, batcherAddr common.Address, txs types.Transactions, log log.Logger) []eth.Data { +func DataFromEVMTransactions(config *rollup.Config, daCfg *rollup.DAConfig, batcherAddr common.Address, txs types.Transactions, log log.Logger) ([]eth.Data, error) { var out []eth.Data l1Signer := config.L1Signer() for j, tx := range txs { @@ -119,8 +138,43 @@ func DataFromEVMTransactions(config *rollup.Config, batcherAddr common.Address, log.Warn("tx in inbox with unauthorized submitter", "index", j, "err", err) continue // not an authorized batch submitter, ignore } - out = append(out, tx.Data()) + + if daCfg != nil { + height, index, err := decodeETHData(tx.Data()) + if err != nil { + log.Warn("unable to decode data pointer", "index", j, "err", err) + continue + } + log.Warn("requesting celestia namespaced data", "namespace", hex.EncodeToString(daCfg.NamespaceId[:]), "height", height) + data, err := daCfg.Client.NamespacedData(context.Background(), daCfg.NamespaceId, uint64(height)) + if err != nil { + log.Warn("unable to retrieve data from da", "err", err) + return nil, err + } + log.Warn("retrieved data", "data", hex.EncodeToString(data[index])) + out = append(out, data[index]) + } else { + out = append(out, tx.Data()) + } } } - return out + return out, nil +} + +// decodeETHData will decode the data retrieved from the EVM, this data +// was previously posted from op-batcher and contains the block height +// with transaction index of the SubmitPFD transaction to the DA. +func decodeETHData(celestiaData []byte) (int64, uint32, error) { + buf := bytes.NewBuffer(celestiaData) + var height int64 + err := binary.Read(buf, binary.BigEndian, &height) + if err != nil { + return 0, 0, fmt.Errorf("error deserializing height: %w", err) + } + var index uint32 + err = binary.Read(buf, binary.BigEndian, &index) + if err != nil { + return 0, 0, fmt.Errorf("error deserializing index: %w", err) + } + return height, index, nil } diff --git a/op-node/rollup/derive/calldata_source_test.go b/op-node/rollup/derive/calldata_source_test.go index b7bfcd5a4ddf..a57fdb4e7d4c 100644 --- a/op-node/rollup/derive/calldata_source_test.go +++ b/op-node/rollup/derive/calldata_source_test.go @@ -121,8 +121,9 @@ func TestDataFromEVMTransactions(t *testing.T) { } } - out := DataFromEVMTransactions(cfg, batcherAddr, txs, testlog.Logger(t, log.LvlCrit)) + out, err := DataFromEVMTransactions(cfg, nil, batcherAddr, txs, testlog.Logger(t, log.LvlCrit)) require.ElementsMatch(t, expectedData, out) + require.NoError(t, err) } } diff --git a/op-node/rollup/derive/pipeline.go b/op-node/rollup/derive/pipeline.go index 4dcd74a8e778..22cbc97163ae 100644 --- a/op-node/rollup/derive/pipeline.go +++ b/op-node/rollup/derive/pipeline.go @@ -75,11 +75,11 @@ type DerivationPipeline struct { } // NewDerivationPipeline creates a derivation pipeline, which should be reset before use. -func NewDerivationPipeline(log log.Logger, cfg *rollup.Config, l1Fetcher L1Fetcher, engine Engine, metrics Metrics) *DerivationPipeline { +func NewDerivationPipeline(log log.Logger, cfg *rollup.Config, daCfg *rollup.DAConfig, l1Fetcher L1Fetcher, engine Engine, metrics Metrics) *DerivationPipeline { // Pull stages l1Traversal := NewL1Traversal(log, cfg, l1Fetcher) - dataSrc := NewDataSourceFactory(log, cfg, l1Fetcher) // auxiliary stage for L1Retrieval + dataSrc := NewDataSourceFactory(log, cfg, daCfg, l1Fetcher) // auxiliary stage for L1Retrieval l1Src := NewL1Retrieval(log, dataSrc, l1Traversal) frameQueue := NewFrameQueue(log, l1Src) bank := NewChannelBank(log, cfg, frameQueue, l1Fetcher) diff --git a/op-node/rollup/driver/driver.go b/op-node/rollup/driver/driver.go index 08d1c844eca9..500ea102b076 100644 --- a/op-node/rollup/driver/driver.go +++ b/op-node/rollup/driver/driver.go @@ -102,12 +102,12 @@ type AltSync interface { } // NewDriver composes an events handler that tracks L1 state, triggers L2 derivation, and optionally sequences new L2 blocks. -func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, altSync AltSync, network Network, log log.Logger, snapshotLog log.Logger, metrics Metrics) *Driver { +func NewDriver(driverCfg *Config, cfg *rollup.Config, daCfg *rollup.DAConfig, l2 L2Chain, l1 L1Chain, altSync AltSync, network Network, log log.Logger, snapshotLog log.Logger, metrics Metrics) *Driver { l1State := NewL1State(log, metrics) sequencerConfDepth := NewConfDepth(driverCfg.SequencerConfDepth, l1State.L1Head, l1) findL1Origin := NewL1OriginSelector(log, cfg, sequencerConfDepth) verifConfDepth := NewConfDepth(driverCfg.VerifierConfDepth, l1State.L1Head, l1) - derivationPipeline := derive.NewDerivationPipeline(log, cfg, verifConfDepth, l2, metrics) + derivationPipeline := derive.NewDerivationPipeline(log, cfg, daCfg, verifConfDepth, l2, metrics) attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, l2) engine := derivationPipeline meteredEngine := NewMeteredEngine(cfg, engine, metrics, log) diff --git a/op-node/service.go b/op-node/service.go index d1df687dd0ca..88e65d652589 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -57,12 +57,18 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { l2SyncEndpoint := NewL2SyncEndpointConfig(ctx) + daCfg, err := rollup.NewDAConfig(flags.DaRPC.Value, flags.NamespaceId.Value) + if err != nil { + return nil, fmt.Errorf("failed to load da config: %w", err) + } + cfg := &node.Config{ - L1: l1Endpoint, - L2: l2Endpoint, - L2Sync: l2SyncEndpoint, - Rollup: *rollupConfig, - Driver: *driverConfig, + L1: l1Endpoint, + L2: l2Endpoint, + L2Sync: l2SyncEndpoint, + Rollup: *rollupConfig, + DAConfig: *daCfg, + Driver: *driverConfig, RPC: node.RPCConfig{ ListenAddr: ctx.GlobalString(flags.RPCListenAddr.Name), ListenPort: ctx.GlobalInt(flags.RPCListenPort.Name), diff --git a/op-program/client/boot.go b/op-program/client/boot.go index 064aa392c7f5..11d29fb20e31 100644 --- a/op-program/client/boot.go +++ b/op-program/client/boot.go @@ -14,6 +14,7 @@ import ( type BootInfo struct { // TODO(CLI-XXX): The rollup config will be hardcoded. It's configurable for testing purposes. Rollup *rollup.Config `json:"rollup"` + DAConfig *rollup.DAConfig `json:"da_config"` L2ChainConfig *params.ChainConfig `json:"l2_chain_config"` L1Head common.Hash `json:"l1_head"` L2Head common.Hash `json:"l2_head"` diff --git a/op-program/client/driver/driver.go b/op-program/client/driver/driver.go index 8372d1996a82..4d98b807a6f4 100644 --- a/op-program/client/driver/driver.go +++ b/op-program/client/driver/driver.go @@ -34,8 +34,8 @@ type Driver struct { targetBlockNum uint64 } -func NewDriver(logger log.Logger, cfg *rollup.Config, l1Source derive.L1Fetcher, l2Source L2Source, targetBlockNum uint64) *Driver { - pipeline := derive.NewDerivationPipeline(logger, cfg, l1Source, l2Source, metrics.NoopMetrics) +func NewDriver(logger log.Logger, cfg *rollup.Config, daCfg *rollup.DAConfig, l1Source derive.L1Fetcher, l2Source L2Source, targetBlockNum uint64) *Driver { + pipeline := derive.NewDerivationPipeline(logger, cfg, daCfg, l1Source, l2Source, metrics.NoopMetrics) pipeline.Reset() return &Driver{ logger: logger, diff --git a/op-program/client/program.go b/op-program/client/program.go index fa14dcca6cbf..0d3a1669f446 100644 --- a/op-program/client/program.go +++ b/op-program/client/program.go @@ -52,6 +52,7 @@ func RunProgram(logger log.Logger, bootOracle io.Reader, preimageOracle io.ReadW return runDerivation( logger, bootInfo.Rollup, + bootInfo.DAConfig, bootInfo.L2ChainConfig, bootInfo.L1Head, bootInfo.L2Head, @@ -63,7 +64,7 @@ func RunProgram(logger log.Logger, bootOracle io.Reader, preimageOracle io.ReadW } // runDerivation executes the L2 state transition, given a minimal interface to retrieve data. -func runDerivation(logger log.Logger, cfg *rollup.Config, l2Cfg *params.ChainConfig, l1Head common.Hash, l2Head common.Hash, l2Claim common.Hash, l2ClaimBlockNum uint64, l1Oracle l1.Oracle, l2Oracle l2.Oracle) error { +func runDerivation(logger log.Logger, cfg *rollup.Config, daCfg *rollup.DAConfig, l2Cfg *params.ChainConfig, l1Head common.Hash, l2Head common.Hash, l2Claim common.Hash, l2ClaimBlockNum uint64, l1Oracle l1.Oracle, l2Oracle l2.Oracle) error { l1Source := l1.NewOracleL1Client(logger, l1Oracle, l1Head) engineBackend, err := l2.NewOracleBackedL2Chain(logger, l2Oracle, l2Cfg, l2Head) if err != nil { @@ -72,7 +73,7 @@ func runDerivation(logger log.Logger, cfg *rollup.Config, l2Cfg *params.ChainCon l2Source := l2.NewOracleEngine(cfg, logger, engineBackend) logger.Info("Starting derivation") - d := cldr.NewDriver(logger, cfg, l1Source, l2Source, l2ClaimBlockNum) + d := cldr.NewDriver(logger, cfg, daCfg, l1Source, l2Source, l2ClaimBlockNum) for { if err = d.Step(context.Background()); errors.Is(err, io.EOF) { break diff --git a/op-proposer/flags/flags.go b/op-proposer/flags/flags.go index dcd5d9cfd047..b97af0b10865 100644 --- a/op-proposer/flags/flags.go +++ b/op-proposer/flags/flags.go @@ -38,6 +38,12 @@ var ( "creating a new batch", EnvVar: opservice.PrefixEnvVar(envVarPrefix, "POLL_INTERVAL"), } + DaRpcFlag = cli.StringFlag{ + Name: "da-rpc", + Usage: "HTTP provider URL for DA node", + Required: true, + EnvVar: opservice.PrefixEnvVar(envVarPrefix, "DA_RPC"), + } // Optional flags AllowNonFinalizedFlag = cli.BoolFlag{ Name: "allow-non-finalized", @@ -53,6 +59,7 @@ var requiredFlags = []cli.Flag{ RollupRpcFlag, L2OOAddressFlag, PollIntervalFlag, + DaRpcFlag, } var optionalFlags = []cli.Flag{ diff --git a/op-proposer/proposer/l2_output_submitter.go b/op-proposer/proposer/l2_output_submitter.go index 0b6120877612..a977d5a526ca 100644 --- a/op-proposer/proposer/l2_output_submitter.go +++ b/op-proposer/proposer/l2_output_submitter.go @@ -328,9 +328,8 @@ func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.Out return err } receipt, err := l.txMgr.Send(ctx, txmgr.TxCandidate{ - TxData: data, - To: &l.l2ooContractAddr, - GasLimit: 0, + TxData: data, + To: &l.l2ooContractAddr, }) if err != nil { return err diff --git a/op-service/txmgr/cli.go b/op-service/txmgr/cli.go index eb4ac7899b21..0dff03fd97c6 100644 --- a/op-service/txmgr/cli.go +++ b/op-service/txmgr/cli.go @@ -31,6 +31,8 @@ const ( TxSendTimeoutFlagName = "txmgr.send-timeout" TxNotInMempoolTimeoutFlagName = "txmgr.not-in-mempool-timeout" ReceiptQueryIntervalFlagName = "txmgr.receipt-query-interval" + DaRpcFlagName = "da-rpc" + NamespaceIdFlagName = "namespace-id" ) var ( @@ -109,6 +111,12 @@ func CLIFlags(envPrefix string) []cli.Flag { Value: 12 * time.Second, EnvVar: opservice.PrefixEnvVar(envPrefix, "TXMGR_RECEIPT_QUERY_INTERVAL"), }, + cli.StringFlag{ + Name: NamespaceIdFlagName, + Usage: "Namespace ID of the DA layer", + Value: "e8e5f679bf7116cb", + EnvVar: opservice.PrefixEnvVar(envPrefix, "NAMESPACE_ID"), + }, }, client.CLIFlags(envPrefix)...) } @@ -127,6 +135,8 @@ type CLIConfig struct { NetworkTimeout time.Duration TxSendTimeout time.Duration TxNotInMempoolTimeout time.Duration + DaRpc string + NamespaceId string } func (m CLIConfig) Check() error { @@ -173,6 +183,8 @@ func ReadCLIConfig(ctx *cli.Context) CLIConfig { NetworkTimeout: ctx.GlobalDuration(NetworkTimeoutFlagName), TxSendTimeout: ctx.GlobalDuration(TxSendTimeoutFlagName), TxNotInMempoolTimeout: ctx.GlobalDuration(TxNotInMempoolTimeoutFlagName), + DaRpc: ctx.GlobalString(DaRpcFlagName), + NamespaceId: ctx.GlobalString(NamespaceIdFlagName), } } @@ -261,6 +273,12 @@ type Config struct { // confirmation. SafeAbortNonceTooLowCount uint64 + // DaRpc is the HTTP provider URL for the Data Availability node. + DaRpc string + + // NamespaceId is the id of the namespace of the Data Availability node. + NamespaceId string + // Signer is used to sign transactions when the gas price is increased. Signer opcrypto.SignerFn From common.Address diff --git a/op-service/txmgr/txmgr.go b/op-service/txmgr/txmgr.go index 16bd54abe59f..7b09ce023ba6 100644 --- a/op-service/txmgr/txmgr.go +++ b/op-service/txmgr/txmgr.go @@ -1,7 +1,10 @@ package txmgr import ( + "bytes" "context" + "encoding/binary" + "encoding/hex" "errors" "fmt" "sync/atomic" @@ -11,6 +14,7 @@ import ( "sync" "time" + "github.com/celestiaorg/go-cnc" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -84,6 +88,9 @@ type SimpleTxManager struct { name string chainID *big.Int + daClient *cnc.Client + namespaceId [8]byte + backend ETHBackend l log.Logger metr metrics.TxMetricer @@ -103,14 +110,32 @@ func NewSimpleTxManager(name string, l log.Logger, m metrics.TxMetricer, cfg CLI return nil, err } + daClient, err := cnc.NewClient(cfg.DaRpc, cnc.WithTimeout(90*time.Second)) + if err != nil { + return nil, err + } + + var nid [8]byte + + if cfg.NamespaceId == "" { + return nil, errors.New("namespace id cannot be blank") + } + namespaceId, err := hex.DecodeString(cfg.NamespaceId) + if err != nil { + return nil, err + } + copy(nid[:], namespaceId) + return &SimpleTxManager{ - chainID: conf.ChainID, - name: name, - cfg: conf, - backend: conf.Backend, - l: l.New("service", name), - metr: m, - resetC: make(chan struct{}), + chainID: conf.ChainID, + name: name, + cfg: conf, + daClient: daClient, + namespaceId: nid, + backend: conf.Backend, + l: l.New("service", name), + metr: m, + resetC: make(chan struct{}), }, nil } @@ -188,6 +213,45 @@ func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*typ ctx, cancel = context.WithTimeout(ctx, m.cfg.TxSendTimeout) defer cancel() } + // TODO: this is a hack to route only batcher transactions through celestia + // SimpleTxManager is used by both batcher and proposer but since proposer + // writes to a smart contract, we overwrite _only_ batcher candidate as the + // frame pointer to celestia, while retaining the proposer pathway that + // writes the state commitment data to ethereum. + if candidate.To.Hex() == "0xfF00000000000000000000000000000000000000" { + res, err := m.daClient.SubmitPFB(ctx, m.namespaceId, candidate.TxData, 20000, 700000) + if err != nil { + m.l.Warn("unable to publish tx to celestia", "err", err) + return nil, err + } + fmt.Printf("res: %v\n", res) + + height := res.Height + + // FIXME: needs to be tx index / share index? + index := uint32(0) // res.Logs[0].MsgIndex + + // DA pointer serialization format + // | -------------------------| + // | 8 bytes | 4 bytes | + // | block height | tx index | + // | -------------------------| + + buf := new(bytes.Buffer) + err = binary.Write(buf, binary.BigEndian, height) + if err != nil { + return nil, fmt.Errorf("data pointer block height serialization failed: %w", err) + } + err = binary.Write(buf, binary.BigEndian, index) + if err != nil { + return nil, fmt.Errorf("data pointer tx index serialization failed: %w", err) + } + + serialized := buf.Bytes() + fmt.Printf("TxData: %v\n", serialized) + candidate = TxCandidate{TxData: serialized, To: candidate.To, GasLimit: candidate.GasLimit} + } + tx, err := m.craftTx(ctx, candidate) if err != nil { return nil, fmt.Errorf("failed to create the tx: %w", err) @@ -236,6 +300,7 @@ func (m *SimpleTxManager) craftTx(ctx context.Context, candidate TxCandidate) (* GasTipCap: gasTipCap, Data: rawTx.Data, }) + m.l.Warn("estimating gas", "candidate", candidate, "gasFeeCap", gasFeeCap, "gasTipCap", gasTipCap, "err", err) if err != nil { return nil, fmt.Errorf("failed to estimate gas: %w", err) } diff --git a/ops-bedrock/devnet-up.sh b/ops-bedrock/devnet-up.sh index b055bd3e3a53..63c91656c1d4 100755 --- a/ops-bedrock/devnet-up.sh +++ b/ops-bedrock/devnet-up.sh @@ -82,8 +82,8 @@ fi ( cd ops-bedrock echo "Bringing up L1..." - DOCKER_BUILDKIT=1 docker-compose build --progress plain - docker-compose up -d l1 + DOCKER_BUILDKIT=1 docker-compose -f docker-compose-devnet.yml build --progress plain + docker-compose -f docker-compose-devnet.yml up -d l1 wait_up $L1_URL ) @@ -91,7 +91,7 @@ fi ( cd ops-bedrock echo "Bringing up L2..." - docker-compose up -d l2 + docker-compose -f docker-compose-devnet.yml up -d l2 wait_up $L2_URL ) @@ -102,10 +102,10 @@ L2OO_ADDRESS="0x6900000000000000000000000000000000000000" cd ops-bedrock echo "Bringing up devnet..." L2OO_ADDRESS="$L2OO_ADDRESS" \ - docker-compose up -d op-proposer op-batcher + docker-compose -f docker-compose-devnet.yml up -d op-proposer op-batcher echo "Bringing up stateviz webserver..." - docker-compose up -d stateviz + docker-compose -f docker-compose-devnet.yml up -d stateviz ) echo "Devnet ready." diff --git a/ops-bedrock/docker-compose.yml b/ops-bedrock/docker-compose-devnet.yml similarity index 86% rename from ops-bedrock/docker-compose.yml rename to ops-bedrock/docker-compose-devnet.yml index 0e181208f815..fa05f451917f 100644 --- a/ops-bedrock/docker-compose.yml +++ b/ops-bedrock/docker-compose-devnet.yml @@ -11,6 +11,19 @@ volumes: services: + da: + platform: linux/x86_64 + image: "ghcr.io/rollkit/local-celestia-devnet:v0.10.0" + ports: + - "26657:26657" + - "26659:26659" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:26659/header/1"] + interval: 5s + timeout: 5s + retries: 5 + start_period: 10s + l1: build: context: . @@ -70,6 +83,8 @@ services: --metrics.port=7300 --pprof.enabled --rpc.enable-admin + --da-rpc=http://da:26659 + --namespace-id=e8e5f679bf7116cb ports: - "7545:8545" - "9003:9003" @@ -106,12 +121,15 @@ services: OP_PROPOSER_PPROF_ENABLED: "true" OP_PROPOSER_METRICS_ENABLED: "true" OP_PROPOSER_ALLOW_NON_FINALIZED: "true" + OP_PROPOSER_NAMESPACE_ID: "e8e5f679bf7116cb" + OP_PROPOSER_DA_RPC: http://da:26659 op-batcher: depends_on: - l1 - l2 - op-node + - da build: context: ../ dockerfile: ./op-batcher/Dockerfile @@ -119,11 +137,14 @@ services: - "6061:6060" - "7301:7300" - "6545:8545" + depends_on: + da: + condition: service_healthy environment: OP_BATCHER_L1_ETH_RPC: http://l1:8545 OP_BATCHER_L2_ETH_RPC: http://l2:8545 OP_BATCHER_ROLLUP_RPC: http://op-node:8545 - OFFLINE_GAS_ESTIMATION: false + OFFLINE_GAS_ESTIMATION: null OP_BATCHER_MAX_CHANNEL_DURATION: 1 OP_BATCHER_MAX_L1_TX_SIZE_BYTES: 120000 OP_BATCHER_TARGET_L1_TX_SIZE_BYTES: 100000 @@ -139,6 +160,8 @@ services: OP_BATCHER_PPROF_ENABLED: "true" OP_BATCHER_METRICS_ENABLED: "true" OP_BATCHER_RPC_ENABLE_ADMIN: "true" + OP_BATCHER_NAMESPACE_ID: "e8e5f679bf7116cb" + OP_BATCHER_DA_RPC: http://da:26659 stateviz: build: diff --git a/ops-bedrock/docker-compose-testnet.yml b/ops-bedrock/docker-compose-testnet.yml new file mode 100644 index 000000000000..bdc17f8423aa --- /dev/null +++ b/ops-bedrock/docker-compose-testnet.yml @@ -0,0 +1,184 @@ +version: '3.4' + +# This Compose file is expected to be used with the testnet-up.sh script. +# The volumes below mount the configs generated by the script into each +# service. + +volumes: + l1_data: + l2_data: + op_log: + + +services: + da: + container_name: celestia-light-node + user: root + platform: "${PLATFORM}" + image: "ghcr.io/celestiaorg/celestia-node:v0.10.0" + command: celestia light start --core.ip https://celestia.rpc.waynewayner.de/ --gateway --gateway.addr da --gateway.port 26659 --p2p.network blockspacerace + environment: + - NODE_TYPE=light + - P2P_NETWORK=blockspacerace + volumes: + - $HOME/.celestia-light-blockspacerace-0/:/home/celestia/.celestia-light-blockspacerace-0/ + ports: + - "26657:26657" + - "26659:26659" + + l1: + build: + context: . + dockerfile: Dockerfile.l1 + ports: + - "8545:8545" + - "7060:6060" + volumes: + - "l1_data:/db" + - "${PWD}/../.devnet/genesis-l1.json:/genesis.json" + - "${PWD}/test-jwt-secret.txt:/config/test-jwt-secret.txt" + + l2: + build: + context: . + dockerfile: Dockerfile.l2 + ports: + - "9545:8545" + - "8060:6060" + volumes: + - "l2_data:/db" + - "${PWD}/../.devnet/genesis-l2.json:/genesis.json" + - "${PWD}/test-jwt-secret.txt:/config/test-jwt-secret.txt" + entrypoint: # pass the L2 specific flags by overriding the entry-point and adding extra arguments + - "/bin/sh" + - "/entrypoint.sh" + - "--authrpc.jwtsecret=/config/test-jwt-secret.txt" + + op-node: + depends_on: + - l1 + - l2 + build: + context: ../ + dockerfile: ./op-node/Dockerfile + command: > + op-node + --l1=ws://l1:8546 + --l2=http://l2:8551 + --l2.jwt-secret=/config/test-jwt-secret.txt + --sequencer.enabled + --sequencer.l1-confs=0 + --verifier.l1-confs=0 + --p2p.sequencer.key=8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba + --rollup.config=/rollup.json + --rpc.addr=0.0.0.0 + --rpc.port=8545 + --p2p.listen.ip=0.0.0.0 + --p2p.listen.tcp=9003 + --p2p.listen.udp=9003 + --p2p.scoring.peers=light + --p2p.ban.peers=true + --snapshotlog.file=/op_log/snapshot.log + --p2p.priv.path=/config/p2p-node-key.txt + --metrics.enabled + --metrics.addr=0.0.0.0 + --metrics.port=7300 + --pprof.enabled + --rpc.enable-admin + --da-rpc=http://da:26659 + --namespace-id=e8e5f679bf7116cb + ports: + - "7545:8545" + - "9003:9003" + - "7300:7300" + - "6060:6060" + volumes: + - "${PWD}/p2p-sequencer-key.txt:/config/p2p-sequencer-key.txt" + - "${PWD}/p2p-node-key.txt:/config/p2p-node-key.txt" + - "${PWD}/test-jwt-secret.txt:/config/test-jwt-secret.txt" + - "${PWD}/../.devnet/rollup.json:/rollup.json" + - op_log:/op_log + + op-proposer: + depends_on: + - l1 + - l2 + - op-node + build: + context: ../ + dockerfile: ./op-proposer/Dockerfile + ports: + - "6062:6060" + - "7302:7300" + environment: + OP_PROPOSER_L1_ETH_RPC: http://l1:8545 + OP_PROPOSER_ROLLUP_RPC: http://op-node:8545 + OP_PROPOSER_POLL_INTERVAL: 1s + OP_PROPOSER_NUM_CONFIRMATIONS: 1 + OP_PROPOSER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3 + OP_PROPOSER_RESUBMISSION_TIMEOUT: 30s + OP_PROPOSER_MNEMONIC: test test test test test test test test test test test junk + OP_PROPOSER_L2_OUTPUT_HD_PATH: "m/44'/60'/0'/0/1" + OP_PROPOSER_L2OO_ADDRESS: "${L2OO_ADDRESS}" + OP_PROPOSER_PPROF_ENABLED: "true" + OP_PROPOSER_METRICS_ENABLED: "true" + OP_PROPOSER_ALLOW_NON_FINALIZED: "true" + OP_PROPOSER_NAMESPACE_ID: "e8e5f679bf7116cb" + OP_PROPOSER_DA_RPC: http://da:26659 + OP_PROPOSER_NETWORK_TIMEOUT: 180s + + op-batcher: + depends_on: + - l1 + - l2 + - op-node + - da + build: + context: ../ + dockerfile: ./op-batcher/Dockerfile + ports: + - "6061:6060" + - "7301:7300" + - "6545:8545" + healthcheck: + test: ["CMD", "curl", "-f", "http://da:26659/header/1"] + interval: 5s + timeout: 5s + retries: 5 + start_period: 10s + environment: + OP_BATCHER_L1_ETH_RPC: http://l1:8545 + OP_BATCHER_L2_ETH_RPC: http://l2:8545 + OP_BATCHER_ROLLUP_RPC: http://op-node:8545 + OFFLINE_GAS_ESTIMATION: null + OP_BATCHER_MAX_CHANNEL_DURATION: 1 + OP_BATCHER_MAX_L1_TX_SIZE_BYTES: 120000 + OP_BATCHER_TARGET_L1_TX_SIZE_BYTES: 100000 + OP_BATCHER_TARGET_NUM_FRAMES: 1 + OP_BATCHER_APPROX_COMPR_RATIO: 0.4 + OP_BATCHER_SUB_SAFETY_MARGIN: 4 # SWS is 15, ChannelTimeout is 40 + OP_BATCHER_POLL_INTERVAL: 1s + OP_BATCHER_NUM_CONFIRMATIONS: 1 + OP_BATCHER_SAFE_ABORT_NONCE_TOO_LOW_COUNT: 3 + OP_BATCHER_RESUBMISSION_TIMEOUT: 30s + OP_BATCHER_MNEMONIC: test test test test test test test test test test test junk + OP_BATCHER_SEQUENCER_HD_PATH: "m/44'/60'/0'/0/2" + OP_BATCHER_PPROF_ENABLED: "true" + OP_BATCHER_METRICS_ENABLED: "true" + OP_BATCHER_RPC_ENABLE_ADMIN: "true" + OP_BATCHER_NAMESPACE_ID: "e8e5f679bf7116cb" + OP_BATCHER_DA_RPC: http://da:26659 + + stateviz: + build: + context: ../ + dockerfile: ./ops-bedrock/Dockerfile.stateviz + command: + - stateviz + - -addr=0.0.0.0:8080 + - -snapshot=/op_log/snapshot.log + - -refresh=10s + ports: + - "9090:8080" + volumes: + - op_log:/op_log:ro diff --git a/ops-bedrock/testnet-up.sh b/ops-bedrock/testnet-up.sh new file mode 100755 index 000000000000..d1bd52fbbd52 --- /dev/null +++ b/ops-bedrock/testnet-up.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash + +# This script starts a local devnet using Docker Compose. We have to use +# this more complicated Bash script rather than Compose's native orchestration +# tooling because we need to start each service in a specific order, and specify +# their configuration along the way. The order is: +# +# 1. Start L1. +# 2. Compile contracts. +# 3. Deploy the contracts to L1 if necessary. +# 4. Start L2, inserting the compiled contract artifacts into the genesis. +# 5. Get the genesis hashes and timestamps from L1/L2. +# 6. Generate the rollup driver's config using the genesis hashes and the +# timestamps recovered in step 4 as well as the address of the OptimismPortal +# contract deployed in step 3. +# 7. Start the rollup driver. +# 8. Start the L2 output submitter. +# +# The timestamps are critically important here, since the rollup driver will fill in +# empty blocks if the tip of L1 lags behind the current timestamp. This can lead to +# a perceived infinite loop. To get around this, we set the timestamp to the current +# time in this script. +# +# This script is safe to run multiple times. It stores state in `.devnet`, and +# contracts-bedrock/deployments/devnetL1. +# +# Don't run this script directly. Run it using the makefile, e.g. `make testnet-up`. +# To clean up your devnet, run `make testnet-clean`. + +set -eu + +L1_URL="http://localhost:8545" +L2_URL="http://localhost:9545" + +OP_NODE="$PWD/op-node" +CONTRACTS_BEDROCK="$PWD/packages/contracts-bedrock" +NETWORK=devnetL1 +DEVNET="$PWD/.devnet" + +# Helper method that waits for a given URL to be up. Can't use +# cURL's built-in retry logic because connection reset errors +# are ignored unless you're using a very recent version of cURL +function wait_up { + echo -n "Waiting for $1 to come up..." + i=0 + until curl -s -f -o /dev/null "$1" + do + echo -n . + sleep 0.25 + + ((i=i+1)) + if [ "$i" -eq 300 ]; then + echo " Timeout!" >&2 + exit 1 + fi + done + echo "Done!" +} + +mkdir -p ./.devnet + +# Regenerate the L1 genesis file if necessary. The existence of the genesis +# file is used to determine if we need to recreate the devnet's state folder. +if [ ! -f "$DEVNET/done" ]; then + echo "Regenerating genesis files" + + TIMESTAMP=$(date +%s | xargs printf '0x%x') + cat "$CONTRACTS_BEDROCK/deploy-config/devnetL1.json" | jq -r ".l1GenesisBlockTimestamp = \"$TIMESTAMP\"" > /tmp/bedrock-devnet-deploy-config.json + + ( + cd "$OP_NODE" + go run cmd/main.go genesis devnet \ + --deploy-config /tmp/bedrock-devnet-deploy-config.json \ + --outfile.l1 $DEVNET/genesis-l1.json \ + --outfile.l2 $DEVNET/genesis-l2.json \ + --outfile.rollup $DEVNET/rollup.json + touch "$DEVNET/done" + ) +fi + +# Bring up L1. +( + cd ops-bedrock + echo "Bringing up L1..." + DOCKER_BUILDKIT=1 docker-compose -f docker-compose-testnet.yml build --progress plain + docker-compose -f docker-compose-testnet.yml up -d l1 + wait_up $L1_URL +) + +# Bring up L2. +( + cd ops-bedrock + echo "Bringing up L2..." + docker-compose -f docker-compose-testnet.yml up -d l2 + wait_up $L2_URL +) + +L2OO_ADDRESS="0x6900000000000000000000000000000000000000" + +# Bring up everything else. +( + cd ops-bedrock + echo "Bringing up devnet..." + L2OO_ADDRESS="$L2OO_ADDRESS" \ + docker-compose -f docker-compose-testnet.yml up -d op-proposer op-batcher + + echo "Bringing up stateviz webserver..." + docker-compose -f docker-compose-testnet.yml up -d stateviz +) + +echo "Devnet ready." diff --git a/packages/contracts-bedrock/deploy-config/devnetL1.json b/packages/contracts-bedrock/deploy-config/devnetL1.json index dd6c426e6ca6..aec479c85483 100644 --- a/packages/contracts-bedrock/deploy-config/devnetL1.json +++ b/packages/contracts-bedrock/deploy-config/devnetL1.json @@ -2,18 +2,18 @@ "l1ChainID": 900, "l2ChainID": 901, "l2BlockTime": 2, - "maxSequencerDrift": 300, - "sequencerWindowSize": 200, - "channelTimeout": 120, + "maxSequencerDrift": 600, + "sequencerWindowSize": 3600, + "channelTimeout": 300, "p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", "batchInboxAddress": "0xff00000000000000000000000000000000000000", "batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", - "l2OutputOracleSubmissionInterval": 20, + "l2OutputOracleSubmissionInterval": 120, "l2OutputOracleStartingTimestamp": -1, "l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "l2OutputOracleChallenger": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", "l2GenesisBlockGasLimit": "0x1c9c380", - "l1BlockTime": 3, + "l1BlockTime": 15, "cliqueSignerAddress": "0xca062b0fd91172d89bcd4bb084ac4e21972cc467", "baseFeeVaultRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788", @@ -22,7 +22,7 @@ "finalSystemOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "portalGuardian": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "controller": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", - "finalizationPeriodSeconds": 2, + "finalizationPeriodSeconds": 12, "deploymentWaitConfirmations": 1, "fundDevAccounts": true, "l2GenesisBlockBaseFeePerGas": "0x3B9ACA00", diff --git a/packages/contracts-bedrock/tasks/deposits.ts b/packages/contracts-bedrock/tasks/deposits.ts index cf07b54293b9..d0f0f0eb91fb 100644 --- a/packages/contracts-bedrock/tasks/deposits.ts +++ b/packages/contracts-bedrock/tasks/deposits.ts @@ -39,11 +39,11 @@ task('deposit', 'Deposits funds onto L2.') ) .setAction(async (args, hre) => { const { l1ProviderUrl, l2ProviderUrl, to, amountEth, privateKey } = args - const proxy = await hre.deployments.get('OptimismPortalProxy') + // const proxy = await hre.deployments.get('OptimismPortalProxy') const OptimismPortal = await hre.ethers.getContractAt( 'OptimismPortal', - proxy.address + '0x6900000000000000000000000000000000000001' ) const l1Provider = new providers.JsonRpcProvider(l1ProviderUrl)