Compare commits

..

33 Commits

Author SHA1 Message Date
georgehao
64d6e5fc5c feat: update 2024-04-21 10:19:54 +08:00
georgehao
ce2777943a feat: update 2024-04-21 10:06:36 +08:00
georgehao
74f839e7f3 feat: update 2024-04-21 10:03:06 +08:00
georgehao
005c425a6b feat: update 2024-04-21 09:56:34 +08:00
georgehao
4d3117fea6 feat: update 2024-04-21 09:52:43 +08:00
georgehao
0b4c48061e feat: update 2024-04-21 09:43:32 +08:00
georgehao
1357a1c947 feat: update 2024-04-21 09:02:53 +08:00
georgehao
9dfb082cf4 feat: update 2024-04-20 23:57:43 +08:00
georgehao
dd9892ed25 feat: update 2024-04-20 23:40:28 +08:00
georgehao
ad185c328d feat: update 2024-04-20 23:37:17 +08:00
georgehao
557734ea99 feat: update 2024-04-20 23:34:00 +08:00
georgehao
026030746b feat: update 2024-04-20 23:30:15 +08:00
georgehao
fbcafc260c feat: update 2024-04-20 23:19:20 +08:00
georgehao
3740eb2b3e feat: update 2024-04-20 23:14:09 +08:00
georgehao
86b852c7ae feat: update 2024-04-20 23:07:58 +08:00
georgehao
4aa7e2d7b0 feat: update 2024-04-20 22:58:17 +08:00
georgehao
8fe045b810 feat: update 2024-04-20 22:54:02 +08:00
georgehao
2ec0e1d1b8 feat: update 2024-04-20 22:49:14 +08:00
georgehao
d49ce4ca4f feat: update 2024-04-20 22:34:52 +08:00
georgehao
23c3b208a3 feat: update 2024-04-20 22:31:32 +08:00
georgehao
7a5e704c69 feat: update 2024-04-20 22:25:06 +08:00
georgehao
a498f55d1e feat: update 2024-04-20 22:20:45 +08:00
georgehao
8d3221900d feat: test 2024-04-20 22:16:51 +08:00
georgehao
59ba4b90d7 feat: update 2024-04-20 22:13:23 +08:00
georgehao
609a4b92e5 feat: update 2024-04-20 22:09:35 +08:00
georgehao
fa813dbfc4 feat: update 2024-04-20 21:54:52 +08:00
georgehao
100124985a feat: update 2024-04-20 21:50:38 +08:00
georgehao
8fc60d1d3a feat: update 2024-04-20 19:58:56 +08:00
georgehao
3479f1d7d2 feat: upddate 2024-04-20 19:05:44 +08:00
georgehao
06af04827c feat: update 2024-04-20 00:35:28 +08:00
georgehao
ec5b3c3a18 feat: update 2024-04-20 00:18:03 +08:00
georgehao
f535dd977f feat: update 2024-04-20 00:14:11 +08:00
georgehao
f0e34b8141 feat: update 2024-04-19 23:57:34 +08:00
103 changed files with 790 additions and 3097 deletions

View File

@@ -29,7 +29,7 @@ jobs:
steps:
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2023-12-03
toolchain: nightly-2022-12-10
override: true
components: rustfmt, clippy
- name: Install Go

View File

@@ -33,7 +33,7 @@ jobs:
steps:
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2023-12-03
toolchain: nightly-2022-12-10
override: true
components: rustfmt, clippy
- name: Install Go

View File

@@ -144,51 +144,6 @@ jobs:
${{ env.ECR_REGISTRY }}/${{ env.REPOSITORY }}:${{ env.IMAGE_TAG }}
${{ env.ECR_REGISTRY }}/${{ env.REPOSITORY }}:latest
rollup-db-cli:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: check repo and create it if not exist
env:
REPOSITORY: rollup-db-cli
run: |
aws --region ${{ env.AWS_REGION }} ecr describe-repositories --repository-names ${{ env.REPOSITORY }} && : || aws --region ${{ env.AWS_REGION }} ecr create-repository --repository-name ${{ env.REPOSITORY }}
- name: Build and push
uses: docker/build-push-action@v3
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: rollup-db-cli
IMAGE_TAG: ${{ github.ref_name }}
with:
context: .
file: ./build/dockerfiles/db_cli.Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPOSITORY }}:${{ env.IMAGE_TAG }}
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPOSITORY }}:latest
${{ env.ECR_REGISTRY }}/${{ env.REPOSITORY }}:${{ env.IMAGE_TAG }}
${{ env.ECR_REGISTRY }}/${{ env.REPOSITORY }}:latest
bridgehistoryapi-fetcher:
runs-on: ubuntu-latest
steps:
@@ -316,7 +271,7 @@ jobs:
with:
context: .
file: ./build/dockerfiles/coordinator-api.Dockerfile
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPOSITORY }}:${{ env.IMAGE_TAG }}

View File

@@ -7,12 +7,12 @@ on:
description: 'Go version'
required: true
type: string
default: '1.21'
default: '1.20'
RUST_VERSION:
description: 'Rust toolchain version'
required: true
type: string
default: 'nightly-2023-12-03'
default: 'nightly-2022-12-10'
PYTHON_VERSION:
description: 'Python version'
required: false
@@ -29,191 +29,31 @@ defaults:
working-directory: 'build/dockerfiles/intermediate'
jobs:
build-and-publish-cuda-go-rust-builder:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build image
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
file: build/dockerfiles/intermediate/cuda-go-rust-builder.Dockerfile
tags: scrolltech/cuda-go-rust-builder:cuda-${{ github.event.inputs.CUDA_VERSION }}-go-${{ github.event.inputs.GO_VERSION }}-rust-${{ github.event.inputs.RUST_VERSION }}
build-args: |
CUDA_VERSION: ${{ github.event.inputs.CUDA_VERSION }}
GO_VERSION: ${{ github.event.inputs.GO_VERSION }}
RUST_VERSION: ${{ github.event.inputs.RUST_VERSION }}
build-and-publish-go-rust-builder:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build image
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
file: build/dockerfiles/intermediate/go-rust-builder.Dockerfile
platforms: linux/amd64,linux/arm64
tags: scrolltech/go-rust-builder:go-${{ github.event.inputs.GO_VERSION }}-rust-${{ github.event.inputs.RUST_VERSION }}
build-args: |
GO_VERSION: ${{ github.event.inputs.GO_VERSION }}
RUST_VERSION: ${{ github.event.inputs.RUST_VERSION }}
build-and-publish-go-alpine-builder:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build image
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
file: build/dockerfiles/intermediate/go-alpine-builder.Dockerfile
platforms: linux/amd64,linux/arm64
tags: scrolltech/go-alpine-builder:${{ github.event.inputs.GO_VERSION }}
build-args: |
GO_VERSION: ${{ github.event.inputs.GO_VERSION }}
RUST_VERSION: ${{ github.event.inputs.RUST_VERSION }}
build-and-publish-rust-builder:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build image
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
file: build/dockerfiles/intermediate/rust-builder.Dockerfile
platforms: linux/amd64,linux/arm64
tags: scrolltech/rust-builder:${{ github.event.inputs.RUST_VERSION }}
build-args: |
RUST_VERSION: ${{ github.event.inputs.RUST_VERSION }}
build-and-publish-rust-alpine-builder:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build image
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
file: build/dockerfiles/intermediate/rust-alpine-builder.Dockerfile
platforms: linux/amd64,linux/arm64
tags: scrolltech/rust-alpine-builder:${{ github.event.inputs.RUST_VERSION }}
build-args: |
RUST_VERSION: ${{ github.event.inputs.RUST_VERSION }}
build-and-publish-go-rust-alpine-builder:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build image
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
file: build/dockerfiles/intermediate/go-rust-alpine-builder.Dockerfile
platforms: linux/amd64,linux/arm64
tags: scrolltech/go-rust-alpine-builder:go-${{ github.event.inputs.GO_VERSION }}-rust-${{ github.event.inputs.RUST_VERSION }}
build-args: |
GO_VERSION: ${{ github.event.inputs.GO_VERSION }}
RUST_VERSION: ${{ github.event.inputs.RUST_VERSION }}
build-and-publish-py-runner:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build image
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
file: build/dockerfiles/intermediate/py-runner.Dockerfile
platforms: linux/amd64,linux/arm64
tags: scrolltech/py-runner:${{ github.event.inputs.PYTHON_VERSION }}
build-args: |
CUDA_VERSION: ${{ github.event.inputs.CUDA_VERSION }}
GO_VERSION: ${{ github.event.inputs.GO_VERSION }}
RUST_VERSION: ${{ github.event.inputs.RUST_VERSION }}
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build
run: |
make all
env:
GO_VERSION: ${{ inputs.GO_VERSION }}
RUST_VERSION: ${{ inputs.RUST_VERSION }}
PYTHON_VERSION: ${{ inputs.PYTHON_VERSION }}
CUDA_VERSION: ${{ inputs.CUDA_VERSION }}
- name: Publish
run: |
make publish
env:
GO_VERSION: ${{ inputs.GO_VERSION }}
RUST_VERSION: ${{ inputs.RUST_VERSION }}
PYTHON_VERSION: ${{ inputs.PYTHON_VERSION }}
CUDA_VERSION: ${{ inputs.CUDA_VERSION }}

View File

@@ -50,7 +50,7 @@ jobs:
steps:
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2023-12-03
toolchain: nightly-2022-12-10
override: true
components: rustfmt, clippy
- name: Install Go

View File

@@ -1,6 +1,6 @@
.PHONY: fmt dev_docker build_test_docker run_test_docker clean update
L2GETH_TAG=scroll-v5.3.0
L2GETH_TAG=scroll-v5.1.6
help: ## Display this help message
@grep -h \
@@ -47,5 +47,11 @@ dev_docker: ## build docker images for development/testing usages
docker build -t scroll_l1geth ./common/docker/l1geth/
docker build -t scroll_l2geth ./common/docker/l2geth/
build_test_docker: ## build Docker image for local testing on M1/M2 Silicon Mac
docker build -t scroll_test_image -f ./build/dockerfiles/local_testing.Dockerfile $$(mktemp -d)
run_test_docker: ## run Docker image for local testing on M1/M2 Silicon Mac
docker run -it --rm --name scroll_test_container --network=host -v /var/run/docker.sock:/var/run/docker.sock -v $(PWD):/go/src/app -e HOST_PATH=$(PWD) scroll_test_image
clean: ## Empty out the bin folder
@rm -rf build/bin

View File

@@ -43,6 +43,8 @@ make dev_docker
## Testing Rollup & Coordinator
### For Non-Apple Silicon (M1/M2) Macs
Run the tests using the following commands:
```bash
@@ -52,6 +54,39 @@ go test -v -race -covermode=atomic scroll-tech/database/...
go test -v -race -covermode=atomic scroll-tech/common/...
```
### For Apple Silicon (M1/M2) Macs
To run tests on Apple Silicon Macs, build and execute the Docker image as outlined below:
#### Build a Docker Image for Testing
Use the following command to build a Docker image:
```bash
make build_test_docker
```
This command builds a Docker image named `scroll_test_image` using the Dockerfile found at `./build/dockerfiles/local_test.Dockerfile`.
#### Run Docker Image
After the image is built, run a Docker container from it:
```bash
make run_test_docker
```
This command runs a Docker container named `scroll_test_container` from the `scroll_test_image` image. The container uses the host network and has access to the Docker socket and the current directory.
Once the Docker container is running, execute the tests using the following commands:
```bash
go test -v -race -covermode=atomic scroll-tech/rollup/...
go test -tags="mock_verifier" -v -race -covermode=atomic scroll-tech/coordinator/...
go test -v -race -covermode=atomic scroll-tech/database/...
go test -v -race -covermode=atomic scroll-tech/common/...
```
## Testing Contracts
You can find the unit tests in [`contracts/src/test/`](/contracts/src/test/), and integration tests in [`contracts/integration-test/`](/contracts/integration-test/).

View File

@@ -79,50 +79,3 @@ provides REST APIs. Please refer to the API details below.
// @Success 200
// @Router /api/txsbyhashes [post]
```
## Running bridge-history-api locally
1. Pull the latest Redis image:
```
docker pull redis:latest
```
2. Run the Redis container:
```
docker run --name bridgehistoryapi-redis -d -p 6379:6379 redis:latest
```
3. Pull the latest PostgreSQL image:
```
docker pull postgres:latest
```
4. Run the PostgreSQL container:
```
docker run --name bridgehistoryapi-history-db -p 5444:5432 -e POSTGRES_PASSWORD=123456 -e POSTGRES_DB=test -d postgres
```
5. Run database migrations to initialize the tables:
```
make bridgehistoryapi-db-cli
./build/bin/bridgehistoryapi-db-cli migrate
```
6. Run bridgehistoryapi-fetcher:
```
make bridgehistoryapi-fetcher
./build/bin/bridgehistoryapi-fetcher
```
7. Run bridgehistoryapi-api:
```
make bridgehistoryapi-api
./build/bin/bridgehistoryapi-api
```
The endpoints provided in [./conf/config.json](./conf/config.json) are all public endpoints and have rate limits.
For production usage:
- For L1 endpoints, utilizing a service provider's free tier should suffice.
- For L2 endpoints, consider [running a Scroll L2geth node](https://docs.scroll.xyz/en/developers/guides/running-a-scroll-node) and using the exposed HTTP port.

View File

@@ -15,7 +15,6 @@
"USDCGatewayAddr": "0xf1AF3b23DE0A5Ca3CAb7261cb0061C0D779A5c7B",
"LIDOGatewayAddr": "0x6625C6332c9F91F2D27c304E729B86db87A3f504",
"DAIGatewayAddr": "0x67260A8B73C5B77B55c1805218A42A7A6F98F515",
"PufferGatewayAddr": "0xA033Ff09f2da45f0e9ae495f525363722Df42b2a",
"ScrollChainAddr": "0xa13BAF47339d63B743e7Da8741db5456DAc1E556",
"GatewayRouterAddr": "0xF8B1378579659D8F7EE5f3C929c2f3E332E41Fd6",
"MessageQueueAddr": "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B"
@@ -35,9 +34,7 @@
"USDCGatewayAddr": "0x33B60d5Dd260d453cAC3782b0bDC01ce84672142",
"LIDOGatewayAddr": "0x8aE8f22226B9d789A36AC81474e633f8bE2856c9",
"DAIGatewayAddr": "0xaC78dff3A87b5b534e366A93E785a0ce8fA6Cc62",
"PufferGatewayAddr": "0x9eBf2f33526CD571f8b2ad312492cb650870CFd6",
"GatewayRouterAddr": "0x4C0926FF5252A435FD19e10ED15e5a249Ba19d79",
"MessageQueueAddr": "0x5300000000000000000000000000000000000000"
"GatewayRouterAddr": "0x4C0926FF5252A435FD19e10ED15e5a249Ba19d79"
},
"db": {
"dsn": "postgres://postgres:123456@localhost:5444/test?sslmode=disable",

View File

@@ -104,12 +104,10 @@ linters-settings:
# minimal occurrences count to trigger, 3 by default
min-occurrences: 3
depguard:
rules:
main:
files:
- $all
deny:
- pkg: "github.com/davecgh/go-spew/spew"
list-type: blacklist
include-go-root: false
packages:
- github.com/davecgh/go-spew/spew
misspell:
# Correct spellings using locale preferences for US or UK.
# Default is to use a neutral variety of English.

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM golang:1.21-alpine3.19 as base
FROM golang:1.20-alpine3.16 as base
WORKDIR /src
COPY go.mod* ./

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM golang:1.21-alpine3.19 as base
FROM golang:1.20-alpine3.16 as base
WORKDIR /src
COPY ./bridge-history-api/go.* ./

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM golang:1.21-alpine3.19 as base
FROM golang:1.20-alpine3.16 as base
WORKDIR /src
COPY go.mod* ./

View File

@@ -1,5 +1,5 @@
# Build libzkp dependency
FROM scrolltech/go-rust-builder:go-1.21-rust-nightly-2023-12-03 as chef
FROM scrolltech/go-rust-builder:go-1.20-rust-nightly-2022-12-10 as chef
WORKDIR app
FROM chef as planner
@@ -17,7 +17,7 @@ RUN find ./ | grep libzktrie.so | xargs -I{} cp {} /app/target/release/
# Download Go dependencies
FROM scrolltech/go-rust-builder:go-1.21-rust-nightly-2023-12-03 as base
FROM scrolltech/go-rust-builder:go-1.20-rust-nightly-2022-12-10 as base
WORKDIR /src
COPY go.work* ./
COPY ./rollup/go.* ./rollup/

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM scrolltech/go-alpine-builder:1.21 as base
FROM scrolltech/go-alpine-builder:1.20 as base
WORKDIR /src
COPY go.work* ./

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM scrolltech/go-alpine-builder:1.21 as base
FROM scrolltech/go-alpine-builder:1.20 as base
WORKDIR /src
COPY go.work* ./

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM scrolltech/go-alpine-builder:1.21 as base
FROM scrolltech/go-alpine-builder:1.20 as base
WORKDIR /src
COPY go.work* ./

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM scrolltech/go-alpine-builder:1.21 as base
FROM scrolltech/go-alpine-builder:1.20 as base
WORKDIR /src
COPY go.work* ./

View File

@@ -1,8 +1,8 @@
ifeq ($(GO_VERSION),)
GO_VERSION=1.21
GO_VERSION=1.20
endif
ifeq ($(RUST_VERSION),)
RUST_VERSION=nightly-2023-12-03
RUST_VERSION=nightly-2022-12-10
endif
ifeq ($(PYTHON_VERSION),)
PYTHON_VERSION=3.10

View File

@@ -1,6 +1,6 @@
ARG CUDA_VERSION=11.7.1
ARG GO_VERSION=1.21
ARG RUST_VERSION=nightly-2023-12-03
ARG GO_VERSION=1.20
ARG RUST_VERSION=nightly-2022-12-10
ARG CARGO_CHEF_TAG=0.1.41
FROM nvidia/cuda:${CUDA_VERSION}-devel-ubuntu22.04

View File

@@ -1,4 +1,4 @@
ARG GO_VERSION=1.21
ARG GO_VERSION=1.20
FROM golang:${GO_VERSION}-alpine

View File

@@ -1,5 +1,5 @@
ARG GO_VERSION=1.21
ARG RUST_VERSION=nightly-2023-12-03
ARG GO_VERSION=1.20
ARG RUST_VERSION=nightly-2022-12-10
ARG CARGO_CHEF_TAG=0.1.41
FROM golang:${GO_VERSION}-alpine

View File

@@ -1,5 +1,5 @@
ARG GO_VERSION=1.21
ARG RUST_VERSION=nightly-2023-12-03
ARG GO_VERSION=1.20
ARG RUST_VERSION=nightly-2022-12-10
ARG CARGO_CHEF_TAG=0.1.41
FROM ubuntu:20.04

View File

@@ -1,5 +1,5 @@
ARG ALPINE_VERSION=3.15
ARG RUST_VERSION=nightly-2023-12-03
ARG RUST_VERSION=nightly-2022-12-10
ARG CARGO_CHEF_TAG=0.1.41
FROM alpine:${ALPINE_VERSION}

View File

@@ -1,4 +1,4 @@
ARG RUST_VERSION=nightly-2023-12-03
ARG RUST_VERSION=nightly-2022-12-10
ARG CARGO_CHEF_TAG=0.1.41
FROM ubuntu:20.04

View File

@@ -0,0 +1,11 @@
# Start from the latest golang base image
FROM golang:1.21
# Install Docker
RUN apt-get update && apt-get install -y docker.io docker-compose
# Set the working directory
WORKDIR /go/src/app
# This container will be executable
ENTRYPOINT [ "/bin/bash" ]

View File

@@ -1,5 +1,5 @@
# Download Go dependencies
FROM scrolltech/go-alpine-builder:1.21 as base
FROM scrolltech/go-alpine-builder:1.20 as base
WORKDIR /src
COPY go.work* ./

View File

@@ -15,7 +15,7 @@ import (
const (
// GolangCIVersion to be used for linting.
GolangCIVersion = "github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2"
GolangCIVersion = "github.com/golangci/golangci-lint/cmd/golangci-lint@v1.52.2"
)
// GOBIN environment variable.
@@ -51,7 +51,7 @@ func lint() {
}
cmd = exec.Command(filepath.Join(goBin(), "golangci-lint"))
cmd.Args = append(cmd.Args, "run", "--config", "../build/.golangci.yml", "--timeout", "10m")
cmd.Args = append(cmd.Args, "run", "--config", "../build/.golangci.yml")
if *v {
cmd.Args = append(cmd.Args, "-v")

View File

@@ -0,0 +1,127 @@
package dockercompose
import (
"context"
"crypto/rand"
"fmt"
"math/big"
"os"
"path/filepath"
"time"
"github.com/cloudflare/cfssl/log"
"github.com/scroll-tech/go-ethereum/ethclient"
tc "github.com/testcontainers/testcontainers-go/modules/compose"
"github.com/testcontainers/testcontainers-go/wait"
)
// PoSL1TestEnv represents the config needed to test in PoS Layer 1.
type PoSL1TestEnv struct {
dockerComposeFile string
compose tc.ComposeStack
gethHTTPPort int
hostPath string
}
// NewPoSL1TestEnv creates and initializes a new instance of PoSL1TestEnv with a random HTTP port.
func NewPoSL1TestEnv() (*PoSL1TestEnv, error) {
rootDir, err := findProjectRootDir()
if err != nil {
return nil, fmt.Errorf("failed to find project root directory: %v", err)
}
hostPath, found := os.LookupEnv("HOST_PATH")
if !found {
hostPath = ""
}
rnd, err := rand.Int(rand.Reader, big.NewInt(65536-1024))
if err != nil {
return nil, fmt.Errorf("failed to generate a random: %v", err)
}
gethHTTPPort := int(rnd.Int64()) + 1024
if err := os.Setenv("GETH_HTTP_PORT", fmt.Sprintf("%d", gethHTTPPort)); err != nil {
return nil, fmt.Errorf("failed to set GETH_HTTP_PORT: %v", err)
}
return &PoSL1TestEnv{
dockerComposeFile: filepath.Join(rootDir, "common", "docker-compose", "l1", "docker-compose.yml"),
gethHTTPPort: gethHTTPPort,
hostPath: hostPath,
}, nil
}
// Start starts the PoS L1 test environment by running the associated Docker Compose configuration.
func (e *PoSL1TestEnv) Start() error {
var err error
e.compose, err = tc.NewDockerCompose([]string{e.dockerComposeFile}...)
if err != nil {
return fmt.Errorf("failed to create docker compose: %w", err)
}
env := map[string]string{
"GETH_HTTP_PORT": fmt.Sprintf("%d", e.gethHTTPPort),
}
if e.hostPath != "" {
env["HOST_PATH"] = e.hostPath
}
if err = e.compose.WaitForService("geth", wait.NewHTTPStrategy("/").WithPort("8545/tcp").WithStartupTimeout(15*time.Second)).WithEnv(env).Up(context.Background()); err != nil {
if errStop := e.Stop(); errStop != nil {
log.Error("failed to stop PoS L1 test environment", "err", errStop)
}
return fmt.Errorf("failed to start PoS L1 test environment: %w", err)
}
return nil
}
// Stop stops the PoS L1 test environment by stopping and removing the associated Docker Compose services.
func (e *PoSL1TestEnv) Stop() error {
if e.compose != nil {
if err := e.compose.Down(context.Background(), tc.RemoveOrphans(true), tc.RemoveVolumes(true), tc.RemoveImagesLocal); err != nil {
return fmt.Errorf("failed to stop PoS L1 test environment: %w", err)
}
}
return nil
}
// Endpoint returns the HTTP endpoint for the PoS L1 test environment.
func (e *PoSL1TestEnv) Endpoint() string {
return fmt.Sprintf("http://127.0.0.1:%d", e.gethHTTPPort)
}
// L1Client returns an ethclient by dialing the running PoS L1 test environment
func (e *PoSL1TestEnv) L1Client() (*ethclient.Client, error) {
if e == nil {
return nil, fmt.Errorf("PoS L1 test environment is not initialized")
}
client, err := ethclient.Dial(e.Endpoint())
if err != nil {
return nil, fmt.Errorf("failed to dial PoS L1 test environment: %w", err)
}
return client, nil
}
func findProjectRootDir() (string, error) {
currentDir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to get working directory: %w", err)
}
for {
_, err := os.Stat(filepath.Join(currentDir, "go.work"))
if err == nil {
return currentDir, nil
}
parentDir := filepath.Dir(currentDir)
if parentDir == currentDir {
return "", fmt.Errorf("go.work file not found in any parent directory")
}
currentDir = parentDir
}
}

View File

@@ -8,14 +8,14 @@ services:
mkdir -p /data/execution &&
cp -a /execution/* /data/execution/"
volumes:
- ../../common/testcontainers/consensus:/consensus
- ../../common/testcontainers/execution:/execution
- ${HOST_PATH:-../../..}/common/docker-compose/l1/consensus:/consensus
- ${HOST_PATH:-../../..}/common/docker-compose/l1/execution:/execution
- data:/data
# Creates a genesis state for the beacon chain using a YAML configuration file and
# a deterministic set of 64 validators.
create-beacon-chain-genesis:
image: "gcr.io/prysmaticlabs/prysm/cmd/prysmctl:HEAD-263557"
image: "gcr.io/prysmaticlabs/prysm/cmd/prysmctl:latest"
command:
- testnet
- generate-genesis
@@ -96,7 +96,7 @@ services:
- --nodiscover
- --syncmode=full
ports:
- 8545
- ${GETH_HTTP_PORT:-8545}:8545
depends_on:
geth-genesis:
condition: service_completed_successfully

View File

@@ -5,6 +5,7 @@ go 1.21
require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/bits-and-blooms/bitset v1.12.0
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004
github.com/docker/docker v25.0.3+incompatible
github.com/gin-contrib/pprof v1.4.0
github.com/gin-gonic/gin v1.9.1
@@ -13,7 +14,7 @@ require (
github.com/modern-go/reflect2 v1.0.2
github.com/orcaman/concurrent-map v1.0.0
github.com/prometheus/client_golang v1.16.0
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea
github.com/scroll-tech/go-ethereum v1.10.14-0.20240326144132-0f0cd99f7a2e
github.com/stretchr/testify v1.9.0
github.com/testcontainers/testcontainers-go v0.28.0
github.com/testcontainers/testcontainers-go/modules/compose v0.28.0
@@ -61,7 +62,7 @@ require (
github.com/containerd/typeurl/v2 v2.1.1 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/distribution/reference v0.5.0 // indirect
@@ -182,7 +183,7 @@ require (
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/scroll-tech/zktrie v0.8.2 // indirect
github.com/scroll-tech/zktrie v0.7.1 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect

View File

@@ -148,8 +148,8 @@ github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoY
github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI=
github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA=
github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
@@ -607,10 +607,10 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea h1:CH1WXWrpEpLaP3N+bFs2a1xdE0+lRm1AuJQb5YvE6Ls=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea/go.mod h1:i4VBgWoaW/y0D8MmQb7hSOulyw1dKhuiSFAbznwivCA=
github.com/scroll-tech/zktrie v0.8.2 h1:UMuIfA+jdgWMLmTgTL64Emo+zzMOdcnH0+eYdDcshxQ=
github.com/scroll-tech/zktrie v0.8.2/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240326144132-0f0cd99f7a2e h1:FcoK0rykAWI+5E7cQM6ALRLd5CmjBTHRvJztRBH2xeM=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240326144132-0f0cd99f7a2e/go.mod h1:7Rz2bh9pn42rGuxjh51CG7HL9SKMG3ZugJkL3emdZx8=
github.com/scroll-tech/zktrie v0.7.1 h1:NrmZNjuBzsbrKePqdHDG+t2cXnimbtezPAFS0+L9ElE=
github.com/scroll-tech/zktrie v0.7.1/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE=
github.com/secure-systems-lab/go-securesystemslib v0.4.0/go.mod h1:FGBZgq2tXWICsxWQW1msNf49F0Pf2Op5Htayx335Qbs=
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 h1:ka9QPuQg2u4LGipiZGsgkg3rJCo4iIUCy75FddM0GRQ=

View File

@@ -0,0 +1,127 @@
package testcontainers
import (
"context"
"crypto/rand"
"fmt"
"math/big"
"os"
"path/filepath"
"time"
"github.com/cloudflare/cfssl/log"
"github.com/scroll-tech/go-ethereum/ethclient"
tc "github.com/testcontainers/testcontainers-go/modules/compose"
"github.com/testcontainers/testcontainers-go/wait"
)
// PoSL1TestEnv represents the config needed to test in PoS Layer 1.
type PoSL1TestEnv struct {
dockerComposeFile string
compose tc.ComposeStack
gethHTTPPort int
hostPath string
}
// NewPoSL1TestEnv creates and initializes a new instance of PoSL1TestEnv with a random HTTP port.
func NewPoSL1TestEnv() (*PoSL1TestEnv, error) {
rootDir, err := findProjectRootDir()
if err != nil {
return nil, fmt.Errorf("failed to find project root directory: %v", err)
}
hostPath, found := os.LookupEnv("HOST_PATH")
if !found {
hostPath = ""
}
rnd, err := rand.Int(rand.Reader, big.NewInt(65536-1024))
if err != nil {
return nil, fmt.Errorf("failed to generate a random: %v", err)
}
gethHTTPPort := int(rnd.Int64()) + 1024
if err := os.Setenv("GETH_HTTP_PORT", fmt.Sprintf("%d", gethHTTPPort)); err != nil {
return nil, fmt.Errorf("failed to set GETH_HTTP_PORT: %v", err)
}
return &PoSL1TestEnv{
dockerComposeFile: filepath.Join(rootDir, "common", "docker-compose", "l1", "docker-compose.yml"),
gethHTTPPort: gethHTTPPort,
hostPath: hostPath,
}, nil
}
// Start starts the PoS L1 test environment by running the associated Docker Compose configuration.
func (e *PoSL1TestEnv) Start() error {
var err error
e.compose, err = tc.NewDockerCompose([]string{e.dockerComposeFile}...)
if err != nil {
return fmt.Errorf("failed to create docker compose: %w", err)
}
env := map[string]string{
"GETH_HTTP_PORT": fmt.Sprintf("%d", e.gethHTTPPort),
}
if e.hostPath != "" {
env["HOST_PATH"] = e.hostPath
}
if err = e.compose.WaitForService("geth", wait.NewHTTPStrategy("/").WithPort("8545/tcp").WithStartupTimeout(15*time.Second)).WithEnv(env).Up(context.Background()); err != nil {
if errStop := e.Stop(); errStop != nil {
log.Error("failed to stop PoS L1 test environment", "err", errStop)
}
return fmt.Errorf("failed to start PoS L1 test environment: %w", err)
}
return nil
}
// Stop stops the PoS L1 test environment by stopping and removing the associated Docker Compose services.
func (e *PoSL1TestEnv) Stop() error {
if e.compose != nil {
if err := e.compose.Down(context.Background(), tc.RemoveOrphans(true), tc.RemoveVolumes(true), tc.RemoveImagesLocal); err != nil {
return fmt.Errorf("failed to stop PoS L1 test environment: %w", err)
}
}
return nil
}
// Endpoint returns the HTTP endpoint for the PoS L1 test environment.
func (e *PoSL1TestEnv) Endpoint() string {
return fmt.Sprintf("http://127.0.0.1:%d", e.gethHTTPPort)
}
// L1Client returns an ethclient by dialing the running PoS L1 test environment
func (e *PoSL1TestEnv) L1Client() (*ethclient.Client, error) {
if e == nil {
return nil, fmt.Errorf("PoS L1 test environment is not initialized")
}
client, err := ethclient.Dial(e.Endpoint())
if err != nil {
return nil, fmt.Errorf("failed to dial PoS L1 test environment: %w", err)
}
return client, nil
}
func findProjectRootDir() (string, error) {
currentDir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to get working directory: %w", err)
}
for {
_, err := os.Stat(filepath.Join(currentDir, "go.work"))
if err == nil {
return currentDir, nil
}
parentDir := filepath.Dir(currentDir)
if parentDir == currentDir {
return "", fmt.Errorf("go.work file not found in any parent directory")
}
currentDir = parentDir
}
}

View File

@@ -4,13 +4,10 @@ import (
"context"
"fmt"
"log"
"os"
"path/filepath"
"time"
"github.com/scroll-tech/go-ethereum/ethclient"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/compose"
"github.com/testcontainers/testcontainers-go/modules/postgres"
"github.com/testcontainers/testcontainers-go/wait"
"gorm.io/gorm"
@@ -21,8 +18,8 @@ import (
// TestcontainerApps testcontainers struct
type TestcontainerApps struct {
postgresContainer *postgres.PostgresContainer
l1GethContainer *testcontainers.DockerContainer
l2GethContainer *testcontainers.DockerContainer
poSL1Container compose.ComposeStack
// common time stamp in nanoseconds.
Timestamp int
@@ -31,11 +28,6 @@ type TestcontainerApps struct {
// NewTestcontainerApps returns new instance of TestcontainerApps struct
func NewTestcontainerApps() *TestcontainerApps {
timestamp := time.Now().Nanosecond()
// In order to solve the problem of "creating reaper failed: failed to create container"
// refer to https://github.com/testcontainers/testcontainers-go/issues/2172
if err := os.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true"); err != nil {
panic("set env failed: " + err.Error())
}
return &TestcontainerApps{
Timestamp: timestamp,
}
@@ -61,6 +53,33 @@ func (t *TestcontainerApps) StartPostgresContainer() error {
return nil
}
// StartL1GethContainer starts a L1Geth container
func (t *TestcontainerApps) StartL1GethContainer() error {
if t.l1GethContainer != nil && t.l1GethContainer.IsRunning() {
return nil
}
req := testcontainers.ContainerRequest{
Image: "scroll_l1geth",
ExposedPorts: []string{"8546/tcp", "8545/tcp"},
WaitingFor: wait.ForAll(
wait.ForListeningPort("8546").WithStartupTimeout(100*time.Second),
wait.ForListeningPort("8545").WithStartupTimeout(100*time.Second),
),
Cmd: []string{"--log.debug", "ANY"},
}
genericContainerReq := testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
}
container, err := testcontainers.GenericContainer(context.Background(), genericContainerReq)
if err != nil {
log.Printf("failed to start scroll_l1geth container: %s", err)
return err
}
t.l1GethContainer, _ = container.(*testcontainers.DockerContainer)
return nil
}
// StartL2GethContainer starts a L2Geth container
func (t *TestcontainerApps) StartL2GethContainer() error {
if t.l2GethContainer != nil && t.l2GethContainer.IsRunning() {
@@ -87,55 +106,6 @@ func (t *TestcontainerApps) StartL2GethContainer() error {
return nil
}
// StartPoSL1Container starts the PoS L1 container by running the associated Docker Compose configuration
func (t *TestcontainerApps) StartPoSL1Container() error {
var (
err error
rootDir string
dockerComposeFile string
)
if rootDir, err = findProjectRootDir(); err != nil {
return fmt.Errorf("failed to find project root directory: %v", err)
}
dockerComposeFile = filepath.Join(rootDir, "common", "testcontainers", "docker-compose.yml")
if t.poSL1Container, err = compose.NewDockerCompose([]string{dockerComposeFile}...); err != nil {
return err
}
err = t.poSL1Container.WaitForService("geth", wait.NewHTTPStrategy("/").
WithPort("8545/tcp").
WithStartupTimeout(15*time.Second)).
Up(context.Background())
if err != nil {
t.poSL1Container = nil
return fmt.Errorf("failed to start PoS L1 container: %w", err)
}
return nil
}
// GetPoSL1EndPoint returns the endpoint of the running PoS L1 endpoint
func (t *TestcontainerApps) GetPoSL1EndPoint() (string, error) {
if t.poSL1Container == nil {
return "", fmt.Errorf("PoS L1 container is not running")
}
contrainer, err := t.poSL1Container.ServiceContainer(context.Background(), "geth")
if err != nil {
return "", err
}
return contrainer.PortEndpoint(context.Background(), "8545/tcp", "http")
}
// GetPoSL1Client returns a ethclient by dialing running PoS L1 client
func (t *TestcontainerApps) GetPoSL1Client() (*ethclient.Client, error) {
endpoint, err := t.GetPoSL1EndPoint()
if err != nil {
return nil, err
}
return ethclient.Dial(endpoint)
}
// GetDBEndPoint returns the endpoint of the running postgres container
func (t *TestcontainerApps) GetDBEndPoint() (string, error) {
if t.postgresContainer == nil || !t.postgresContainer.IsRunning() {
@@ -144,6 +114,18 @@ func (t *TestcontainerApps) GetDBEndPoint() (string, error) {
return t.postgresContainer.ConnectionString(context.Background(), "sslmode=disable")
}
// GetL1GethEndPoint returns the endpoint of the running L1Geth container
func (t *TestcontainerApps) GetL1GethEndPoint() (string, error) {
if t.l1GethContainer == nil || !t.l1GethContainer.IsRunning() {
return "", fmt.Errorf("l1 geth is not running")
}
endpoint, err := t.l1GethContainer.PortEndpoint(context.Background(), "8546/tcp", "ws")
if err != nil {
return "", err
}
return endpoint, nil
}
// GetL2GethEndPoint returns the endpoint of the running L2Geth container
func (t *TestcontainerApps) GetL2GethEndPoint() (string, error) {
if t.l2GethContainer == nil || !t.l2GethContainer.IsRunning() {
@@ -171,6 +153,19 @@ func (t *TestcontainerApps) GetGormDBClient() (*gorm.DB, error) {
return database.InitDB(dbCfg)
}
// GetL1GethClient returns a ethclient by dialing running L1Geth
func (t *TestcontainerApps) GetL1GethClient() (*ethclient.Client, error) {
endpoint, err := t.GetL1GethEndPoint()
if err != nil {
return nil, err
}
client, err := ethclient.Dial(endpoint)
if err != nil {
return nil, err
}
return client, nil
}
// GetL2GethClient returns a ethclient by dialing running L2Geth
func (t *TestcontainerApps) GetL2GethClient() (*ethclient.Client, error) {
endpoint, err := t.GetL2GethEndPoint()
@@ -192,38 +187,14 @@ func (t *TestcontainerApps) Free() {
log.Printf("failed to stop postgres container: %s", err)
}
}
if t.l1GethContainer != nil && t.l1GethContainer.IsRunning() {
if err := t.l1GethContainer.Terminate(ctx); err != nil {
log.Printf("failed to stop scroll_l1geth container: %s", err)
}
}
if t.l2GethContainer != nil && t.l2GethContainer.IsRunning() {
if err := t.l2GethContainer.Terminate(ctx); err != nil {
log.Printf("failed to stop scroll_l2geth container: %s", err)
}
}
if t.poSL1Container != nil {
if err := t.poSL1Container.Down(context.Background(), compose.RemoveOrphans(true), compose.RemoveVolumes(true), compose.RemoveImagesLocal); err != nil {
log.Printf("failed to stop PoS L1 container: %s", err)
} else {
t.poSL1Container = nil
}
}
}
// findProjectRootDir find project root directory
func findProjectRootDir() (string, error) {
currentDir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to get working directory: %w", err)
}
for {
_, err := os.Stat(filepath.Join(currentDir, "go.work"))
if err == nil {
return currentDir, nil
}
parentDir := filepath.Dir(currentDir)
if parentDir == currentDir {
return "", fmt.Errorf("go.work file not found in any parent directory")
}
currentDir = parentDir
}
}

View File

@@ -17,9 +17,8 @@ func TestNewTestcontainerApps(t *testing.T) {
ethclient *ethclient.Client
)
testApps := NewTestcontainerApps()
// test start testcontainers
testApps := NewTestcontainerApps()
assert.NoError(t, testApps.StartPostgresContainer())
endpoint, err = testApps.GetDBEndPoint()
assert.NoError(t, err)
@@ -28,6 +27,14 @@ func TestNewTestcontainerApps(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, gormDBclient)
assert.NoError(t, testApps.StartL1GethContainer())
endpoint, err = testApps.GetL1GethEndPoint()
assert.NoError(t, err)
assert.NotEmpty(t, endpoint)
ethclient, err = testApps.GetL1GethClient()
assert.NoError(t, err)
assert.NotNil(t, ethclient)
assert.NoError(t, testApps.StartL2GethContainer())
endpoint, err = testApps.GetL2GethEndPoint()
assert.NoError(t, err)
@@ -36,25 +43,17 @@ func TestNewTestcontainerApps(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, ethclient)
assert.NoError(t, testApps.StartPoSL1Container())
endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
assert.NotEmpty(t, endpoint)
ethclient, err = testApps.GetPoSL1Client()
assert.NoError(t, err)
assert.NotNil(t, ethclient)
// test free testcontainers
testApps.Free()
endpoint, err = testApps.GetDBEndPoint()
assert.EqualError(t, err, "postgres is not running")
assert.Empty(t, endpoint)
endpoint, err = testApps.GetL1GethEndPoint()
assert.EqualError(t, err, "l1 geth is not running")
assert.Empty(t, endpoint)
endpoint, err = testApps.GetL2GethEndPoint()
assert.EqualError(t, err, "l2 geth is not running")
assert.Empty(t, endpoint)
endpoint, err = testApps.GetPoSL1EndPoint()
assert.EqualError(t, err, "PoS L1 container is not running")
assert.Empty(t, endpoint)
}

View File

@@ -302,6 +302,8 @@ func GetMemoryExpansionCost(memoryByteSize uint64) uint64 {
}
// EstimateBlockL1CommitCalldataSize calculates the calldata size in l1 commit for this block approximately.
// TODO: The calculation could be more accurate by using 58 + len(l2TxDataBytes) (see Chunk).
// This needs to be adjusted in the future.
func EstimateBlockL1CommitCalldataSize(b *encoding.Block) (uint64, error) {
var size uint64
for _, txData := range b.Transactions {

View File

@@ -338,7 +338,7 @@ func constructBlobPayload(chunks []*encoding.Chunk) (*kzg4844.Blob, common.Hash,
}
// compute blob versioned hash
c, err := kzg4844.BlobToCommitment(blob)
c, err := kzg4844.BlobToCommitment(*blob)
if err != nil {
return nil, common.Hash{}, nil, fmt.Errorf("failed to create blob commitment")
}
@@ -364,7 +364,7 @@ func constructBlobPayload(chunks []*encoding.Chunk) (*kzg4844.Blob, common.Hash,
func makeBlobCanonical(blobBytes []byte) (*kzg4844.Blob, error) {
// blob contains 131072 bytes but we can only utilize 31/32 of these
if len(blobBytes) > 126976 {
return nil, fmt.Errorf("oversized batch payload, blob bytes length: %v, max length: %v", len(blobBytes), 126976)
return nil, fmt.Errorf("oversized batch payload")
}
// the canonical (padded) blob payload
@@ -435,12 +435,12 @@ func (b *DABatch) BlobDataProof() ([]byte, error) {
return nil, errors.New("called BlobDataProof with empty z")
}
commitment, err := kzg4844.BlobToCommitment(b.blob)
commitment, err := kzg4844.BlobToCommitment(*b.blob)
if err != nil {
return nil, fmt.Errorf("failed to create blob commitment")
}
proof, y, err := kzg4844.ComputeProof(b.blob, *b.z)
proof, y, err := kzg4844.ComputeProof(*b.blob, *b.z)
if err != nil {
log.Crit("failed to create KZG proof at point", "err", err, "z", hex.EncodeToString(b.z[:]))
}
@@ -472,7 +472,8 @@ func EstimateChunkL1CommitBlobSize(c *encoding.Chunk) (uint64, error) {
if err != nil {
return 0, err
}
return calculatePaddedBlobSize(metadataSize + chunkDataSize), nil
paddedSize := ((metadataSize + chunkDataSize + 30) / 31) * 32
return paddedSize, nil
}
// EstimateBatchL1CommitBlobSize estimates the total size of the L1 commit blob for a batch.
@@ -486,7 +487,8 @@ func EstimateBatchL1CommitBlobSize(b *encoding.Batch) (uint64, error) {
}
batchDataSize += chunkDataSize
}
return calculatePaddedBlobSize(metadataSize + batchDataSize), nil
paddedSize := ((metadataSize + batchDataSize + 30) / 31) * 32
return paddedSize, nil
}
func chunkL1CommitBlobDataSize(c *encoding.Chunk) (uint64, error) {
@@ -504,134 +506,3 @@ func chunkL1CommitBlobDataSize(c *encoding.Chunk) (uint64, error) {
}
return dataSize, nil
}
// CalldataNonZeroByteGas is the gas consumption per non zero byte in calldata.
const CalldataNonZeroByteGas = 16
// GetKeccak256Gas calculates the gas cost for computing the keccak256 hash of a given size.
func GetKeccak256Gas(size uint64) uint64 {
return GetMemoryExpansionCost(size) + 30 + 6*((size+31)/32)
}
// GetMemoryExpansionCost calculates the cost of memory expansion for a given memoryByteSize.
func GetMemoryExpansionCost(memoryByteSize uint64) uint64 {
memorySizeWord := (memoryByteSize + 31) / 32
memoryCost := (memorySizeWord*memorySizeWord)/512 + (3 * memorySizeWord)
return memoryCost
}
// EstimateBlockL1CommitGas calculates the total L1 commit gas for this block approximately.
func EstimateBlockL1CommitGas(b *encoding.Block) uint64 {
var total uint64
var numL1Messages uint64
for _, txData := range b.Transactions {
if txData.Type == types.L1MessageTxType {
numL1Messages++
continue
}
}
// 60 bytes BlockContext calldata
total += CalldataNonZeroByteGas * 60
// sload
total += 2100 * numL1Messages // numL1Messages times cold sload in L1MessageQueue
// staticcall
total += 100 * numL1Messages // numL1Messages times call to L1MessageQueue
total += 100 * numL1Messages // numL1Messages times warm address access to L1MessageQueue
total += GetMemoryExpansionCost(36) * numL1Messages // staticcall to proxy
total += 100 * numL1Messages // read admin in proxy
total += 100 * numL1Messages // read impl in proxy
total += 100 * numL1Messages // access impl
total += GetMemoryExpansionCost(36) * numL1Messages // delegatecall to impl
return total
}
// EstimateChunkL1CommitCalldataSize calculates the calldata size needed for committing a chunk to L1 approximately.
func EstimateChunkL1CommitCalldataSize(c *encoding.Chunk) uint64 {
return uint64(60 * len(c.Blocks))
}
// EstimateChunkL1CommitGas calculates the total L1 commit gas for this chunk approximately.
func EstimateChunkL1CommitGas(c *encoding.Chunk) uint64 {
var totalNonSkippedL1Messages uint64
var totalL1CommitGas uint64
for _, block := range c.Blocks {
totalNonSkippedL1Messages += uint64(len(block.Transactions)) - block.NumL2Transactions()
blockL1CommitGas := EstimateBlockL1CommitGas(block)
totalL1CommitGas += blockL1CommitGas
}
numBlocks := uint64(len(c.Blocks))
totalL1CommitGas += 100 * numBlocks // numBlocks times warm sload
totalL1CommitGas += CalldataNonZeroByteGas // numBlocks field of chunk encoding in calldata
totalL1CommitGas += CalldataNonZeroByteGas * numBlocks * 60 // numBlocks of BlockContext in chunk
totalL1CommitGas += GetKeccak256Gas(58*numBlocks + 32*totalNonSkippedL1Messages) // chunk hash
return totalL1CommitGas
}
// EstimateBatchL1CommitGas calculates the total L1 commit gas for this batch approximately.
func EstimateBatchL1CommitGas(b *encoding.Batch) uint64 {
var totalL1CommitGas uint64
// Add extra gas costs
totalL1CommitGas += 100000 // constant to account for ops like _getAdmin, _implementation, _requireNotPaused, etc
totalL1CommitGas += 4 * 2100 // 4 one-time cold sload for commitBatch
totalL1CommitGas += 20000 // 1 time sstore
totalL1CommitGas += 21000 // base fee for tx
totalL1CommitGas += CalldataNonZeroByteGas // version in calldata
// adjusting gas:
// add 1 time cold sload (2100 gas) for L1MessageQueue
// add 1 time cold address access (2600 gas) for L1MessageQueue
// minus 1 time warm sload (100 gas) & 1 time warm address access (100 gas)
totalL1CommitGas += (2100 + 2600 - 100 - 100)
totalL1CommitGas += GetKeccak256Gas(89 + 32) // parent batch header hash, length is estimated as 89 (constant part)+ 32 (1 skippedL1MessageBitmap)
totalL1CommitGas += CalldataNonZeroByteGas * (89 + 32) // parent batch header in calldata
// adjust batch data hash gas cost
totalL1CommitGas += GetKeccak256Gas(uint64(32 * len(b.Chunks)))
totalL1MessagePoppedBefore := b.TotalL1MessagePoppedBefore
for _, chunk := range b.Chunks {
chunkL1CommitGas := EstimateChunkL1CommitGas(chunk)
totalL1CommitGas += chunkL1CommitGas
totalL1MessagePoppedInChunk := chunk.NumL1Messages(totalL1MessagePoppedBefore)
totalL1MessagePoppedBefore += totalL1MessagePoppedInChunk
totalL1CommitGas += CalldataNonZeroByteGas * (32 * (totalL1MessagePoppedInChunk + 255) / 256)
totalL1CommitGas += GetKeccak256Gas(89 + 32*(totalL1MessagePoppedInChunk+255)/256)
totalL1CommitCalldataSize := EstimateChunkL1CommitCalldataSize(chunk)
totalL1CommitGas += GetMemoryExpansionCost(totalL1CommitCalldataSize)
}
return totalL1CommitGas
}
// EstimateBatchL1CommitCalldataSize calculates the calldata size in l1 commit for this batch approximately.
func EstimateBatchL1CommitCalldataSize(b *encoding.Batch) uint64 {
var totalL1CommitCalldataSize uint64
for _, chunk := range b.Chunks {
totalL1CommitCalldataSize += EstimateChunkL1CommitCalldataSize(chunk)
}
return totalL1CommitCalldataSize
}
// calculatePaddedBlobSize calculates the required size on blob storage
// where every 32 bytes can store only 31 bytes of actual data, with the first byte being zero.
func calculatePaddedBlobSize(dataSize uint64) uint64 {
paddedSize := (dataSize / 31) * 32
if dataSize%31 != 0 {
paddedSize += 1 + dataSize%31 // Add 1 byte for the first empty byte plus the remainder bytes
}
return paddedSize
}

View File

@@ -592,7 +592,7 @@ func TestCodecV1BatchChallengeWithStandardTestCases(t *testing.T) {
actualZ := hex.EncodeToString(z[:])
assert.Equal(t, tc.expectedz, actualZ)
_, y, err := kzg4844.ComputeProof(b, *z)
_, y, err := kzg4844.ComputeProof(*b, *z)
assert.NoError(t, err)
actualY := hex.EncodeToString(y[:])
assert.Equal(t, tc.expectedy, actualY)
@@ -759,121 +759,49 @@ func TestCodecV1BatchSkipBitmap(t *testing.T) {
assert.Equal(t, 42, int(batch.TotalL1MessagePopped))
}
func TestCodecV1ChunkAndBatchCommitBlobSizeEstimation(t *testing.T) {
func TestCodecV1ChunkAndBatchBlobSizeEstimation(t *testing.T) {
trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
chunk2BlobSize, err := EstimateChunkL1CommitBlobSize(chunk2)
assert.NoError(t, err)
assert.Equal(t, uint64(302), chunk2BlobSize)
assert.Equal(t, uint64(320), chunk2BlobSize)
batch2 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
batch2BlobSize, err := EstimateBatchL1CommitBlobSize(batch2)
assert.NoError(t, err)
assert.Equal(t, uint64(302), batch2BlobSize)
assert.Equal(t, uint64(320), batch2BlobSize)
trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
chunk3BlobSize, err := EstimateChunkL1CommitBlobSize(chunk3)
assert.NoError(t, err)
assert.Equal(t, uint64(5929), chunk3BlobSize)
assert.Equal(t, uint64(5952), chunk3BlobSize)
batch3 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
batch3BlobSize, err := EstimateBatchL1CommitBlobSize(batch3)
assert.NoError(t, err)
assert.Equal(t, uint64(5929), batch3BlobSize)
assert.Equal(t, uint64(5952), batch3BlobSize)
trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
chunk4BlobSize, err := EstimateChunkL1CommitBlobSize(chunk4)
assert.NoError(t, err)
assert.Equal(t, uint64(98), chunk4BlobSize)
assert.Equal(t, uint64(128), chunk4BlobSize)
batch4 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
batch4BlobSize, err := EstimateBatchL1CommitBlobSize(batch4)
assert.NoError(t, err)
assert.Equal(t, uint64(98), batch4BlobSize)
assert.Equal(t, uint64(128), batch4BlobSize)
chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3}}
chunk5BlobSize, err := EstimateChunkL1CommitBlobSize(chunk5)
assert.NoError(t, err)
assert.Equal(t, uint64(6166), chunk5BlobSize)
assert.Equal(t, uint64(6176), chunk5BlobSize)
chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
chunk6BlobSize, err := EstimateChunkL1CommitBlobSize(chunk6)
assert.NoError(t, err)
assert.Equal(t, uint64(98), chunk6BlobSize)
assert.Equal(t, uint64(128), chunk6BlobSize)
batch5 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk5, chunk6}}
batch5BlobSize, err := EstimateBatchL1CommitBlobSize(batch5)
assert.NoError(t, err)
assert.Equal(t, uint64(6199), batch5BlobSize)
}
func TestCodecV1ChunkAndBatchCommitCalldataSizeEstimation(t *testing.T) {
trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
chunk2CalldataSize := EstimateChunkL1CommitCalldataSize(chunk2)
assert.Equal(t, uint64(60), chunk2CalldataSize)
batch2 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
batch2CalldataSize := EstimateBatchL1CommitCalldataSize(batch2)
assert.Equal(t, uint64(60), batch2CalldataSize)
trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
chunk3CalldataSize := EstimateChunkL1CommitCalldataSize(chunk3)
assert.Equal(t, uint64(60), chunk3CalldataSize)
batch3 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
batch3CalldataSize := EstimateBatchL1CommitCalldataSize(batch3)
assert.Equal(t, uint64(60), batch3CalldataSize)
trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
chunk4CalldataSize := EstimateChunkL1CommitCalldataSize(chunk4)
assert.Equal(t, uint64(60), chunk4CalldataSize)
batch4 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
batch4BlobSize := EstimateBatchL1CommitCalldataSize(batch4)
assert.Equal(t, uint64(60), batch4BlobSize)
chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3}}
chunk5CalldataSize := EstimateChunkL1CommitCalldataSize(chunk5)
assert.Equal(t, uint64(120), chunk5CalldataSize)
chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
chunk6BlobSize := EstimateChunkL1CommitCalldataSize(chunk6)
assert.Equal(t, uint64(60), chunk6BlobSize)
batch5 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk5, chunk6}}
batch5CalldataSize := EstimateBatchL1CommitCalldataSize(batch5)
assert.Equal(t, uint64(180), batch5CalldataSize)
}
func TestCodecV1ChunkAndBatchCommitGasEstimation(t *testing.T) {
trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
chunk2Gas := EstimateChunkL1CommitGas(chunk2)
assert.Equal(t, uint64(2084), chunk2Gas)
batch2 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
batch2Gas := EstimateBatchL1CommitGas(batch2)
assert.Equal(t, uint64(158609), batch2Gas)
trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
chunk3Gas := EstimateChunkL1CommitGas(chunk3)
assert.Equal(t, uint64(2084), chunk3Gas)
batch3 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
batch3Gas := EstimateBatchL1CommitGas(batch3)
assert.Equal(t, uint64(158609), batch3Gas)
trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
chunk4Gas := EstimateChunkL1CommitGas(chunk4)
assert.Equal(t, uint64(4705), chunk4Gas)
batch4 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
batch4Gas := EstimateBatchL1CommitGas(batch4)
assert.Equal(t, uint64(161262), batch4Gas)
chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3}}
chunk5Gas := EstimateChunkL1CommitGas(chunk5)
assert.Equal(t, uint64(4122), chunk5Gas)
chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
chunk6Gas := EstimateChunkL1CommitGas(chunk6)
assert.Equal(t, uint64(4705), chunk6Gas)
batch5 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk5, chunk6}}
batch5Gas := EstimateBatchL1CommitGas(batch5)
assert.Equal(t, uint64(165967), batch5Gas)
assert.Equal(t, uint64(6208), batch5BlobSize)
}
func readBlockFromJSON(t *testing.T, filename string) *encoding.Block {

View File

@@ -9,7 +9,7 @@ import (
// CheckScrollProverVersion check the "scroll-prover" version, if it's different from the local one, return false
func CheckScrollProverVersion(proverVersion string) bool {
// note the version is in fact in the format of "tag-commit-scroll_prover-halo2",
// note the the version is in fact in the format of "tag-commit-scroll_prover-halo2",
// so split-by-'-' length should be 4
remote := strings.Split(proverVersion, "-")
if len(remote) != 4 {

View File

@@ -5,7 +5,7 @@ import (
"runtime/debug"
)
var tag = "v4.4.4"
var tag = "v4.3.93"
var commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok {

View File

@@ -67,7 +67,7 @@ Commit a batch of transactions on layer 1.
function committedBatches(uint256) external view returns (bytes32)
```
Return the batch hash of a committed batch.
@@ -81,7 +81,7 @@ function committedBatches(uint256) external view returns (bytes32)
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | The batch hash of a committed batch. |
| _0 | bytes32 | undefined |
### finalizeBatchWithProof
@@ -130,7 +130,7 @@ Finalize a committed batch (with blob) on layer 1.
function finalizedStateRoots(uint256) external view returns (bytes32)
```
Return the state root of a committed batch.
@@ -144,7 +144,7 @@ function finalizedStateRoots(uint256) external view returns (bytes32)
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | The state root of a committed batch. |
| _0 | bytes32 | undefined |
### importGenesisBatch
@@ -160,8 +160,8 @@ Import layer 2 genesis block
| Name | Type | Description |
|---|---|---|
| _batchHeader | bytes | The header of the genesis batch. |
| _stateRoot | bytes32 | The state root of the genesis block. |
| _batchHeader | bytes | undefined |
| _stateRoot | bytes32 | undefined |
### initialize
@@ -187,7 +187,7 @@ Initialize the storage of ScrollChain.
function isBatchFinalized(uint256 _batchIndex) external view returns (bool)
```
Return whether the batch is finalized by batch index.
@@ -201,7 +201,7 @@ function isBatchFinalized(uint256 _batchIndex) external view returns (bool)
| Name | Type | Description |
|---|---|---|
| _0 | bool | Whether the batch is finalized by batch index. |
| _0 | bool | undefined |
### isProver
@@ -253,7 +253,7 @@ Whether an account is a sequencer.
function lastFinalizedBatchIndex() external view returns (uint256)
```
The latest finalized batch index.
@@ -262,7 +262,7 @@ function lastFinalizedBatchIndex() external view returns (uint256)
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | The latest finalized batch index. |
| _0 | uint256 | undefined |
### layer2ChainId
@@ -480,7 +480,7 @@ The address of RollupVerifier.
function withdrawRoots(uint256) external view returns (bytes32)
```
Return the message root of a committed batch.
@@ -494,7 +494,7 @@ function withdrawRoots(uint256) external view returns (bytes32)
| Name | Type | Description |
|---|---|---|
| _0 | bytes32 | The message root of a committed batch. |
| _0 | bytes32 | undefined |

View File

@@ -11,7 +11,7 @@ import {IScrollERC20Upgradeable} from "../../libraries/token/IScrollERC20Upgrade
/// @title L2ERC20Gateway
/// @notice The `L2ERC20Gateway` is used to withdraw custom ERC20 compatible tokens on layer 2 and
/// finalize deposit the tokens from layer 1.
/// @dev The withdrawn tokens will be burned directly. On finalizing deposit, the corresponding
/// @dev The withdrawn tokens tokens will be burned directly. On finalizing deposit, the corresponding
/// tokens will be minted and transferred to the recipient.
contract L2CustomERC20Gateway is L2ERC20Gateway {
/**********

View File

@@ -1,35 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
library BatchBridgeCodec {
/// @dev Encode the `token` and `batchIndex` to single `bytes32`.
function encodeInitialNode(address token, uint64 batchIndex) internal pure returns (bytes32 node) {
assembly {
node := add(shl(96, token), batchIndex)
}
}
/// @dev Encode the `sender` and `amount` to single `bytes32`.
function encodeNode(address sender, uint96 amount) internal pure returns (bytes32 node) {
assembly {
node := add(shl(96, sender), amount)
}
}
/// @dev Decode `bytes32` `node` to `receiver` and `amount`.
function decodeNode(bytes32 node) internal pure returns (address receiver, uint256 amount) {
receiver = address(uint160(uint256(node) >> 96));
amount = uint256(node) & 0xffffffffffffffffffffffff;
}
/// @dev Compute `keccak256(concat(a, b))`.
function hash(bytes32 a, bytes32 b) internal pure returns (bytes32 value) {
// solhint-disable-next-line no-inline-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}

View File

@@ -1,425 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
import {AccessControlEnumerableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {AddressUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import {IL1ERC20Gateway} from "../L1/gateways/IL1ERC20Gateway.sol";
import {IL1GatewayRouter} from "../L1/gateways/IL1GatewayRouter.sol";
import {IL1MessageQueue} from "../L1/rollup/IL1MessageQueue.sol";
import {IL1ScrollMessenger} from "../L1/IL1ScrollMessenger.sol";
import {BatchBridgeCodec} from "./BatchBridgeCodec.sol";
import {L2BatchBridgeGateway} from "./L2BatchBridgeGateway.sol";
/// @title L1BatchBridgeGateway
contract L1BatchBridgeGateway is AccessControlEnumerableUpgradeable, ReentrancyGuardUpgradeable {
using SafeERC20Upgradeable for IERC20Upgradeable;
/**********
* Events *
**********/
/// @notice Emitted when some user deposited token to this contract.
/// @param sender The address of token sender.
/// @param token The address of deposited token.
/// @param batchIndex The batch index of current deposit.
/// @param amount The amount of token deposited (including fee).
/// @param fee The amount of fee charged.
event Deposit(
address indexed sender,
address indexed token,
uint256 indexed batchIndex,
uint256 amount,
uint256 fee
);
/// @notice Emitted when a batch deposit is initiated.
/// @param caller The address of caller who initiate the deposit.
/// @param l1Token The address of the token in L1 to deposit.
/// @param batchIndex The index of current batch deposit.
/// @param l2Token The address of the corresponding token in L2.
event BatchDeposit(address indexed caller, address indexed l1Token, uint256 indexed batchIndex, address l2Token);
/**********
* Errors *
**********/
/// @dev Thrown when caller is not `messenger`.
error ErrorCallerNotMessenger();
/// @dev Thrown when the deposited amount is smaller than `minAmountPerTx`.
error ErrorDepositAmountTooSmall();
/// @dev Thrown when users try to deposit ETH with `depositERC20` method.
error ErrorIncorrectMethodForETHDeposit();
/// @dev Thrown when the `msg.value` is not enough for batch deposit fee.
error ErrorInsufficientMsgValueForBatchDepositFee();
/// @dev Thrown when the given new batch config is invalid.
error ErrorInvalidBatchConfig();
/// @dev Thrown when no pending batch exists.
error ErrorNoPendingBatch();
/// @dev Thrown when user deposits unsupported tokens.
error ErrorTokenNotSupported();
/// @dev Thrown when ETH transfer failed.
error ErrorTransferETHFailed();
/*************
* Constants *
*************/
/// @notice The role for batch deposit keeper.
bytes32 public constant KEEPER_ROLE = keccak256("KEEPER_ROLE");
/// @notice The safe gas limit for batch bridge.
uint256 private constant SAFE_BATCH_BRIDGE_GAS_LIMIT = 200000;
/// @notice The address of corresponding `L2BatchDepositGateway` contract.
address public immutable counterpart;
/// @notice The address of `L1GatewayRouter` contract.
address public immutable router;
/// @notice The address of `L1ScrollMessenger` contract.
address public immutable messenger;
/// @notice The address of `L1MessageQueue` contract.
address public immutable queue;
/***********
* Structs *
***********/
/// @notice The config for batch token bridge.
/// @dev Compiler will pack this into a single `bytes32`.
/// @param feeAmountPerTx The amount of fee charged for each deposit.
/// @param minAmountPerTx The minimum amount of token for each deposit.
/// @param maxTxsPerBatch The maximum number of deposit in each batch.
/// @param maxDelayPerBatch The maximum number of seconds to wait in each batch.
/// @param safeBridgeGasLimit The safe bridge gas limit for bridging token from L1 to L2.
struct BatchConfig {
uint96 feeAmountPerTx;
uint96 minAmountPerTx;
uint16 maxTxsPerBatch;
uint24 maxDelayPerBatch;
uint24 safeBridgeGasLimit;
}
/// @dev Compiler will pack this into two `bytes32`.
/// @param amount The total amount of token to deposit in current batch.
/// @param startTime The timestamp of the first deposit.
/// @param numDeposits The total number of deposits in current batch.
/// @param hash The hash of current batch.
/// Suppose there are `n` deposits in current batch with `senders` and `amounts`. The hash is computed as
/// ```text
/// hash[0] = concat(token, batch_index)
/// hash[i] = keccak(hash[i-1], concat(senders[i], amounts[i]))
/// ```
/// The type of `token` and `senders` is `address`, while The type of `batch_index` and `amounts[i]` is `uint96`.
/// In current way, the hash of each batch among all tokens should be different.
struct BatchState {
uint128 amount;
uint64 startTime;
uint64 numDeposits;
bytes32 hash;
}
/// @dev Compiler will pack this into a single `bytes32`.
/// @param pending The total amount of token pending to bridge.
/// @param currentBatchIndex The index of current batch.
/// @param pendingBatchIndex The index of pending batch (next batch to bridge).
struct TokenState {
uint128 pending;
uint64 currentBatchIndex;
uint64 pendingBatchIndex;
}
/*************
* Variables *
*************/
/// @notice Mapping from token address to batch bridge config.
/// @dev The `address(0)` is used for ETH.
mapping(address => BatchConfig) public configs;
/// @notice Mapping from token address to batch index to batch state.
/// @dev The `address(0)` is used for ETH.
mapping(address => mapping(uint256 => BatchState)) public batches;
/// @notice Mapping from token address to token state.
/// @dev The `address(0)` is used for ETH.
mapping(address => TokenState) public tokens;
/// @notice The address of fee vault.
address public feeVault;
/***************
* Constructor *
***************/
/// @param _counterpart The address of `L2BatchDepositGateway` contract in L2.
/// @param _router The address of `L1GatewayRouter` contract in L1.
/// @param _messenger The address of `L1ScrollMessenger` contract in L1.
/// @param _queue The address of `L1MessageQueue` contract in L1.
constructor(
address _counterpart,
address _router,
address _messenger,
address _queue
) {
_disableInitializers();
counterpart = _counterpart;
router = _router;
messenger = _messenger;
queue = _queue;
}
/// @notice Initialize the storage of `L1BatchDepositGateway`.
/// @param _feeVault The address of fee vault contract.
function initialize(address _feeVault) external initializer {
__Context_init(); // from ContextUpgradeable
__ERC165_init(); // from ERC165Upgradeable
__AccessControl_init(); // from AccessControlUpgradeable
__AccessControlEnumerable_init(); // from AccessControlEnumerableUpgradeable
__ReentrancyGuard_init(); // from ReentrancyGuardUpgradeable
feeVault = _feeVault;
_grantRole(DEFAULT_ADMIN_ROLE, _msgSender());
}
/*****************************
* Public Mutating Functions *
*****************************/
/// @notice Receive refunded ETH from `L1ScrollMessenger`.
receive() external payable {
if (_msgSender() != messenger) {
revert ErrorCallerNotMessenger();
}
}
/// @notice Deposit ETH.
function depositETH() external payable {
// no safe cast check here, since no one has so much ETH yet.
_deposit(address(0), _msgSender(), uint96(msg.value));
}
/// @notice Deposit ERC20 token.
///
/// @param token The address of token.
/// @param amount The amount of token to deposit. We use type `uint96`, since it is enough for most of the major tokens.
function depositERC20(address token, uint96 amount) external {
if (token == address(0)) revert ErrorIncorrectMethodForETHDeposit();
// common practice to handle fee on transfer token.
uint256 beforeBalance = IERC20Upgradeable(token).balanceOf(address(this));
IERC20Upgradeable(token).safeTransferFrom(_msgSender(), address(this), amount);
amount = uint96(IERC20Upgradeable(token).balanceOf(address(this)) - beforeBalance);
_deposit(token, _msgSender(), amount);
}
/************************
* Restricted Functions *
************************/
/// @notice Add or update the batch bridge config for the given token.
///
/// @dev The caller should make sure `safeBridgeGasLimit` is enough for batch bridging.
///
/// @param token The address of token to update.
/// @param newConfig The new config.
function setBatchConfig(address token, BatchConfig memory newConfig) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (
newConfig.maxTxsPerBatch == 0 ||
newConfig.maxDelayPerBatch == 0 ||
newConfig.feeAmountPerTx > newConfig.minAmountPerTx
) {
revert ErrorInvalidBatchConfig();
}
configs[token] = newConfig;
}
/// @notice Initiate the batch bridge of current pending batch.
/// @param token The address of the token.
function executeBatchDeposit(address token) external payable onlyRole(KEEPER_ROLE) {
BatchConfig memory cachedBatchConfig = configs[token];
TokenState memory cachedTokenState = tokens[token];
_tryFinalizeCurrentBatch(token, cachedBatchConfig, cachedTokenState);
// no batch to bridge
if (cachedTokenState.currentBatchIndex == cachedTokenState.pendingBatchIndex) {
revert ErrorNoPendingBatch();
}
// check bridge fee
uint256 depositFee = IL1MessageQueue(queue).estimateCrossDomainMessageFee(cachedBatchConfig.safeBridgeGasLimit);
uint256 batchBridgeFee = IL1MessageQueue(queue).estimateCrossDomainMessageFee(SAFE_BATCH_BRIDGE_GAS_LIMIT);
if (msg.value < depositFee + batchBridgeFee) {
revert ErrorInsufficientMsgValueForBatchDepositFee();
}
// take accumulated fee to fee vault
uint256 accumulatedFee;
if (token == address(0)) {
// no uncheck here just in case
accumulatedFee = address(this).balance - msg.value - cachedTokenState.pending;
} else {
// no uncheck here just in case
accumulatedFee = IERC20Upgradeable(token).balanceOf(address(this)) - cachedTokenState.pending;
}
if (accumulatedFee > 0) {
_transferToken(token, feeVault, accumulatedFee);
}
// deposit token to L2
BatchState memory cachedBatchState = batches[token][cachedTokenState.pendingBatchIndex];
address l2Token;
if (token == address(0)) {
IL1ScrollMessenger(messenger).sendMessage{value: cachedBatchState.amount + depositFee}(
counterpart,
cachedBatchState.amount,
new bytes(0),
cachedBatchConfig.safeBridgeGasLimit
);
} else {
address gateway = IL1GatewayRouter(router).getERC20Gateway(token);
l2Token = IL1ERC20Gateway(gateway).getL2ERC20Address(token);
IERC20Upgradeable(token).safeApprove(gateway, 0);
IERC20Upgradeable(token).safeApprove(gateway, cachedBatchState.amount);
IL1ERC20Gateway(gateway).depositERC20{value: depositFee}(
token,
counterpart,
cachedBatchState.amount,
cachedBatchConfig.safeBridgeGasLimit
);
}
// notify `L2BatchBridgeGateway`
IL1ScrollMessenger(messenger).sendMessage{value: batchBridgeFee}(
counterpart,
0,
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(token, l2Token, cachedTokenState.pendingBatchIndex, cachedBatchState.hash)
),
SAFE_BATCH_BRIDGE_GAS_LIMIT
);
emit BatchDeposit(_msgSender(), token, cachedTokenState.pendingBatchIndex, l2Token);
// update token state
unchecked {
cachedTokenState.pending -= uint128(cachedBatchState.amount);
cachedTokenState.pendingBatchIndex += 1;
}
tokens[token] = cachedTokenState;
// refund keeper fee
unchecked {
if (msg.value > depositFee + batchBridgeFee) {
_transferToken(address(0), _msgSender(), msg.value - depositFee - batchBridgeFee);
}
}
}
/**********************
* Internal Functions *
**********************/
/// @dev Internal function to deposit token.
/// @param token The address of token to deposit.
/// @param sender The address of token sender.
/// @param amount The amount of token to deposit.
function _deposit(
address token,
address sender,
uint96 amount
) internal nonReentrant {
BatchConfig memory cachedBatchConfig = configs[token];
TokenState memory cachedTokenState = tokens[token];
_tryFinalizeCurrentBatch(token, cachedBatchConfig, cachedTokenState);
BatchState memory cachedBatchState = batches[token][cachedTokenState.currentBatchIndex];
if (amount < cachedBatchConfig.minAmountPerTx) {
revert ErrorDepositAmountTooSmall();
}
emit Deposit(sender, token, cachedTokenState.currentBatchIndex, amount, cachedBatchConfig.feeAmountPerTx);
// deduct fee and update cached state
unchecked {
amount -= cachedBatchConfig.feeAmountPerTx;
cachedTokenState.pending += amount;
cachedBatchState.amount += amount;
cachedBatchState.numDeposits += 1;
}
// compute the hash chain
bytes32 node = BatchBridgeCodec.encodeNode(sender, amount);
if (cachedBatchState.hash == bytes32(0)) {
bytes32 initialNode = BatchBridgeCodec.encodeInitialNode(token, cachedTokenState.currentBatchIndex);
// this is first tx in this batch
cachedBatchState.hash = BatchBridgeCodec.hash(initialNode, node);
cachedBatchState.startTime = uint64(block.timestamp);
} else {
cachedBatchState.hash = BatchBridgeCodec.hash(cachedBatchState.hash, node);
}
batches[token][cachedTokenState.currentBatchIndex] = cachedBatchState;
tokens[token] = cachedTokenState;
}
/// @dev Internal function to finalize current batch.
/// This function may change the value of `cachedTokenState`, which can be used in later operation.
/// @param token The address of token to finalize.
/// @param cachedBatchConfig The cached batch config in memory.
/// @param cachedTokenState The cached token state in memory.
function _tryFinalizeCurrentBatch(
address token,
BatchConfig memory cachedBatchConfig,
TokenState memory cachedTokenState
) internal view {
if (cachedBatchConfig.maxTxsPerBatch == 0) {
revert ErrorTokenNotSupported();
}
BatchState memory cachedBatchState = batches[token][cachedTokenState.currentBatchIndex];
// return if it is the very first deposit in the current batch
if (cachedBatchState.numDeposits == 0) return;
// finalize current batchIndex when `maxTxsPerBatch` or `maxDelayPerBatch` reached.
if (
cachedBatchState.numDeposits == cachedBatchConfig.maxTxsPerBatch ||
block.timestamp - cachedBatchState.startTime > cachedBatchConfig.maxDelayPerBatch
) {
cachedTokenState.currentBatchIndex += 1;
}
}
/// @dev Internal function to transfer token, including ETH.
/// @param token The address of token.
/// @param receiver The address of token receiver.
/// @param amount The amount of token to transfer.
function _transferToken(
address token,
address receiver,
uint256 amount
) private {
if (token == address(0)) {
(bool success, ) = receiver.call{value: amount}("");
if (!success) revert ErrorTransferETHFailed();
} else {
IERC20Upgradeable(token).safeTransfer(receiver, amount);
}
}
}

View File

@@ -1,246 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
import {AccessControlEnumerableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import {IL2ScrollMessenger} from "../L2/IL2ScrollMessenger.sol";
import {BatchBridgeCodec} from "./BatchBridgeCodec.sol";
/// @title L2BatchBridgeGateway
contract L2BatchBridgeGateway is AccessControlEnumerableUpgradeable {
/**********
* Events *
**********/
/// @notice Emitted when token mapping for ERC20 token is updated.
/// @param l2Token The address of corresponding ERC20 token in layer 2.
/// @param oldL1Token The address of the old corresponding ERC20 token in layer 1.
/// @param newL1Token The address of the new corresponding ERC20 token in layer 1.
event UpdateTokenMapping(address indexed l2Token, address indexed oldL1Token, address indexed newL1Token);
/// @notice Emitted when batch bridge is finalized.
/// @param l1Token The address of token in L1.
/// @param l2Token The address of token in L2.
/// @param batchIndex The index of batch finalized.
event FinalizeBatchDeposit(address indexed l1Token, address indexed l2Token, uint256 indexed batchIndex);
/// @notice Emitted when batch distribution finished.
/// @param l1Token The address of token in L1.
/// @param l2Token The address of token in L2.
/// @param batchIndex The index of batch distributed.
event BatchDistribute(address indexed l1Token, address indexed l2Token, uint256 indexed batchIndex);
/// @notice Emitted when token distribute failed.
/// @param l2Token The address of token in L2.
/// @param batchIndex The index of the batch.
/// @param receiver The address of token receiver.
/// @param amount The amount of token to distribute.
event DistributeFailed(address indexed l2Token, uint256 indexed batchIndex, address receiver, uint256 amount);
/**********
* Errors *
**********/
/// @dev Thrown when caller is not `messenger`.
error ErrorCallerNotMessenger();
/// @dev Thrown when the L1 token mapping mismatch with `finalizeBatchBridge`.
error ErrorL1TokenMismatched();
/// @dev Thrown when message sender is not `counterpart`.
error ErrorMessageSenderNotCounterpart();
/// @dev Thrown no failed distribution exists.
error ErrorNoFailedDistribution();
/// @dev Thrown when the batch hash mismatch.
error ErrorBatchHashMismatch();
/// @dev Thrown when distributing the same batch.
error ErrorBatchDistributed();
/*************
* Constants *
*************/
/// @notice The role for batch deposit keeper.
bytes32 public constant KEEPER_ROLE = keccak256("KEEPER_ROLE");
/// @notice The safe gas limit for ETH transfer
uint256 private constant SAFE_ETH_TRANSFER_GAS_LIMIT = 50000;
/// @notice The address of corresponding `L1BatchBridgeGateway` contract.
address public immutable counterpart;
/// @notice The address of corresponding `L2ScrollMessenger` contract.
address public immutable messenger;
/*************
* Variables *
*************/
/// @notice Mapping from l2 token address to l1 token address.
mapping(address => address) public tokenMapping;
/// @notice Mapping from L2 token address to batch index to batch hash.
mapping(address => mapping(uint256 => bytes32)) public batchHashes;
/// @notice Mapping from token address to the amount of failed distribution.
mapping(address => uint256) public failedAmount;
/// @notice Mapping from batch hash to the distribute status.
mapping(bytes32 => bool) public isDistributed;
/*************
* Modifiers *
*************/
modifier onlyMessenger() {
if (_msgSender() != messenger) {
revert ErrorCallerNotMessenger();
}
_;
}
/***************
* Constructor *
***************/
/// @param _counterpart The address of `L1BatchBridgeGateway` contract in L1.
/// @param _messenger The address of `L2ScrollMessenger` contract in L2.
constructor(address _counterpart, address _messenger) {
_disableInitializers();
counterpart = _counterpart;
messenger = _messenger;
}
/// @notice Initialize the storage of `L2BatchBridgeGateway`.
function initialize() external initializer {
__Context_init(); // from ContextUpgradeable
__ERC165_init(); // from ERC165Upgradeable
__AccessControl_init(); // from AccessControlUpgradeable
__AccessControlEnumerable_init(); // from AccessControlEnumerableUpgradeable
_grantRole(DEFAULT_ADMIN_ROLE, _msgSender());
}
/*****************************
* Public Mutating Functions *
*****************************/
/// @notice Receive batch bridged ETH from `L2ScrollMessenger`.
receive() external payable onlyMessenger {
// empty
}
/// @notice Finalize L1 initiated batch token deposit.
/// @param l1Token The address of the token in L1.
/// @param l2Token The address of the token in L2.
/// @param batchIndex The index of this batch bridge.
/// @param hash The hash of this batch.
function finalizeBatchDeposit(
address l1Token,
address l2Token,
uint256 batchIndex,
bytes32 hash
) external onlyMessenger {
if (counterpart != IL2ScrollMessenger(messenger).xDomainMessageSender()) {
revert ErrorMessageSenderNotCounterpart();
}
// trust the messenger and update `tokenMapping` in first call
// another assumption is this function should never fail due to out of gas
address storedL1Token = tokenMapping[l2Token];
if (storedL1Token == address(0) && l1Token != address(0)) {
tokenMapping[l2Token] = l1Token;
} else if (storedL1Token != l1Token) {
// this usually won't happen, check just in case.
revert ErrorL1TokenMismatched();
}
batchHashes[l2Token][batchIndex] = hash;
emit FinalizeBatchDeposit(l1Token, l2Token, batchIndex);
}
/************************
* Restricted Functions *
************************/
/// @notice Withdraw distribution failed tokens.
/// @param token The address of token to withdraw.
/// @param receiver The address of token receiver.
function withdrawFailedAmount(address token, address receiver) external onlyRole(DEFAULT_ADMIN_ROLE) {
uint256 amount = failedAmount[token];
if (amount == 0) revert ErrorNoFailedDistribution();
failedAmount[token] = 0;
_transferToken(token, receiver, amount);
}
/// @notice Distribute deposited token to corresponding receivers.
/// @param l2Token The address of L2 token.
/// @param batchIndex The index of batch to distribute.
/// @param nodes The list of encoded L1 deposits.
function distribute(
address l2Token,
uint64 batchIndex,
bytes32[] memory nodes
) external onlyRole(KEEPER_ROLE) {
address l1Token = tokenMapping[l2Token];
bytes32 hash = BatchBridgeCodec.encodeInitialNode(l1Token, batchIndex);
for (uint256 i = 0; i < nodes.length; i++) {
hash = BatchBridgeCodec.hash(hash, nodes[i]);
}
if (batchHashes[l2Token][batchIndex] != hash) {
revert ErrorBatchHashMismatch();
}
if (isDistributed[hash]) {
revert ErrorBatchDistributed();
}
isDistributed[hash] = true;
// do transfer and allow failure to avoid DDOS attack
for (uint256 i = 0; i < nodes.length; i++) {
(address receiver, uint256 amount) = BatchBridgeCodec.decodeNode(nodes[i]);
if (!_transferToken(l2Token, receiver, amount)) {
failedAmount[l2Token] += amount;
emit DistributeFailed(l2Token, batchIndex, receiver, amount);
}
}
emit BatchDistribute(l1Token, l2Token, batchIndex);
}
/**********************
* Internal Functions *
**********************/
/// @dev Internal function to transfer token, including ETH.
/// @param token The address of token.
/// @param receiver The address of token receiver.
/// @param amount The amount of token to transfer.
/// @return success Whether the transfer is successful.
function _transferToken(
address token,
address receiver,
uint256 amount
) private returns (bool success) {
if (token == address(0)) {
// We add gas limit here to avoid DDOS from malicious receiver.
(success, ) = receiver.call{value: amount, gas: SAFE_ETH_TRANSFER_GAS_LIMIT}("");
} else {
// We perform a low level call here, to bypass Solidity's return data size checking mechanism.
// Normally, the token is selected that the call would not revert unless out of gas.
bytes memory returnData;
(success, returnData) = token.call(abi.encodeCall(IERC20Upgradeable.transfer, (receiver, amount)));
if (success && returnData.length > 0) {
success = abi.decode(returnData, (bool));
}
}
}
}

View File

@@ -79,7 +79,7 @@ library BatchHeaderV0Codec {
/// @notice Get the number of L1 messages popped before this batch.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _totalL1MessagePopped The number of L1 messages popped before this batch.
/// @return _totalL1MessagePopped The the number of L1 messages popped before this batch.
function getTotalL1MessagePopped(uint256 batchPtr) internal pure returns (uint256 _totalL1MessagePopped) {
assembly {
_totalL1MessagePopped := shr(192, mload(add(batchPtr, 17)))

View File

@@ -79,7 +79,7 @@ library BatchHeaderV1Codec {
/// @notice Get the number of L1 messages popped before this batch.
/// @param batchPtr The start memory offset of the batch header in memory.
/// @return _totalL1MessagePopped The number of L1 messages popped before this batch.
/// @return _totalL1MessagePopped The the number of L1 messages popped before this batch.
function getTotalL1MessagePopped(uint256 batchPtr) internal pure returns (uint256 _totalL1MessagePopped) {
assembly {
_totalL1MessagePopped := shr(192, mload(add(batchPtr, 17)))

View File

@@ -98,7 +98,7 @@ According to the Scroll documentation, `L1ScrollMessenger`:
This contract is central in the L2-to-L1 communication process since all messages from L2 that verified by the zkevm proof are executed on behalf of this contract.
In case of a vulnerability in the `L1ScrollMessenger`, which allows the attacker to send arbitrary messages bypassing the zkevm proof, an attacker can immediately drain tokens from the L1 bridge.
In case of a vulnerability in the `L1ScrollMessenger`, which allows the attacker to send arbitrary messages bypassing the the zkevm proof, an attacker can immediately drain tokens from the L1 bridge.
Additional risk creates the upgradeability of the `L1ScrollMessenger`. Exist a risk of an attack with the replacement of the implementation with some malicious functionality. Such an attack might be reduced to the above vulnerability and steal all locked tokens on the L1 bridge.

View File

@@ -1,634 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {L1BatchBridgeGateway} from "../../batch-bridge/L1BatchBridgeGateway.sol";
import {L2BatchBridgeGateway} from "../../batch-bridge/L2BatchBridgeGateway.sol";
import {BatchBridgeCodec} from "../../batch-bridge/BatchBridgeCodec.sol";
import {IL1ERC20Gateway, L1CustomERC20Gateway} from "../../L1/gateways/L1CustomERC20Gateway.sol";
import {L1GatewayRouter} from "../../L1/gateways/L1GatewayRouter.sol";
import {IL2ERC20Gateway, L2CustomERC20Gateway} from "../../L2/gateways/L2CustomERC20Gateway.sol";
import {AddressAliasHelper} from "../../libraries/common/AddressAliasHelper.sol";
import {ScrollConstants} from "../../libraries/constants/ScrollConstants.sol";
import {L1GatewayTestBase} from "../L1GatewayTestBase.t.sol";
contract L1BatchBridgeGatewayTest is L1GatewayTestBase {
event Deposit(
address indexed sender,
address indexed token,
uint256 indexed batchIndex,
uint256 amount,
uint256 fee
);
event BatchDeposit(address indexed caller, address indexed l1Token, uint256 indexed batchIndex, address l2Token);
event DepositERC20(
address indexed _l1Token,
address indexed _l2Token,
address indexed _from,
address _to,
uint256 _amount,
bytes _data
);
uint24 private constant SAFE_BATCH_BRIDGE_GAS_LIMIT = 200000;
uint24 ETH_DEPOSIT_SAFE_GAS_LIMIT = 300000;
uint24 ERC20_DEPOSIT_SAFE_GAS_LIMIT = 200000;
uint256 private constant L2_GAS_PRICE = 10;
L1BatchBridgeGateway private batch;
L1CustomERC20Gateway private gateway;
L1GatewayRouter private router;
L2CustomERC20Gateway private counterpartGateway;
L2BatchBridgeGateway private counterpartBatch;
MockERC20 private l1Token;
MockERC20 private l2Token;
address private batchFeeVault;
function setUp() public {
__L1GatewayTestBase_setUp();
batchFeeVault = address(uint160(address(this)) - 2);
// Deploy tokens
l1Token = new MockERC20("Mock L1", "ML1", 18);
l2Token = new MockERC20("Mock L2", "ML2", 18);
// Deploy L2 contracts
counterpartGateway = new L2CustomERC20Gateway(address(1), address(1), address(1));
counterpartBatch = new L2BatchBridgeGateway(address(1), address(1));
// Deploy L1 contracts
router = L1GatewayRouter(_deployProxy(address(new L1GatewayRouter())));
gateway = L1CustomERC20Gateway(_deployProxy(address(0)));
batch = L1BatchBridgeGateway(payable(_deployProxy(address(0))));
// Initialize L1 contracts
admin.upgrade(
ITransparentUpgradeableProxy(address(gateway)),
address(new L1CustomERC20Gateway(address(counterpartGateway), address(router), address(l1Messenger)))
);
gateway.initialize(address(counterpartGateway), address(router), address(l1Messenger));
admin.upgrade(
ITransparentUpgradeableProxy(address(batch)),
address(
new L1BatchBridgeGateway(
address(counterpartBatch),
address(router),
address(l1Messenger),
address(messageQueue)
)
)
);
batch.initialize(batchFeeVault);
router.initialize(address(0), address(gateway));
messageQueue.setL2BaseFee(L2_GAS_PRICE);
// Prepare token balances
l1Token.mint(address(this), type(uint128).max);
gateway.updateTokenMapping(address(l1Token), address(l2Token));
hevm.warp(1000000);
}
function testInitialized() external {
assertBoolEq(true, batch.hasRole(bytes32(0), address(this)));
assertEq(address(counterpartBatch), batch.counterpart());
assertEq(address(router), batch.router());
assertEq(address(l1Messenger), batch.messenger());
assertEq(address(messageQueue), batch.queue());
hevm.expectRevert("Initializable: contract is already initialized");
batch.initialize(address(0));
}
function testSetTokenSetting() external {
// revert not admin
hevm.startPrank(address(1));
hevm.expectRevert(
"AccessControl: account 0x0000000000000000000000000000000000000001 is missing role 0x0000000000000000000000000000000000000000000000000000000000000000"
);
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(0, 0, 0, 0, 0));
hevm.stopPrank();
// revert maxTxsPerBatch = 0
hevm.expectRevert(L1BatchBridgeGateway.ErrorInvalidBatchConfig.selector);
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(0, 0, 0, 0, 0));
// revert maxDelayPerBatch = 0
hevm.expectRevert(L1BatchBridgeGateway.ErrorInvalidBatchConfig.selector);
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(0, 0, 1, 0, 0));
// revert feeAmountPerTx > minAmountPerTx
hevm.expectRevert(L1BatchBridgeGateway.ErrorInvalidBatchConfig.selector);
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(1, 0, 1, 1, 0));
// succeed
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(1, 2, 3, 4, 5));
(
uint96 feeAmountPerTx,
uint96 minAmountPerTx,
uint16 maxTxsPerBatch,
uint24 maxDelayPerBatch,
uint24 safeBridgeGasLimit
) = batch.configs(address(0));
assertEq(feeAmountPerTx, 1);
assertEq(minAmountPerTx, 2);
assertEq(maxTxsPerBatch, 3);
assertEq(maxDelayPerBatch, 4);
assertEq(safeBridgeGasLimit, 5);
}
function testSetTokenSettingFuzzing(address token, L1BatchBridgeGateway.BatchConfig memory config) external {
hevm.assume(config.maxTxsPerBatch > 0);
hevm.assume(config.maxDelayPerBatch > 0);
hevm.assume(config.feeAmountPerTx <= config.minAmountPerTx);
(
uint96 feeAmountPerTx,
uint96 minAmountPerTx,
uint16 maxTxsPerBatch,
uint24 maxDelayPerBatch,
uint24 safeBridgeGasLimit
) = batch.configs(token);
assertEq(feeAmountPerTx, 0);
assertEq(minAmountPerTx, 0);
assertEq(maxTxsPerBatch, 0);
assertEq(maxDelayPerBatch, 0);
assertEq(safeBridgeGasLimit, 0);
batch.setBatchConfig(token, config);
(feeAmountPerTx, minAmountPerTx, maxTxsPerBatch, maxDelayPerBatch, safeBridgeGasLimit) = batch.configs(token);
assertEq(feeAmountPerTx, config.feeAmountPerTx);
assertEq(minAmountPerTx, config.minAmountPerTx);
assertEq(maxTxsPerBatch, config.maxTxsPerBatch);
assertEq(maxDelayPerBatch, config.maxDelayPerBatch);
assertEq(safeBridgeGasLimit, config.safeBridgeGasLimit);
}
function checkBatchState(
address token,
uint256 phase,
L1BatchBridgeGateway.BatchState memory expected
) private {
(uint128 amount, uint64 startTime, uint64 numDeposits, bytes32 hash) = batch.batches(token, phase);
assertEq(amount, expected.amount);
assertEq(startTime, expected.startTime);
assertEq(numDeposits, expected.numDeposits);
// assertEq(hash, expected.hash);
}
function checkTokenState(address token, L1BatchBridgeGateway.TokenState memory expected) private {
(uint128 pending, uint64 currentBatchIndex, uint64 pendingBatchIndex) = batch.tokens(token);
assertEq(pending, expected.pending);
assertEq(currentBatchIndex, expected.currentBatchIndex);
assertEq(pendingBatchIndex, expected.pendingBatchIndex);
}
function testDepositETH() external {
// revert token not supported
hevm.expectRevert(L1BatchBridgeGateway.ErrorTokenNotSupported.selector);
batch.depositETH();
// revert deposit amount too small
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(0, 100, 2, 100, ETH_DEPOSIT_SAFE_GAS_LIMIT));
hevm.expectRevert(L1BatchBridgeGateway.ErrorDepositAmountTooSmall.selector);
batch.depositETH{value: 10}();
// no fee
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(0, 0, 2, 100, ETH_DEPOSIT_SAFE_GAS_LIMIT));
assertEq(0, address(batch).balance);
checkBatchState(address(0), 0, L1BatchBridgeGateway.BatchState(0, 0, 0, bytes32(0)));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(0, 0, 0));
hevm.warp(1000001);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(0), 0, 1000, 0);
batch.depositETH{value: 1000}();
assertEq(1000, address(batch).balance);
checkBatchState(address(0), 0, L1BatchBridgeGateway.BatchState(1000, 1000001, 1, bytes32(0)));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(1000, 0, 0));
hevm.warp(1000002);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(0), 0, 2000, 0);
batch.depositETH{value: 2000}();
assertEq(3000, address(batch).balance);
checkBatchState(address(0), 0, L1BatchBridgeGateway.BatchState(3000, 1000001, 2, bytes32(0)));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(3000, 0, 0));
hevm.warp(1000003);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(0), 1, 3000, 0);
batch.depositETH{value: 3000}();
assertEq(6000, address(batch).balance);
checkBatchState(address(0), 1, L1BatchBridgeGateway.BatchState(3000, 1000003, 1, bytes32(0)));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(6000, 1, 0));
// with fee
batch.setBatchConfig(
address(0),
L1BatchBridgeGateway.BatchConfig(100, 1000, 2, 100, ETH_DEPOSIT_SAFE_GAS_LIMIT)
);
hevm.warp(1000004);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(0), 1, 1000, 100);
batch.depositETH{value: 1000}();
assertEq(7000, address(batch).balance);
checkBatchState(address(0), 1, L1BatchBridgeGateway.BatchState(3900, 1000003, 2, bytes32(0)));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(6900, 1, 0));
hevm.warp(1000005);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(0), 2, 2000, 100);
batch.depositETH{value: 2000}();
assertEq(9000, address(batch).balance);
checkBatchState(address(0), 2, L1BatchBridgeGateway.BatchState(1900, 1000005, 1, bytes32(0)));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(8800, 2, 0));
hevm.warp(1000006);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(0), 2, 3000, 100);
batch.depositETH{value: 3000}();
assertEq(12000, address(batch).balance);
checkBatchState(address(0), 2, L1BatchBridgeGateway.BatchState(4800, 1000005, 2, bytes32(0)));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(11700, 2, 0));
// switch phase by timestamp
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(0, 0, 100, 100, ETH_DEPOSIT_SAFE_GAS_LIMIT));
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(0), 2, 1000, 0);
batch.depositETH{value: 1000}();
assertEq(13000, address(batch).balance);
checkBatchState(address(0), 2, L1BatchBridgeGateway.BatchState(5800, 1000005, 3, bytes32(0)));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(12700, 2, 0));
hevm.warp(1000005 + 100 + 1);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(0), 3, 1000, 0);
batch.depositETH{value: 1000}();
assertEq(14000, address(batch).balance);
checkBatchState(address(0), 3, L1BatchBridgeGateway.BatchState(1000, 1000005 + 100 + 1, 1, bytes32(0)));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(13700, 3, 0));
}
function testDepositERC20() external {
// revert token is zero
hevm.expectRevert(L1BatchBridgeGateway.ErrorIncorrectMethodForETHDeposit.selector);
batch.depositERC20(address(0), 0);
// revert token not supported
hevm.expectRevert(L1BatchBridgeGateway.ErrorTokenNotSupported.selector);
batch.depositERC20(address(l1Token), 0);
// revert deposit amount too small
batch.setBatchConfig(
address(l1Token),
L1BatchBridgeGateway.BatchConfig(0, 100, 2, 100, ERC20_DEPOSIT_SAFE_GAS_LIMIT)
);
l1Token.approve(address(batch), 10);
hevm.expectRevert(L1BatchBridgeGateway.ErrorDepositAmountTooSmall.selector);
batch.depositERC20(address(l1Token), 10);
// no fee
batch.setBatchConfig(
address(l1Token),
L1BatchBridgeGateway.BatchConfig(0, 0, 2, 100, ERC20_DEPOSIT_SAFE_GAS_LIMIT)
);
assertEq(0, l1Token.balanceOf(address(batch)));
checkBatchState(address(l1Token), 0, L1BatchBridgeGateway.BatchState(0, 0, 0, bytes32(0)));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(0, 0, 0));
hevm.warp(1000001);
l1Token.approve(address(batch), 1000);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(l1Token), 0, 1000, 0);
batch.depositERC20(address(l1Token), 1000);
assertEq(1000, l1Token.balanceOf(address(batch)));
checkBatchState(address(l1Token), 0, L1BatchBridgeGateway.BatchState(1000, 1000001, 1, bytes32(0)));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(1000, 0, 0));
hevm.warp(1000002);
l1Token.approve(address(batch), 2000);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(l1Token), 0, 2000, 0);
batch.depositERC20(address(l1Token), 2000);
assertEq(3000, l1Token.balanceOf(address(batch)));
checkBatchState(address(l1Token), 0, L1BatchBridgeGateway.BatchState(3000, 1000001, 2, bytes32(0)));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(3000, 0, 0));
hevm.warp(1000003);
l1Token.approve(address(batch), 3000);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(l1Token), 1, 3000, 0);
batch.depositERC20(address(l1Token), 3000);
assertEq(6000, l1Token.balanceOf(address(batch)));
checkBatchState(address(l1Token), 1, L1BatchBridgeGateway.BatchState(3000, 1000003, 1, bytes32(0)));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(6000, 1, 0));
// with fee
batch.setBatchConfig(
address(l1Token),
L1BatchBridgeGateway.BatchConfig(100, 1000, 2, 100, ERC20_DEPOSIT_SAFE_GAS_LIMIT)
);
hevm.warp(1000004);
l1Token.approve(address(batch), 1000);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(l1Token), 1, 1000, 100);
batch.depositERC20(address(l1Token), 1000);
assertEq(7000, l1Token.balanceOf(address(batch)));
checkBatchState(address(l1Token), 1, L1BatchBridgeGateway.BatchState(3900, 1000003, 2, bytes32(0)));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(6900, 1, 0));
hevm.warp(1000005);
l1Token.approve(address(batch), 2000);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(l1Token), 2, 2000, 100);
batch.depositERC20(address(l1Token), 2000);
assertEq(9000, l1Token.balanceOf(address(batch)));
checkBatchState(address(l1Token), 2, L1BatchBridgeGateway.BatchState(1900, 1000005, 1, bytes32(0)));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(8800, 2, 0));
hevm.warp(1000006);
l1Token.approve(address(batch), 3000);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(l1Token), 2, 3000, 100);
batch.depositERC20(address(l1Token), 3000);
assertEq(12000, l1Token.balanceOf(address(batch)));
checkBatchState(address(l1Token), 2, L1BatchBridgeGateway.BatchState(4800, 1000005, 2, bytes32(0)));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(11700, 2, 0));
// switch phase by timestamp
batch.setBatchConfig(
address(l1Token),
L1BatchBridgeGateway.BatchConfig(0, 0, 100, 100, ERC20_DEPOSIT_SAFE_GAS_LIMIT)
);
l1Token.approve(address(batch), 1000);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(l1Token), 2, 1000, 0);
batch.depositERC20(address(l1Token), 1000);
assertEq(13000, l1Token.balanceOf(address(batch)));
checkBatchState(address(l1Token), 2, L1BatchBridgeGateway.BatchState(5800, 1000005, 3, bytes32(0)));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(12700, 2, 0));
hevm.warp(1000005 + 100 + 1);
l1Token.approve(address(batch), 1000);
hevm.expectEmit(true, true, true, true);
emit Deposit(address(this), address(l1Token), 3, 1000, 0);
batch.depositERC20(address(l1Token), 1000);
assertEq(14000, l1Token.balanceOf(address(batch)));
checkBatchState(address(l1Token), 3, L1BatchBridgeGateway.BatchState(1000, 1000005 + 100 + 1, 1, bytes32(0)));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(13700, 3, 0));
}
function testBatchBridgeFailure() external {
// revert not keeper
hevm.startPrank(address(1));
hevm.expectRevert(
"AccessControl: account 0x0000000000000000000000000000000000000001 is missing role 0xfc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab"
);
batch.executeBatchDeposit(address(0));
hevm.stopPrank();
batch.grantRole(batch.KEEPER_ROLE(), address(this));
// revert token not supported
hevm.expectRevert(L1BatchBridgeGateway.ErrorTokenNotSupported.selector);
batch.executeBatchDeposit(address(0));
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(0, 0, 1, 1, ETH_DEPOSIT_SAFE_GAS_LIMIT));
// revert no pending
hevm.expectRevert(L1BatchBridgeGateway.ErrorNoPendingBatch.selector);
batch.executeBatchDeposit(address(0));
// revert insufficient msg.value
batch.depositETH{value: 1000}();
hevm.expectRevert(L1BatchBridgeGateway.ErrorInsufficientMsgValueForBatchDepositFee.selector);
batch.executeBatchDeposit(address(0));
hevm.expectRevert(L1BatchBridgeGateway.ErrorInsufficientMsgValueForBatchDepositFee.selector);
batch.executeBatchDeposit{value: L2_GAS_PRICE * ETH_DEPOSIT_SAFE_GAS_LIMIT}(address(0));
hevm.expectRevert(L1BatchBridgeGateway.ErrorInsufficientMsgValueForBatchDepositFee.selector);
batch.executeBatchDeposit{value: L2_GAS_PRICE * (SAFE_BATCH_BRIDGE_GAS_LIMIT + ETH_DEPOSIT_SAFE_GAS_LIMIT) - 1}(
address(0)
);
// succeed
batch.executeBatchDeposit{value: L2_GAS_PRICE * (SAFE_BATCH_BRIDGE_GAS_LIMIT + ETH_DEPOSIT_SAFE_GAS_LIMIT)}(
address(0)
);
}
function testBatchBridgeETH() external {
batch.grantRole(batch.KEEPER_ROLE(), address(this));
// no deposit fee
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(0, 0, 1, 1, ETH_DEPOSIT_SAFE_GAS_LIMIT));
batch.depositETH{value: 1000}();
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(1000, 0, 0));
// emit SentMessage by deposit ETH
hevm.expectEmit(true, true, false, true);
emit SentMessage(address(batch), address(counterpartBatch), 1000, 0, ETH_DEPOSIT_SAFE_GAS_LIMIT, "");
// emit SentMessage by batchBridge
hevm.expectEmit(true, true, false, true);
emit SentMessage(
address(batch),
address(counterpartBatch),
0,
1,
SAFE_BATCH_BRIDGE_GAS_LIMIT,
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(
address(0),
address(0),
0,
BatchBridgeCodec.hash(
BatchBridgeCodec.encodeInitialNode(address(0), 0),
BatchBridgeCodec.encodeNode(address(this), 1000)
)
)
)
);
// emit BatchBridge
hevm.expectEmit(true, true, true, true);
emit BatchDeposit(address(this), address(0), 0, address(0));
uint256 batchFeeVaultBefore = batchFeeVault.balance;
uint256 messengerBefore = address(l1Messenger).balance;
batch.executeBatchDeposit{value: 1 ether}(address(0));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(0, 1, 1));
assertEq(batchFeeVaultBefore, batchFeeVault.balance);
assertEq(messengerBefore + 1000, address(l1Messenger).balance);
// has deposit fee = 100
batch.setBatchConfig(address(0), L1BatchBridgeGateway.BatchConfig(100, 1000, 1, 1, ETH_DEPOSIT_SAFE_GAS_LIMIT));
batch.depositETH{value: 1000}();
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(900, 1, 1));
// emit SentMessage by deposit ETH
hevm.expectEmit(true, true, false, true);
emit SentMessage(address(batch), address(counterpartBatch), 900, 2, ETH_DEPOSIT_SAFE_GAS_LIMIT, "");
// emit SentMessage by batchBridge
hevm.expectEmit(true, true, false, true);
emit SentMessage(
address(batch),
address(counterpartBatch),
0,
3,
SAFE_BATCH_BRIDGE_GAS_LIMIT,
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(
address(0),
address(0),
1,
BatchBridgeCodec.hash(
BatchBridgeCodec.encodeInitialNode(address(0), 1),
BatchBridgeCodec.encodeNode(address(this), 900)
)
)
)
);
// emit BatchBridge
hevm.expectEmit(true, true, true, true);
emit BatchDeposit(address(this), address(0), 1, address(0));
batchFeeVaultBefore = batchFeeVault.balance;
messengerBefore = address(l1Messenger).balance;
batch.executeBatchDeposit{value: 1 ether}(address(0));
checkTokenState(address(0), L1BatchBridgeGateway.TokenState(0, 2, 2));
assertEq(batchFeeVaultBefore + 100, batchFeeVault.balance);
assertEq(messengerBefore + 900, address(l1Messenger).balance);
}
function testBatchBridgeERC20() external {
batch.grantRole(batch.KEEPER_ROLE(), address(this));
// no deposit fee
batch.setBatchConfig(
address(l1Token),
L1BatchBridgeGateway.BatchConfig(0, 0, 1, 1, ERC20_DEPOSIT_SAFE_GAS_LIMIT)
);
l1Token.approve(address(batch), 1000);
batch.depositERC20(address(l1Token), 1000);
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(1000, 0, 0));
bytes memory message = abi.encodeWithSelector(
IL2ERC20Gateway.finalizeDepositERC20.selector,
address(l1Token),
address(l2Token),
address(batch),
address(counterpartBatch),
1000,
new bytes(0)
);
// emit SentMessage by deposit ERC20
hevm.expectEmit(true, true, false, true);
emit SentMessage(address(gateway), address(counterpartGateway), 0, 0, ERC20_DEPOSIT_SAFE_GAS_LIMIT, message);
// emit SentMessage by batchBridge
hevm.expectEmit(true, true, false, true);
emit SentMessage(
address(batch),
address(counterpartBatch),
0,
1,
SAFE_BATCH_BRIDGE_GAS_LIMIT,
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(
address(l1Token),
address(l2Token),
0,
BatchBridgeCodec.hash(
BatchBridgeCodec.encodeInitialNode(address(l1Token), 0),
BatchBridgeCodec.encodeNode(address(this), 1000)
)
)
)
);
// emit BatchBridge
hevm.expectEmit(true, true, true, true);
emit BatchDeposit(address(this), address(l1Token), 0, address(l2Token));
uint256 batchFeeVaultBefore = l1Token.balanceOf(batchFeeVault);
uint256 gatewayBefore = l1Token.balanceOf(address(gateway));
batch.executeBatchDeposit{value: 1 ether}(address(l1Token));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(0, 1, 1));
assertEq(batchFeeVaultBefore, l1Token.balanceOf(batchFeeVault));
assertEq(gatewayBefore + 1000, l1Token.balanceOf(address(gateway)));
// has deposit fee = 100
batch.setBatchConfig(
address(l1Token),
L1BatchBridgeGateway.BatchConfig(100, 1000, 1, 1, ERC20_DEPOSIT_SAFE_GAS_LIMIT)
);
l1Token.approve(address(batch), 1000);
batch.depositERC20(address(l1Token), 1000);
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(900, 1, 1));
message = abi.encodeWithSelector(
IL2ERC20Gateway.finalizeDepositERC20.selector,
address(l1Token),
address(l2Token),
address(batch),
address(counterpartBatch),
900,
new bytes(0)
);
// emit SentMessage by deposit ERC20
hevm.expectEmit(true, true, false, true);
emit SentMessage(address(gateway), address(counterpartGateway), 0, 2, ERC20_DEPOSIT_SAFE_GAS_LIMIT, message);
// emit SentMessage by batchBridge
hevm.expectEmit(true, true, false, true);
emit SentMessage(
address(batch),
address(counterpartBatch),
0,
3,
SAFE_BATCH_BRIDGE_GAS_LIMIT,
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(
address(l1Token),
address(l2Token),
1,
BatchBridgeCodec.hash(
BatchBridgeCodec.encodeInitialNode(address(l1Token), 1),
BatchBridgeCodec.encodeNode(address(this), 900)
)
)
)
);
// emit BatchBridge
hevm.expectEmit(true, true, true, true);
emit BatchDeposit(address(this), address(l1Token), 1, address(l2Token));
batchFeeVaultBefore = l1Token.balanceOf(batchFeeVault);
gatewayBefore = l1Token.balanceOf(address(gateway));
batch.executeBatchDeposit{value: 1 ether}(address(l1Token));
checkTokenState(address(l1Token), L1BatchBridgeGateway.TokenState(0, 2, 2));
assertEq(batchFeeVaultBefore + 100, l1Token.balanceOf(batchFeeVault));
assertEq(gatewayBefore + 900, l1Token.balanceOf(address(gateway)));
}
}

View File

@@ -1,454 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {L1BatchBridgeGateway} from "../../batch-bridge/L1BatchBridgeGateway.sol";
import {L2BatchBridgeGateway} from "../../batch-bridge/L2BatchBridgeGateway.sol";
import {BatchBridgeCodec} from "../../batch-bridge/BatchBridgeCodec.sol";
import {RevertOnTransferToken} from "../mocks/tokens/RevertOnTransferToken.sol";
import {MockScrollMessenger} from "../mocks/MockScrollMessenger.sol";
import {ScrollTestBase} from "../ScrollTestBase.t.sol";
contract L2BatchBridgeGatewayTest is ScrollTestBase {
event UpdateTokenMapping(address indexed l2Token, address indexed oldL1Token, address indexed newL1Token);
event FinalizeBatchDeposit(address indexed l1Token, address indexed l2Token, uint256 indexed batchIndex);
event BatchDistribute(address indexed l1Token, address indexed l2Token, uint256 indexed batchIndex);
event DistributeFailed(address indexed l2Token, uint256 indexed batchIndex, address receiver, uint256 amount);
L1BatchBridgeGateway private counterpartBatch;
L2BatchBridgeGateway private batch;
MockScrollMessenger messenger;
MockERC20 private l1Token;
MockERC20 private l2Token;
RevertOnTransferToken private maliciousL2Token;
bool revertOnReceive;
bool loopOnReceive;
// two safe EOAs to receive ETH
address private recipient1;
address private recipient2;
receive() external payable {
if (revertOnReceive) revert();
if (loopOnReceive) {
for (uint256 i = 0; i < 1000000000; i++) {
recipient1 = address(uint160(address(this)) - 1);
}
}
}
function setUp() public {
__ScrollTestBase_setUp();
recipient1 = address(uint160(address(this)) - 1);
recipient2 = address(uint160(address(this)) - 2);
// Deploy tokens
l1Token = new MockERC20("Mock L1", "ML1", 18);
l2Token = new MockERC20("Mock L2", "ML2", 18);
maliciousL2Token = new RevertOnTransferToken("X", "Y", 18);
messenger = new MockScrollMessenger();
counterpartBatch = new L1BatchBridgeGateway(address(1), address(1), address(1), address(1));
batch = L2BatchBridgeGateway(payable(_deployProxy(address(0))));
// Initialize L2 contracts
admin.upgrade(
ITransparentUpgradeableProxy(address(batch)),
address(new L2BatchBridgeGateway(address(counterpartBatch), address(messenger)))
);
batch.initialize();
}
function testInitialized() external {
assertBoolEq(true, batch.hasRole(bytes32(0), address(this)));
assertEq(address(counterpartBatch), batch.counterpart());
assertEq(address(messenger), batch.messenger());
hevm.expectRevert("Initializable: contract is already initialized");
batch.initialize();
}
function testFinalizeBatchDeposit() external {
// revert caller not messenger
hevm.expectRevert(L2BatchBridgeGateway.ErrorCallerNotMessenger.selector);
batch.finalizeBatchDeposit(address(0), address(0), 0, bytes32(0));
// revert xDomainMessageSender not counterpart
hevm.expectRevert(L2BatchBridgeGateway.ErrorMessageSenderNotCounterpart.selector);
messenger.callTarget(
address(batch),
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(address(l1Token), address(l2Token), 0, bytes32(0))
)
);
messenger.setXDomainMessageSender(address(counterpartBatch));
// emit FinalizeBatchDeposit
assertEq(address(0), batch.tokenMapping(address(l2Token)));
hevm.expectEmit(true, true, true, true);
emit FinalizeBatchDeposit(address(l1Token), address(l2Token), 1);
messenger.callTarget(
address(batch),
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(address(l1Token), address(l2Token), 1, bytes32(uint256(1)))
)
);
assertEq(address(l1Token), batch.tokenMapping(address(l2Token)));
assertEq(batch.batchHashes(address(l2Token), 1), bytes32(uint256(1)));
// revert token not match
hevm.expectRevert(L2BatchBridgeGateway.ErrorL1TokenMismatched.selector);
messenger.callTarget(
address(batch),
abi.encodeCall(L2BatchBridgeGateway.finalizeBatchDeposit, (address(0), address(l2Token), 0, bytes32(0)))
);
}
function testFinalizeBatchDepositFuzzing(
address token1,
address token2,
uint256 batchIndex,
bytes32 hash
) external {
messenger.setXDomainMessageSender(address(counterpartBatch));
assertEq(address(0), batch.tokenMapping(token2));
hevm.expectEmit(true, true, true, true);
emit FinalizeBatchDeposit(token1, token2, batchIndex);
messenger.callTarget(
address(batch),
abi.encodeCall(L2BatchBridgeGateway.finalizeBatchDeposit, (token1, token2, batchIndex, hash))
);
assertEq(token1, batch.tokenMapping(token2));
assertEq(batch.batchHashes(token2, batchIndex), hash);
}
function testDistributeETH() external {
// revert not keeper
hevm.startPrank(address(1));
hevm.expectRevert(
"AccessControl: account 0x0000000000000000000000000000000000000001 is missing role 0xfc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab"
);
batch.distribute(address(0), 0, new bytes32[](0));
hevm.stopPrank();
batch.grantRole(batch.KEEPER_ROLE(), address(this));
// revert ErrorBatchHashMismatch
hevm.expectRevert(L2BatchBridgeGateway.ErrorBatchHashMismatch.selector);
batch.distribute(address(0), 1, new bytes32[](0));
// send some ETH to `L2BatchBridgeGateway`.
messenger.setXDomainMessageSender(address(counterpartBatch));
messenger.callTarget{value: 1 ether}(address(batch), "");
address[] memory receivers = new address[](2);
uint256[] memory amounts = new uint256[](2);
receivers[0] = recipient1;
receivers[1] = recipient2;
amounts[0] = 100;
amounts[1] = 200;
// all success
(bytes32[] memory nodes, bytes32 batchHash) = _encodeNodes(address(0), 0, receivers, amounts);
messenger.callTarget(
address(batch),
abi.encodeCall(L2BatchBridgeGateway.finalizeBatchDeposit, (address(0), address(0), 0, batchHash))
);
assertEq(0, recipient1.balance);
assertEq(0, recipient2.balance);
uint256 batchBalanceBefore = address(batch).balance;
hevm.expectEmit(true, true, true, true);
emit BatchDistribute(address(0), address(0), 0);
batch.distribute(address(0), 0, nodes);
assertEq(100, recipient1.balance);
assertEq(200, recipient2.balance);
assertEq(batchBalanceBefore - 300, address(batch).balance);
assertBoolEq(true, batch.isDistributed(batchHash));
// revert ErrorBatchDistributed
hevm.expectRevert(L2BatchBridgeGateway.ErrorBatchDistributed.selector);
batch.distribute(address(0), 0, nodes);
// all failed due to revert
revertOnReceive = true;
loopOnReceive = false;
receivers[0] = address(this);
receivers[1] = address(this);
(nodes, batchHash) = _encodeNodes(address(0), 1, receivers, amounts);
messenger.callTarget(
address(batch),
abi.encodeCall(L2BatchBridgeGateway.finalizeBatchDeposit, (address(0), address(0), 1, batchHash))
);
uint256 thisBalanceBefore = address(this).balance;
batchBalanceBefore = address(batch).balance;
hevm.expectEmit(true, true, false, true);
emit DistributeFailed(address(0), 1, address(this), 100);
hevm.expectEmit(true, true, false, true);
emit DistributeFailed(address(0), 1, address(this), 200);
hevm.expectEmit(true, true, true, true);
emit BatchDistribute(address(0), address(0), 1);
batch.distribute(address(0), 1, nodes);
assertEq(batchBalanceBefore, address(batch).balance);
assertEq(thisBalanceBefore, address(this).balance);
assertBoolEq(true, batch.isDistributed(batchHash));
assertEq(300, batch.failedAmount(address(0)));
// all failed due to out of gas
revertOnReceive = false;
loopOnReceive = true;
(nodes, batchHash) = _encodeNodes(address(0), 2, receivers, amounts);
messenger.callTarget(
address(batch),
abi.encodeCall(L2BatchBridgeGateway.finalizeBatchDeposit, (address(0), address(0), 2, batchHash))
);
thisBalanceBefore = address(this).balance;
batchBalanceBefore = address(batch).balance;
hevm.expectEmit(true, true, false, true);
emit DistributeFailed(address(0), 2, address(this), 100);
hevm.expectEmit(true, true, false, true);
emit DistributeFailed(address(0), 2, address(this), 200);
hevm.expectEmit(true, true, true, true);
emit BatchDistribute(address(0), address(0), 2);
batch.distribute(address(0), 2, nodes);
assertEq(batchBalanceBefore, address(batch).balance);
assertEq(thisBalanceBefore, address(this).balance);
assertBoolEq(true, batch.isDistributed(batchHash));
assertEq(600, batch.failedAmount(address(0)));
}
function testDistributeERC20() external {
// revert not keeper
hevm.startPrank(address(1));
hevm.expectRevert(
"AccessControl: account 0x0000000000000000000000000000000000000001 is missing role 0xfc8737ab85eb45125971625a9ebdb75cc78e01d5c1fa80c4c6e5203f47bc4fab"
);
batch.distribute(address(l2Token), 0, new bytes32[](0));
hevm.stopPrank();
batch.grantRole(batch.KEEPER_ROLE(), address(this));
// revert ErrorBatchHashMismatch
hevm.expectRevert(L2BatchBridgeGateway.ErrorBatchHashMismatch.selector);
batch.distribute(address(l2Token), 1, new bytes32[](0));
// mint some ERC20 to `L2BatchBridgeGateway`.
messenger.setXDomainMessageSender(address(counterpartBatch));
l2Token.mint(address(batch), 1 ether);
address[] memory receivers = new address[](2);
uint256[] memory amounts = new uint256[](2);
receivers[0] = recipient1;
receivers[1] = recipient2;
amounts[0] = 100;
amounts[1] = 200;
// all success
(bytes32[] memory nodes, bytes32 batchHash) = _encodeNodes(address(l1Token), 0, receivers, amounts);
messenger.callTarget(
address(batch),
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(address(l1Token), address(l2Token), 0, batchHash)
)
);
assertEq(0, recipient1.balance);
assertEq(0, recipient2.balance);
uint256 batchBalanceBefore = l2Token.balanceOf(address(batch));
hevm.expectEmit(true, true, true, true);
emit BatchDistribute(address(l1Token), address(l2Token), 0);
batch.distribute(address(l2Token), 0, nodes);
assertEq(100, l2Token.balanceOf(recipient1));
assertEq(200, l2Token.balanceOf(recipient2));
assertEq(batchBalanceBefore - 300, l2Token.balanceOf(address(batch)));
assertBoolEq(true, batch.isDistributed(batchHash));
// revert ErrorBatchDistributed
hevm.expectRevert(L2BatchBridgeGateway.ErrorBatchDistributed.selector);
batch.distribute(address(l2Token), 0, nodes);
maliciousL2Token.mint(address(batch), 1 ether);
// all failed due to revert
maliciousL2Token.setRevertOnTransfer(true);
receivers[0] = address(this);
receivers[1] = address(this);
(nodes, batchHash) = _encodeNodes(address(l1Token), 1, receivers, amounts);
messenger.callTarget(
address(batch),
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(address(l1Token), address(maliciousL2Token), 1, batchHash)
)
);
uint256 thisBalanceBefore = maliciousL2Token.balanceOf(address(this));
batchBalanceBefore = maliciousL2Token.balanceOf(address(batch));
hevm.expectEmit(true, true, false, true);
emit DistributeFailed(address(maliciousL2Token), 1, address(this), 100);
hevm.expectEmit(true, true, false, true);
emit DistributeFailed(address(maliciousL2Token), 1, address(this), 200);
hevm.expectEmit(true, true, true, true);
emit BatchDistribute(address(l1Token), address(maliciousL2Token), 1);
batch.distribute(address(maliciousL2Token), 1, nodes);
assertEq(batchBalanceBefore, maliciousL2Token.balanceOf(address(batch)));
assertEq(thisBalanceBefore, maliciousL2Token.balanceOf(address(this)));
assertBoolEq(true, batch.isDistributed(batchHash));
assertEq(300, batch.failedAmount(address(maliciousL2Token)));
// all failed due to transfer return false
maliciousL2Token.setRevertOnTransfer(false);
maliciousL2Token.setTransferReturn(false);
(nodes, batchHash) = _encodeNodes(address(l1Token), 2, receivers, amounts);
messenger.callTarget(
address(batch),
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(address(l1Token), address(maliciousL2Token), 2, batchHash)
)
);
thisBalanceBefore = maliciousL2Token.balanceOf(address(this));
batchBalanceBefore = maliciousL2Token.balanceOf(address(batch));
hevm.expectEmit(true, true, false, true);
emit DistributeFailed(address(maliciousL2Token), 2, address(this), 100);
hevm.expectEmit(true, true, false, true);
emit DistributeFailed(address(maliciousL2Token), 2, address(this), 200);
hevm.expectEmit(true, true, true, true);
emit BatchDistribute(address(l1Token), address(maliciousL2Token), 2);
batch.distribute(address(maliciousL2Token), 2, nodes);
assertEq(batchBalanceBefore, maliciousL2Token.balanceOf(address(batch)));
assertEq(thisBalanceBefore, maliciousL2Token.balanceOf(address(this)));
assertBoolEq(true, batch.isDistributed(batchHash));
assertEq(600, batch.failedAmount(address(maliciousL2Token)));
}
function testWithdrawFailedAmountETH() external {
batch.grantRole(batch.KEEPER_ROLE(), address(this));
// revert not admin
hevm.startPrank(address(1));
hevm.expectRevert(
"AccessControl: account 0x0000000000000000000000000000000000000001 is missing role 0x0000000000000000000000000000000000000000000000000000000000000000"
);
batch.withdrawFailedAmount(address(0), address(this));
hevm.stopPrank();
// revert no failed
hevm.expectRevert(L2BatchBridgeGateway.ErrorNoFailedDistribution.selector);
batch.withdrawFailedAmount(address(0), address(this));
// send some ETH to `L2BatchBridgeGateway`.
messenger.setXDomainMessageSender(address(counterpartBatch));
messenger.callTarget{value: 1 ether}(address(batch), "");
// make a failed distribution
address[] memory receivers = new address[](2);
uint256[] memory amounts = new uint256[](2);
receivers[0] = address(this);
receivers[1] = address(this);
amounts[0] = 100;
amounts[1] = 200;
revertOnReceive = true;
(bytes32[] memory nodes, bytes32 batchHash) = _encodeNodes(address(0), 1, receivers, amounts);
messenger.callTarget(
address(batch),
abi.encodeCall(L2BatchBridgeGateway.finalizeBatchDeposit, (address(0), address(0), 1, batchHash))
);
assertEq(0, batch.failedAmount(address(0)));
batch.distribute(address(0), 1, nodes);
assertEq(300, batch.failedAmount(address(0)));
// withdraw failed
uint256 thisBalance = recipient1.balance;
uint256 batchBalance = address(batch).balance;
batch.withdrawFailedAmount(address(0), recipient1);
assertEq(0, batch.failedAmount(address(0)));
assertEq(thisBalance + 300, recipient1.balance);
assertEq(batchBalance - 300, address(batch).balance);
// revert no failed
hevm.expectRevert(L2BatchBridgeGateway.ErrorNoFailedDistribution.selector);
batch.withdrawFailedAmount(address(0), recipient1);
}
function testWithdrawFailedAmountERC20() external {
batch.grantRole(batch.KEEPER_ROLE(), address(this));
// revert not admin
hevm.startPrank(address(1));
hevm.expectRevert(
"AccessControl: account 0x0000000000000000000000000000000000000001 is missing role 0x0000000000000000000000000000000000000000000000000000000000000000"
);
batch.withdrawFailedAmount(address(0), address(this));
hevm.stopPrank();
// revert no failed
hevm.expectRevert(L2BatchBridgeGateway.ErrorNoFailedDistribution.selector);
batch.withdrawFailedAmount(address(0), address(this));
// send some ETH to `L2BatchBridgeGateway`.
messenger.setXDomainMessageSender(address(counterpartBatch));
maliciousL2Token.mint(address(batch), 1 ether);
// make a failed distribution
address[] memory receivers = new address[](2);
uint256[] memory amounts = new uint256[](2);
receivers[0] = address(this);
receivers[1] = address(this);
amounts[0] = 100;
amounts[1] = 200;
maliciousL2Token.setRevertOnTransfer(true);
(bytes32[] memory nodes, bytes32 batchHash) = _encodeNodes(address(l1Token), 1, receivers, amounts);
messenger.callTarget(
address(batch),
abi.encodeCall(
L2BatchBridgeGateway.finalizeBatchDeposit,
(address(l1Token), address(maliciousL2Token), 1, batchHash)
)
);
assertEq(0, batch.failedAmount(address(maliciousL2Token)));
batch.distribute(address(maliciousL2Token), 1, nodes);
assertEq(300, batch.failedAmount(address(maliciousL2Token)));
// withdraw failed
maliciousL2Token.setRevertOnTransfer(false);
maliciousL2Token.setTransferReturn(true);
uint256 thisBalance = maliciousL2Token.balanceOf(recipient1);
uint256 batchBalance = maliciousL2Token.balanceOf(address(batch));
batch.withdrawFailedAmount(address(maliciousL2Token), recipient1);
assertEq(0, batch.failedAmount(address(maliciousL2Token)));
assertEq(thisBalance + 300, maliciousL2Token.balanceOf(recipient1));
assertEq(batchBalance - 300, maliciousL2Token.balanceOf(address(batch)));
// revert no failed
hevm.expectRevert(L2BatchBridgeGateway.ErrorNoFailedDistribution.selector);
batch.withdrawFailedAmount(address(maliciousL2Token), recipient1);
}
function _encodeNodes(
address token,
uint256 batchIndex,
address[] memory receivers,
uint256[] memory amounts
) private returns (bytes32[] memory nodes, bytes32 hash) {
nodes = new bytes32[](receivers.length);
hash = BatchBridgeCodec.encodeInitialNode(token, uint64(batchIndex));
for (uint256 i = 0; i < receivers.length; i++) {
nodes[i] = BatchBridgeCodec.encodeNode(receivers[i], uint96(amounts[i]));
hash = BatchBridgeCodec.hash(hash, nodes[i]);
}
}
}

View File

@@ -1,45 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.24;
import {MockERC20} from "solmate/test/utils/mocks/MockERC20.sol";
// solhint-disable no-empty-blocks
contract RevertOnTransferToken is MockERC20 {
bool private revertOnTransfer;
bool private transferReturn;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) MockERC20(_name, _symbol, _decimals) {
transferReturn = true;
}
function setRevertOnTransfer(bool _revertOnTransfer) external payable {
revertOnTransfer = _revertOnTransfer;
}
function setTransferReturn(bool _transferReturn) external payable {
transferReturn = _transferReturn;
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
if (revertOnTransfer) revert();
if (!transferReturn) return false;
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
}

View File

@@ -3,7 +3,7 @@ module scroll-tech/coordinator
go 1.21
require (
github.com/appleboy/gin-jwt/v2 v2.9.1
github.com/appleboy/gin-jwt/v2 v2.9.2
github.com/gin-gonic/gin v1.9.1
github.com/go-resty/resty/v2 v2.7.0
github.com/mitchellh/mapstructure v1.5.0
@@ -11,38 +11,38 @@ require (
github.com/shopspring/decimal v1.3.1
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.25.7
golang.org/x/arch v0.5.0 // indirect
golang.org/x/arch v0.7.0 // indirect
gorm.io/gorm v1.25.5
)
require (
github.com/bytedance/sonic v1.10.1 // indirect
github.com/bytedance/sonic v1.10.2 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.15.5 // indirect
github.com/go-playground/validator/v10 v10.17.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/leodido/go-urn v1.3.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
golang.org/x/net v0.18.0 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
)
require (
@@ -55,7 +55,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.12.0 // indirect
github.com/btcsuite/btcd v0.20.1-beta // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
@@ -69,6 +69,7 @@ require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/iden3/go-iden3-crypto v0.0.15 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
@@ -82,7 +83,7 @@ require (
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.17.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

View File

@@ -2,8 +2,8 @@ github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bw
github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/appleboy/gin-jwt/v2 v2.9.1 h1:l29et8iLW6omcHltsOP6LLk4s3v4g2FbFs0koxGWVZs=
github.com/appleboy/gin-jwt/v2 v2.9.1/go.mod h1:jwcPZJ92uoC9nOUTOKWoN/f6JZOgMSKlFSHw5/FrRUk=
github.com/appleboy/gin-jwt/v2 v2.9.2 h1:GeS3lm9mb9HMmj7+GNjYUtpp3V1DAQ1TkUFa5poiZ7Y=
github.com/appleboy/gin-jwt/v2 v2.9.2/go.mod h1:mxGjKt9Lrx9Xusy1SrnmsCJMZG6UJwmdHN9bN27/QDw=
github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4=
github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -21,16 +21,17 @@ 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/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiaysc=
github.com/bytedance/sonic v1.10.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M=
@@ -47,38 +48,29 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 h1:B2mpK+MNqgPqk2/KNi1LbqwtZDy5F7iy0mynQiBr8VA=
github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4/go.mod h1:y4GA2JbAUama1S4QwYjC2hefgGLU8Ul0GMtL/ADMF1c=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24=
github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74=
github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
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-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -112,25 +104,17 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/leodido/go-urn v1.3.0 h1:jX8FDLfW4ThVXctBNZ+3cIWnCSnrACDV73r76dy0aQQ=
github.com/leodido/go-urn v1.3.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
@@ -152,11 +136,8 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -174,8 +155,6 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
@@ -192,12 +171,10 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
@@ -205,8 +182,8 @@ github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2 h1:wh1wzwAhZ
github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
@@ -217,58 +194,33 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y=
golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -276,38 +228,25 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
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/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=

View File

@@ -40,9 +40,9 @@ func (a *AuthController) Login(c *gin.Context) (interface{}, error) {
}
// check the challenge is used, if used, return failure
if err := a.loginLogic.InsertChallengeString(c, login.Message.Challenge); err != nil {
return "", fmt.Errorf("login insert challenge string failure:%w", err)
}
//if err := a.loginLogic.InsertChallengeString(c, login.Message.Challenge); err != nil {
// return "", fmt.Errorf("login insert challenge string failure:%w", err)
//}
return login, nil
}

View File

@@ -30,8 +30,8 @@ func (c *Collector) cleanupChallenge() {
log.Error("manager context canceled with error", "error", c.ctx.Err())
}
return
case <-c.stopCleanChallengeChan:
log.Info("the coordinator cleanupChallenge run loop exit")
case <-c.stopTimeoutChan:
log.Info("the coordinator run loop exit")
return
}
}

View File

@@ -23,10 +23,7 @@ type Collector struct {
db *gorm.DB
ctx context.Context
stopChunkTimeoutChan chan struct{}
stopBatchTimeoutChan chan struct{}
stopBatchAllChunkReadyChan chan struct{}
stopCleanChallengeChan chan struct{}
stopTimeoutChan chan struct{}
proverTaskOrm *orm.ProverTask
chunkOrm *orm.Chunk
@@ -43,17 +40,14 @@ type Collector struct {
// NewCollector create a collector to cron collect the data to send to prover
func NewCollector(ctx context.Context, db *gorm.DB, cfg *config.Config, reg prometheus.Registerer) *Collector {
c := &Collector{
cfg: cfg,
db: db,
ctx: ctx,
stopChunkTimeoutChan: make(chan struct{}),
stopBatchTimeoutChan: make(chan struct{}),
stopBatchAllChunkReadyChan: make(chan struct{}),
stopCleanChallengeChan: make(chan struct{}),
proverTaskOrm: orm.NewProverTask(db),
chunkOrm: orm.NewChunk(db),
batchOrm: orm.NewBatch(db),
challenge: orm.NewChallenge(db),
cfg: cfg,
db: db,
ctx: ctx,
stopTimeoutChan: make(chan struct{}),
proverTaskOrm: orm.NewProverTask(db),
chunkOrm: orm.NewChunk(db),
batchOrm: orm.NewBatch(db),
challenge: orm.NewChallenge(db),
timeoutBatchCheckerRunTotal: promauto.With(reg).NewCounter(prometheus.CounterOpts{
Name: "coordinator_batch_timeout_checker_run_total",
@@ -89,13 +83,10 @@ func NewCollector(ctx context.Context, db *gorm.DB, cfg *config.Config, reg prom
// Stop all the collector
func (c *Collector) Stop() {
c.stopChunkTimeoutChan <- struct{}{}
c.stopBatchTimeoutChan <- struct{}{}
c.stopBatchAllChunkReadyChan <- struct{}{}
c.stopCleanChallengeChan <- struct{}{}
c.stopTimeoutChan <- struct{}{}
}
// timeoutBatchProofTask cron check the send task is timeout. if timeout reached, restore the
// timeoutTask cron check the send task is timeout. if timeout reached, restore the
// chunk/batch task to unassigned. then the batch/chunk collector can retry it.
func (c *Collector) timeoutBatchProofTask() {
defer func() {
@@ -122,8 +113,8 @@ func (c *Collector) timeoutBatchProofTask() {
log.Error("manager context canceled with error", "error", c.ctx.Err())
}
return
case <-c.stopBatchTimeoutChan:
log.Info("the coordinator timeoutBatchProofTask run loop exit")
case <-c.stopTimeoutChan:
log.Info("the coordinator run loop exit")
return
}
}
@@ -155,8 +146,8 @@ func (c *Collector) timeoutChunkProofTask() {
log.Error("manager context canceled with error", "error", c.ctx.Err())
}
return
case <-c.stopChunkTimeoutChan:
log.Info("the coordinator timeoutChunkProofTask run loop exit")
case <-c.stopTimeoutChan:
log.Info("the coordinator run loop exit")
return
}
}
@@ -262,8 +253,8 @@ func (c *Collector) checkBatchAllChunkReady() {
log.Error("manager context canceled with error", "error", c.ctx.Err())
}
return
case <-c.stopBatchAllChunkReadyChan:
log.Info("the coordinator checkBatchAllChunkReady run loop exit")
case <-c.stopTimeoutChan:
log.Info("the coordinator run loop exit")
return
}
}

View File

@@ -21,5 +21,5 @@ func NewLoginLogic(db *gorm.DB) *LoginLogic {
// InsertChallengeString insert and check the challenge string is existed
func (l *LoginLogic) InsertChallengeString(ctx *gin.Context, challenge string) error {
return l.challengeOrm.InsertChallenge(ctx.Copy(), challenge)
return l.challengeOrm.InsertChallenge(ctx, challenge)
}

View File

@@ -83,7 +83,7 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
var endChunkIndex uint64 = math.MaxInt64
fromBlockNum, toBlockNum := forks.BlockRange(hardForkNumber, bp.forkHeights)
if fromBlockNum != 0 {
startChunk, chunkErr := bp.chunkOrm.GetChunkByStartBlockNumber(ctx.Copy(), fromBlockNum)
startChunk, chunkErr := bp.chunkOrm.GetChunkByStartBlockNumber(ctx, fromBlockNum)
if chunkErr != nil {
log.Error("failed to get fork start chunk index", "forkName", taskCtx.HardForkName, "fromBlockNumber", fromBlockNum, "err", chunkErr)
return nil, ErrCoordinatorInternalFailure
@@ -94,7 +94,7 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
startChunkIndex = startChunk.Index
}
if toBlockNum != math.MaxInt64 {
toChunk, chunkErr := bp.chunkOrm.GetChunkByStartBlockNumber(ctx.Copy(), toBlockNum)
toChunk, chunkErr := bp.chunkOrm.GetChunkByStartBlockNumber(ctx, toBlockNum)
if chunkErr != nil {
log.Error("failed to get fork end chunk index", "forkName", taskCtx.HardForkName, "toBlockNumber", toBlockNum, "err", chunkErr)
return nil, ErrCoordinatorInternalFailure
@@ -112,7 +112,7 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
for i := 0; i < 5; i++ {
var getTaskError error
var tmpBatchTask *orm.Batch
tmpBatchTask, getTaskError = bp.batchOrm.GetAssignedBatch(ctx.Copy(), startChunkIndex, endChunkIndex, maxActiveAttempts, maxTotalAttempts)
tmpBatchTask, getTaskError = bp.batchOrm.GetAssignedBatch(ctx, startChunkIndex, endChunkIndex, maxActiveAttempts, maxTotalAttempts)
if getTaskError != nil {
log.Error("failed to get assigned batch proving tasks", "height", getTaskParameter.ProverHeight, "err", getTaskError)
return nil, ErrCoordinatorInternalFailure
@@ -121,7 +121,7 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
// Why here need get again? In order to support a task can assign to multiple prover, need also assign `ProvingTaskAssigned`
// batch to prover. But use `proving_status in (1, 2)` will not use the postgres index. So need split the sql.
if tmpBatchTask == nil {
tmpBatchTask, getTaskError = bp.batchOrm.GetUnassignedBatch(ctx.Copy(), startChunkIndex, endChunkIndex, maxActiveAttempts, maxTotalAttempts)
tmpBatchTask, getTaskError = bp.batchOrm.GetUnassignedBatch(ctx, startChunkIndex, endChunkIndex, maxActiveAttempts, maxTotalAttempts)
if getTaskError != nil {
log.Error("failed to get unassigned batch proving tasks", "height", getTaskParameter.ProverHeight, "err", getTaskError)
return nil, ErrCoordinatorInternalFailure
@@ -133,7 +133,7 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
return nil, nil
}
rowsAffected, updateAttemptsErr := bp.batchOrm.UpdateBatchAttempts(ctx.Copy(), tmpBatchTask.Index, tmpBatchTask.ActiveAttempts, tmpBatchTask.TotalAttempts)
rowsAffected, updateAttemptsErr := bp.batchOrm.UpdateBatchAttempts(ctx, tmpBatchTask.Index, tmpBatchTask.ActiveAttempts, tmpBatchTask.TotalAttempts)
if updateAttemptsErr != nil {
log.Error("failed to update batch attempts", "height", getTaskParameter.ProverHeight, "err", updateAttemptsErr)
return nil, ErrCoordinatorInternalFailure
@@ -168,13 +168,13 @@ func (bp *BatchProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
}
// Store session info.
if err = bp.proverTaskOrm.InsertProverTask(ctx.Copy(), &proverTask); err != nil {
if err = bp.proverTaskOrm.InsertProverTask(ctx, &proverTask); err != nil {
bp.recoverActiveAttempts(ctx, batchTask)
log.Error("insert batch prover task info fail", "taskID", batchTask.Hash, "publicKey", taskCtx.PublicKey, "err", err)
return nil, ErrCoordinatorInternalFailure
}
taskMsg, err := bp.formatProverTask(ctx.Copy(), &proverTask)
taskMsg, err := bp.formatProverTask(ctx, &proverTask)
if err != nil {
bp.recoverActiveAttempts(ctx, batchTask)
log.Error("format prover task failure", "hash", batchTask.Hash, "err", err)
@@ -242,7 +242,7 @@ func (bp *BatchProverTask) formatProverTask(ctx context.Context, task *orm.Prove
}
func (bp *BatchProverTask) recoverActiveAttempts(ctx *gin.Context, batchTask *orm.Batch) {
if err := bp.chunkOrm.DecreaseActiveAttemptsByHash(ctx.Copy(), batchTask.Hash); err != nil {
if err := bp.chunkOrm.DecreaseActiveAttemptsByHash(ctx, batchTask.Hash); err != nil {
log.Error("failed to recover batch active attempts", "hash", batchTask.Hash, "error", err)
}
}

View File

@@ -85,7 +85,7 @@ func (cp *ChunkProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
for i := 0; i < 5; i++ {
var getTaskError error
var tmpChunkTask *orm.Chunk
tmpChunkTask, getTaskError = cp.chunkOrm.GetAssignedChunk(ctx.Copy(), fromBlockNum, toBlockNum, maxActiveAttempts, maxTotalAttempts)
tmpChunkTask, getTaskError = cp.chunkOrm.GetAssignedChunk(ctx, fromBlockNum, toBlockNum, maxActiveAttempts, maxTotalAttempts)
if getTaskError != nil {
log.Error("failed to get assigned chunk proving tasks", "height", getTaskParameter.ProverHeight, "err", getTaskError)
return nil, ErrCoordinatorInternalFailure
@@ -94,7 +94,7 @@ func (cp *ChunkProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
// Why here need get again? In order to support a task can assign to multiple prover, need also assign `ProvingTaskAssigned`
// chunk to prover. But use `proving_status in (1, 2)` will not use the postgres index. So need split the sql.
if tmpChunkTask == nil {
tmpChunkTask, getTaskError = cp.chunkOrm.GetUnassignedChunk(ctx.Copy(), fromBlockNum, toBlockNum, maxActiveAttempts, maxTotalAttempts)
tmpChunkTask, getTaskError = cp.chunkOrm.GetUnassignedChunk(ctx, fromBlockNum, toBlockNum, maxActiveAttempts, maxTotalAttempts)
if getTaskError != nil {
log.Error("failed to get unassigned chunk proving tasks", "height", getTaskParameter.ProverHeight, "err", getTaskError)
return nil, ErrCoordinatorInternalFailure
@@ -106,7 +106,7 @@ func (cp *ChunkProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
return nil, nil
}
rowsAffected, updateAttemptsErr := cp.chunkOrm.UpdateChunkAttempts(ctx.Copy(), tmpChunkTask.Index, tmpChunkTask.ActiveAttempts, tmpChunkTask.TotalAttempts)
rowsAffected, updateAttemptsErr := cp.chunkOrm.UpdateChunkAttempts(ctx, tmpChunkTask.Index, tmpChunkTask.ActiveAttempts, tmpChunkTask.TotalAttempts)
if updateAttemptsErr != nil {
log.Error("failed to update chunk attempts", "height", getTaskParameter.ProverHeight, "err", updateAttemptsErr)
return nil, ErrCoordinatorInternalFailure
@@ -140,13 +140,13 @@ func (cp *ChunkProverTask) Assign(ctx *gin.Context, getTaskParameter *coordinato
AssignedAt: utils.NowUTC(),
}
if err = cp.proverTaskOrm.InsertProverTask(ctx.Copy(), &proverTask); err != nil {
if err = cp.proverTaskOrm.InsertProverTask(ctx, &proverTask); err != nil {
cp.recoverActiveAttempts(ctx, chunkTask)
log.Error("insert chunk prover task fail", "taskID", chunkTask.Hash, "publicKey", taskCtx.PublicKey, "err", err)
return nil, ErrCoordinatorInternalFailure
}
taskMsg, err := cp.formatProverTask(ctx.Copy(), &proverTask)
taskMsg, err := cp.formatProverTask(ctx, &proverTask)
if err != nil {
cp.recoverActiveAttempts(ctx, chunkTask)
log.Error("format prover task failure", "hash", chunkTask.Hash, "err", err)

View File

@@ -100,7 +100,7 @@ func (b *BaseProverTask) checkParameter(ctx *gin.Context, getTaskParameter *coor
return nil, fmt.Errorf("incompatible vk. please check your params files or config files")
}
isBlocked, err := b.proverBlockListOrm.IsPublicKeyBlocked(ctx.Copy(), publicKey.(string))
isBlocked, err := b.proverBlockListOrm.IsPublicKeyBlocked(ctx, publicKey.(string))
if err != nil {
return nil, fmt.Errorf("failed to check whether the public key %s is blocked before assigning a chunk task, err: %w, proverName: %s, proverVersion: %s", publicKey, err, proverName, proverVersion)
}
@@ -108,7 +108,7 @@ func (b *BaseProverTask) checkParameter(ctx *gin.Context, getTaskParameter *coor
return nil, fmt.Errorf("public key %s is blocked from fetching tasks. ProverName: %s, ProverVersion: %s", publicKey, proverName, proverVersion)
}
isAssigned, err := b.proverTaskOrm.IsProverAssigned(ctx.Copy(), publicKey.(string))
isAssigned, err := b.proverTaskOrm.IsProverAssigned(ctx, publicKey.(string))
if err != nil {
return nil, fmt.Errorf("failed to check if prover %s is assigned a task, err: %w", publicKey.(string), err)
}

View File

@@ -139,14 +139,14 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofMsg *message.P
var proverTask *orm.ProverTask
var err error
if proofParameter.UUID != "" {
proverTask, err = m.proverTaskOrm.GetProverTaskByUUIDAndPublicKey(ctx.Copy(), proofParameter.UUID, pk)
proverTask, err = m.proverTaskOrm.GetProverTaskByUUIDAndPublicKey(ctx, proofParameter.UUID, pk)
if proverTask == nil || err != nil {
log.Error("get none prover task for the proof", "uuid", proofParameter.UUID, "key", pk, "taskID", proofMsg.ID, "error", err)
return ErrValidatorFailureProverTaskEmpty
}
} else {
// TODO When prover all have upgrade, need delete this logic
proverTask, err = m.proverTaskOrm.GetAssignedProverTaskByTaskIDAndProver(ctx.Copy(), proofMsg.Type, proofMsg.ID, pk, pv)
proverTask, err = m.proverTaskOrm.GetAssignedProverTaskByTaskIDAndProver(ctx, proofMsg.Type, proofMsg.ID, pk, pv)
if proverTask == nil || err != nil {
log.Error("get none prover task for the proof", "key", pk, "taskID", proofMsg.ID, "error", err)
return ErrValidatorFailureProverTaskEmpty
@@ -159,7 +159,7 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofMsg *message.P
log.Info("handling zk proof", "proofID", proofMsg.ID, "proverName", proverTask.ProverName,
"proverPublicKey", pk, "proveType", proverTask.TaskType, "proofTime", proofTimeSec, "hardForkName", hardForkName)
if err = m.validator(ctx.Copy(), proverTask, pk, proofMsg, proofParameter, hardForkName); err != nil {
if err = m.validator(ctx, proverTask, pk, proofMsg, proofParameter, hardForkName); err != nil {
return err
}
@@ -175,7 +175,7 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofMsg *message.P
if verifyErr != nil || !success {
m.verifierFailureTotal.WithLabelValues(pv).Inc()
m.proofRecover(ctx.Copy(), proverTask, types.ProverTaskFailureTypeVerifiedFailed, proofMsg)
m.proofRecover(ctx, proverTask, types.ProverTaskFailureTypeVerifiedFailed, proofMsg)
log.Info("proof verified by coordinator failed", "proof id", proofMsg.ID, "prover name", proverTask.ProverName,
"prover pk", pk, "forkName", hardForkName, "prove type", proofMsg.Type, "proof time", proofTimeSec, "error", verifyErr)
@@ -191,10 +191,10 @@ func (m *ProofReceiverLogic) HandleZkProof(ctx *gin.Context, proofMsg *message.P
log.Info("proof verified and valid", "proof id", proofMsg.ID, "prover name", proverTask.ProverName,
"prover pk", pk, "prove type", proofMsg.Type, "proof time", proofTimeSec, "forkName", hardForkName)
if err := m.closeProofTask(ctx.Copy(), proverTask, proofMsg, proofTimeSec); err != nil {
if err := m.closeProofTask(ctx, proverTask, proofMsg, proofTimeSec); err != nil {
m.proofSubmitFailure.Inc()
m.proofRecover(ctx.Copy(), proverTask, types.ProverTaskFailureTypeServerError, proofMsg)
m.proofRecover(ctx, proverTask, types.ProverTaskFailureTypeServerError, proofMsg)
return ErrCoordinatorInternalFailure
}

View File

@@ -4,8 +4,6 @@ import (
"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus"
"scroll-tech/common/observability"
"scroll-tech/coordinator/internal/config"
"scroll-tech/coordinator/internal/controller/api"
"scroll-tech/coordinator/internal/middleware"
@@ -15,7 +13,7 @@ import (
func Route(router *gin.Engine, cfg *config.Config, reg prometheus.Registerer) {
router.Use(gin.Recovery())
observability.Use(router, "coordinator", reg)
//observability.Use(router, "coordinator", reg)
r := router.Group("coordinator")

View File

@@ -19,12 +19,13 @@ import (
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
"scroll-tech/database/migrate"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types"
"scroll-tech/common/types/encoding"
"scroll-tech/common/types/message"
"scroll-tech/common/version"
"scroll-tech/database/migrate"
"scroll-tech/coordinator/internal/config"
"scroll-tech/coordinator/internal/controller/api"
@@ -200,15 +201,15 @@ func TestApis(t *testing.T) {
// Set up the test environment.
setEnv(t)
t.Run("TestHandshake", testHandshake)
t.Run("TestFailedHandshake", testFailedHandshake)
//t.Run("TestHandshake", testHandshake)
//t.Run("TestFailedHandshake", testFailedHandshake)
t.Run("TestGetTaskBlocked", testGetTaskBlocked)
t.Run("TestOutdatedProverVersion", testOutdatedProverVersion)
//t.Run("TestOutdatedProverVersion", testOutdatedProverVersion)
t.Run("TestValidProof", testValidProof)
t.Run("TestInvalidProof", testInvalidProof)
t.Run("TestProofGeneratedFailed", testProofGeneratedFailed)
t.Run("TestTimeoutProof", testTimeoutProof)
t.Run("TestHardFork", testHardForkAssignTask)
//t.Run("TestInvalidProof", testInvalidProof)
//t.Run("TestProofGeneratedFailed", testProofGeneratedFailed)
//t.Run("TestTimeoutProof", testTimeoutProof)
//t.Run("TestHardFork", testHardForkAssignTask)
}
func testHandshake(t *testing.T) {
@@ -245,10 +246,10 @@ func testFailedHandshake(t *testing.T) {
func testGetTaskBlocked(t *testing.T) {
coordinatorURL := randomURL()
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL, map[string]int64{"homestead": forkNumberOne})
collector, _ := setupCoordinator(t, 3, coordinatorURL, map[string]int64{"homestead": forkNumberOne})
defer func() {
collector.Stop()
assert.NoError(t, httpHandler.Shutdown(context.Background()))
//assert.NoError(t, httpHandler.Shutdown(context.Background()))
}()
chunkProver := newMockProver(t, "prover_chunk_test", coordinatorURL, message.ProofTypeChunk, version.Version)
@@ -546,11 +547,7 @@ func testHardForkAssignTask(t *testing.T) {
func testValidProof(t *testing.T) {
coordinatorURL := randomURL()
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL, map[string]int64{"istanbul": forkNumberTwo})
defer func() {
collector.Stop()
assert.NoError(t, httpHandler.Shutdown(context.Background()))
}()
collector, _ := setupCoordinator(t, 3, coordinatorURL, map[string]int64{"istanbul": forkNumberTwo})
err := l2BlockOrm.InsertL2Blocks(context.Background(), []*encoding.Block{block1, block2})
assert.NoError(t, err)
@@ -563,7 +560,7 @@ func testValidProof(t *testing.T) {
err = chunkOrm.UpdateBatchHashInRange(context.Background(), 0, 0, batch.Hash)
assert.NoError(t, err)
// create mock provers.
//create mock provers.
provers := make([]*mockProver, 2)
for i := 0; i < len(provers); i++ {
var proofType message.ProofType
@@ -582,6 +579,8 @@ func testValidProof(t *testing.T) {
assert.NotNil(t, proverTask)
provers[i].submitProof(t, proverTask, proofStatus, types.Success, "istanbul")
}
collector.Stop()
//assert.NoError(t, httpHandler.Shutdown(context.Background()))
// verify proof status
var (
@@ -609,6 +608,10 @@ func testValidProof(t *testing.T) {
return
}
if chunkProofStatus == types.ProvingTaskVerified {
return
}
chunkActiveAttempts, chunkMaxAttempts, err = chunkOrm.GetAttemptsByHash(context.Background(), dbChunk.Hash)
assert.NoError(t, err)
assert.Equal(t, 1, int(chunkMaxAttempts))

View File

@@ -59,20 +59,20 @@ func testResetDB(t *testing.T) {
cur, err := Current(pgDB)
assert.NoError(t, err)
// total number of tables.
assert.Equal(t, int64(20), cur)
assert.Equal(t, int64(18), cur)
}
func testMigrate(t *testing.T) {
assert.NoError(t, Migrate(pgDB))
cur, err := Current(pgDB)
assert.NoError(t, err)
assert.Equal(t, int64(20), cur)
assert.Equal(t, int64(18), cur)
}
func testRollback(t *testing.T) {
version, err := Current(pgDB)
assert.NoError(t, err)
assert.Equal(t, int64(20), version)
assert.Equal(t, int64(18), version)
assert.NoError(t, Rollback(pgDB, nil))

View File

@@ -1,15 +0,0 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE l1_block
ADD COLUMN blob_base_fee BIGINT DEFAULT 0;
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
ALTER TABLE IF EXISTS l1_block
DROP COLUMN blob_base_fee;
-- +goose StatementEnd

View File

@@ -1,17 +0,0 @@
-- +goose Up
-- +goose StatementBegin
DROP INDEX if exists idx_prover_block_list_on_public_key;
CREATE UNIQUE INDEX if not exists uniq_prover_block_list_on_public_key ON prover_block_list(public_key) where deleted_at IS NULL;
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
CREATE INDEX if not exists idx_prover_block_list_on_public_key ON prover_block_list(public_key);
DROP INDEX if exists uniq_prover_block_list_on_public_key;
-- +goose StatementEnd

View File

@@ -443,6 +443,8 @@ github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfT
github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/appleboy/gin-jwt/v2 v2.9.2 h1:GeS3lm9mb9HMmj7+GNjYUtpp3V1DAQ1TkUFa5poiZ7Y=
github.com/appleboy/gin-jwt/v2 v2.9.2/go.mod h1:mxGjKt9Lrx9Xusy1SrnmsCJMZG6UJwmdHN9bN27/QDw=
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 h1:7Ip0wMmLHLRJdrloDxZfhMm0xrLXZS8+COSu2bXmEQs=
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA=
@@ -544,6 +546,8 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/c-bata/go-prompt v0.2.2 h1:uyKRz6Z6DUyj49QVijyM339UJV9yhbr70gESwbNU3e0=
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
@@ -556,6 +560,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/logex v1.2.0 h1:+eqR0HfOetur4tgnC8ftU5imRnhi4te+BadWS95c5AM=
@@ -667,8 +673,6 @@ github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 h1:DuBDHVjgGMP
github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI=
github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ=
github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs=
github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI=
github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c h1:/ovYnF02fwL0kvspmy9AuyKg1JhdTRUgPw4nUxd9oZM=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
@@ -800,6 +804,8 @@ github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgxrzK5E1fW7RQGeDwE8F/ZZnUYc=
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8=
github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8=
@@ -860,6 +866,8 @@ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/j
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74=
github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@@ -1221,6 +1229,8 @@ github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6 h1:KAZ1BW2TCmT6PRihDPpocIy1QTtsAsrx6TneU/4+CMg=
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada h1:3L+neHp83cTjegPdCiOxVOJtRIy7/8RldvMTsyPYH10=
@@ -1245,6 +1255,8 @@ github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.3.0 h1:jX8FDLfW4ThVXctBNZ+3cIWnCSnrACDV73r76dy0aQQ=
github.com/leodido/go-urn v1.3.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=
@@ -1405,6 +1417,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/penglongli/gin-metrics v0.1.10/go.mod h1:wxGsGUwpVGv3hmYSxQn2GZgRL3YuCgiRFq2d0X6+EOU=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@@ -1492,11 +1506,7 @@ github.com/scroll-tech/go-ethereum v1.10.14-0.20230306131930-03b4de32b78b/go.mod
github.com/scroll-tech/go-ethereum v1.10.14-0.20230321020420-127af384ed04/go.mod h1:jH8c08L9K8Hieaf0r/ur2P/cpesn4dFhmLm2Mmoi8kI=
github.com/scroll-tech/go-ethereum v1.10.14-0.20230802095950-4b2bbf6225e7/go.mod h1:DiN3p2inoXOxGffxSswDKqWjQ7bU+Mp0c9v0XQXKmaA=
github.com/scroll-tech/go-ethereum v1.10.14-0.20230829000527-f883dcdc21fc/go.mod h1:DiN3p2inoXOxGffxSswDKqWjQ7bU+Mp0c9v0XQXKmaA=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea h1:CH1WXWrpEpLaP3N+bFs2a1xdE0+lRm1AuJQb5YvE6Ls=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea/go.mod h1:i4VBgWoaW/y0D8MmQb7hSOulyw1dKhuiSFAbznwivCA=
github.com/scroll-tech/zktrie v0.6.0/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/scroll-tech/zktrie v0.8.2 h1:UMuIfA+jdgWMLmTgTL64Emo+zzMOdcnH0+eYdDcshxQ=
github.com/scroll-tech/zktrie v0.8.2/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/segmentio/kafka-go v0.2.0 h1:HtCSf6B4gN/87yc5qTl7WsxPKQIIGXLPPM1bMCPOsoY=
github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
@@ -1565,6 +1575,8 @@ github.com/tdewolff/parse/v2 v2.6.4 h1:KCkDvNUMof10e3QExio9OPZJT8SbdKojLBumw8YZy
github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs=
github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM=
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tinylib/msgp v1.0.2 h1:DfdQrzQa7Yh2es9SuLkixqxuXS2SxsdYn0KbdrOGWD8=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
@@ -1584,6 +1596,8 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8=
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
@@ -1703,6 +1717,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -1727,6 +1743,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1814,6 +1832,8 @@ golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1894,12 +1914,15 @@ golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -2064,6 +2087,8 @@ google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

2
l2geth

Submodule l2geth updated: 246955a4df...38a3a9c919

View File

@@ -9,12 +9,12 @@ import (
"github.com/scroll-tech/go-ethereum/rpc"
"scroll-tech/prover/config"
"scroll-tech/common/cmd"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types/message"
"scroll-tech/common/utils"
"scroll-tech/prover/config"
)
var (

View File

@@ -31,9 +31,9 @@ clean: ## Empty out the bin folder
@rm -rf build/bin
docker_push:
docker push scrolltech/gas-oracle:${IMAGE_VERSION}
docker push scrolltech/event-watcher:${IMAGE_VERSION}
docker push scrolltech/rollup-relayer:${IMAGE_VERSION}
docker docker push scrolltech/gas-oracle:${IMAGE_VERSION}
docker docker push scrolltech/event-watcher:${IMAGE_VERSION}
docker docker push scrolltech/rollup-relayer:${IMAGE_VERSION}
docker:
DOCKER_BUILDKIT=1 docker build -t scrolltech/gas-oracle:${IMAGE_VERSION} ${REPO_ROOT_DIR}/ -f ${REPO_ROOT_DIR}/build/dockerfiles/gas_oracle.Dockerfile

View File

@@ -16,7 +16,7 @@ go install -v github.com/scroll-tech/go-ethereum/cmd/abigen
2. `solc`
Ensure you install the version of solc required by [MockBridge.sol](./mock_bridge/MockBridge.sol#L2) (e.g., 0.8.24). See https://docs.soliditylang.org/en/latest/installing-solidity.html
See https://docs.soliditylang.org/en/latest/installing-solidity.html
## Build
@@ -31,7 +31,7 @@ make rollup_bins
(Note: make sure you use different private keys for different senders in config.json.)
```bash
./build/bin/event_watcher --config ./conf/config.json
./build/bin/gas_oracle --config ./conf/config.json
./build/bin/rollup_relayer --config ./conf/config.json
./build/bin/event_watcher --config ./config.json
./build/bin/gas_oracle --config ./config.json
./build/bin/rollup_relayer --config ./config.json
```

View File

@@ -78,15 +78,9 @@ func action(ctx *cli.Context) error {
log.Crit("failed to connect l2 geth", "config file", cfgFile, "error", err)
}
genesisPath := ctx.String(utils.Genesis.Name)
genesis, err := utils.ReadGenesis(genesisPath)
if err != nil {
log.Crit("failed to read genesis", "genesis file", genesisPath, "error", err)
}
l1watcher := watcher.NewL1WatcherClient(ctx.Context, l1client, cfg.L1Config.StartHeight, cfg.L1Config.Confirmations, cfg.L1Config.L1MessageQueueAddress, cfg.L1Config.ScrollChainContractAddress, db, registry)
l1relayer, err := relayer.NewLayer1Relayer(ctx.Context, db, cfg.L1Config.RelayerConfig, genesis.Config, relayer.ServiceTypeL1GasOracle, registry)
l1relayer, err := relayer.NewLayer1Relayer(ctx.Context, db, cfg.L1Config.RelayerConfig, relayer.ServiceTypeL1GasOracle, registry)
if err != nil {
log.Crit("failed to create new l1 relayer", "config file", cfgFile, "error", err)
}

View File

@@ -7,11 +7,11 @@ import (
"testing"
"time"
"scroll-tech/rollup/internal/config"
"scroll-tech/common/cmd"
"scroll-tech/common/testcontainers"
"scroll-tech/common/utils"
"scroll-tech/rollup/internal/config"
)
// MockApp mockApp-test client manager.
@@ -85,7 +85,7 @@ func (b *MockApp) MockConfig(store bool) error {
return err
}
l1GethEndpoint, err := b.testApps.GetPoSL1EndPoint()
l1GethEndpoint, err := b.testApps.GetL1GethEndPoint()
if err != nil {
return err
}

View File

@@ -19,9 +19,7 @@
},
"gas_oracle_config": {
"min_gas_price": 0,
"gas_price_diff": 50000,
"l1_base_fee_weight": 0.132,
"l1_blob_base_fee_weight": 0.145
"gas_price_diff": 50000
},
"gas_oracle_sender_private_key": "1313131313131313131313131313131313131313131313131313131313131313"
}

View File

@@ -3,14 +3,14 @@ module scroll-tech/rollup
go 1.21
require (
github.com/agiledragon/gomonkey/v2 v2.11.0
github.com/agiledragon/gomonkey/v2 v2.9.0
github.com/consensys/gnark-crypto v0.12.1
github.com/crate-crypto/go-kzg-4844 v1.0.0
github.com/crate-crypto/go-kzg-4844 v0.7.0
github.com/gin-gonic/gin v1.9.1
github.com/go-resty/resty/v2 v2.7.0
github.com/holiman/uint256 v1.2.4
github.com/prometheus/client_golang v1.16.0
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea
github.com/scroll-tech/go-ethereum v1.10.14-0.20240326144132-0f0cd99f7a2e
github.com/smartystreets/goconvey v1.8.0
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.25.7
@@ -87,7 +87,7 @@ require (
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/scroll-tech/zktrie v0.8.2 // indirect
github.com/scroll-tech/zktrie v0.7.1 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/smartystreets/assertions v1.13.1 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect

View File

@@ -2,8 +2,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40=
github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/agiledragon/gomonkey/v2 v2.11.0 h1:5oxSgA+tC1xuGsrIorR+sYiziYltmJyEZ9qA25b6l5U=
github.com/agiledragon/gomonkey/v2 v2.11.0/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/agiledragon/gomonkey/v2 v2.9.0 h1:PDiKKybR596O6FHW+RVSG0Z7uGCBNbmbUXh3uCNQ7Hc=
github.com/agiledragon/gomonkey/v2 v2.9.0/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
@@ -43,8 +43,8 @@ github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJ
github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI=
github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA=
github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -237,10 +237,10 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea h1:CH1WXWrpEpLaP3N+bFs2a1xdE0+lRm1AuJQb5YvE6Ls=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240426041101-a860446ebaea/go.mod h1:i4VBgWoaW/y0D8MmQb7hSOulyw1dKhuiSFAbznwivCA=
github.com/scroll-tech/zktrie v0.8.2 h1:UMuIfA+jdgWMLmTgTL64Emo+zzMOdcnH0+eYdDcshxQ=
github.com/scroll-tech/zktrie v0.8.2/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240326144132-0f0cd99f7a2e h1:FcoK0rykAWI+5E7cQM6ALRLd5CmjBTHRvJztRBH2xeM=
github.com/scroll-tech/go-ethereum v1.10.14-0.20240326144132-0f0cd99f7a2e/go.mod h1:7Rz2bh9pn42rGuxjh51CG7HL9SKMG3ZugJkL3emdZx8=
github.com/scroll-tech/zktrie v0.7.1 h1:NrmZNjuBzsbrKePqdHDG+t2cXnimbtezPAFS0+L9ElE=
github.com/scroll-tech/zktrie v0.7.1/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=

View File

@@ -70,14 +70,8 @@ type RelayerConfig struct {
type GasOracleConfig struct {
// MinGasPrice store the minimum gas price to set.
MinGasPrice uint64 `json:"min_gas_price"`
// GasPriceDiff is the minimum percentage of gas price difference to update gas oracle.
// GasPriceDiff store the percentage of gas price difference.
GasPriceDiff uint64 `json:"gas_price_diff"`
// The following configs are only for updating L1 gas price, used for sender in L2.
// The weight for L1 base fee.
L1BaseFeeWeight float64 `json:"l1_base_fee_weight"`
// The weight for L1 blob base fee.
L1BlobBaseFeeWeight float64 `json:"l1_blob_base_fee_weight"`
}
// relayerConfigAlias RelayerConfig alias name

View File

@@ -3,14 +3,12 @@ package relayer
import (
"context"
"fmt"
"math"
"math/big"
"github.com/prometheus/client_golang/prometheus"
"github.com/scroll-tech/go-ethereum/accounts/abi"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/log"
"github.com/scroll-tech/go-ethereum/params"
"gorm.io/gorm"
"scroll-tech/common/types"
@@ -30,26 +28,21 @@ import (
type Layer1Relayer struct {
ctx context.Context
cfg *config.RelayerConfig
chainCfg *params.ChainConfig
cfg *config.RelayerConfig
gasOracleSender *sender.Sender
l1GasOracleABI *abi.ABI
lastGasPrice uint64
minGasPrice uint64
gasPriceDiff uint64
l1BaseFeeWeight float64
l1BlobBaseFeeWeight float64
lastGasPrice uint64
minGasPrice uint64
gasPriceDiff uint64
l1BlockOrm *orm.L1Block
l2BlockOrm *orm.L2Block
metrics *l1RelayerMetrics
metrics *l1RelayerMetrics
}
// NewLayer1Relayer will return a new instance of Layer1RelayerClient
func NewLayer1Relayer(ctx context.Context, db *gorm.DB, cfg *config.RelayerConfig, chainCfg *params.ChainConfig, serviceType ServiceType, reg prometheus.Registerer) (*Layer1Relayer, error) {
func NewLayer1Relayer(ctx context.Context, db *gorm.DB, cfg *config.RelayerConfig, serviceType ServiceType, reg prometheus.Registerer) (*Layer1Relayer, error) {
var gasOracleSender *sender.Sender
var err error
@@ -81,18 +74,14 @@ func NewLayer1Relayer(ctx context.Context, db *gorm.DB, cfg *config.RelayerConfi
l1Relayer := &Layer1Relayer{
cfg: cfg,
chainCfg: chainCfg,
ctx: ctx,
l1BlockOrm: orm.NewL1Block(db),
l2BlockOrm: orm.NewL2Block(db),
gasOracleSender: gasOracleSender,
l1GasOracleABI: bridgeAbi.L1GasPriceOracleABI,
minGasPrice: minGasPrice,
gasPriceDiff: gasPriceDiff,
l1BaseFeeWeight: cfg.GasOracleConfig.L1BaseFeeWeight,
l1BlobBaseFeeWeight: cfg.GasOracleConfig.L1BlobBaseFeeWeight,
minGasPrice: minGasPrice,
gasPriceDiff: gasPriceDiff,
}
l1Relayer.metrics = initL1RelayerMetrics(reg)
@@ -134,27 +123,12 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
if r.lastGasPrice > 0 && expectedDelta == 0 {
expectedDelta = 1
}
latestL2Height, err := r.l2BlockOrm.GetL2BlocksLatestHeight(r.ctx)
if err != nil {
log.Warn("Failed to fetch latest L2 block height from db", "err", err)
return
}
var isBernoulli = r.chainCfg.IsBernoulli(new(big.Int).SetUint64(latestL2Height))
var baseFee uint64
if isBernoulli && block.BlobBaseFee != 0 {
baseFee = uint64(math.Ceil(r.l1BaseFeeWeight*float64(block.BaseFee) + r.l1BlobBaseFeeWeight*float64(block.BlobBaseFee)))
} else {
baseFee = block.BaseFee
}
// last is undefined or (baseFee >= minGasPrice && exceed diff)
if r.lastGasPrice == 0 || (baseFee >= r.minGasPrice && (baseFee >= r.lastGasPrice+expectedDelta || baseFee <= r.lastGasPrice-expectedDelta)) {
data, err := r.l1GasOracleABI.Pack("setL1BaseFee", new(big.Int).SetUint64(baseFee))
// last is undefine or (block.BaseFee >= minGasPrice && exceed diff)
if r.lastGasPrice == 0 || (block.BaseFee >= r.minGasPrice && (block.BaseFee >= r.lastGasPrice+expectedDelta || block.BaseFee <= r.lastGasPrice-expectedDelta)) {
baseFee := big.NewInt(int64(block.BaseFee))
data, err := r.l1GasOracleABI.Pack("setL1BaseFee", baseFee)
if err != nil {
log.Error("Failed to pack setL1BaseFee", "block.Hash", block.Hash, "block.Height", block.Number, "block.BaseFee", baseFee, "isBernoulli", isBernoulli, "err", err)
log.Error("Failed to pack setL1BaseFee", "block.Hash", block.Hash, "block.Height", block.Number, "block.BaseFee", block.BaseFee, "err", err)
return
}
@@ -169,9 +143,9 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() {
log.Error("UpdateGasOracleStatusAndOracleTxHash failed", "block.Hash", block.Hash, "block.Height", block.Number, "err", err)
return
}
r.lastGasPrice = baseFee
r.lastGasPrice = block.BaseFee
r.metrics.rollupL1RelayerLastGasPrice.Set(float64(r.lastGasPrice))
log.Info("Update l1 base fee", "txHash", hash.String(), "baseFee", baseFee, "isBernoulli", isBernoulli)
log.Info("Update l1 base fee", "txHash", hash.String(), "baseFee", baseFee)
}
}
}

View File

@@ -8,7 +8,6 @@ import (
"github.com/agiledragon/gomonkey/v2"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto/kzg4844"
"github.com/scroll-tech/go-ethereum/params"
"github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
@@ -36,7 +35,7 @@ func setupL1RelayerDB(t *testing.T) *gorm.DB {
func testCreateNewL1Relayer(t *testing.T) {
db := setupL1RelayerDB(t)
defer database.CloseDB(db)
relayer, err := NewLayer1Relayer(context.Background(), db, cfg.L2Config.RelayerConfig, &params.ChainConfig{}, ServiceTypeL1GasOracle, nil)
relayer, err := NewLayer1Relayer(context.Background(), db, cfg.L2Config.RelayerConfig, ServiceTypeL1GasOracle, nil)
assert.NoError(t, err)
assert.NotNil(t, relayer)
defer relayer.StopSenders()
@@ -58,7 +57,7 @@ func testL1RelayerGasOracleConfirm(t *testing.T) {
l1Cfg := cfg.L1Config
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
l1Relayer, err := NewLayer1Relayer(ctx, db, l1Cfg.RelayerConfig, &params.ChainConfig{}, ServiceTypeL1GasOracle, nil)
l1Relayer, err := NewLayer1Relayer(ctx, db, l1Cfg.RelayerConfig, ServiceTypeL1GasOracle, nil)
assert.NoError(t, err)
defer l1Relayer.StopSenders()
@@ -91,7 +90,7 @@ func testL1RelayerProcessGasPriceOracle(t *testing.T) {
l1Cfg := cfg.L1Config
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
l1Relayer, err := NewLayer1Relayer(ctx, db, l1Cfg.RelayerConfig, &params.ChainConfig{}, ServiceTypeL1GasOracle, nil)
l1Relayer, err := NewLayer1Relayer(ctx, db, l1Cfg.RelayerConfig, ServiceTypeL1GasOracle, nil)
assert.NoError(t, err)
assert.NotNil(t, l1Relayer)
defer l1Relayer.StopSenders()

View File

@@ -14,6 +14,7 @@ import (
"github.com/stretchr/testify/assert"
"scroll-tech/common/database"
dockercompose "scroll-tech/common/docker-compose/l1"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types/encoding"
"scroll-tech/common/types/encoding/codecv0"
@@ -25,7 +26,9 @@ var (
// config
cfg *config.Config
testApps *testcontainers.TestcontainerApps
testApps *testcontainers.TestcontainerApps
posL1TestEnv *dockercompose.PoSL1TestEnv
// l2geth client
l2Cli *ethclient.Client
@@ -50,13 +53,15 @@ func setupEnv(t *testing.T) {
cfg, err = config.NewConfig("../../../conf/config.json")
assert.NoError(t, err)
posL1TestEnv, err = dockercompose.NewPoSL1TestEnv()
assert.NoError(t, err, "failed to create PoS L1 test environment")
assert.NoError(t, posL1TestEnv.Start(), "failed to start PoS L1 test environment")
testApps = testcontainers.NewTestcontainerApps()
assert.NoError(t, testApps.StartPostgresContainer())
assert.NoError(t, testApps.StartL2GethContainer())
assert.NoError(t, testApps.StartPoSL1Container())
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = posL1TestEnv.Endpoint()
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetL2GethEndPoint()
assert.NoError(t, err)
@@ -105,6 +110,9 @@ func TestMain(m *testing.M) {
if testApps != nil {
testApps.Free()
}
if posL1TestEnv != nil {
posL1TestEnv.Stop()
}
}()
m.Run()
}

View File

@@ -618,13 +618,13 @@ func makeSidecar(blob *kzg4844.Blob) (*gethTypes.BlobTxSidecar, error) {
var commitments []kzg4844.Commitment
var proofs []kzg4844.Proof
for i := range blobs {
c, err := kzg4844.BlobToCommitment(&blobs[i])
for _, b := range blobs {
c, err := kzg4844.BlobToCommitment(b)
if err != nil {
return nil, fmt.Errorf("failed to get blob commitment, err: %w", err)
}
p, err := kzg4844.ComputeBlobProof(&blobs[i], c)
p, err := kzg4844.ComputeBlobProof(b, c)
if err != nil {
return nil, fmt.Errorf("failed to compute blob proof, err: %w", err)
}

View File

@@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
dockercompose "scroll-tech/common/docker-compose/l1"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types"
"scroll-tech/database/migrate"
@@ -40,6 +41,7 @@ var (
privateKey *ecdsa.PrivateKey
cfg *config.Config
testApps *testcontainers.TestcontainerApps
posL1TestEnv *dockercompose.PoSL1TestEnv
txTypes = []string{"LegacyTx", "DynamicFeeTx", "DynamicFeeTx"}
txBlob = []*kzg4844.Blob{nil, nil, randBlob()}
txUint8Types = []uint8{0, 2, 3}
@@ -52,6 +54,9 @@ func TestMain(m *testing.M) {
if testApps != nil {
testApps.Free()
}
if posL1TestEnv != nil {
posL1TestEnv.Stop()
}
}()
m.Run()
}
@@ -68,13 +73,16 @@ func setupEnv(t *testing.T) {
assert.NoError(t, err)
privateKey = priv
posL1TestEnv, err = dockercompose.NewPoSL1TestEnv()
assert.NoError(t, err, "failed to create PoS L1 test environment")
assert.NoError(t, posL1TestEnv.Start(), "failed to start PoS L1 test environment")
testApps = testcontainers.NewTestcontainerApps()
assert.NoError(t, testApps.StartPostgresContainer())
assert.NoError(t, testApps.StartL1GethContainer())
assert.NoError(t, testApps.StartL2GethContainer())
assert.NoError(t, testApps.StartPoSL1Container())
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint = posL1TestEnv.Endpoint()
db, err = testApps.GetGormDBClient()
assert.NoError(t, err)
@@ -82,7 +90,7 @@ func setupEnv(t *testing.T) {
assert.NoError(t, err)
assert.NoError(t, migrate.ResetDB(sqlDB))
l1Client, err := testApps.GetPoSL1Client()
l1Client, err := posL1TestEnv.L1Client()
assert.NoError(t, err)
chainID, err := l1Client.ChainID(context.Background())
@@ -751,7 +759,7 @@ func testBlobTransactionWithBlobhashOpContractCall(t *testing.T) {
pointBigInt := new(big.Int).SetBytes(pointHash.Bytes())
point := kzg4844.Point(new(big.Int).Mod(pointBigInt, blsModulo).Bytes())
commitment := sideCar.Commitments[0]
proof, claim, err := kzg4844.ComputeProof(blob, point)
proof, claim, err := kzg4844.ComputeProof(*blob, point)
assert.NoError(t, err)
var claimArray [32]byte

View File

@@ -133,13 +133,15 @@ func (p *BatchProposer) TryProposeBatch() {
func (p *BatchProposer) updateDBBatchInfo(batch *encoding.Batch, codecVersion encoding.CodecVersion) error {
err := p.db.Transaction(func(dbTX *gorm.DB) error {
dbBatch, dbErr := p.batchOrm.InsertBatch(p.ctx, batch, codecVersion, dbTX)
batch, dbErr := p.batchOrm.InsertBatch(p.ctx, batch, codecVersion, dbTX)
if dbErr != nil {
log.Warn("BatchProposer.updateBatchInfoInDB insert batch failure", "index", batch.Index, "parent hash", batch.ParentBatchHash.Hex(), "error", dbErr)
log.Warn("BatchProposer.updateBatchInfoInDB insert batch failure",
"start chunk index", batch.StartChunkIndex, "end chunk index", batch.EndChunkIndex, "error", dbErr)
return dbErr
}
if dbErr = p.chunkOrm.UpdateBatchHashInRange(p.ctx, dbBatch.StartChunkIndex, dbBatch.EndChunkIndex, dbBatch.Hash, dbTX); dbErr != nil {
log.Warn("BatchProposer.UpdateBatchHashInRange update the chunk's batch hash failure", "hash", dbBatch.Hash, "error", dbErr)
dbErr = p.chunkOrm.UpdateBatchHashInRange(p.ctx, batch.StartChunkIndex, batch.EndChunkIndex, batch.Hash, dbTX)
if dbErr != nil {
log.Warn("BatchProposer.UpdateBatchHashInRange update the chunk's batch hash failure", "hash", batch.Hash, "error", dbErr)
return dbErr
}
return nil

View File

@@ -192,69 +192,27 @@ func testBatchProposerCodecv1Limits(t *testing.T) {
tests := []struct {
name string
maxChunkNum uint64
maxL1CommitGas uint64
maxL1CommitCalldataSize uint64
batchTimeoutSec uint64
forkBlock *big.Int
expectedBatchesLen int
expectedChunksInFirstBatch uint64 // only be checked when expectedBatchesLen > 0
}{
{
name: "NoLimitReached",
maxChunkNum: 10,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
batchTimeoutSec: 1000000000000,
expectedBatchesLen: 0,
name: "NoLimitReached",
maxChunkNum: 10,
batchTimeoutSec: 1000000000000,
expectedBatchesLen: 0,
},
{
name: "Timeout",
maxChunkNum: 10,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
batchTimeoutSec: 0,
expectedBatchesLen: 1,
expectedChunksInFirstBatch: 2,
},
{
name: "MaxL1CommitGasPerBatchIs0",
maxChunkNum: 10,
maxL1CommitGas: 0,
maxL1CommitCalldataSize: 1000000,
batchTimeoutSec: 1000000000000,
expectedBatchesLen: 0,
},
{
name: "MaxL1CommitCalldataSizePerBatchIs0",
maxChunkNum: 10,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 0,
batchTimeoutSec: 1000000000000,
expectedBatchesLen: 0,
},
{
name: "MaxChunkNumPerBatchIs1",
maxChunkNum: 1,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
batchTimeoutSec: 1000000000000,
expectedBatchesLen: 1,
expectedChunksInFirstBatch: 1,
},
{
name: "MaxL1CommitGasPerBatchIsFirstChunk",
maxChunkNum: 10,
maxL1CommitGas: 190352,
maxL1CommitCalldataSize: 1000000,
batchTimeoutSec: 1000000000000,
expectedBatchesLen: 1,
expectedChunksInFirstBatch: 1,
},
{
name: "MaxL1CommitCalldataSizePerBatchIsFirstChunk",
maxChunkNum: 10,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 60,
batchTimeoutSec: 1000000000000,
expectedBatchesLen: 1,
expectedChunksInFirstBatch: 1,
@@ -262,8 +220,6 @@ func testBatchProposerCodecv1Limits(t *testing.T) {
{
name: "ForkBlockReached",
maxChunkNum: 10,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
batchTimeoutSec: 1000000000000,
expectedBatchesLen: 1,
expectedChunksInFirstBatch: 1,
@@ -287,7 +243,7 @@ func testBatchProposerCodecv1Limits(t *testing.T) {
Blocks: []*encoding.Block{block},
}
chunkOrm := orm.NewChunk(db)
_, err := chunkOrm.InsertChunk(context.Background(), chunk, encoding.CodecV0)
_, err := chunkOrm.InsertChunk(context.Background(), chunk, encoding.CodecV1)
assert.NoError(t, err)
batch := &encoding.Batch{
Index: 0,
@@ -296,7 +252,7 @@ func testBatchProposerCodecv1Limits(t *testing.T) {
Chunks: []*encoding.Chunk{chunk},
}
batchOrm := orm.NewBatch(db)
_, err = batchOrm.InsertBatch(context.Background(), batch, encoding.CodecV0)
_, err = batchOrm.InsertBatch(context.Background(), batch, encoding.CodecV1)
assert.NoError(t, err)
l2BlockOrm := orm.NewL2Block(db)
@@ -306,34 +262,32 @@ func testBatchProposerCodecv1Limits(t *testing.T) {
cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{
MaxBlockNumPerChunk: 1,
MaxTxNumPerChunk: 10000,
MaxL1CommitGasPerChunk: 50000000000,
MaxL1CommitCalldataSizePerChunk: 1000000,
MaxL1CommitGasPerChunk: 1,
MaxL1CommitCalldataSizePerChunk: 1,
MaxRowConsumptionPerChunk: 1000000,
ChunkTimeoutSec: 300,
GasCostIncreaseMultiplier: 1.2,
}, &params.ChainConfig{
BernoulliBlock: big.NewInt(0),
HomesteadBlock: tt.forkBlock,
BernoulliBlock: big.NewInt(0), HomesteadBlock: tt.forkBlock,
}, db, nil)
cp.TryProposeChunk() // chunk1 contains block1
cp.TryProposeChunk() // chunk2 contains block2
chunks, err := chunkOrm.GetChunksInRange(context.Background(), 1, 2)
assert.NoError(t, err)
assert.Equal(t, uint64(2084), chunks[0].TotalL1CommitGas)
assert.Equal(t, uint64(60), chunks[0].TotalL1CommitCalldataSize)
assert.Equal(t, uint64(2084), chunks[1].TotalL1CommitGas)
assert.Equal(t, uint64(60), chunks[1].TotalL1CommitCalldataSize)
assert.Equal(t, uint64(0), chunks[0].TotalL1CommitGas)
assert.Equal(t, uint64(0), chunks[0].TotalL1CommitCalldataSize)
assert.Equal(t, uint64(0), chunks[1].TotalL1CommitGas)
assert.Equal(t, uint64(0), chunks[1].TotalL1CommitCalldataSize)
bp := NewBatchProposer(context.Background(), &config.BatchProposerConfig{
MaxChunkNumPerBatch: tt.maxChunkNum,
MaxL1CommitGasPerBatch: tt.maxL1CommitGas,
MaxL1CommitCalldataSizePerBatch: tt.maxL1CommitCalldataSize,
MaxL1CommitGasPerBatch: 1,
MaxL1CommitCalldataSizePerBatch: 1,
BatchTimeoutSec: tt.batchTimeoutSec,
GasCostIncreaseMultiplier: 1.2,
}, &params.ChainConfig{
BernoulliBlock: big.NewInt(0),
HomesteadBlock: tt.forkBlock,
BernoulliBlock: big.NewInt(0), HomesteadBlock: tt.forkBlock,
}, db, nil)
bp.TryProposeBatch()
@@ -359,7 +313,7 @@ func testBatchProposerCodecv1Limits(t *testing.T) {
}
}
func testBatchCommitGasAndCalldataSizeCodecv0Estimation(t *testing.T) {
func testBatchCommitGasAndCalldataSizeEstimation(t *testing.T) {
db := setupDB(t)
defer database.CloseDB(db)
@@ -439,86 +393,6 @@ func testBatchCommitGasAndCalldataSizeCodecv0Estimation(t *testing.T) {
assert.Equal(t, uint64(6035), batches[0].TotalL1CommitCalldataSize)
}
func testBatchCommitGasAndCalldataSizeCodecv1Estimation(t *testing.T) {
db := setupDB(t)
defer database.CloseDB(db)
// Add genesis batch.
block := &encoding.Block{
Header: &gethTypes.Header{
Number: big.NewInt(0),
},
RowConsumption: &gethTypes.RowConsumption{},
}
chunk := &encoding.Chunk{
Blocks: []*encoding.Block{block},
}
chunkOrm := orm.NewChunk(db)
_, err := chunkOrm.InsertChunk(context.Background(), chunk, encoding.CodecV0)
assert.NoError(t, err)
batch := &encoding.Batch{
Index: 0,
TotalL1MessagePoppedBefore: 0,
ParentBatchHash: common.Hash{},
Chunks: []*encoding.Chunk{chunk},
}
batchOrm := orm.NewBatch(db)
_, err = batchOrm.InsertBatch(context.Background(), batch, encoding.CodecV0)
assert.NoError(t, err)
l2BlockOrm := orm.NewL2Block(db)
err = l2BlockOrm.InsertL2Blocks(context.Background(), []*encoding.Block{block1, block2})
assert.NoError(t, err)
cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{
MaxBlockNumPerChunk: 1,
MaxTxNumPerChunk: 10000,
MaxL1CommitGasPerChunk: 50000000000,
MaxL1CommitCalldataSizePerChunk: 1000000,
MaxRowConsumptionPerChunk: 1000000,
ChunkTimeoutSec: 300,
GasCostIncreaseMultiplier: 1.2,
}, &params.ChainConfig{BernoulliBlock: big.NewInt(0)}, db, nil)
cp.TryProposeChunk() // chunk1 contains block1
cp.TryProposeChunk() // chunk2 contains block2
chunks, err := chunkOrm.GetChunksInRange(context.Background(), 1, 2)
assert.NoError(t, err)
assert.Equal(t, uint64(2084), chunks[0].TotalL1CommitGas)
assert.Equal(t, uint64(60), chunks[0].TotalL1CommitCalldataSize)
assert.Equal(t, uint64(2084), chunks[1].TotalL1CommitGas)
assert.Equal(t, uint64(60), chunks[1].TotalL1CommitCalldataSize)
bp := NewBatchProposer(context.Background(), &config.BatchProposerConfig{
MaxChunkNumPerBatch: 10,
MaxL1CommitGasPerBatch: 50000000000,
MaxL1CommitCalldataSizePerBatch: 1000000,
BatchTimeoutSec: 0,
GasCostIncreaseMultiplier: 1.2,
}, &params.ChainConfig{BernoulliBlock: big.NewInt(0)}, db, nil)
bp.TryProposeBatch()
batches, err := batchOrm.GetBatches(context.Background(), map[string]interface{}{}, []string{}, 0)
assert.NoError(t, err)
assert.Len(t, batches, 2)
batches = batches[1:]
assert.Equal(t, uint64(1), batches[0].StartChunkIndex)
assert.Equal(t, uint64(2), batches[0].EndChunkIndex)
assert.Equal(t, types.RollupPending, types.RollupStatus(batches[0].RollupStatus))
assert.Equal(t, types.ProvingTaskUnassigned, types.ProvingStatus(batches[0].ProvingStatus))
dbChunks, err := chunkOrm.GetChunksInRange(context.Background(), 1, 2)
assert.NoError(t, err)
assert.Len(t, dbChunks, 2)
for _, chunk := range dbChunks {
assert.Equal(t, batches[0].Hash, chunk.BatchHash)
assert.Equal(t, types.ProvingTaskUnassigned, types.ProvingStatus(chunk.ProvingStatus))
}
assert.Equal(t, uint64(161270), batches[0].TotalL1CommitGas)
assert.Equal(t, uint64(120), batches[0].TotalL1CommitCalldataSize)
}
func testBatchProposerBlobSizeLimit(t *testing.T) {
db := setupDB(t)
defer database.CloseDB(db)
@@ -549,8 +423,8 @@ func testBatchProposerBlobSizeLimit(t *testing.T) {
cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{
MaxBlockNumPerChunk: math.MaxUint64,
MaxTxNumPerChunk: math.MaxUint64,
MaxL1CommitGasPerChunk: math.MaxUint64,
MaxL1CommitCalldataSizePerChunk: math.MaxUint64,
MaxL1CommitGasPerChunk: 1,
MaxL1CommitCalldataSizePerChunk: 1,
MaxRowConsumptionPerChunk: math.MaxUint64,
ChunkTimeoutSec: math.MaxUint64,
GasCostIncreaseMultiplier: 1,
@@ -569,8 +443,8 @@ func testBatchProposerBlobSizeLimit(t *testing.T) {
bp := NewBatchProposer(context.Background(), &config.BatchProposerConfig{
MaxChunkNumPerBatch: math.MaxUint64,
MaxL1CommitGasPerBatch: math.MaxUint64,
MaxL1CommitCalldataSizePerBatch: math.MaxUint64,
MaxL1CommitGasPerBatch: 1,
MaxL1CommitCalldataSizePerBatch: 1,
BatchTimeoutSec: math.MaxUint64,
GasCostIncreaseMultiplier: 1,
}, &params.ChainConfig{BernoulliBlock: big.NewInt(0)}, db, nil)

View File

@@ -205,8 +205,6 @@ func testChunkProposerCodecv1Limits(t *testing.T) {
name string
maxBlockNum uint64
maxTxNum uint64
maxL1CommitGas uint64
maxL1CommitCalldataSize uint64
maxRowConsumption uint64
chunkTimeoutSec uint64
forkBlock *big.Int
@@ -214,72 +212,42 @@ func testChunkProposerCodecv1Limits(t *testing.T) {
expectedBlocksInFirstChunk int // only be checked when expectedChunksLen > 0
}{
{
name: "NoLimitReached",
maxBlockNum: 100,
maxTxNum: 10000,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 0,
name: "NoLimitReached",
maxBlockNum: 100,
maxTxNum: 10000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 0,
},
{
name: "Timeout",
maxBlockNum: 100,
maxTxNum: 10000,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 0,
expectedChunksLen: 1,
expectedBlocksInFirstChunk: 2,
},
{
name: "MaxTxNumPerChunkIs0",
maxBlockNum: 10,
maxTxNum: 0,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 0,
name: "MaxTxNumPerChunkIs0",
maxBlockNum: 10,
maxTxNum: 0,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 0,
},
{
name: "MaxL1CommitGasPerChunkIs0",
maxBlockNum: 10,
maxTxNum: 10000,
maxL1CommitGas: 0,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 0,
},
{
name: "MaxL1CommitCalldataSizePerChunkIs0",
maxBlockNum: 10,
maxTxNum: 10000,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 0,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 0,
},
{
name: "MaxRowConsumptionPerChunkIs0",
maxBlockNum: 100,
maxTxNum: 10000,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 0,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 0,
name: "MaxRowConsumptionPerChunkIs0",
maxBlockNum: 100,
maxTxNum: 10000,
maxRowConsumption: 0,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 0,
},
{
name: "MaxBlockNumPerChunkIs1",
maxBlockNum: 1,
maxTxNum: 10000,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 1,
@@ -289,30 +257,6 @@ func testChunkProposerCodecv1Limits(t *testing.T) {
name: "MaxTxNumPerChunkIsFirstBlock",
maxBlockNum: 10,
maxTxNum: 2,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 1,
expectedBlocksInFirstChunk: 1,
},
{
name: "MaxL1CommitGasPerChunkIsFirstBlock",
maxBlockNum: 10,
maxTxNum: 10000,
maxL1CommitGas: 2522,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 1,
expectedBlocksInFirstChunk: 1,
},
{
name: "MaxL1CommitCalldataSizePerChunkIsFirstBlock",
maxBlockNum: 10,
maxTxNum: 10000,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 60,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 1,
@@ -322,8 +266,6 @@ func testChunkProposerCodecv1Limits(t *testing.T) {
name: "MaxRowConsumptionPerChunkIs1",
maxBlockNum: 10,
maxTxNum: 10000,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 1,
@@ -333,8 +275,6 @@ func testChunkProposerCodecv1Limits(t *testing.T) {
name: "ForkBlockReached",
maxBlockNum: 100,
maxTxNum: 10000,
maxL1CommitGas: 50000000000,
maxL1CommitCalldataSize: 1000000,
maxRowConsumption: 1000000,
chunkTimeoutSec: 1000000000000,
expectedChunksLen: 1,
@@ -355,14 +295,12 @@ func testChunkProposerCodecv1Limits(t *testing.T) {
cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{
MaxBlockNumPerChunk: tt.maxBlockNum,
MaxTxNumPerChunk: tt.maxTxNum,
MaxL1CommitGasPerChunk: tt.maxL1CommitGas,
MaxL1CommitCalldataSizePerChunk: tt.maxL1CommitCalldataSize,
MaxL1CommitGasPerChunk: 1,
MaxL1CommitCalldataSizePerChunk: 1,
MaxRowConsumptionPerChunk: tt.maxRowConsumption,
ChunkTimeoutSec: tt.chunkTimeoutSec,
GasCostIncreaseMultiplier: 1.2,
}, &params.ChainConfig{
BernoulliBlock: big.NewInt(0), HomesteadBlock: tt.forkBlock,
}, db, nil)
}, &params.ChainConfig{BernoulliBlock: big.NewInt(0), HomesteadBlock: tt.forkBlock}, db, nil)
cp.TryProposeChunk()
chunkOrm := orm.NewChunk(db)
@@ -399,8 +337,8 @@ func testChunkProposerCodecv1BlobSizeLimit(t *testing.T) {
cp := NewChunkProposer(context.Background(), &config.ChunkProposerConfig{
MaxBlockNumPerChunk: math.MaxUint64,
MaxTxNumPerChunk: math.MaxUint64,
MaxL1CommitGasPerChunk: math.MaxUint64,
MaxL1CommitCalldataSizePerChunk: math.MaxUint64,
MaxL1CommitGasPerChunk: 1,
MaxL1CommitCalldataSizePerChunk: 1,
MaxRowConsumptionPerChunk: math.MaxUint64,
ChunkTimeoutSec: math.MaxUint64,
GasCostIncreaseMultiplier: 1,

View File

@@ -9,7 +9,6 @@ import (
geth "github.com/scroll-tech/go-ethereum"
"github.com/scroll-tech/go-ethereum/accounts/abi"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/consensus/misc"
gethTypes "github.com/scroll-tech/go-ethereum/core/types"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/ethclient"
@@ -136,16 +135,10 @@ func (w *L1WatcherClient) FetchBlockHeader(blockHeight uint64) error {
baseFee = block.BaseFee.Uint64()
}
var blobBaseFee uint64
if excess := block.ExcessBlobGas; excess != nil {
blobBaseFee = misc.CalcBlobFee(*excess).Uint64()
}
l1Block := orm.L1Block{
Number: blockHeight,
Hash: block.Hash().String(),
BaseFee: baseFee,
BlobBaseFee: blobBaseFee,
GasOracleStatus: int16(types.GasOraclePending),
}

View File

@@ -27,7 +27,7 @@ import (
func setupL1Watcher(t *testing.T) (*L1WatcherClient, *gorm.DB) {
db := setupDB(t)
client, err := testApps.GetPoSL1Client()
client, err := testApps.GetL1GethClient()
assert.NoError(t, err)
l1Cfg := cfg.L1Config
watcher := NewL1WatcherClient(context.Background(), client, l1Cfg.StartHeight, l1Cfg.Confirmations, l1Cfg.L1MessageQueueAddress, l1Cfg.RelayerConfig.RollupContractAddress, db, nil)

View File

@@ -43,10 +43,10 @@ func setupEnv(t *testing.T) (err error) {
testApps = testcontainers.NewTestcontainerApps()
assert.NoError(t, testApps.StartPostgresContainer())
assert.NoError(t, testApps.StartPoSL1Container())
assert.NoError(t, testApps.StartL1GethContainer())
assert.NoError(t, testApps.StartL2GethContainer())
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetPoSL1EndPoint()
cfg.L2Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetL1GethEndPoint()
assert.NoError(t, err)
cfg.L1Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetL2GethEndPoint()
assert.NoError(t, err)
@@ -109,11 +109,10 @@ func TestFunction(t *testing.T) {
t.Run("TestChunkProposerCodecv1Limits", testChunkProposerCodecv1Limits)
t.Run("TestChunkProposerCodecv1BlobSizeLimit", testChunkProposerCodecv1BlobSizeLimit)
// Run batch proposer test cases.
// Run chunk proposer test cases.
t.Run("TestBatchProposerCodecv0Limits", testBatchProposerCodecv0Limits)
t.Run("TestBatchProposerCodecv1Limits", testBatchProposerCodecv1Limits)
t.Run("TestBatchCommitGasAndCalldataSizeCodecv0Estimation", testBatchCommitGasAndCalldataSizeCodecv0Estimation)
t.Run("TestBatchCommitGasAndCalldataSizeCodecv1Estimation", testBatchCommitGasAndCalldataSizeCodecv1Estimation)
t.Run("TestBatchCommitGasAndCalldataSizeEstimation", testBatchCommitGasAndCalldataSizeEstimation)
t.Run("TestBatchProposerBlobSizeLimit", testBatchProposerBlobSizeLimit)
}

View File

@@ -15,10 +15,9 @@ type L1Block struct {
db *gorm.DB `gorm:"column:-"`
// block
Number uint64 `json:"number" gorm:"column:number"`
Hash string `json:"hash" gorm:"column:hash"`
BaseFee uint64 `json:"base_fee" gorm:"column:base_fee"`
BlobBaseFee uint64 `json:"blob_base_fee" gorm:"column:blob_base_fee"`
Number uint64 `json:"number" gorm:"column:number"`
Hash string `json:"hash" gorm:"column:hash"`
BaseFee uint64 `json:"base_fee" gorm:"column:base_fee"`
// oracle
GasOracleStatus int16 `json:"oracle_status" gorm:"column:oracle_status;default:1"`

View File

@@ -12,12 +12,13 @@ import (
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
"scroll-tech/database/migrate"
"scroll-tech/common/testcontainers"
"scroll-tech/common/types"
"scroll-tech/common/types/encoding"
"scroll-tech/common/types/encoding/codecv0"
"scroll-tech/common/types/encoding/codecv1"
"scroll-tech/database/migrate"
)
var (

View File

@@ -76,6 +76,7 @@ type ChunkMetrics struct {
CrcMax uint64
FirstBlockTimestamp uint64
// codecv0 metrics, default 0 for codecv1
L1CommitCalldataSize uint64
L1CommitGas uint64
@@ -107,8 +108,6 @@ func CalculateChunkMetrics(chunk *encoding.Chunk, codecVersion encoding.CodecVer
}
return metrics, nil
case encoding.CodecV1:
metrics.L1CommitGas = codecv1.EstimateChunkL1CommitGas(chunk)
metrics.L1CommitCalldataSize = codecv1.EstimateChunkL1CommitCalldataSize(chunk)
metrics.L1CommitBlobSize, err = codecv1.EstimateChunkL1CommitBlobSize(chunk)
if err != nil {
return nil, fmt.Errorf("failed to estimate chunk L1 commit blob size: %w", err)
@@ -125,6 +124,7 @@ type BatchMetrics struct {
NumChunks uint64
FirstBlockTimestamp uint64
// codecv0 metrics, default 0 for codecv1
L1CommitCalldataSize uint64
L1CommitGas uint64
@@ -151,8 +151,6 @@ func CalculateBatchMetrics(batch *encoding.Batch, codecVersion encoding.CodecVer
}
return metrics, nil
case encoding.CodecV1:
metrics.L1CommitGas = codecv1.EstimateBatchL1CommitGas(batch)
metrics.L1CommitCalldataSize = codecv1.EstimateBatchL1CommitCalldataSize(batch)
metrics.L1CommitBlobSize, err = codecv1.EstimateBatchL1CommitBlobSize(batch)
if err != nil {
return nil, fmt.Errorf("failed to estimate chunk L1 commit blob size: %w", err)

View File

@@ -14,6 +14,7 @@ import (
"scroll-tech/database/migrate"
"scroll-tech/common/database"
dockercompose "scroll-tech/common/docker-compose/l1"
tc "scroll-tech/common/testcontainers"
"scroll-tech/common/utils"
@@ -33,8 +34,9 @@ import (
)
var (
testApps *tc.TestcontainerApps
rollupApp *bcmd.MockApp
testApps *tc.TestcontainerApps
rollupApp *bcmd.MockApp
posL1TestEnv *dockercompose.PoSL1TestEnv
// clients
l1Client *ethclient.Client
@@ -70,6 +72,9 @@ func TestMain(m *testing.M) {
if rollupApp != nil {
rollupApp.Free()
}
if posL1TestEnv != nil {
posL1TestEnv.Stop()
}
}()
m.Run()
}
@@ -84,13 +89,17 @@ func setupEnv(t *testing.T) {
l1GethChainID *big.Int
)
posL1TestEnv, err = dockercompose.NewPoSL1TestEnv()
assert.NoError(t, err, "failed to create PoS L1 test environment")
assert.NoError(t, posL1TestEnv.Start(), "failed to start PoS L1 test environment")
testApps = tc.NewTestcontainerApps()
assert.NoError(t, testApps.StartPostgresContainer())
assert.NoError(t, testApps.StartL1GethContainer())
assert.NoError(t, testApps.StartL2GethContainer())
assert.NoError(t, testApps.StartPoSL1Container())
rollupApp = bcmd.NewRollupApp(testApps, "../conf/config.json")
l1Client, err = testApps.GetPoSL1Client()
l1Client, err = posL1TestEnv.L1Client()
assert.NoError(t, err)
l2Client, err = testApps.GetL2GethClient()
assert.NoError(t, err)
@@ -105,10 +114,8 @@ func setupEnv(t *testing.T) {
l1Auth, err = bind.NewKeyedTransactorWithChainID(rollupApp.Config.L2Config.RelayerConfig.CommitSenderPrivateKey, l1GethChainID)
assert.NoError(t, err)
rollupApp.Config.L1Config.Endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
rollupApp.Config.L2Config.RelayerConfig.SenderConfig.Endpoint, err = testApps.GetPoSL1EndPoint()
assert.NoError(t, err)
rollupApp.Config.L1Config.Endpoint = posL1TestEnv.Endpoint()
rollupApp.Config.L2Config.RelayerConfig.SenderConfig.Endpoint = posL1TestEnv.Endpoint()
port, err := rand.Int(rand.Reader, big.NewInt(10000))
assert.NoError(t, err)

View File

@@ -28,7 +28,7 @@ func testImportL1GasPrice(t *testing.T) {
l1Cfg := rollupApp.Config.L1Config
// Create L1Relayer
l1Relayer, err := relayer.NewLayer1Relayer(context.Background(), db, l1Cfg.RelayerConfig, &params.ChainConfig{}, relayer.ServiceTypeL1GasOracle, nil)
l1Relayer, err := relayer.NewLayer1Relayer(context.Background(), db, l1Cfg.RelayerConfig, relayer.ServiceTypeL1GasOracle, nil)
assert.NoError(t, err)
defer l1Relayer.StopSenders()

Some files were not shown because too many files have changed in this diff Show More