diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..474e8651 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @0xPolygon/core-cdk diff --git a/.github/actions/monitor-cdk-verified-batches/action.yml b/.github/actions/monitor-cdk-verified-batches/action.yml new file mode 100644 index 00000000..83372bd7 --- /dev/null +++ b/.github/actions/monitor-cdk-verified-batches/action.yml @@ -0,0 +1,21 @@ +--- +name: monitor-cdk-verified-batches +description: Check that batches are being verified in a CDK environment + +inputs: + verified_batches_target: + description: The minimum number of batches to be verified + required: false + default: '30' + timeout: + description: The script timeout in seconds + required: false + default: '600' # 10 minutes + +runs: + using: "composite" + steps: + - name: Check that batches are being verified + working-directory: .github/actions/monitor-cdk-verified-batches + shell: bash + run: ./batch_verification_monitor.sh ${{ inputs.verified_batches_target }} ${{ inputs.timeout }} diff --git a/.github/actions/monitor-cdk-verified-batches/batch_verification_monitor.sh b/.github/actions/monitor-cdk-verified-batches/batch_verification_monitor.sh new file mode 100644 index 00000000..16a34a6e --- /dev/null +++ b/.github/actions/monitor-cdk-verified-batches/batch_verification_monitor.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# This script monitors the verification progress of zkEVM batches. +# Usage: ./batch_verification_monitor + +# The number of batches to be verified. +verified_batches_target="$1" + +# The script timeout (in seconds). +timeout="$2" + +start_time=$(date +%s) +end_time=$((start_time + timeout)) + +rpc_url="$(kurtosis port print cdk-v1 cdk-erigon-node-001 http-rpc)" +while true; do + verified_batches="$(cast to-dec "$(cast rpc --rpc-url "$rpc_url" zkevm_verifiedBatchNumber | sed 's/"//g')")" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] Verified Batches: $verified_batches" + + current_time=$(date +%s) + if (( current_time > end_time )); then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ❌ Exiting... Timeout reached!" + exit 1 + fi + + if (( verified_batches > verified_batches_target )); then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✅ Exiting... $verified_batches batches were verified!" + exit 0 + fi + + sleep 10 +done diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6da7ca4b..93a826af 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -48,6 +48,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: '1.21.x' + # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 diff --git a/.github/workflows/deb_packager.yml b/.github/workflows/deb_packager.yml new file mode 100644 index 00000000..3dcb5d52 --- /dev/null +++ b/.github/workflows/deb_packager.yml @@ -0,0 +1,126 @@ +name: deb_packager + +on: + push: + branches: + - 'main' + paths: + - '**' + tags: + - 'v*.*.*' + - 'v*.*.*-*' + +jobs: + build: + permissions: + id-token: write + contents: write + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@master + with: + go-version: 1.22.x + # Variables + - name: Adding TAG to ENV + run: echo "GIT_TAG=`echo $(git describe --tags --abbrev=0)`" >> $GITHUB_ENV + - name: adding version + run: | + NUMERIC_VERSION=$( echo ${{ env.GIT_TAG }} | sed 's/[^0-9.]//g' ) + echo "VERSION=$NUMERIC_VERSION" >> $GITHUB_ENV + + - name: make clean + run: make clean + + - name: build for amd64/x86 + run: make build + + - name: Making directory structure + run: mkdir -p packaging/deb/cdk-data-availability/usr/bin/ + - name: Copying necessary binary file + run: cp -rp dist/cdk-data-availability packaging/deb/cdk-data-availability/usr/bin/ + - name: create directory structure for systemd + run: mkdir -p packaging/deb/cdk-data-availability/lib/systemd/system + - name: copy the service file + run: cp -rp packaging/package_scripts/systemd/cdk-data-availability.service packaging/deb/cdk-data-availability/lib/systemd/system/ + + + # Control file creation + - name: create control file + run: | + echo "Package: cdk-data-availability" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Version: ${{ env.VERSION }}" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Section: base" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Priority: optional" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Architecture: amd64" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Maintainer: devops@polygon.technology" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Description: cdk-data-availability binary package" >> packaging/deb/cdk-data-availability/DEBIAN/control + + - name: Creating package for binary for cdk-data-availability ${{ env.ARCH }} + run: cp -rp packaging/deb/cdk-data-availability packaging/deb/cdk-data-availability-${{ env.GIT_TAG }}-${{ env.ARCH }} + env: + ARCH: amd64 + + - name: Running package build + run: dpkg-deb --build --root-owner-group packaging/deb/cdk-data-availability-${{ env.GIT_TAG }}-${{ env.ARCH }} + env: + ARCH: amd64 + + ### Arm64 setup + - name: prepping environment for arm64 build + run: make clean + + - name: removing amd64 control file + run: rm -rf packaging/deb/cdk-data-availability/DEBIAN/control + + - name: Adding requirements for cross compile + run: sudo apt-get install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu + + - name: build for arm64 + run: GOARCH=arm64 GOOS=linux CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ CGO_ENABLED=1 go build -o dist/cdk-data-availability ./cmd/main.go + + - name: copying necessary files + run: cp -rp dist/cdk-data-availability packaging/deb/cdk-data-availability/usr/bin/ + + - name: create control file + run: | + echo "Package: cdk-data-availability" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Version: ${{ env.VERSION }}" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Section: base" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Priority: optional" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Architecture: arm64" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Maintainer: devops@polygon.technology" >> packaging/deb/cdk-data-availability/DEBIAN/control + echo "Description: cdk-data-availability binary package" >> packaging/deb/cdk-data-availability/DEBIAN/control + + - name: Creating package for binary for cdk-data-availability ${{ env.ARCH }} + run: cp -rp packaging/deb/cdk-data-availability packaging/deb/cdk-data-availability-${{ env.GIT_TAG }}-${{ env.ARCH }} + env: + ARCH: arm64 + + - name: Running package build + run: dpkg-deb --build --root-owner-group packaging/deb/cdk-data-availability-${{ env.GIT_TAG }}-${{ env.ARCH }} + env: + ARCH: arm64 + + - name: create checksum for the amd64 package for cdk-data-availability + run: cd packaging/deb/ && sha256sum cdk-data-availability-${{ env.GIT_TAG }}-${{ env.ARCH }}.deb > cdk-data-availability-${{ env.GIT_TAG }}-${{ env.ARCH }}.deb.checksum + env: + ARCH: amd64 + + - name: create checksum for the arm64 package for cdk-data-availability + run: cd packaging/deb/ && sha256sum cdk-data-availability-${{ env.GIT_TAG }}-${{ env.ARCH }}.deb > cdk-data-availability-${{ env.GIT_TAG }}-${{ env.ARCH }}.deb.checksum + env: + ARCH: arm64 + + - name: Release cdk-data-availability Packages + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ env.GIT_TAG }} + prerelease: true + files: | + packaging/deb/cdk-data-availability**.deb + packaging/deb/cdk-data-availability**.deb.checksum diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5d2d399a..ab17b48e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,10 +15,11 @@ jobs: - name: Install Go uses: actions/setup-go@v3 with: - go-version: 1.19.x + go-version: 1.21.x + cache: false - name: Checkout code uses: actions/checkout@v3 - name: Lint - run: | - make install-linter - make lint + uses: golangci/golangci-lint-action@v6.0.1 + with: + args: --timeout 10m --verbose diff --git a/.github/workflows/regression-tests.yml b/.github/workflows/regression-tests.yml new file mode 100644 index 00000000..2d2a3377 --- /dev/null +++ b/.github/workflows/regression-tests.yml @@ -0,0 +1,49 @@ +name: Regression Tests + +on: + pull_request: + types: [opened, synchronize] # Trigger on new PR and existing with new commits + branches: + - main + +jobs: + deploy_devnet: + runs-on: ubuntu-latest + steps: + - name: Checkout cdk-data-availability + uses: actions/checkout@v4 + with: + path: cdk-data-availability + + - name: Checkout kurtosis-cdk + uses: actions/checkout@v4 + with: + repository: 0xPolygon/kurtosis-cdk + ref: main + path: kurtosis-cdk + + - name: Install Kurtosis CDK tools + uses: ./kurtosis-cdk/.github/actions/setup-kurtosis-cdk + + - name: Build docker image + working-directory: ./cdk-data-availability + run: docker build -t cdk-data-availability:local --file Dockerfile . + + - name: Configure Kurtosis CDK + working-directory: ./kurtosis-cdk + run: | + yq -Y --in-place '.args.data_availability_mode = "cdk-validium"' params.yml + yq -Y --in-place '.args.zkevm_da_image = "cdk-data-availability:local"' params.yml + + - name: Deploy Kurtosis CDK package + working-directory: ./kurtosis-cdk + run: kurtosis run --enclave cdk-v1 --args-file params.yml --image-download always . + + - name: Set executable permissions for the script + working-directory: ./cdk-data-availability + run: sudo chmod +x .github/actions/monitor-cdk-verified-batches/batch_verification_monitor.sh + + - name: Monitor verified batches + working-directory: ./cdk-data-availability + shell: bash + run: .github/actions/monitor-cdk-verified-batches/batch_verification_monitor.sh 19 600 \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..bbb6821a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,43 @@ +name: Release + +on: + push: + tags: + # run only against tags that follow semver (https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string) + - 'v[0-9]+.[0-9]+.[0-9]+*' + - 'v[0-9]+.[0-9]+.[0-9]+*.[0-9]+' + +permissions: + contents: write + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.21.x + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/security-build.yml b/.github/workflows/security-build.yml new file mode 100644 index 00000000..138e33a3 --- /dev/null +++ b/.github/workflows/security-build.yml @@ -0,0 +1,22 @@ +name: Security Build +on: + push: + workflow_dispatch: {} + +jobs: + govuln: + name: Run govuln check and Publish + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Running govulncheck + uses: Templum/govulncheck-action@v0.0.8 + continue-on-error: true + env: + DEBUG: "true" + with: + go-version: 1.21.x + vulncheck-version: latest + package: ./... + github-token: ${{ secrets.GITHUB_TOKEN }} + fail-on-vuln: true diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index f0f58870..9964e95a 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: [ 1.19.x ] + go-version: [ 1.21.x ] goarch: [ "amd64" ] runs-on: ubuntu-latest steps: diff --git a/.github/workflows/test-unit.yml b/.github/workflows/test-unit.yml index 89f6b258..b31e73ab 100644 --- a/.github/workflows/test-unit.yml +++ b/.github/workflows/test-unit.yml @@ -16,7 +16,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: [ 1.19.x ] + go-version: [ 1.21.x ] goarch: [ "amd64" ] runs-on: ubuntu-latest steps: @@ -40,24 +40,24 @@ jobs: name: code-coverage-report path: test/coverage.out - # sonar-cloud: - # needs: test-unit - # name: SonarCloud - # runs-on: ubuntu-latest - # steps: - # - name: Checkout Code - # uses: actions/checkout@v3 - # with: - # submodules: recursive - # fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - # - name: Download code coverage results - # uses: actions/download-artifact@v3 - # with: - # name: code-coverage-report - - # - name: Analyze with SonarCloud - # uses: sonarsource/sonarcloud-github-action@master - # env: - # GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN }} - # SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} +# sonar-cloud: +# needs: test-unit +# name: SonarCloud +# runs-on: ubuntu-latest +# steps: +# - name: Checkout Code +# uses: actions/checkout@v3 +# with: +# submodules: recursive +# fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis +# +# - name: Download code coverage results +# uses: actions/download-artifact@v3 +# with: +# name: code-coverage-report +# +# - name: Analyze with SonarCloud +# uses: sonarsource/sonarcloud-github-action@master +# env: +# GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN }} +# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.gitignore b/.gitignore index cea8f969..2d9e949d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ dist test/gethData test/coverage.out +coverage.out diff --git a/.golangci.yml b/.golangci.yml index 2891a8ba..06fefcfe 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -6,17 +6,33 @@ run: - state/runtime/instrumentation - test - ci + - mocks linters: enable: - - whitespace - - gosec + - whitespace # Tool for detection of leading and trailing whitespace + - gosec # Security problems - gci - - misspell - - gomnd - - gofmt - - goimports + - misspell # Misspelled English words in comments + - mnd + - gofmt # Whether the code was gofmt-ed + - goimports # Unused imports - revive + - wastedassign # Finds wasted assignment statements + - unconvert # Unnecessary type conversions + - prealloc # Finds slice declarations that could potentially be pre-allocated + - predeclared # Finds code that shadows one of Go's predeclared identifiers + - nolintlint # Ill-formed or insufficient nolint directives + - makezero # Finds slice declarations with non-zero initial length + - importas # Enforces consistent import aliases + - dogsled # Checks assignments with too many blank identifiers (e.g. x, , , _, := f()) + - errname # Checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error + - goconst # Repeated strings that could be replaced by a constant + - forcetypeassert # Finds forced type assertions + - tparallel # Detects inappropriate usage of t.Parallel() method in your Go test codes + - thelper # Detects golang test helpers without t.Helper() call and checks the consistency of test helpers + - errcheck # Errcheck is a go lint rule for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases + - lll # Long lines linters-settings: revive: @@ -24,8 +40,16 @@ linters-settings: - name: exported arguments: - disableStutteringCheck + goconst: + min-len: 4 + min-occurrences: 3 issues: + exclude-rules: + - path: _test\.go + linters: + - gosec + - lll include: - EXC0012 # EXC0012 revive: Annoying issue about not having a comment. The rare codebase has such comments - EXC0014 # EXC0014 revive: Annoying issue about not having a comment. The rare codebase has such comments diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 00000000..c5d50a1c --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,82 @@ +# .goreleaser.yaml +project_name: cdk-data-availability + +release: + disable: false + draft: true + prerelease: auto + +before: + hooks: + - go mod download + +builds: + - main: ./cmd/ + binary: cdk-data-availability + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + env: + - CGO_ENABLED=0 + ldflags: + - -s -w + - -X github.com/0xPolygon/cdk-data-availability.Version={{ .Version }} + - -X github.com/0xPolygon/cdk-data-availability.GitRev={{ .Commit }} + - -X github.com/0xPolygon/cdk-data-availability.BuildDate={{ .Date }} + - -X github.com/0xPolygon/cdk-data-availability.GitBranch={{ .Branch }} + +archives: + - files: + - LICENSE + - README.md + +dockers: + - image_templates: + - 0xpolygon/{{ .ProjectName }}:{{ replace .Version "+" "-" }}-amd64 + dockerfile: Dockerfile.release + use: buildx + goos: linux + goarch: amd64 + build_flag_templates: + - --platform=linux/amd64 + - --label=org.opencontainers.image.title={{ .ProjectName }} + - --label=org.opencontainers.image.description={{ .ProjectName }} + - --label=org.opencontainers.image.url=https://github.com/{{ .ProjectName }} + - --label=org.opencontainers.image.source=https://github.com/{{ .ProjectName }} + - --label=org.opencontainers.image.version={{ replace .Version "+" "-" }} + - --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }} + - --label=org.opencontainers.image.revision={{ .FullCommit }} + skip_push: false + + - image_templates: + - 0xpolygon/{{ .ProjectName }}:{{ replace .Version "+" "-" }}-arm64 + dockerfile: Dockerfile.release + use: buildx + goos: linux + goarch: arm64 + build_flag_templates: + - --platform=linux/arm64 + - --label=org.opencontainers.image.title={{ .ProjectName }} + - --label=org.opencontainers.image.description={{ .ProjectName }} + - --label=org.opencontainers.image.url=https://github.com/{{ .ProjectName }} + - --label=org.opencontainers.image.source=https://github.com/{{ .ProjectName }} + - --label=org.opencontainers.image.version={{ replace .Version "+" "-" }} + - --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }} + - --label=org.opencontainers.image.revision={{ .FullCommit }} + skip_push: false + +docker_manifests: + - name_template: 0xpolygon/{{ .ProjectName }}:{{ replace .Version "+" "-" }} + image_templates: + - 0xpolygon/{{ .ProjectName }}:{{ replace .Version "+" "-" }}-amd64 + - 0xpolygon/{{ .ProjectName }}:{{ replace .Version "+" "-" }}-arm64 + skip_push: false + + - name_template: 0xpolygon/{{ .ProjectName }}:latest + image_templates: + - 0xpolygon/{{ .ProjectName }}:{{ replace .Version "+" "-" }}-amd64 + - 0xpolygon/{{ .ProjectName }}:{{ replace .Version "+" "-" }}-arm64 + skip_push: false diff --git a/.mockery.yaml b/.mockery.yaml index 83b1530c..bb55d443 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -36,12 +36,9 @@ packages: SequencerTracker: config: filename: sequencer_tracker.generated.go - github.com/0xPolygon/cdk-data-availability/types: + github.com/0xPolygon/cdk-data-availability/services/status: config: interfaces: - EthClient: + GapsDetector: config: - filename: eth_client.generated.go - EthClientFactory: - config: - filename: eth_client_factory.generated.go \ No newline at end of file + filename: gaps_detector.generated.go diff --git a/Dockerfile b/Dockerfile index 7f3401e2..ac292bbb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,21 @@ # CONTAINER FOR BUILDING BINARY -FROM golang:1.19 AS build +FROM golang:1.21 AS build + +WORKDIR $GOPATH/src/github.com/0xPolygon/cdk-data-availability # INSTALL DEPENDENCIES -RUN go install github.com/gobuffalo/packr/v2/packr2@v2.8.3 -COPY go.mod go.sum /src/ -WORKDIR /src +COPY go.mod go.sum ./ RUN go mod download # BUILD BINARY -COPY . /src - -WORKDIR /src/db -RUN packr2 - -WORKDIR /src +COPY . . RUN make build # CONTAINER FOR RUNNING BINARY FROM alpine:3.16.0 -COPY --from=build /src/dist/xlayer-data-availability /app/xlayer-data-availability + +COPY --from=build /go/src/github.com/0xPolygon/cdk-data-availability/dist/xlayer-data-availability /app/xlayer-data-availability + EXPOSE 8444 + CMD ["/bin/sh", "-c", "/app/xlayer-data-availability run"] diff --git a/Dockerfile.release b/Dockerfile.release new file mode 100644 index 00000000..9cd67527 --- /dev/null +++ b/Dockerfile.release @@ -0,0 +1,12 @@ +FROM alpine:3.18 + +EXPOSE 8444 + +COPY cdk-data-availability /app/cdk-data-availability + +RUN addgroup -S cdk-dac-group \ + && adduser -S cdk-dac-user -G cdk-dac-group + +USER cdk-dac-user + +CMD ["/app/cdk-data-availability"] diff --git a/LICENSE b/LICENSE index 5422d2fe..59983b12 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Polygon zkEVM Mainnet Beta +CDK Data Availability Layer Copyright (C) 2023 Catenable AG This program is free software: you can redistribute it and/or modify it diff --git a/Makefile b/Makefile index c4cfaa33..d179b566 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,11 @@ ifndef CHECK_DOCKER $(error "Docker is not installed. Please install Docker and retry.") endif +clean: + env GO111MODULE=on go clean -cache + rm -fr build/_workspace/pkg/ $(GOBIN)/* + + # Targets that require the checks generate: check-go build: check-go @@ -74,7 +79,7 @@ build-docker-nc: ## Builds a docker image with the node binary - but without bui .PHONY: install-linter install-linter: ## Installs the linter - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.52.2 + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.59.1 .PHONY: lint lint: ## Runs the linter diff --git a/README.md b/README.md index 4ac0763a..a007fe11 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,23 @@ -# XLayer Data Availability +# X Layer CDK Data Availability -### Data Availability Layer for XLayer Validium +### Data Availability Layer for CDK Validium -The xlayer-data-availability project is a specialized Data Availability Node (DA Node) that is part of XLayer's CDK (Chain Development Kit) Validium. +The xlayer-data-availability project is a specialized Data Availability Node (DA Node) that is part of Polygon's CDK (Chain Development Kit) Validium. ## Overview of Validium -The XLayer Validium solution is made up of several components; start with the [XLayer Node](https://github.com/okx/xlayer-node). For quick reference, the complete list of components are outlined below: + +For a full overview of the Polygon CDK Validium, please reference the [CDK documentation](https://wiki.polygon.technology/docs/cdk/). + +The CDK Validium solution is made up of several components; start with the [CDK Validium Node](https://github.com/0xPolygon/cdk-validium-node). For quick reference, the complete list of components are outlined below: | Component | Description | | ----------------------------------------------------------------------------- | -------------------------------------------------------------------- | -| [XLayer Node](https://github.com/okx/xlayer-node) | Node implementation for the XLayer networks in Validium mode | -| [XLayer Contracts](https://github.com/okx/xlayer-contracts) | Smart contract implementation for the XLayer networks in Validium mode | -| [XLayer Data Availability](https://github.com/okx/xlayer-data-availability) | Data availability implementation for the XLayer networks | -| [Prover / Executor](https://github.com/okx/xlayer-prover) | zkEVM engine and prover implementation | -| [Bridge Service](https://github.com/okx/xlayer-bridge-service) | Bridge service implementation for XLayer networks | +| [CDK Validium Node](https://github.com/0xPolygon/cdk-validium-node) | Node implementation for the CDK networks in Validium mode | +| [CDK Validium Contracts](https://github.com/0xPolygon/cdk-validium-contracts) | Smart contract implementation for the CDK networks in Validium mode | +| [CDK Data Availability](https://github.com/0xPolygon/cdk-data-availability) | Data availability implementation for the CDK networks | +| [Prover / Executor](https://github.com/0xPolygonHermez/zkevm-prover) | zkEVM engine and prover implementation | +| [Bridge Service](https://github.com/0xPolygonHermez/zkevm-bridge-service) | Bridge service implementation for CDK networks | +| [Bridge UI](https://github.com/0xPolygonHermez/zkevm-bridge-ui) | UI for the CDK networks bridge | --- @@ -21,18 +25,23 @@ The XLayer Validium solution is made up of several components; start with the [X As blockchain networks grow, the volume of data that needs to be stored and validated increases, posing challenges in scalability and efficiency. Storing all data on-chain can lead to bloated blockchains, slow transactions, and high fees. -Data Availability Nodes facilitate a separation between transaction execution and data storage. They allow transaction data to reside off-chain while remaining accessible for validation. This significantly improves scalability and reduces costs. Within the framework of XLayer's CDK, Data Availability Committees (DAC) members run DA nodes to ensure the security, accessibility, and reliability of off-chain data. +Data Availability Nodes facilitate a separation between transaction execution and data storage. They allow transaction data to reside off-chain while remaining accessible for validation. This significantly improves scalability and reduces costs. Within the framework of Polygon's CDK, Data Availability Committees (DAC) members run DA nodes to ensure the security, accessibility, and reliability of off-chain data. To learn more about how the data availability layer works in the validium, please see the CDK documentation [here](https://wiki.polygon.technology/docs/cdk/dac-overview/). ### Off-Chain Data -The off-chain data is stored in a distributed manner and managed by a data availability committee, ensuring that it is available for validation. The data availability committee is defined as a core smart contract, available [here](https://github.com/okx/xlayer-contracts/blob/main/contracts/DataCommittee.sol). This is crucial for the Validium model, where data computation happens off-chain but needs to be verifiable on-chain. +The off-chain data is stored in a distributed manner and managed by a data availability committee, ensuring that it is available for validation. The data availability committee is defined as a core smart contract, available [here](https://github.com/0xPolygon/cdk-validium-contracts/blob/main/contracts/CDKDataCommittee.sol). This is crucial for the Validium model, where data computation happens off-chain but needs to be verifiable on-chain. ### Running Instructions on how to run this software can be found [here](./docs/running.md) +## Contact + +For more discussions, please head to the [R&D Discord](https://discord.gg/0xPolygonRnD) + + ## License -The xlayer-node project is licensed under the [GNU Affero General Public License](LICENSE) free software license. +The cdk-validium-node project is licensed under the [GNU Affero General Public License](LICENSE) free software license. diff --git a/client/client.go b/client/client.go index fe26b194..1d33d948 100644 --- a/client/client.go +++ b/client/client.go @@ -17,8 +17,11 @@ type Factory interface { // Client is the interface that defines the implementation of all the endpoints type Client interface { + GetStatus(ctx context.Context) (*types.DACStatus, error) GetOffChainData(ctx context.Context, hash common.Hash) ([]byte, error) - SignSequence(signedSequence types.SignedSequence) ([]byte, error) + ListOffChainData(ctx context.Context, hashes []common.Hash) (map[common.Hash][]byte, error) + SignSequence(ctx context.Context, signedSequence types.SignedSequence) ([]byte, error) + SignSequenceBanana(ctx context.Context, signedSequence types.SignedSequenceBanana) ([]byte, error) } // factory is the implementation of the data committee client factory @@ -46,10 +49,49 @@ func New(url string) Client { } } +// GetStatus returns DAC status +func (c *client) GetStatus(ctx context.Context) (*types.DACStatus, error) { + response, err := rpc.JSONRPCCallWithContext(ctx, c.url, "status_getStatus") + if err != nil { + return nil, err + } + + if response.Error != nil { + return nil, fmt.Errorf("%v %v", response.Error.Code, response.Error.Message) + } + + var result types.DACStatus + if err = json.Unmarshal(response.Result, &result); err != nil { + return nil, err + } + + return &result, nil +} + // SignSequence sends a request to sign the given sequence by the data committee member // if successful returns the signature. The signature should be validated after using this method! -func (c *client) SignSequence(signedSequence types.SignedSequence) ([]byte, error) { - response, err := rpc.JSONRPCCall(c.url, "datacom_signSequence", signedSequence) +func (c *client) SignSequence(ctx context.Context, signedSequence types.SignedSequence) ([]byte, error) { + response, err := rpc.JSONRPCCallWithContext(ctx, c.url, "datacom_signSequence", signedSequence) + if err != nil { + return nil, err + } + + if response.Error != nil { + return nil, fmt.Errorf("%v %v", response.Error.Code, response.Error.Message) + } + + var result types.ArgBytes + if err = json.Unmarshal(response.Result, &result); err != nil { + return nil, err + } + + return result, nil +} + +// SignSequenceBanana sends a request to sign the given sequence by the data committee member +// if successful returns the signature. The signature should be validated after using this method! +func (c *client) SignSequenceBanana(ctx context.Context, signedSequence types.SignedSequenceBanana) ([]byte, error) { + response, err := rpc.JSONRPCCallWithContext(ctx, c.url, "datacom_signSequenceBanana", signedSequence) if err != nil { return nil, err } @@ -84,3 +126,27 @@ func (c *client) GetOffChainData(ctx context.Context, hash common.Hash) ([]byte, return result, nil } + +// ListOffChainData returns data based on the given hashes +func (c *client) ListOffChainData(ctx context.Context, hashes []common.Hash) (map[common.Hash][]byte, error) { + response, err := rpc.JSONRPCCallWithContext(ctx, c.url, "sync_listOffChainData", hashes) + if err != nil { + return nil, err + } + + if response.Error != nil { + return nil, fmt.Errorf("%v %v", response.Error.Code, response.Error.Message) + } + + result := make(map[common.Hash]types.ArgBytes) + if err = json.Unmarshal(response.Result, &result); err != nil { + return nil, err + } + + preparedResult := make(map[common.Hash][]byte) + for key, val := range result { + preparedResult[key] = val + } + + return preparedResult, nil +} diff --git a/client/client_test.go b/client/client_test.go index 2eb73530..72114843 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -16,7 +16,74 @@ import ( "github.com/stretchr/testify/require" ) +func TestClient_GetStatus(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + result string + status *types.DACStatus + statusCode int + err error + }{ + { + name: "successfully got status", + result: `{"result":{"version":"v1.0.0","uptime":"123","key_count":2,"backfill_progress":5}}`, + status: &types.DACStatus{ + Uptime: "123", + Version: "v1.0.0", + KeyCount: 2, + BackfillProgress: 5, + }, + }, + { + name: "error returned by server", + result: `{"error":{"code":123,"message":"test error"}}`, + err: errors.New("123 test error"), + }, + { + name: "unsuccessful status code returned by server", + statusCode: http.StatusInternalServerError, + err: errors.New("invalid status code, expected: 200, found: 500"), + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var res rpc.Request + require.NoError(t, json.NewDecoder(r.Body).Decode(&res)) + require.Equal(t, "status_getStatus", res.Method) + + if tt.statusCode > 0 { + w.WriteHeader(tt.statusCode) + } + + _, err := fmt.Fprint(w, tt.result) + require.NoError(t, err) + })) + defer srv.Close() + + client := New(srv.URL) + + got, err := client.GetStatus(context.Background()) + if tt.err != nil { + require.Error(t, err) + require.EqualError(t, tt.err, err.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.status, got) + } + }) + } +} + func TestClient_SignSequence(t *testing.T) { + t.Parallel() + tests := []struct { name string ss types.SignedSequence @@ -87,7 +154,7 @@ func TestClient_SignSequence(t *testing.T) { client := New(srv.URL) - got, err := client.SignSequence(tt.ss) + got, err := client.SignSequence(context.Background(), tt.ss) if tt.err != nil { require.Error(t, err) require.EqualError(t, tt.err, err.Error()) @@ -100,6 +167,8 @@ func TestClient_SignSequence(t *testing.T) { } func TestClient_GetOffChainData(t *testing.T) { + t.Parallel() + tests := []struct { name string hash common.Hash @@ -169,3 +238,182 @@ func TestClient_GetOffChainData(t *testing.T) { }) } } + +func TestClient_ListOffChainData(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + hashes []common.Hash + result string + data map[common.Hash][]byte + statusCode int + err error + }{ + { + name: "successfully got offhcain data", + hashes: []common.Hash{common.BytesToHash([]byte("hash"))}, + result: fmt.Sprintf(`{"result":{"%s":"%s"}}`, + common.BytesToHash([]byte("hash")).Hex(), hex.EncodeToString([]byte("offchaindata"))), + data: map[common.Hash][]byte{ + common.BytesToHash([]byte("hash")): []byte("offchaindata"), + }, + }, + { + name: "error returned by server", + hashes: []common.Hash{common.BytesToHash([]byte("hash"))}, + result: `{"error":{"code":123,"message":"test error"}}`, + err: errors.New("123 test error"), + }, + { + name: "invalid offchain data returned by server", + hashes: []common.Hash{common.BytesToHash([]byte("hash"))}, + result: fmt.Sprintf(`{"result":{"%s":"invalid-signature"}}`, + common.BytesToHash([]byte("hash")).Hex()), + data: map[common.Hash][]byte{ + common.BytesToHash([]byte("hash")): nil, + }, + }, + { + name: "unsuccessful status code returned by server", + hashes: []common.Hash{common.BytesToHash([]byte("hash"))}, + statusCode: http.StatusUnauthorized, + err: errors.New("invalid status code, expected: 200, found: 401"), + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var res rpc.Request + require.NoError(t, json.NewDecoder(r.Body).Decode(&res)) + require.Equal(t, "sync_listOffChainData", res.Method) + + var params [][]common.Hash + require.NoError(t, json.Unmarshal(res.Params, ¶ms)) + require.Equal(t, tt.hashes, params[0]) + + if tt.statusCode > 0 { + w.WriteHeader(tt.statusCode) + } + + _, err := fmt.Fprint(w, tt.result) + require.NoError(t, err) + })) + defer svr.Close() + + c := &client{url: svr.URL} + + got, err := c.ListOffChainData(context.Background(), tt.hashes) + if tt.err != nil { + require.Error(t, err) + require.EqualError(t, tt.err, err.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.data, got) + } + }) + } +} + +func TestClient_SignSequenceBanana(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + ssb types.SignedSequenceBanana + result string + signature []byte + statusCode int + err error + }{ + { + name: "successfully signed banana sequence", + ssb: types.SignedSequenceBanana{ + Sequence: types.SequenceBanana{}, + Signature: []byte("signature00"), + }, + result: fmt.Sprintf(`{"result":"%s"}`, hex.EncodeToString([]byte("signature11"))), + signature: []byte("signature11"), + }, + { + name: "error returned by rpc server", + ssb: types.SignedSequenceBanana{ + Sequence: types.SequenceBanana{}, + Signature: []byte("signature00"), + }, + result: `{"error":{"code":123,"message":"test error"}}`, + err: errors.New("123 test error"), + }, + { + name: "invalid signature returned by rpc server", + ssb: types.SignedSequenceBanana{ + Sequence: types.SequenceBanana{}, + Signature: []byte("signature00"), + }, + result: `{"result":"invalid-signature"}`, + }, + { + name: "unsuccessful status code returned by rpc server", + ssb: types.SignedSequenceBanana{ + Sequence: types.SequenceBanana{}, + Signature: []byte("signature00"), + }, + statusCode: http.StatusInternalServerError, + err: errors.New("invalid status code, expected: 200, found: 500"), + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var request rpc.Request + require.NoError(t, json.NewDecoder(r.Body).Decode(&request)) + require.Equal(t, "datacom_signSequenceBanana", request.Method) + + var params []types.SignedSequenceBanana + require.NoError(t, json.Unmarshal(request.Params, ¶ms)) + require.Equal(t, tt.ssb, params[0]) + + if tt.statusCode > 0 { + w.WriteHeader(tt.statusCode) + } + + _, err := fmt.Fprint(w, tt.result) + require.NoError(t, err) + })) + defer srv.Close() + + client := New(srv.URL) + + result, err := client.SignSequenceBanana(context.Background(), tt.ssb) + if tt.err != nil { + require.Error(t, err) + require.EqualError(t, tt.err, err.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.signature, result) + } + }) + } +} + +func TestClient_Factory_New(t *testing.T) { + t.Parallel() + + url := "http://example.com" + f := NewFactory() + + c := f.New(url) + require.NotNil(t, c) + + client, ok := c.(*client) + require.True(t, ok) + require.Equal(t, url, client.url) +} diff --git a/cmd/main.go b/cmd/main.go index 1c765df6..52befafc 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -16,15 +16,16 @@ import ( "github.com/0xPolygon/cdk-data-availability/rpc" "github.com/0xPolygon/cdk-data-availability/sequencer" "github.com/0xPolygon/cdk-data-availability/services/datacom" + "github.com/0xPolygon/cdk-data-availability/services/status" "github.com/0xPolygon/cdk-data-availability/services/sync" "github.com/0xPolygon/cdk-data-availability/synchronizer" - "github.com/0xPolygon/cdk-data-availability/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" _ "github.com/lib/pq" "github.com/urfave/cli/v2" ) -const appName = "xlayer-data-availability" //nolint:gosec +const appName = "xlayer-data-availability" var ( configFileFlag = cli.StringFlag{ @@ -47,6 +48,16 @@ func main() { Action: start, Flags: []cli.Flag{&configFileFlag}, }, + { + Name: "version", + Aliases: []string{}, + Usage: "Show version", + Action: func(c *cli.Context) error { + dataavailability.PrintVersion(os.Stderr) + return nil + }, + Flags: []cli.Flag{&configFileFlag}, + }, } err := app.Run(os.Args) @@ -64,6 +75,8 @@ func start(cliCtx *cli.Context) error { } setupLog(c.Log) + log.Infof("Starting application...\n%s", dataavailability.GetVersionInfo()) + // Prepare DB pg, err := db.InitContext(cliCtx.Context, c.DB) if err != nil { @@ -74,7 +87,10 @@ func start(cliCtx *cli.Context) error { log.Fatal(err) } - storage := db.New(pg) + storage, err := db.New(cliCtx.Context, pg) + if err != nil { + log.Fatal(err) + } // Load private key pk, err := config.NewKeyFromKeystore(c.PrivateKey) @@ -88,67 +104,71 @@ func start(cliCtx *cli.Context) error { log.Fatal(err) } - // derive address - selfAddr := crypto.PubkeyToAddress(pk.PublicKey) - // ensure synchro/reorg start block is set - err = synchronizer.InitStartBlock(storage, types.NewEthClientFactory(), c.L1) + err = synchronizer.InitStartBlock( + cliCtx.Context, + storage, + etm, + c.L1.GenesisBlock, + common.HexToAddress(c.L1.PolygonValidiumAddress), + ) if err != nil { log.Fatal(err) } var cancelFuncs []context.CancelFunc - log.Infof("cfg PolygonValidiumAddress:%v, DataCommitteeAddress:%v", c.L1.PolygonValidiumAddress, c.L1.DataCommitteeAddress) - sequencerTracker, err := sequencer.NewTracker(c.L1, etm) - if err != nil { - log.Fatal(err) - } + sequencerTracker := sequencer.NewTracker(c.L1, etm) go sequencerTracker.Start(cliCtx.Context) cancelFuncs = append(cancelFuncs, sequencerTracker.Stop) - detector, err := synchronizer.NewReorgDetector(c.L1.RpcURL, 1*time.Second) + detector, err := synchronizer.NewReorgDetector(c.L1.RpcURL, time.Second) if err != nil { log.Fatal(err) } - err = detector.Start() - if err != nil { + if err = detector.Start(cliCtx.Context); err != nil { log.Fatal(err) } cancelFuncs = append(cancelFuncs, detector.Stop) - batchSynchronizer, err := synchronizer.NewBatchSynchronizer(c.L1, selfAddr, - storage, detector.Subscribe(), etm, sequencerTracker, client.NewFactory()) + batchSynchronizer, err := synchronizer.NewBatchSynchronizer( + c.L1, + crypto.PubkeyToAddress(pk.PublicKey), + storage, + detector.Subscribe(), + etm, + sequencerTracker, + client.NewFactory(), + ) if err != nil { log.Fatal(err) } - go batchSynchronizer.Start() + go batchSynchronizer.Start(cliCtx.Context) cancelFuncs = append(cancelFuncs, batchSynchronizer.Stop) // Register services server := rpc.NewServer( c.RPC, []rpc.Service{ + { + Name: status.APISTATUS, + Service: status.NewEndpoints(storage, batchSynchronizer), + }, { Name: sync.APISYNC, - Service: sync.NewSyncEndpoints(storage), + Service: sync.NewEndpoints(storage), }, { - Name: datacom.APIDATACOM, - Service: datacom.NewDataComEndpoints( - storage, - pk, - sequencerTracker, - c.PermitApiAddress, - ), + Name: datacom.APIDATACOM, + Service: datacom.NewEndpoints(storage, pk, sequencerTracker, common.Address{}), }, }, ) // Run! - if err := server.Start(); err != nil { + if err = server.Start(); err != nil { log.Fatal(err) } diff --git a/config/config.go b/config/config.go index bfff7482..4327c771 100644 --- a/config/config.go +++ b/config/config.go @@ -35,13 +35,17 @@ type Config struct { // L1Config is a struct that defines L1 contract and service settings type L1Config struct { - WsURL string `mapstructure:"WsURL"` - RpcURL string `mapstructure:"RpcURL"` - PolygonValidiumAddress string `mapstructure:"PolygonValidiumAddress"` - DataCommitteeAddress string `mapstructure:"DataCommitteeAddress"` - Timeout types.Duration `mapstructure:"Timeout"` - RetryPeriod types.Duration `mapstructure:"RetryPeriod"` - BlockBatchSize uint `mapstructure:"BlockBatchSize"` + RpcURL string `mapstructure:"RpcURL"` + PolygonValidiumAddress string `mapstructure:"PolygonValidiumAddress"` + DataCommitteeAddress string `mapstructure:"DataCommitteeAddress"` + Timeout types.Duration `mapstructure:"Timeout"` + RetryPeriod types.Duration `mapstructure:"RetryPeriod"` + BlockBatchSize uint `mapstructure:"BlockBatchSize"` + TrackSequencer bool `mapstructure:"TrackSequencer"` + TrackSequencerPollInterval types.Duration `mapstructure:"TrackSequencerPollInterval"` + + // GenesisBlock represents the block number where PolygonValidium contract is deployed on L1 + GenesisBlock uint64 `mapstructure:"GenesisBlock"` } // Load loads the configuration baseed on the cli context @@ -74,7 +78,12 @@ func Load(ctx *cli.Context) (*Config, error) { decodeHooks := []viper.DecoderConfigOption{ // this allows arrays to be decoded from env var separated by ",", example: MY_VAR="value1,value2,value3" - viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(mapstructure.TextUnmarshallerHookFunc(), mapstructure.StringToSliceHookFunc(","))), + viper.DecodeHook( + mapstructure.ComposeDecodeHookFunc( + mapstructure.TextUnmarshallerHookFunc(), + mapstructure.StringToSliceHookFunc(","), + ), + ), } err = viper.Unmarshal(&cfg, decodeHooks...) return cfg, err diff --git a/config/config_test.go b/config/config_test.go index d032ed85..8f84d3ef 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -20,17 +20,13 @@ func Test_Defaults(t *testing.T) { path string expectedValue interface{} }{ - { - path: "L1.WsURL", - expectedValue: "ws://127.0.0.1:8546", - }, { path: "L1.RpcURL", - expectedValue: "http://127.0.0.1:8545", + expectedValue: "ws://127.0.0.1:8546", }, { path: "L1.PolygonValidiumAddress", - expectedValue: "0x975725832B4909Aab87D3604A0b501569dbBE7A9", + expectedValue: "0x8dAF17A20c9DBA35f005b6324F493785D239719d", }, { path: "L1.Timeout", @@ -90,6 +86,59 @@ func Test_ConfigFileOverride(t *testing.T) { require.Equal(t, "0xDEADBEEF", cfg.L1.PolygonValidiumAddress) } +func Test_NewKeyFromKeystore(t *testing.T) { + t.Parallel() + + t.Run("valid keystore file", func(t *testing.T) { + t.Parallel() + + cfg := types.KeystoreFileConfig{ + Path: "../test/config/test-member.keystore", + Password: "testonly", + } + + key, err := NewKeyFromKeystore(cfg) + require.NoError(t, err) + require.NotNil(t, key) + }) + + t.Run("no path and password", func(t *testing.T) { + t.Parallel() + + cfg := types.KeystoreFileConfig{} + + key, err := NewKeyFromKeystore(cfg) + require.NoError(t, err) + require.Nil(t, key) + }) + + t.Run("invalid keystore file", func(t *testing.T) { + t.Parallel() + + cfg := types.KeystoreFileConfig{ + Path: "non-existent.keystore", + Password: "testonly", + } + + key, err := NewKeyFromKeystore(cfg) + require.ErrorContains(t, err, "no such file or directory") + require.Nil(t, key) + }) + + t.Run("invalid password", func(t *testing.T) { + t.Parallel() + + cfg := types.KeystoreFileConfig{ + Path: "../test/config/test-member.keystore", + Password: "invalid", + } + + key, err := NewKeyFromKeystore(cfg) + require.ErrorContains(t, err, "could not decrypt key with given password") + require.Nil(t, key) + }) +} + func getValueFromStruct(path string, object interface{}) interface{} { keySlice := strings.Split(path, ".") v := reflect.ValueOf(object) diff --git a/config/default.go b/config/default.go index 0ab619f0..e824204c 100644 --- a/config/default.go +++ b/config/default.go @@ -13,13 +13,15 @@ PrivateKey = {Path = "/pk/test-member.keystore", Password = "testonly"} PermitApiAddress = "0x0000000000000000000000000000000000000000" [L1] -WsURL = "ws://127.0.0.1:8546" -RpcURL = "http://127.0.0.1:8545" -PolygonValidiumAddress = "0x975725832B4909Aab87D3604A0b501569dbBE7A9" -DataCommitteeAddress = "0x2f08F654B896208dD968aFdAEf733edC5FF62c03" +RpcURL = "ws://127.0.0.1:8546" +PolygonValidiumAddress = "0x8dAF17A20c9DBA35f005b6324F493785D239719d" +DataCommitteeAddress = "0x68B1D87F95878fE05B998F19b66F4baba5De1aed" Timeout = "1m" RetryPeriod = "5s" BlockBatchSize = "64" +GenesisBlock = "0" +TrackSequencer = true +TrackSequencerPollInterval = "1m" [Log] Environment = "development" # "production" or "development" @@ -30,7 +32,7 @@ Outputs = ["stderr"] User = "committee_user" Password = "committee_password" Name = "committee_db" -Host = "xlayer-data-availability-db" +Host = "cdk-data-availability-db" Port = "5432" EnableLog = false MaxConns = 200 diff --git a/db/db.go b/db/db.go index db1aad18..c4e4bed8 100644 --- a/db/db.go +++ b/db/db.go @@ -3,14 +3,66 @@ package db import ( "context" "database/sql" - "database/sql/driver" "errors" + "fmt" + "strings" "github.com/0xPolygon/cdk-data-availability/types" "github.com/ethereum/go-ethereum/common" "github.com/jmoiron/sqlx" ) +const ( + // storeLastProcessedBlockSQL is a query that stores the last processed block for a given task + storeLastProcessedBlockSQL = ` + INSERT INTO data_node.sync_tasks (task, block) + VALUES ($1, $2) + ON CONFLICT (task) DO UPDATE + SET block = EXCLUDED.block, processed = NOW();` + + // getLastProcessedBlockSQL is a query that returns the last processed block for a given task + getLastProcessedBlockSQL = `SELECT block FROM data_node.sync_tasks WHERE task = $1;` + + // getUnresolvedBatchKeysSQL is a query that returns the unresolved batch keys from the database + getUnresolvedBatchKeysSQL = `SELECT num, hash FROM data_node.unresolved_batches LIMIT $1;` + + // getOffchainDataSQL is a query that returns the offchain data for a given key + getOffchainDataSQL = ` + SELECT key, value, batch_num + FROM data_node.offchain_data + WHERE key = $1 LIMIT 1; + ` + + // listOffchainDataSQL is a query that returns the offchain data for a given list of keys + listOffchainDataSQL = ` + SELECT key, value, batch_num + FROM data_node.offchain_data + WHERE key IN (?); + ` + + // countOffchainDataSQL is a query that returns the count of rows in the offchain_data table + countOffchainDataSQL = "SELECT COUNT(*) FROM data_node.offchain_data;" + + // selectOffchainDataGapsSQL is a query that returns the gaps in the offchain_data table + selectOffchainDataGapsSQL = ` + WITH numbered_batches AS ( + SELECT + batch_num, + ROW_NUMBER() OVER (ORDER BY batch_num) AS row_number + FROM data_node.offchain_data + ) + SELECT + nb1.batch_num AS current_batch_num, + nb2.batch_num AS next_batch_num + FROM + numbered_batches nb1 + LEFT JOIN numbered_batches nb2 ON nb1.row_number = nb2.row_number - 1 + WHERE + nb1.batch_num IS NOT NULL + AND nb2.batch_num IS NOT NULL + AND nb1.batch_num + 1 <> nb2.batch_num;` +) + var ( // ErrStateNotSynchronized indicates the state database may be empty ErrStateNotSynchronized = errors.New("state not synchronized") @@ -18,123 +70,326 @@ var ( // DB defines functions that a DB instance should implement type DB interface { - BeginStateTransaction(ctx context.Context) (Tx, error) - Exists(ctx context.Context, key common.Hash) bool + StoreLastProcessedBlock(ctx context.Context, block uint64, task string) error GetLastProcessedBlock(ctx context.Context, task string) (uint64, error) - GetOffChainData(ctx context.Context, key common.Hash, dbTx sqlx.QueryerContext) (types.ArgBytes, error) - StoreLastProcessedBlock(ctx context.Context, task string, block uint64, dbTx sqlx.ExecerContext) error - StoreOffChainData(ctx context.Context, od []types.OffChainData, dbTx sqlx.ExecerContext) error -} -// Tx is the interface that defines functions a db tx has to implement -type Tx interface { - sqlx.ExecerContext - sqlx.QueryerContext - driver.Tx + StoreUnresolvedBatchKeys(ctx context.Context, bks []types.BatchKey) error + GetUnresolvedBatchKeys(ctx context.Context, limit uint) ([]types.BatchKey, error) + DeleteUnresolvedBatchKeys(ctx context.Context, bks []types.BatchKey) error + + GetOffChainData(ctx context.Context, key common.Hash) (*types.OffChainData, error) + ListOffChainData(ctx context.Context, keys []common.Hash) ([]types.OffChainData, error) + StoreOffChainData(ctx context.Context, od []types.OffChainData) error + CountOffchainData(ctx context.Context) (uint64, error) + DetectOffchainDataGaps(ctx context.Context) (map[uint64]uint64, error) } // DB is the database layer of the data node type pgDB struct { pg *sqlx.DB + + storeLastProcessedBlockStmt *sqlx.Stmt + getLastProcessedBlockStmt *sqlx.Stmt + getUnresolvedBatchKeysStmt *sqlx.Stmt + getOffChainDataStmt *sqlx.Stmt + countOffChainDataStmt *sqlx.Stmt + detectOffChainDataGapsStmt *sqlx.Stmt } // New instantiates a DB -func New(pg *sqlx.DB) DB { +func New(ctx context.Context, pg *sqlx.DB) (DB, error) { + storeLastProcessedBlockStmt, err := pg.PreparexContext(ctx, storeLastProcessedBlockSQL) + if err != nil { + return nil, fmt.Errorf("failed to prepare the store last processed block statement: %w", err) + } + + getLastProcessedBlockStmt, err := pg.PreparexContext(ctx, getLastProcessedBlockSQL) + if err != nil { + return nil, fmt.Errorf("failed to prepare the get last processed block statement: %w", err) + } + + getUnresolvedBatchKeysStmt, err := pg.PreparexContext(ctx, getUnresolvedBatchKeysSQL) + if err != nil { + return nil, fmt.Errorf("failed to prepare the get unresolved batch keys statement: %w", err) + } + + getOffChainDataStmt, err := pg.PreparexContext(ctx, getOffchainDataSQL) + if err != nil { + return nil, fmt.Errorf("failed to prepare the get offchain data statement: %w", err) + } + + countOffChainDataStmt, err := pg.PreparexContext(ctx, countOffchainDataSQL) + if err != nil { + return nil, fmt.Errorf("failed to prepare the count offchain data statement: %w", err) + } + + detectOffChainDataGapsStmt, err := pg.PreparexContext(ctx, selectOffchainDataGapsSQL) + if err != nil { + return nil, fmt.Errorf("failed to prepare the detect offchain data gaps statement: %w", err) + } + return &pgDB{ - pg: pg, + pg: pg, + storeLastProcessedBlockStmt: storeLastProcessedBlockStmt, + getLastProcessedBlockStmt: getLastProcessedBlockStmt, + getUnresolvedBatchKeysStmt: getUnresolvedBatchKeysStmt, + getOffChainDataStmt: getOffChainDataStmt, + countOffChainDataStmt: countOffChainDataStmt, + detectOffChainDataGapsStmt: detectOffChainDataGapsStmt, + }, nil +} + +// StoreLastProcessedBlock stores a record of a block processed by the synchronizer for named task +func (db *pgDB) StoreLastProcessedBlock(ctx context.Context, block uint64, task string) error { + _, err := db.storeLastProcessedBlockStmt.ExecContext(ctx, task, block) + return err +} + +// GetLastProcessedBlock returns the latest block successfully processed by the synchronizer for named task +func (db *pgDB) GetLastProcessedBlock(ctx context.Context, task string) (uint64, error) { + var lastBlock uint64 + + if err := db.getLastProcessedBlockStmt.QueryRowContext(ctx, task).Scan(&lastBlock); err != nil { + return 0, err } + + return lastBlock, nil } -// BeginStateTransaction begins a DB transaction. The caller is responsible for committing or rolling back the transaction -func (db *pgDB) BeginStateTransaction(ctx context.Context) (Tx, error) { - return db.pg.BeginTxx(ctx, nil) +// StoreUnresolvedBatchKeys stores unresolved batch keys in the database +func (db *pgDB) StoreUnresolvedBatchKeys(ctx context.Context, bks []types.BatchKey) error { + if len(bks) == 0 { + return nil + } + + query, args := buildBatchKeysInsertQuery(bks) + + if _, err := db.pg.ExecContext(ctx, query, args...); err != nil { + return fmt.Errorf("failed to store unresolved batches: %w", err) + } + + return nil } -// StoreOffChainData stores and array of key values in the Db -func (db *pgDB) StoreOffChainData(ctx context.Context, od []types.OffChainData, dbTx sqlx.ExecerContext) error { - const storeOffChainDataSQL = ` - INSERT INTO data_node.offchain_data (key, value) - VALUES ($1, $2) - ON CONFLICT (key) DO NOTHING; - ` +// GetUnresolvedBatchKeys returns the unresolved batch keys from the database +func (db *pgDB) GetUnresolvedBatchKeys(ctx context.Context, limit uint) ([]types.BatchKey, error) { + rows, err := db.getUnresolvedBatchKeysStmt.QueryxContext(ctx, limit) + if err != nil { + return nil, err + } + + defer rows.Close() - for _, d := range od { - if _, err := dbTx.ExecContext( - ctx, storeOffChainDataSQL, - d.Key.Hex(), - common.Bytes2Hex(d.Value), - ); err != nil { - return err + type row struct { + Number uint64 `db:"num"` + Hash string `db:"hash"` + } + + var bks []types.BatchKey + for rows.Next() { + bk := row{} + if err = rows.StructScan(&bk); err != nil { + return nil, err } + + bks = append(bks, types.BatchKey{ + Number: bk.Number, + Hash: common.HexToHash(bk.Hash), + }) + } + + return bks, nil +} + +// DeleteUnresolvedBatchKeys deletes the unresolved batch keys from the database +func (db *pgDB) DeleteUnresolvedBatchKeys(ctx context.Context, bks []types.BatchKey) error { + if len(bks) == 0 { + return nil + } + + const columnsAffected = 2 + + args := make([]interface{}, len(bks)*columnsAffected) + values := make([]string, len(bks)) + for i, bk := range bks { + values[i] = fmt.Sprintf("($%d, $%d)", i*columnsAffected+1, i*columnsAffected+2) //nolint:mnd + args[i*columnsAffected] = bk.Number + args[i*columnsAffected+1] = bk.Hash.Hex() + } + + query := fmt.Sprintf(` + DELETE FROM data_node.unresolved_batches WHERE (num, hash) IN (%s); + `, strings.Join(values, ",")) + + if _, err := db.pg.ExecContext(ctx, query, args...); err != nil { + return fmt.Errorf("failed to delete unresolved batches: %w", err) } return nil } -// GetOffChainData returns the value identified by the key -func (db *pgDB) GetOffChainData(ctx context.Context, key common.Hash, dbTx sqlx.QueryerContext) (types.ArgBytes, error) { - const getOffchainDataSQL = ` - SELECT value - FROM data_node.offchain_data - WHERE key = $1 LIMIT 1; - ` +// StoreOffChainData stores and array of key values in the Db +func (db *pgDB) StoreOffChainData(ctx context.Context, ods []types.OffChainData) error { + if len(ods) == 0 { + return nil + } + + query, args := buildOffchainDataInsertQuery(ods) + if _, err := db.pg.ExecContext(ctx, query, args...); err != nil { + return fmt.Errorf("failed to store offchain data: %w", err) + } + + return nil +} - var ( - hexValue string - ) +// GetOffChainData returns the value identified by the key +func (db *pgDB) GetOffChainData(ctx context.Context, key common.Hash) (*types.OffChainData, error) { + data := struct { + Key string `db:"key"` + Value string `db:"value"` + BatchNum uint64 `db:"batch_num"` + }{} - if err := dbTx.QueryRowxContext(ctx, getOffchainDataSQL, key.Hex()).Scan(&hexValue); err != nil { + if err := db.getOffChainDataStmt.QueryRowxContext(ctx, key.Hex()).StructScan(&data); err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, ErrStateNotSynchronized } + + return nil, err + } + + return &types.OffChainData{ + Key: common.HexToHash(data.Key), + Value: common.FromHex(data.Value), + BatchNum: data.BatchNum, + }, nil +} + +// ListOffChainData returns values identified by the given keys +func (db *pgDB) ListOffChainData(ctx context.Context, keys []common.Hash) ([]types.OffChainData, error) { + if len(keys) == 0 { + return nil, nil + } + + preparedKeys := make([]string, len(keys)) + for i, key := range keys { + preparedKeys[i] = key.Hex() + } + + query, args, err := sqlx.In(listOffchainDataSQL, preparedKeys) + if err != nil { + return nil, err + } + + // sqlx.In returns queries with the `?` bindvar, we can rebind it for our backend + query = db.pg.Rebind(query) + + rows, err := db.pg.QueryxContext(ctx, query, args...) + if err != nil { return nil, err } - return common.FromHex(hexValue), nil + defer rows.Close() + + type row struct { + Key string `db:"key"` + Value string `db:"value"` + BatchNum uint64 `db:"batch_num"` + } + + list := make([]types.OffChainData, 0, len(keys)) + for rows.Next() { + data := row{} + if err = rows.StructScan(&data); err != nil { + return nil, err + } + + list = append(list, types.OffChainData{ + Key: common.HexToHash(data.Key), + Value: common.FromHex(data.Value), + BatchNum: data.BatchNum, + }) + } + + return list, nil } -// Exists checks if a key exists in offchain data table -func (db *pgDB) Exists(ctx context.Context, key common.Hash) bool { - const keyExists = "SELECT COUNT(*) FROM data_node.offchain_data WHERE key = $1;" +// CountOffchainData returns the count of rows in the offchain_data table +func (db *pgDB) CountOffchainData(ctx context.Context) (uint64, error) { + var count uint64 + if err := db.countOffChainDataStmt.QueryRowContext(ctx).Scan(&count); err != nil { + return 0, err + } + + return count, nil +} + +// DetectOffchainDataGaps returns the number of gaps in the offchain_data table +func (db *pgDB) DetectOffchainDataGaps(ctx context.Context) (map[uint64]uint64, error) { + rows, err := db.detectOffChainDataGapsStmt.QueryxContext(ctx) + if err != nil { + return nil, err + } + + defer rows.Close() + + type row struct { + CurrentBatchNum uint64 `db:"current_batch_num"` + NextBatchNum uint64 `db:"next_batch_num"` + } - var ( - count uint - ) + gaps := make(map[uint64]uint64) + for rows.Next() { + var data row + if err = rows.StructScan(&data); err != nil { + return nil, err + } - if err := db.pg.QueryRowContext(ctx, keyExists, key.Hex()).Scan(&count); err != nil { - return false + gaps[data.CurrentBatchNum] = data.NextBatchNum } - return count > 0 + return gaps, nil } -// StoreLastProcessedBlock stores a record of a block processed by the synchronizer for named task -func (db *pgDB) StoreLastProcessedBlock(ctx context.Context, task string, block uint64, dbTx sqlx.ExecerContext) error { - const storeLastProcessedBlockSQL = ` - INSERT INTO data_node.sync_tasks (task, block) - VALUES ($1, $2) - ON CONFLICT (task) DO UPDATE - SET block = EXCLUDED.block, processed = NOW(); - ` +// buildBatchKeysInsertQuery builds the query to insert unresolved batch keys +func buildBatchKeysInsertQuery(bks []types.BatchKey) (string, []interface{}) { + const columnsAffected = 2 - if _, err := dbTx.ExecContext(ctx, storeLastProcessedBlockSQL, task, block); err != nil { - return err + args := make([]interface{}, len(bks)*columnsAffected) + values := make([]string, len(bks)) + for i, bk := range bks { + values[i] = fmt.Sprintf("($%d, $%d)", i*columnsAffected+1, i*columnsAffected+2) //nolint:mnd + args[i*columnsAffected] = bk.Number + args[i*columnsAffected+1] = bk.Hash.Hex() } - return nil + return fmt.Sprintf(` + INSERT INTO data_node.unresolved_batches (num, hash) + VALUES %s + ON CONFLICT (num, hash) DO NOTHING; + `, strings.Join(values, ",")), args } -// GetLastProcessedBlock returns the latest block successfully processed by the synchronizer for named task -func (db *pgDB) GetLastProcessedBlock(ctx context.Context, task string) (uint64, error) { - const getLastProcessedBlockSQL = "SELECT block FROM data_node.sync_tasks WHERE task = $1;" +// buildOffchainDataInsertQuery builds the query to insert offchain data +func buildOffchainDataInsertQuery(ods []types.OffChainData) (string, []interface{}) { + const columnsAffected = 3 - var ( - lastBlock uint64 - ) + // Remove duplicates from the given offchain data + ods = types.RemoveDuplicateOffChainData(ods) - if err := db.pg.QueryRowContext(ctx, getLastProcessedBlockSQL, task).Scan(&lastBlock); err != nil { - return 0, err + args := make([]interface{}, len(ods)*columnsAffected) + values := make([]string, len(ods)) + for i, od := range ods { + values[i] = fmt.Sprintf("($%d, $%d, $%d)", i*columnsAffected+1, i*columnsAffected+2, i*columnsAffected+3) //nolint:mnd + args[i*columnsAffected] = od.Key.Hex() + args[i*columnsAffected+1] = common.Bytes2Hex(od.Value) + args[i*columnsAffected+2] = od.BatchNum } - return lastBlock, nil + return fmt.Sprintf(` + INSERT INTO data_node.offchain_data (key, value, batch_num) + VALUES %s + ON CONFLICT (key) DO UPDATE + SET value = EXCLUDED.value, batch_num = EXCLUDED.batch_num; + `, strings.Join(values, ",")), args } diff --git a/db/db_test.go b/db/db_test.go index 890a1f17..4f268884 100644 --- a/db/db_test.go +++ b/db/db_test.go @@ -2,7 +2,9 @@ package db import ( "context" + "database/sql/driver" "errors" + "regexp" "testing" "github.com/0xPolygon/cdk-data-availability/types" @@ -12,37 +14,262 @@ import ( "github.com/stretchr/testify/require" ) -func Test_DB_StoreOffChainData(t *testing.T) { +func Test_New(t *testing.T) { + t.Parallel() + + db, mock, err := sqlmock.New() + require.NoError(t, err) + + defer db.Close() + + constructorExpect(mock) + + wdb := sqlx.NewDb(db, "postgres") + + _, err = New(context.Background(), wdb) + require.NoError(t, err) +} + +func Test_DB_StoreLastProcessedBlock(t *testing.T) { + t.Parallel() + testTable := []struct { name string - od []types.OffChainData + task string + block uint64 + returnErr error + }{ + { + name: "value inserted", + task: "task1", + block: 1, + }, + { + name: "error returned", + task: "task1", + block: 1, + returnErr: errors.New("test error"), + }, + } + + for _, tt := range testTable { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + db, mock, err := sqlmock.New() + require.NoError(t, err) + + defer db.Close() + + constructorExpect(mock) + + expected := mock.ExpectExec(`INSERT INTO data_node\.sync_tasks \(task, block\) VALUES \(\$1, \$2\) ON CONFLICT \(task\) DO UPDATE SET block = EXCLUDED\.block, processed = NOW\(\)`). + WithArgs(tt.task, tt.block) + if tt.returnErr != nil { + expected.WillReturnError(tt.returnErr) + } else { + expected.WillReturnResult(sqlmock.NewResult(1, 1)) + } + + wdb := sqlx.NewDb(db, "postgres") + + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) + + err = dbPG.StoreLastProcessedBlock(context.Background(), tt.block, tt.task) + if tt.returnErr != nil { + require.ErrorIs(t, err, tt.returnErr) + } else { + require.NoError(t, err) + } + + require.NoError(t, mock.ExpectationsWereMet()) + }) + } +} + +func Test_DB_GetLastProcessedBlock(t *testing.T) { + t.Parallel() + + testTable := []struct { + name string + task string + block uint64 returnErr error + }{ + { + name: "successfully selected block", + task: "task1", + block: 1, + }, + { + name: "error returned", + task: "task1", + block: 1, + returnErr: errors.New("test error"), + }, + } + + for _, tt := range testTable { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + db, mock, err := sqlmock.New() + require.NoError(t, err) + + defer db.Close() + + constructorExpect(mock) + + mock.ExpectExec(`INSERT INTO data_node\.sync_tasks \(task, block\) VALUES \(\$1, \$2\) ON CONFLICT \(task\) DO UPDATE SET block = EXCLUDED\.block, processed = NOW\(\)`). + WithArgs(tt.task, tt.block). + WillReturnResult(sqlmock.NewResult(1, 1)) + + expected := mock.ExpectQuery(`SELECT block FROM data_node\.sync_tasks WHERE task = \$1`). + WithArgs(tt.task) + + if tt.returnErr != nil { + expected.WillReturnError(tt.returnErr) + } else { + expected.WillReturnRows(sqlmock.NewRows([]string{"block"}).AddRow(tt.block)) + } + + wdb := sqlx.NewDb(db, "postgres") + + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) + + err = dbPG.StoreLastProcessedBlock(context.Background(), tt.block, tt.task) + require.NoError(t, err) + + actual, err := dbPG.GetLastProcessedBlock(context.Background(), tt.task) + if tt.returnErr != nil { + require.ErrorIs(t, err, tt.returnErr) + } else { + require.NoError(t, err) + require.Equal(t, tt.block, actual) + } + + require.NoError(t, mock.ExpectationsWereMet()) + }) + } +} + +func Test_DB_StoreUnresolvedBatchKeys(t *testing.T) { + t.Parallel() + + testTable := []struct { + name string + bk []types.BatchKey + expectedQuery string + returnErr error }{ { name: "no values inserted", }, { name: "one value inserted", - od: []types.OffChainData{{ - Key: common.HexToHash("key1"), - Value: []byte("value1"), + bk: []types.BatchKey{{ + Number: 1, + Hash: common.BytesToHash([]byte("key1")), }}, + expectedQuery: `INSERT INTO data_node.unresolved_batches (num, hash) VALUES ($1, $2) ON CONFLICT (num, hash) DO NOTHING`, }, { name: "several values inserted", - od: []types.OffChainData{{ - Key: common.HexToHash("key1"), - Value: []byte("value1"), + bk: []types.BatchKey{{ + Number: 1, + Hash: common.BytesToHash([]byte("key1")), }, { - Key: common.HexToHash("key2"), - Value: []byte("value2"), + Number: 2, + Hash: common.BytesToHash([]byte("key2")), }}, + expectedQuery: `INSERT INTO data_node.unresolved_batches (num, hash) VALUES ($1, $2),($3, $4) ON CONFLICT (num, hash) DO NOTHING`, }, { name: "error returned", - od: []types.OffChainData{{ - Key: common.HexToHash("key1"), - Value: []byte("value1"), + bk: []types.BatchKey{{ + Number: 1, + Hash: common.BytesToHash([]byte("key1")), + }}, + expectedQuery: `INSERT INTO data_node.unresolved_batches (num, hash) VALUES ($1, $2) ON CONFLICT (num, hash) DO NOTHING`, + returnErr: errors.New("test error"), + }, + } + + for _, tt := range testTable { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + db, mock, err := sqlmock.New() + require.NoError(t, err) + + wdb := sqlx.NewDb(db, "postgres") + + mock.ExpectPrepare(regexp.QuoteMeta(storeLastProcessedBlockSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(getLastProcessedBlockSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(getUnresolvedBatchKeysSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(getOffchainDataSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(countOffchainDataSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(selectOffchainDataGapsSQL)) + + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) + + defer db.Close() + + if tt.expectedQuery != "" { + args := make([]driver.Value, 0, len(tt.bk)*2) + for _, o := range tt.bk { + args = append(args, o.Number, o.Hash.Hex()) + } + + expected := mock.ExpectExec(regexp.QuoteMeta(tt.expectedQuery)).WithArgs(args...) + if tt.returnErr != nil { + expected.WillReturnError(tt.returnErr) + } else { + expected.WillReturnResult(sqlmock.NewResult(int64(len(tt.bk)), int64(len(tt.bk)))) + } + } + + err = dbPG.StoreUnresolvedBatchKeys(context.Background(), tt.bk) + if tt.returnErr != nil { + require.ErrorIs(t, err, tt.returnErr) + } else { + require.NoError(t, err) + } + + require.NoError(t, mock.ExpectationsWereMet()) + }) + } +} + +func Test_DB_GetUnresolvedBatchKeys(t *testing.T) { + t.Parallel() + + testTable := []struct { + name string + bks []types.BatchKey + returnErr error + }{ + { + name: "successfully selected data", + bks: []types.BatchKey{{ + Number: 1, + Hash: common.BytesToHash([]byte("key1")), + }}, + }, + { + name: "error returned", + bks: []types.BatchKey{{ + Number: 1, + Hash: common.BytesToHash([]byte("key1")), }}, returnErr: errors.New("test error"), }, @@ -59,21 +286,195 @@ func Test_DB_StoreOffChainData(t *testing.T) { defer db.Close() - for _, o := range tt.od { - expected := mock.ExpectExec(`INSERT INTO data_node\.offchain_data \(key, value\) VALUES \(\$1, \$2\) ON CONFLICT \(key\) DO NOTHING`). - WithArgs(o.Key.Hex(), common.Bytes2Hex(o.Value)) + constructorExpect(mock) + + wdb := sqlx.NewDb(db, "postgres") + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) + + // Seed data + seedUnresolvedBatchKeys(t, dbPG, mock, tt.bks) + + var limit = uint(10) + expected := mock.ExpectQuery(`SELECT num, hash FROM data_node\.unresolved_batches LIMIT \$1\;`).WithArgs(limit) + + if tt.returnErr != nil { + expected.WillReturnError(tt.returnErr) + } else { + for _, bk := range tt.bks { + expected.WillReturnRows(sqlmock.NewRows([]string{"num", "hash"}).AddRow(bk.Number, bk.Hash.Hex())) + } + } + + data, err := dbPG.GetUnresolvedBatchKeys(context.Background(), limit) + if tt.returnErr != nil { + require.ErrorIs(t, err, tt.returnErr) + } else { + require.NoError(t, err) + require.Equal(t, tt.bks, data) + } + + require.NoError(t, mock.ExpectationsWereMet()) + }) + } +} + +func Test_DB_DeleteUnresolvedBatchKeys(t *testing.T) { + t.Parallel() + + testTable := []struct { + name string + bks []types.BatchKey + expectedQuery string + returnErr error + }{ + { + name: "value deleted", + bks: []types.BatchKey{{ + Number: 1, + Hash: common.BytesToHash([]byte("key1")), + }}, + expectedQuery: `DELETE FROM data_node.unresolved_batches WHERE (num, hash) IN (($1, $2))`, + }, + { + name: "multiple values deleted", + bks: []types.BatchKey{{ + Number: 1, + Hash: common.BytesToHash([]byte("key1")), + }, { + Number: 2, + Hash: common.BytesToHash([]byte("key2")), + }}, + expectedQuery: `DELETE FROM data_node.unresolved_batches WHERE (num, hash) IN (($1, $2),($3, $4))`, + }, + { + name: "error returned", + bks: []types.BatchKey{{ + Number: 1, + Hash: common.BytesToHash([]byte("key1")), + }}, + expectedQuery: `DELETE FROM data_node.unresolved_batches WHERE (num, hash) IN (($1, $2))`, + returnErr: errors.New("test error"), + }, + } + + for _, tt := range testTable { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + db, mock, err := sqlmock.New() + require.NoError(t, err) + + constructorExpect(mock) + + wdb := sqlx.NewDb(db, "postgres") + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) + + defer db.Close() + + if tt.expectedQuery != "" { + args := make([]driver.Value, 0, len(tt.bks)*2) + for _, o := range tt.bks { + args = append(args, o.Number, o.Hash.Hex()) + } + + expected := mock.ExpectExec(regexp.QuoteMeta(tt.expectedQuery)).WithArgs(args...) if tt.returnErr != nil { expected.WillReturnError(tt.returnErr) } else { - expected.WillReturnResult(sqlmock.NewResult(int64(len(tt.od)), int64(len(tt.od)))) + expected.WillReturnResult(sqlmock.NewResult(int64(len(tt.bks)), int64(len(tt.bks)))) } } + err = dbPG.DeleteUnresolvedBatchKeys(context.Background(), tt.bks) + if tt.returnErr != nil { + require.ErrorIs(t, err, tt.returnErr) + } else { + require.NoError(t, err) + } + + require.NoError(t, mock.ExpectationsWereMet()) + }) + } +} + +func Test_DB_StoreOffChainData(t *testing.T) { + t.Parallel() + + testTable := []struct { + name string + ods []types.OffChainData + expectedQuery string + returnErr error + }{ + { + name: "no values inserted", + }, + { + name: "one value inserted", + ods: []types.OffChainData{{ + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + }}, + expectedQuery: `INSERT INTO data_node.offchain_data (key, value, batch_num) VALUES ($1, $2, $3) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, batch_num = EXCLUDED.batch_num`, + }, + { + name: "several values inserted", + ods: []types.OffChainData{{ + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + }, { + Key: common.BytesToHash([]byte("key2")), + Value: []byte("value2"), + }}, + expectedQuery: `INSERT INTO data_node.offchain_data (key, value, batch_num) VALUES ($1, $2, $3),($4, $5, $6) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, batch_num = EXCLUDED.batch_num`, + }, + { + name: "error returned", + ods: []types.OffChainData{{ + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + }}, + expectedQuery: `INSERT INTO data_node.offchain_data (key, value, batch_num) VALUES ($1, $2, $3) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, batch_num = EXCLUDED.batch_num`, + returnErr: errors.New("test error"), + }, + } + + for _, tt := range testTable { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + db, mock, err := sqlmock.New() + require.NoError(t, err) + + constructorExpect(mock) + wdb := sqlx.NewDb(db, "postgres") + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) + + defer db.Close() - dbPG := New(wdb) + if tt.expectedQuery != "" { + args := make([]driver.Value, 0, len(tt.ods)*3) + for _, od := range tt.ods { + args = append(args, od.Key.Hex(), common.Bytes2Hex(od.Value), od.BatchNum) + } + + expected := mock.ExpectExec(regexp.QuoteMeta(tt.expectedQuery)).WithArgs(args...) + if tt.returnErr != nil { + expected.WillReturnError(tt.returnErr) + } else { + expected.WillReturnResult(sqlmock.NewResult(int64(len(tt.ods)), int64(len(tt.ods)))) + } + } - err = dbPG.StoreOffChainData(context.Background(), tt.od, wdb) + err = dbPG.StoreOffChainData(context.Background(), tt.ods) if tt.returnErr != nil { require.ErrorIs(t, err, tt.returnErr) } else { @@ -86,26 +487,33 @@ func Test_DB_StoreOffChainData(t *testing.T) { } func Test_DB_GetOffChainData(t *testing.T) { + t.Parallel() + testTable := []struct { name string od []types.OffChainData key common.Hash - expected types.ArgBytes + expected *types.OffChainData returnErr error }{ { name: "successfully selected value", od: []types.OffChainData{{ - Key: common.HexToHash("key1"), - Value: []byte("value1"), + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + BatchNum: 1, }}, - key: common.BytesToHash([]byte("key1")), - expected: []byte("value1"), + key: common.BytesToHash([]byte("key1")), + expected: &types.OffChainData{ + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + BatchNum: 1, + }, }, { name: "error returned", od: []types.OffChainData{{ - Key: common.HexToHash("key1"), + Key: common.BytesToHash([]byte("key1")), Value: []byte("value1"), }}, key: common.BytesToHash([]byte("key1")), @@ -114,10 +522,10 @@ func Test_DB_GetOffChainData(t *testing.T) { { name: "no rows", od: []types.OffChainData{{ - Key: common.HexToHash("key1"), + Key: common.BytesToHash([]byte("key1")), Value: []byte("value1"), }}, - key: common.BytesToHash([]byte("underfined")), + key: common.BytesToHash([]byte("undefined")), returnErr: ErrStateNotSynchronized, }, } @@ -131,25 +539,28 @@ func Test_DB_GetOffChainData(t *testing.T) { db, mock, err := sqlmock.New() require.NoError(t, err) - defer db.Close() + constructorExpect(mock) wdb := sqlx.NewDb(db, "postgres") + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) + + defer db.Close() // Seed data - seedOffchainData(t, wdb, mock, tt.od) + seedOffchainData(t, dbPG, mock, tt.od) - expected := mock.ExpectQuery(`SELECT value FROM data_node\.offchain_data WHERE key = \$1 LIMIT 1`). + expected := mock.ExpectQuery(regexp.QuoteMeta(getOffchainDataSQL)). WithArgs(tt.key.Hex()) if tt.returnErr != nil { expected.WillReturnError(tt.returnErr) } else { - expected.WillReturnRows(sqlmock.NewRows([]string{"value"}).AddRow(common.Bytes2Hex(tt.expected))) + expected.WillReturnRows(sqlmock.NewRows([]string{"key", "value", "batch_num"}). + AddRow(tt.expected.Key.Hex(), common.Bytes2Hex(tt.expected.Value), tt.expected.BatchNum)) } - dbPG := New(wdb) - - data, err := dbPG.GetOffChainData(context.Background(), tt.key, wdb) + data, err := dbPG.GetOffChainData(context.Background(), tt.key) if tt.returnErr != nil { require.ErrorIs(t, err, tt.returnErr) } else { @@ -162,47 +573,88 @@ func Test_DB_GetOffChainData(t *testing.T) { } } -func Test_DB_Exist(t *testing.T) { +func Test_DB_ListOffChainData(t *testing.T) { + t.Parallel() + testTable := []struct { name string od []types.OffChainData - key common.Hash - count int + keys []common.Hash + expected []types.OffChainData + sql string returnErr error }{ { - name: "two values found", + name: "successfully selected one value", od: []types.OffChainData{{ - Key: common.HexToHash("key1"), + Key: common.BytesToHash([]byte("key1")), Value: []byte("value1"), - }, { - Key: common.HexToHash("key1"), - Value: []byte("value2"), }}, - key: common.BytesToHash([]byte("key1")), - count: 2, + keys: []common.Hash{ + common.BytesToHash([]byte("key1")), + }, + expected: []types.OffChainData{ + { + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + BatchNum: 0, + }, + }, + sql: `SELECT key, value, batch_num FROM data_node\.offchain_data WHERE key IN \(\$1\)`, }, { - name: "no values found", + name: "successfully selected two values", od: []types.OffChainData{{ - Key: common.HexToHash("key1"), - Value: []byte("value1"), + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + BatchNum: 1, }, { - Key: common.HexToHash("key1"), - Value: []byte("value2"), + Key: common.BytesToHash([]byte("key2")), + Value: []byte("value2"), + BatchNum: 2, }}, - key: common.BytesToHash([]byte("undefined")), - count: 0, + keys: []common.Hash{ + common.BytesToHash([]byte("key1")), + common.BytesToHash([]byte("key2")), + }, + expected: []types.OffChainData{ + { + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + BatchNum: 1, + }, + { + Key: common.BytesToHash([]byte("key2")), + Value: []byte("value2"), + BatchNum: 2, + }, + }, + sql: `SELECT key, value, batch_num FROM data_node\.offchain_data WHERE key IN \(\$1\, \$2\)`, }, { name: "error returned", od: []types.OffChainData{{ - Key: common.HexToHash("key1"), + Key: common.BytesToHash([]byte("key1")), Value: []byte("value1"), }}, - key: common.BytesToHash([]byte("undefined")), + keys: []common.Hash{ + common.BytesToHash([]byte("key1")), + }, + sql: `SELECT key, value, batch_num FROM data_node\.offchain_data WHERE key IN \(\$1\)`, returnErr: errors.New("test error"), }, + { + name: "no rows", + od: []types.OffChainData{{ + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + }}, + keys: []common.Hash{ + common.BytesToHash([]byte("undefined")), + }, + sql: `SELECT key, value, batch_num FROM data_node\.offchain_data WHERE key IN \(\$1\)`, + returnErr: ErrStateNotSynchronized, + }, } for _, tt := range testTable { @@ -216,47 +668,78 @@ func Test_DB_Exist(t *testing.T) { defer db.Close() + constructorExpect(mock) + wdb := sqlx.NewDb(db, "postgres") + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) // Seed data - seedOffchainData(t, wdb, mock, tt.od) + seedOffchainData(t, dbPG, mock, tt.od) - expected := mock.ExpectQuery(`SELECT COUNT\(\*\) FROM data_node\.offchain_data WHERE key = \$1`). - WithArgs(tt.key.Hex()) + preparedKeys := make([]driver.Value, len(tt.keys)) + for i, key := range tt.keys { + preparedKeys[i] = key.Hex() + } + + expected := mock.ExpectQuery(tt.sql). + WithArgs(preparedKeys...) if tt.returnErr != nil { expected.WillReturnError(tt.returnErr) } else { - expected.WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(tt.count)) - } + returnData := sqlmock.NewRows([]string{"key", "value", "batch_num"}) - dbPG := New(wdb) + for _, data := range tt.expected { + returnData = returnData.AddRow(data.Key.Hex(), common.Bytes2Hex(data.Value), data.BatchNum) + } - actual := dbPG.Exists(context.Background(), tt.key) - require.NoError(t, err) - require.Equal(t, tt.count > 0, actual) + expected.WillReturnRows(returnData) + } + + data, err := dbPG.ListOffChainData(context.Background(), tt.keys) + if tt.returnErr != nil { + require.ErrorIs(t, err, tt.returnErr) + } else { + require.NoError(t, err) + require.Equal(t, tt.expected, data) + } require.NoError(t, mock.ExpectationsWereMet()) }) } } -func Test_DB_StoreLastProcessedBlock(t *testing.T) { +func Test_DB_CountOffchainData(t *testing.T) { + t.Parallel() + testTable := []struct { name string - task string - block uint64 + od []types.OffChainData + count uint64 returnErr error }{ { - name: "value inserted", - task: "task1", - block: 1, + name: "two values found", + od: []types.OffChainData{{ + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + }, { + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value2"), + }}, + count: 2, }, { - name: "error returned", - task: "task1", - block: 1, + name: "no values found", + count: 0, + }, + { + name: "error returned", + od: []types.OffChainData{{ + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + }}, returnErr: errors.New("test error"), }, } @@ -272,23 +755,29 @@ func Test_DB_StoreLastProcessedBlock(t *testing.T) { defer db.Close() - expected := mock.ExpectExec(`INSERT INTO data_node\.sync_tasks \(task, block\) VALUES \(\$1, \$2\) ON CONFLICT \(task\) DO UPDATE SET block = EXCLUDED\.block, processed = NOW\(\)`). - WithArgs(tt.task, tt.block) + constructorExpect(mock) + + wdb := sqlx.NewDb(db, "postgres") + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) + + // Seed data + seedOffchainData(t, dbPG, mock, tt.od) + + expected := mock.ExpectQuery(regexp.QuoteMeta(countOffchainDataSQL)) + if tt.returnErr != nil { expected.WillReturnError(tt.returnErr) } else { - expected.WillReturnResult(sqlmock.NewResult(1, 1)) + expected.WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(tt.count)) } - wdb := sqlx.NewDb(db, "postgres") - - dbPG := New(wdb) - - err = dbPG.StoreLastProcessedBlock(context.Background(), tt.task, tt.block, wdb) + actual, err := dbPG.CountOffchainData(context.Background()) if tt.returnErr != nil { require.ErrorIs(t, err, tt.returnErr) } else { require.NoError(t, err) + require.Equal(t, tt.count, actual) } require.NoError(t, mock.ExpectationsWereMet()) @@ -296,22 +785,40 @@ func Test_DB_StoreLastProcessedBlock(t *testing.T) { } } -func Test_DB_GetLastProcessedBlock(t *testing.T) { +func Test_DB_DetectOffchainDataGaps(t *testing.T) { + t.Parallel() + testTable := []struct { name string - task string - block uint64 + seed []types.OffChainData + gaps map[uint64]uint64 returnErr error }{ { - name: "successfully selected block", - task: "task1", - block: 1, + name: "one gap found", + seed: []types.OffChainData{{ + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + BatchNum: 1, + }, { + Key: common.BytesToHash([]byte("key2")), + Value: []byte("value2"), + BatchNum: 2, + }, { + Key: common.HexToHash("key4"), + Value: []byte("value4"), + BatchNum: 4, + }}, + gaps: map[uint64]uint64{ + 2: 4, + }, }, { - name: "error returned", - task: "task1", - block: 1, + name: "error returned", + seed: []types.OffChainData{{ + Key: common.BytesToHash([]byte("key1")), + Value: []byte("value1"), + }}, returnErr: errors.New("test error"), }, } @@ -327,32 +834,33 @@ func Test_DB_GetLastProcessedBlock(t *testing.T) { defer db.Close() - mock.ExpectExec(`INSERT INTO data_node\.sync_tasks \(task, block\) VALUES \(\$1, \$2\) ON CONFLICT \(task\) DO UPDATE SET block = EXCLUDED\.block, processed = NOW\(\)`). - WithArgs(tt.task, tt.block). - WillReturnResult(sqlmock.NewResult(1, 1)) + constructorExpect(mock) - expected := mock.ExpectQuery(`SELECT block FROM data_node\.sync_tasks WHERE task = \$1`). - WithArgs(tt.task) + wdb := sqlx.NewDb(db, "postgres") + dbPG, err := New(context.Background(), wdb) + require.NoError(t, err) + + // Seed data + seedOffchainData(t, dbPG, mock, tt.seed) + + expected := mock.ExpectQuery(regexp.QuoteMeta(selectOffchainDataGapsSQL)) if tt.returnErr != nil { expected.WillReturnError(tt.returnErr) } else { - expected.WillReturnRows(sqlmock.NewRows([]string{"block"}).AddRow(tt.block)) + rows := sqlmock.NewRows([]string{"current_batch_num", "next_batch_num"}) + for k, v := range tt.gaps { + rows.AddRow(k, v) + } + expected.WillReturnRows(rows) } - wdb := sqlx.NewDb(db, "postgres") - - dbPG := New(wdb) - - err = dbPG.StoreLastProcessedBlock(context.Background(), tt.task, tt.block, wdb) - require.NoError(t, err) - - actual, err := dbPG.GetLastProcessedBlock(context.Background(), tt.task) + actual, err := dbPG.DetectOffchainDataGaps(context.Background()) if tt.returnErr != nil { require.ErrorIs(t, err, tt.returnErr) } else { require.NoError(t, err) - require.Equal(t, tt.block, actual) + require.Equal(t, tt.gaps, actual) } require.NoError(t, mock.ExpectationsWereMet()) @@ -360,23 +868,53 @@ func Test_DB_GetLastProcessedBlock(t *testing.T) { } } -func seedOffchainData(t *testing.T, db *sqlx.DB, mock sqlmock.Sqlmock, od []types.OffChainData) { +func constructorExpect(mock sqlmock.Sqlmock) { + mock.ExpectPrepare(regexp.QuoteMeta(storeLastProcessedBlockSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(getLastProcessedBlockSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(getUnresolvedBatchKeysSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(getOffchainDataSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(countOffchainDataSQL)) + mock.ExpectPrepare(regexp.QuoteMeta(selectOffchainDataGapsSQL)) +} + +func seedOffchainData(t *testing.T, db DB, mock sqlmock.Sqlmock, ods []types.OffChainData) { t.Helper() - mock.ExpectBegin() - for i, o := range od { - mock.ExpectExec(`INSERT INTO data_node\.offchain_data \(key, value\) VALUES \(\$1, \$2\) ON CONFLICT \(key\) DO NOTHING`). - WithArgs(o.Key.Hex(), common.Bytes2Hex(o.Value)). - WillReturnResult(sqlmock.NewResult(int64(i+1), int64(i+1))) + if len(ods) == 0 { + return } - mock.ExpectCommit() - tx, err := db.BeginTxx(context.Background(), nil) - require.NoError(t, err) + query, args := buildOffchainDataInsertQuery(ods) + + argValues := make([]driver.Value, len(args)) + for i, arg := range args { + argValues[i] = arg + } + + mock.ExpectExec(regexp.QuoteMeta(query)).WithArgs(argValues...). + WillReturnResult(sqlmock.NewResult(int64(len(ods)), int64(len(ods)))) - err = New(db).StoreOffChainData(context.Background(), od, tx) + err := db.StoreOffChainData(context.Background(), ods) require.NoError(t, err) +} + +func seedUnresolvedBatchKeys(t *testing.T, db DB, mock sqlmock.Sqlmock, bks []types.BatchKey) { + t.Helper() + + if len(bks) == 0 { + return + } + + query, args := buildBatchKeysInsertQuery(bks) + + argValues := make([]driver.Value, len(args)) + for i, arg := range args { + argValues[i] = arg + } + + mock.ExpectExec(regexp.QuoteMeta(query)).WithArgs(argValues...). + WillReturnResult(sqlmock.NewResult(int64(len(bks)), int64(len(bks)))) - err = tx.Commit() + err := db.StoreUnresolvedBatchKeys(context.Background(), bks) require.NoError(t, err) } diff --git a/db/migrations.go b/db/migrations.go index a7aa70e6..d687558c 100644 --- a/db/migrations.go +++ b/db/migrations.go @@ -1,13 +1,17 @@ package db import ( + "embed" + "github.com/0xPolygon/cdk-data-availability/log" - "github.com/gobuffalo/packr/v2" "github.com/jmoiron/sqlx" migrate "github.com/rubenv/sql-migrate" ) -var packrMigrations = packr.New("migrations", "./migrations") +var ( + //go:embed migrations/*.sql + embedMigrations embed.FS +) // RunMigrationsUp runs migrate-up for the given config. func RunMigrationsUp(pg *sqlx.DB) error { @@ -19,12 +23,17 @@ func RunMigrationsUp(pg *sqlx.DB) error { // the database updated with the latest changes in either direction, // up or down. func runMigrations(db *sqlx.DB, direction migrate.MigrationDirection) error { - var migrations = &migrate.PackrMigrationSource{Box: packrMigrations} + migrations := &migrate.EmbedFileSystemMigrationSource{ + FileSystem: embedMigrations, + Root: "migrations", + } + nMigrations, err := migrate.Exec(db.DB, "postgres", migrations, direction) if err != nil { return err } log.Info("successfully ran ", nMigrations, " migrations") + return nil } diff --git a/db/migrations/0004.sql b/db/migrations/0004.sql new file mode 100644 index 00000000..6f988924 --- /dev/null +++ b/db/migrations/0004.sql @@ -0,0 +1,12 @@ +-- +migrate Down +DROP TABLE IF EXISTS data_node.unresolved_batches CASCADE; + +-- +migrate Up +CREATE TABLE data_node.unresolved_batches +( + num BIGINT NOT NULL, + hash VARCHAR(255) NOT NULL, + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + + PRIMARY KEY (num, hash) +); diff --git a/db/migrations/0005.sql b/db/migrations/0005.sql new file mode 100644 index 00000000..41cbb20d --- /dev/null +++ b/db/migrations/0005.sql @@ -0,0 +1,12 @@ +-- +migrate Down +ALTER TABLE data_node.offchain_data DROP COLUMN IF EXISTS batch_num; + +-- +migrate Up +ALTER TABLE data_node.offchain_data + ADD COLUMN IF NOT EXISTS batch_num BIGINT NOT NULL DEFAULT 0; + +-- Ensure batch_num is indexed for optimal performance +CREATE INDEX idx_batch_num ON data_node.offchain_data(batch_num); + +-- It triggers resync with an updated logic of all batches +UPDATE data_node.sync_tasks SET block = 0 WHERE task = 'L1'; \ No newline at end of file diff --git a/docs/running.md b/docs/running.md index 77f2550c..ce91f590 100644 --- a/docs/running.md +++ b/docs/running.md @@ -60,7 +60,7 @@ services: ports: - 5434:5432 environment: - - POSTGRES_USER=committee_user # CHANGE THIS: use your prefered user name + - POSTGRES_USER=committee_user # CHANGE THIS: use your preferred user name - POSTGRES_PASSWORD=committee_password # CHANGE THIS: use a safe and strong password - POSTGRES_DB=committee_db command: @@ -76,13 +76,14 @@ services: PrivateKey = {Path = "/pk/test-member.keystore", Password = "testonly"} # CHANGE THIS (the password): according to the private key file password [L1] -WsURL = "ws://URLofYourL1Node:8546" # CHANGE THIS: use the URL of your L1 node -RpcURL = "http://URLofYourL1Node:8545" # CHANGE THIS: use the URL of your L1 node -PolygonValidiumAddress = "0x975725832B4909Aab87D3604A0b501569dbBE7A9" # CHANGE THIS: Address of the Validium smart contract -DataCommitteeAddress = "0x2f08F654B896208dD968aFdAEf733edC5FF62c03" # CHANGE THIS: Address of the data availability committee smart contract +RpcURL = "http://URLofYourL1Node:8545" # CHANGE THIS: use the URL of your L1 node, can be http(s) or ws(s) +PolygonValidiumAddress = "0x8dAF17A20c9DBA35f005b6324F493785D239719d" # CHANGE THIS: Address of the Validium smart contract +DataCommitteeAddress = "0x68B1D87F95878fE05B998F19b66F4baba5De1aed" # CHANGE THIS: Address of the data availability committee smart contract Timeout = "3m" RetryPeriod = "5s" BlockBatchSize = 32 +TrackSequencer = true +TrackSequencerPollInterval = "1m" [Log] Environment = "development" # "production" or "development" diff --git a/etherman/etherman.go b/etherman/etherman.go index ff2b6778..4751961a 100644 --- a/etherman/etherman.go +++ b/etherman/etherman.go @@ -5,9 +5,9 @@ import ( "fmt" "math/big" + "github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygondatacommittee" + "github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonvalidiumetrog" "github.com/0xPolygon/cdk-data-availability/config" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygondatacommittee" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygonvalidium" "github.com/0xPolygon/cdk-data-availability/log" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -31,30 +31,33 @@ type DataCommittee struct { // Etherman defines functions that should be implemented by Etherman type Etherman interface { + GetTx(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) + HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) + BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) + CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) + GetCurrentDataCommittee() (*DataCommittee, error) GetCurrentDataCommitteeMembers() ([]DataCommitteeMember, error) - GetTx(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) - TrustedSequencer() (common.Address, error) + TrustedSequencer(ctx context.Context) (common.Address, error) WatchSetTrustedSequencer( ctx context.Context, - events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer, + events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer, ) (event.Subscription, error) - TrustedSequencerURL() (string, error) + TrustedSequencerURL(ctx context.Context) (string, error) WatchSetTrustedSequencerURL( ctx context.Context, - events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL, + events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL, ) (event.Subscription, error) - HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) FilterSequenceBatches( opts *bind.FilterOpts, numBatch []uint64, - ) (*polygonvalidium.PolygonvalidiumSequenceBatchesIterator, error) + ) (*polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatchesIterator, error) } // etherman is the implementation of EtherMan. type etherman struct { EthClient *ethclient.Client - CDKValidium *polygonvalidium.Polygonvalidium + CDKValidium *polygonvalidiumetrog.Polygonvalidiumetrog DataCommittee *polygondatacommittee.Polygondatacommittee } @@ -63,13 +66,13 @@ func New(ctx context.Context, cfg config.L1Config) (Etherman, error) { ctx, cancel := context.WithTimeout(ctx, cfg.Timeout.Duration) defer cancel() - ethClient, err := ethclient.DialContext(ctx, cfg.WsURL) + ethClient, err := ethclient.DialContext(ctx, cfg.RpcURL) if err != nil { - log.Errorf("error connecting to %s: %+v", cfg.WsURL, err) + log.Errorf("error connecting to %s: %+v", cfg.RpcURL, err) return nil, err } - cdkValidium, err := polygonvalidium.NewPolygonvalidium( + cdkValidium, err := polygonvalidiumetrog.NewPolygonvalidiumetrog( common.HexToAddress(cfg.PolygonValidiumAddress), ethClient, ) @@ -97,40 +100,56 @@ func (e *etherman) GetTx(ctx context.Context, txHash common.Hash) (*types.Transa return e.EthClient.TransactionByHash(ctx, txHash) } +// HeaderByNumber returns header by number from the eth client +func (e *etherman) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { + return e.EthClient.HeaderByNumber(ctx, number) +} + +// BlockByNumber returns a block by the given number +func (e *etherman) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + return e.EthClient.BlockByNumber(ctx, number) +} + +// CodeAt returns the contract code of the given account. +func (e *etherman) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { + return e.EthClient.CodeAt(ctx, account, blockNumber) +} + // TrustedSequencer gets trusted sequencer address -func (e *etherman) TrustedSequencer() (common.Address, error) { - return e.CDKValidium.TrustedSequencer(&bind.CallOpts{Pending: false}) +func (e *etherman) TrustedSequencer(ctx context.Context) (common.Address, error) { + return e.CDKValidium.TrustedSequencer(&bind.CallOpts{ + Context: ctx, + Pending: false, + }) } // WatchSetTrustedSequencer watches trusted sequencer address func (e *etherman) WatchSetTrustedSequencer( ctx context.Context, - events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer, + events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer, ) (event.Subscription, error) { return e.CDKValidium.WatchSetTrustedSequencer(&bind.WatchOpts{Context: ctx}, events) } // TrustedSequencerURL gets trusted sequencer's RPC url -func (e *etherman) TrustedSequencerURL() (string, error) { - return e.CDKValidium.TrustedSequencerURL(&bind.CallOpts{Pending: false}) +func (e *etherman) TrustedSequencerURL(ctx context.Context) (string, error) { + return e.CDKValidium.TrustedSequencerURL(&bind.CallOpts{ + Context: ctx, + Pending: false, + }) } // WatchSetTrustedSequencerURL watches trusted sequencer's RPC url func (e *etherman) WatchSetTrustedSequencerURL( ctx context.Context, - events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL, + events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL, ) (event.Subscription, error) { return e.CDKValidium.WatchSetTrustedSequencerURL(&bind.WatchOpts{Context: ctx}, events) } -// HeaderByNumber returns header by number from the eth client -func (e *etherman) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - return e.EthClient.HeaderByNumber(ctx, number) -} - // FilterSequenceBatches retrieves filtered batches on CDK validium func (e *etherman) FilterSequenceBatches(opts *bind.FilterOpts, - numBatch []uint64) (*polygonvalidium.PolygonvalidiumSequenceBatchesIterator, error) { + numBatch []uint64) (*polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatchesIterator, error) { return e.CDKValidium.FilterSequenceBatches(opts, numBatch) } diff --git a/etherman/smartcontracts/abi/polygondatacommittee.abi b/etherman/smartcontracts/abi/polygondatacommittee.abi deleted file mode 100644 index 71356f29..00000000 --- a/etherman/smartcontracts/abi/polygondatacommittee.abi +++ /dev/null @@ -1,239 +0,0 @@ -[ - { - "inputs": [], - "name": "CommitteeAddressDoesntExist", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyURLNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyRequiredSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "UnexpectedAddrsAndSignaturesSize", - "type": "error" - }, - { - "inputs": [], - "name": "UnexpectedAddrsBytesLength", - "type": "error" - }, - { - "inputs": [], - "name": "UnexpectedCommitteeHash", - "type": "error" - }, - { - "inputs": [], - "name": "WrongAddrOrder", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "committeeHash", - "type": "bytes32" - } - ], - "name": "CommitteeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "committeeHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAmountOfMembers", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getProcotolName", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "members", - "outputs": [ - { - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "requiredAmountOfSignatures", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requiredAmountOfSignatures", - "type": "uint256" - }, - { - "internalType": "string[]", - "name": "urls", - "type": "string[]" - }, - { - "internalType": "bytes", - "name": "addrsBytes", - "type": "bytes" - } - ], - "name": "setupCommittee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "signedHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "signaturesAndAddrs", - "type": "bytes" - } - ], - "name": "verifyMessage", - "outputs": [], - "stateMutability": "view", - "type": "function" - } -] \ No newline at end of file diff --git a/etherman/smartcontracts/abigen.sh b/etherman/smartcontracts/abigen.sh deleted file mode 100755 index ee29a21e..00000000 --- a/etherman/smartcontracts/abigen.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -set -e - -gen() { - local package=$1 - - abigen --bin bin/${package}.bin --abi abi/${package}.abi --pkg=${package} --out=${package}/${package}.go -} - -gen polygonvalidium -gen polygondatacommittee \ No newline at end of file diff --git a/etherman/smartcontracts/bin/polygondatacommittee.bin b/etherman/smartcontracts/bin/polygondatacommittee.bin deleted file mode 100644 index 39e1df2f..00000000 --- a/etherman/smartcontracts/bin/polygondatacommittee.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b50611646806100206000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063715018a611610081578063dce1e2b61161005b578063dce1e2b614610178578063e4f1712014610180578063f2fde38b146101bf57600080fd5b8063715018a6146101405780638129fc1c146101485780638da5cb5b1461015057600080fd5b80635daf08ca116100b25780635daf08ca146100f6578063609d4544146101205780636beedd391461013757600080fd5b8063078fba2a146100ce5780633b51be4b146100e3575b600080fd5b6100e16100dc366004610fe9565b6101d2565b005b6100e16100f1366004611094565b6104d4565b6101096101043660046110e0565b61071f565b60405161011792919061115d565b60405180910390f35b61012960665481565b604051908152602001610117565b61012960655481565b6100e16107f1565b6100e1610805565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610117565b606754610129565b604080518082018252601981527f44617461417661696c6162696c697479436f6d6d697474656500000000000000602082015290516101179190611195565b6100e16101cd3660046111af565b61099c565b6101da610a50565b8285811015610215576040517f2e7dcd6e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610220601482611214565b8214610258576040517f2ab6a12900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61026460676000610ef5565b6000805b8281101561047857600061027d601483611214565b9050600086828761028f60148361122b565b9261029c9392919061123e565b6102a591611268565b60601c90508888848181106102bc576102bc6112b0565b90506020028101906102ce91906112df565b9050600003610309576040517fb54b70e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161061036e576040517fd53cfbe000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606760405180604001604052808b8b8781811061038d5761038d6112b0565b905060200281019061039f91906112df565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093855250505073ffffffffffffffffffffffffffffffffffffffff851660209283015283546001810185559381522081519192600202019081906104139082611415565b5060209190910151600190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905592508190506104708161152f565b915050610268565b508383604051610489929190611567565b6040519081900381206066819055606589905581527f831403fd381b3e6ac875d912ec2eee0e0203d0d29f7b3e0c96fc8f582d6db6579060200160405180910390a150505050505050565b60655460006104e4826041611214565b905080831080610508575060146104fb8285611577565b61050591906115b9565b15155b1561053f576040517f6b8eec4600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60665461054e8483818861123e565b60405161055c929190611567565b60405180910390201461059b576040517f6b156b2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060146105aa8487611577565b6105b491906115cd565b905060005b848110156107155760006105ce604183611214565b9050600061062b8a8a848b6105e460418361122b565b926105f19392919061123e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ad192505050565b90506000855b858110156106c7576000610646601483611214565b610650908a61122b565b905060008c828d61066260148361122b565b9261066f9392919061123e565b61067891611268565b60601c905073ffffffffffffffffffffffffffffffffffffffff851681036106b2576106a583600161122b565b98506001935050506106c7565b505080806106bf9061152f565b915050610631565b50806106ff576040517f8431721300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050808061070d9061152f565b9150506105b9565b5050505050505050565b6067818154811061072f57600080fd5b906000526020600020906002020160009150905080600001805461075290611373565b80601f016020809104026020016040519081016040528092919081815260200182805461077e90611373565b80156107cb5780601f106107a0576101008083540402835291602001916107cb565b820191906000526020600020905b8154815290600101906020018083116107ae57829003601f168201915b5050506001909301549192505073ffffffffffffffffffffffffffffffffffffffff1682565b6107f9610a50565b6108036000610af7565b565b600054610100900460ff16158080156108255750600054600160ff909116105b8061083f5750303b15801561083f575060005460ff166001145b6108d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561092e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610936610b6e565b801561099957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6109a4610a50565b73ffffffffffffffffffffffffffffffffffffffff8116610a47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016108c7565b61099981610af7565b60335473ffffffffffffffffffffffffffffffffffffffff163314610803576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108c7565b6000806000610ae08585610c0e565b91509150610aed81610c53565b5090505b92915050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610c05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108c7565b61080333610af7565b6000808251604103610c445760208301516040840151606085015160001a610c3887828585610e06565b94509450505050610c4c565b506000905060025b9250929050565b6000816004811115610c6757610c676115e1565b03610c6f5750565b6001816004811115610c8357610c836115e1565b03610cea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108c7565b6002816004811115610cfe57610cfe6115e1565b03610d65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108c7565b6003816004811115610d7957610d796115e1565b03610999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016108c7565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610e3d5750600090506003610eec565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015610e91573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116610ee557600060019250925050610eec565b9150600090505b94509492505050565b508054600082556002029060005260206000209081019061099991905b80821115610f59576000610f268282610f5d565b506001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600201610f12565b5090565b508054610f6990611373565b6000825580601f10610f79575050565b601f01602090049060005260206000209081019061099991905b80821115610f595760008155600101610f93565b60008083601f840112610fb957600080fd5b50813567ffffffffffffffff811115610fd157600080fd5b602083019150836020828501011115610c4c57600080fd5b60008060008060006060868803121561100157600080fd5b85359450602086013567ffffffffffffffff8082111561102057600080fd5b818801915088601f83011261103457600080fd5b81358181111561104357600080fd5b8960208260051b850101111561105857600080fd5b60208301965080955050604088013591508082111561107657600080fd5b5061108388828901610fa7565b969995985093965092949392505050565b6000806000604084860312156110a957600080fd5b83359250602084013567ffffffffffffffff8111156110c757600080fd5b6110d386828701610fa7565b9497909650939450505050565b6000602082840312156110f257600080fd5b5035919050565b6000815180845260005b8181101561111f57602081850181015186830182015201611103565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60408152600061117060408301856110f9565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b6020815260006111a860208301846110f9565b9392505050565b6000602082840312156111c157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146111a857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610af157610af16111e5565b80820180821115610af157610af16111e5565b6000808585111561124e57600080fd5b8386111561125b57600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156112a85780818660140360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261131457600080fd5b83018035915067ffffffffffffffff82111561132f57600080fd5b602001915036819003821315610c4c57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c9082168061138757607f821691505b6020821081036113c0577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561141057600081815260208120601f850160051c810160208610156113ed5750805b601f850160051c820191505b8181101561140c578281556001016113f9565b5050505b505050565b815167ffffffffffffffff81111561142f5761142f611344565b6114438161143d8454611373565b846113c6565b602080601f83116001811461149657600084156114605750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561140c565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156114e3578886015182559484019460019091019084016114c4565b508582101561151f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611560576115606111e5565b5060010190565b8183823760009101908152919050565b81810381811115610af157610af16111e5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826115c8576115c861158a565b500690565b6000826115dc576115dc61158a565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea2646970667358221220e34b71e7c7c23d67a42aa345fc1c3d9c57287ac1c2a2024084974dcc23e4088864736f6c63430008140033 \ No newline at end of file diff --git a/etherman/smartcontracts/polygondatacommittee/polygondatacommittee.go b/etherman/smartcontracts/polygondatacommittee/polygondatacommittee.go deleted file mode 100644 index d2e7d5e9..00000000 --- a/etherman/smartcontracts/polygondatacommittee/polygondatacommittee.go +++ /dev/null @@ -1,937 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package polygondatacommittee - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// PolygondatacommitteeMetaData contains all meta data concerning the Polygondatacommittee contract. -var PolygondatacommitteeMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"CommitteeAddressDoesntExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyURLNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyRequiredSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedAddrsAndSignaturesSize\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedAddrsBytesLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedCommitteeHash\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongAddrOrder\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"committeeHash\",\"type\":\"bytes32\"}],\"name\":\"CommitteeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"committeeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAmountOfMembers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getProcotolName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"members\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"url\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requiredAmountOfSignatures\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_requiredAmountOfSignatures\",\"type\":\"uint256\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"addrsBytes\",\"type\":\"bytes\"}],\"name\":\"setupCommittee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"signedHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signaturesAndAddrs\",\"type\":\"bytes\"}],\"name\":\"verifyMessage\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50611646806100206000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063715018a611610081578063dce1e2b61161005b578063dce1e2b614610178578063e4f1712014610180578063f2fde38b146101bf57600080fd5b8063715018a6146101405780638129fc1c146101485780638da5cb5b1461015057600080fd5b80635daf08ca116100b25780635daf08ca146100f6578063609d4544146101205780636beedd391461013757600080fd5b8063078fba2a146100ce5780633b51be4b146100e3575b600080fd5b6100e16100dc366004610fe9565b6101d2565b005b6100e16100f1366004611094565b6104d4565b6101096101043660046110e0565b61071f565b60405161011792919061115d565b60405180910390f35b61012960665481565b604051908152602001610117565b61012960655481565b6100e16107f1565b6100e1610805565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610117565b606754610129565b604080518082018252601981527f44617461417661696c6162696c697479436f6d6d697474656500000000000000602082015290516101179190611195565b6100e16101cd3660046111af565b61099c565b6101da610a50565b8285811015610215576040517f2e7dcd6e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610220601482611214565b8214610258576040517f2ab6a12900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61026460676000610ef5565b6000805b8281101561047857600061027d601483611214565b9050600086828761028f60148361122b565b9261029c9392919061123e565b6102a591611268565b60601c90508888848181106102bc576102bc6112b0565b90506020028101906102ce91906112df565b9050600003610309576040517fb54b70e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161061036e576040517fd53cfbe000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606760405180604001604052808b8b8781811061038d5761038d6112b0565b905060200281019061039f91906112df565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093855250505073ffffffffffffffffffffffffffffffffffffffff851660209283015283546001810185559381522081519192600202019081906104139082611415565b5060209190910151600190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905592508190506104708161152f565b915050610268565b508383604051610489929190611567565b6040519081900381206066819055606589905581527f831403fd381b3e6ac875d912ec2eee0e0203d0d29f7b3e0c96fc8f582d6db6579060200160405180910390a150505050505050565b60655460006104e4826041611214565b905080831080610508575060146104fb8285611577565b61050591906115b9565b15155b1561053f576040517f6b8eec4600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60665461054e8483818861123e565b60405161055c929190611567565b60405180910390201461059b576040517f6b156b2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060146105aa8487611577565b6105b491906115cd565b905060005b848110156107155760006105ce604183611214565b9050600061062b8a8a848b6105e460418361122b565b926105f19392919061123e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ad192505050565b90506000855b858110156106c7576000610646601483611214565b610650908a61122b565b905060008c828d61066260148361122b565b9261066f9392919061123e565b61067891611268565b60601c905073ffffffffffffffffffffffffffffffffffffffff851681036106b2576106a583600161122b565b98506001935050506106c7565b505080806106bf9061152f565b915050610631565b50806106ff576040517f8431721300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050808061070d9061152f565b9150506105b9565b5050505050505050565b6067818154811061072f57600080fd5b906000526020600020906002020160009150905080600001805461075290611373565b80601f016020809104026020016040519081016040528092919081815260200182805461077e90611373565b80156107cb5780601f106107a0576101008083540402835291602001916107cb565b820191906000526020600020905b8154815290600101906020018083116107ae57829003601f168201915b5050506001909301549192505073ffffffffffffffffffffffffffffffffffffffff1682565b6107f9610a50565b6108036000610af7565b565b600054610100900460ff16158080156108255750600054600160ff909116105b8061083f5750303b15801561083f575060005460ff166001145b6108d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561092e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610936610b6e565b801561099957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6109a4610a50565b73ffffffffffffffffffffffffffffffffffffffff8116610a47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016108c7565b61099981610af7565b60335473ffffffffffffffffffffffffffffffffffffffff163314610803576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108c7565b6000806000610ae08585610c0e565b91509150610aed81610c53565b5090505b92915050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610c05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108c7565b61080333610af7565b6000808251604103610c445760208301516040840151606085015160001a610c3887828585610e06565b94509450505050610c4c565b506000905060025b9250929050565b6000816004811115610c6757610c676115e1565b03610c6f5750565b6001816004811115610c8357610c836115e1565b03610cea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016108c7565b6002816004811115610cfe57610cfe6115e1565b03610d65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016108c7565b6003816004811115610d7957610d796115e1565b03610999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f756500000000000000000000000000000000000000000000000000000000000060648201526084016108c7565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115610e3d5750600090506003610eec565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015610e91573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116610ee557600060019250925050610eec565b9150600090505b94509492505050565b508054600082556002029060005260206000209081019061099991905b80821115610f59576000610f268282610f5d565b506001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600201610f12565b5090565b508054610f6990611373565b6000825580601f10610f79575050565b601f01602090049060005260206000209081019061099991905b80821115610f595760008155600101610f93565b60008083601f840112610fb957600080fd5b50813567ffffffffffffffff811115610fd157600080fd5b602083019150836020828501011115610c4c57600080fd5b60008060008060006060868803121561100157600080fd5b85359450602086013567ffffffffffffffff8082111561102057600080fd5b818801915088601f83011261103457600080fd5b81358181111561104357600080fd5b8960208260051b850101111561105857600080fd5b60208301965080955050604088013591508082111561107657600080fd5b5061108388828901610fa7565b969995985093965092949392505050565b6000806000604084860312156110a957600080fd5b83359250602084013567ffffffffffffffff8111156110c757600080fd5b6110d386828701610fa7565b9497909650939450505050565b6000602082840312156110f257600080fd5b5035919050565b6000815180845260005b8181101561111f57602081850181015186830182015201611103565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60408152600061117060408301856110f9565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b6020815260006111a860208301846110f9565b9392505050565b6000602082840312156111c157600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146111a857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610af157610af16111e5565b80820180821115610af157610af16111e5565b6000808585111561124e57600080fd5b8386111561125b57600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156112a85780818660140360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261131457600080fd5b83018035915067ffffffffffffffff82111561132f57600080fd5b602001915036819003821315610c4c57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c9082168061138757607f821691505b6020821081036113c0577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561141057600081815260208120601f850160051c810160208610156113ed5750805b601f850160051c820191505b8181101561140c578281556001016113f9565b5050505b505050565b815167ffffffffffffffff81111561142f5761142f611344565b6114438161143d8454611373565b846113c6565b602080601f83116001811461149657600084156114605750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561140c565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156114e3578886015182559484019460019091019084016114c4565b508582101561151f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611560576115606111e5565b5060010190565b8183823760009101908152919050565b81810381811115610af157610af16111e5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826115c8576115c861158a565b500690565b6000826115dc576115dc61158a565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea2646970667358221220e34b71e7c7c23d67a42aa345fc1c3d9c57287ac1c2a2024084974dcc23e4088864736f6c63430008140033", -} - -// PolygondatacommitteeABI is the input ABI used to generate the binding from. -// Deprecated: Use PolygondatacommitteeMetaData.ABI instead. -var PolygondatacommitteeABI = PolygondatacommitteeMetaData.ABI - -// PolygondatacommitteeBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use PolygondatacommitteeMetaData.Bin instead. -var PolygondatacommitteeBin = PolygondatacommitteeMetaData.Bin - -// DeployPolygondatacommittee deploys a new Ethereum contract, binding an instance of Polygondatacommittee to it. -func DeployPolygondatacommittee(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Polygondatacommittee, error) { - parsed, err := PolygondatacommitteeMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(PolygondatacommitteeBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Polygondatacommittee{PolygondatacommitteeCaller: PolygondatacommitteeCaller{contract: contract}, PolygondatacommitteeTransactor: PolygondatacommitteeTransactor{contract: contract}, PolygondatacommitteeFilterer: PolygondatacommitteeFilterer{contract: contract}}, nil -} - -// Polygondatacommittee is an auto generated Go binding around an Ethereum contract. -type Polygondatacommittee struct { - PolygondatacommitteeCaller // Read-only binding to the contract - PolygondatacommitteeTransactor // Write-only binding to the contract - PolygondatacommitteeFilterer // Log filterer for contract events -} - -// PolygondatacommitteeCaller is an auto generated read-only Go binding around an Ethereum contract. -type PolygondatacommitteeCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// PolygondatacommitteeTransactor is an auto generated write-only Go binding around an Ethereum contract. -type PolygondatacommitteeTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// PolygondatacommitteeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type PolygondatacommitteeFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// PolygondatacommitteeSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type PolygondatacommitteeSession struct { - Contract *Polygondatacommittee // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// PolygondatacommitteeCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type PolygondatacommitteeCallerSession struct { - Contract *PolygondatacommitteeCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// PolygondatacommitteeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type PolygondatacommitteeTransactorSession struct { - Contract *PolygondatacommitteeTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// PolygondatacommitteeRaw is an auto generated low-level Go binding around an Ethereum contract. -type PolygondatacommitteeRaw struct { - Contract *Polygondatacommittee // Generic contract binding to access the raw methods on -} - -// PolygondatacommitteeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type PolygondatacommitteeCallerRaw struct { - Contract *PolygondatacommitteeCaller // Generic read-only contract binding to access the raw methods on -} - -// PolygondatacommitteeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type PolygondatacommitteeTransactorRaw struct { - Contract *PolygondatacommitteeTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewPolygondatacommittee creates a new instance of Polygondatacommittee, bound to a specific deployed contract. -func NewPolygondatacommittee(address common.Address, backend bind.ContractBackend) (*Polygondatacommittee, error) { - contract, err := bindPolygondatacommittee(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Polygondatacommittee{PolygondatacommitteeCaller: PolygondatacommitteeCaller{contract: contract}, PolygondatacommitteeTransactor: PolygondatacommitteeTransactor{contract: contract}, PolygondatacommitteeFilterer: PolygondatacommitteeFilterer{contract: contract}}, nil -} - -// NewPolygondatacommitteeCaller creates a new read-only instance of Polygondatacommittee, bound to a specific deployed contract. -func NewPolygondatacommitteeCaller(address common.Address, caller bind.ContractCaller) (*PolygondatacommitteeCaller, error) { - contract, err := bindPolygondatacommittee(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &PolygondatacommitteeCaller{contract: contract}, nil -} - -// NewPolygondatacommitteeTransactor creates a new write-only instance of Polygondatacommittee, bound to a specific deployed contract. -func NewPolygondatacommitteeTransactor(address common.Address, transactor bind.ContractTransactor) (*PolygondatacommitteeTransactor, error) { - contract, err := bindPolygondatacommittee(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &PolygondatacommitteeTransactor{contract: contract}, nil -} - -// NewPolygondatacommitteeFilterer creates a new log filterer instance of Polygondatacommittee, bound to a specific deployed contract. -func NewPolygondatacommitteeFilterer(address common.Address, filterer bind.ContractFilterer) (*PolygondatacommitteeFilterer, error) { - contract, err := bindPolygondatacommittee(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &PolygondatacommitteeFilterer{contract: contract}, nil -} - -// bindPolygondatacommittee binds a generic wrapper to an already deployed contract. -func bindPolygondatacommittee(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := PolygondatacommitteeMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Polygondatacommittee *PolygondatacommitteeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Polygondatacommittee.Contract.PolygondatacommitteeCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Polygondatacommittee *PolygondatacommitteeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Polygondatacommittee.Contract.PolygondatacommitteeTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Polygondatacommittee *PolygondatacommitteeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Polygondatacommittee.Contract.PolygondatacommitteeTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Polygondatacommittee *PolygondatacommitteeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Polygondatacommittee.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Polygondatacommittee *PolygondatacommitteeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Polygondatacommittee.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Polygondatacommittee *PolygondatacommitteeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Polygondatacommittee.Contract.contract.Transact(opts, method, params...) -} - -// CommitteeHash is a free data retrieval call binding the contract method 0x609d4544. -// -// Solidity: function committeeHash() view returns(bytes32) -func (_Polygondatacommittee *PolygondatacommitteeCaller) CommitteeHash(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Polygondatacommittee.contract.Call(opts, &out, "committeeHash") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// CommitteeHash is a free data retrieval call binding the contract method 0x609d4544. -// -// Solidity: function committeeHash() view returns(bytes32) -func (_Polygondatacommittee *PolygondatacommitteeSession) CommitteeHash() ([32]byte, error) { - return _Polygondatacommittee.Contract.CommitteeHash(&_Polygondatacommittee.CallOpts) -} - -// CommitteeHash is a free data retrieval call binding the contract method 0x609d4544. -// -// Solidity: function committeeHash() view returns(bytes32) -func (_Polygondatacommittee *PolygondatacommitteeCallerSession) CommitteeHash() ([32]byte, error) { - return _Polygondatacommittee.Contract.CommitteeHash(&_Polygondatacommittee.CallOpts) -} - -// GetAmountOfMembers is a free data retrieval call binding the contract method 0xdce1e2b6. -// -// Solidity: function getAmountOfMembers() view returns(uint256) -func (_Polygondatacommittee *PolygondatacommitteeCaller) GetAmountOfMembers(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Polygondatacommittee.contract.Call(opts, &out, "getAmountOfMembers") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetAmountOfMembers is a free data retrieval call binding the contract method 0xdce1e2b6. -// -// Solidity: function getAmountOfMembers() view returns(uint256) -func (_Polygondatacommittee *PolygondatacommitteeSession) GetAmountOfMembers() (*big.Int, error) { - return _Polygondatacommittee.Contract.GetAmountOfMembers(&_Polygondatacommittee.CallOpts) -} - -// GetAmountOfMembers is a free data retrieval call binding the contract method 0xdce1e2b6. -// -// Solidity: function getAmountOfMembers() view returns(uint256) -func (_Polygondatacommittee *PolygondatacommitteeCallerSession) GetAmountOfMembers() (*big.Int, error) { - return _Polygondatacommittee.Contract.GetAmountOfMembers(&_Polygondatacommittee.CallOpts) -} - -// GetProcotolName is a free data retrieval call binding the contract method 0xe4f17120. -// -// Solidity: function getProcotolName() pure returns(string) -func (_Polygondatacommittee *PolygondatacommitteeCaller) GetProcotolName(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _Polygondatacommittee.contract.Call(opts, &out, "getProcotolName") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// GetProcotolName is a free data retrieval call binding the contract method 0xe4f17120. -// -// Solidity: function getProcotolName() pure returns(string) -func (_Polygondatacommittee *PolygondatacommitteeSession) GetProcotolName() (string, error) { - return _Polygondatacommittee.Contract.GetProcotolName(&_Polygondatacommittee.CallOpts) -} - -// GetProcotolName is a free data retrieval call binding the contract method 0xe4f17120. -// -// Solidity: function getProcotolName() pure returns(string) -func (_Polygondatacommittee *PolygondatacommitteeCallerSession) GetProcotolName() (string, error) { - return _Polygondatacommittee.Contract.GetProcotolName(&_Polygondatacommittee.CallOpts) -} - -// Members is a free data retrieval call binding the contract method 0x5daf08ca. -// -// Solidity: function members(uint256 ) view returns(string url, address addr) -func (_Polygondatacommittee *PolygondatacommitteeCaller) Members(opts *bind.CallOpts, arg0 *big.Int) (struct { - Url string - Addr common.Address -}, error) { - var out []interface{} - err := _Polygondatacommittee.contract.Call(opts, &out, "members", arg0) - - outstruct := new(struct { - Url string - Addr common.Address - }) - if err != nil { - return *outstruct, err - } - - outstruct.Url = *abi.ConvertType(out[0], new(string)).(*string) - outstruct.Addr = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) - - return *outstruct, err - -} - -// Members is a free data retrieval call binding the contract method 0x5daf08ca. -// -// Solidity: function members(uint256 ) view returns(string url, address addr) -func (_Polygondatacommittee *PolygondatacommitteeSession) Members(arg0 *big.Int) (struct { - Url string - Addr common.Address -}, error) { - return _Polygondatacommittee.Contract.Members(&_Polygondatacommittee.CallOpts, arg0) -} - -// Members is a free data retrieval call binding the contract method 0x5daf08ca. -// -// Solidity: function members(uint256 ) view returns(string url, address addr) -func (_Polygondatacommittee *PolygondatacommitteeCallerSession) Members(arg0 *big.Int) (struct { - Url string - Addr common.Address -}, error) { - return _Polygondatacommittee.Contract.Members(&_Polygondatacommittee.CallOpts, arg0) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Polygondatacommittee *PolygondatacommitteeCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Polygondatacommittee.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Polygondatacommittee *PolygondatacommitteeSession) Owner() (common.Address, error) { - return _Polygondatacommittee.Contract.Owner(&_Polygondatacommittee.CallOpts) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_Polygondatacommittee *PolygondatacommitteeCallerSession) Owner() (common.Address, error) { - return _Polygondatacommittee.Contract.Owner(&_Polygondatacommittee.CallOpts) -} - -// RequiredAmountOfSignatures is a free data retrieval call binding the contract method 0x6beedd39. -// -// Solidity: function requiredAmountOfSignatures() view returns(uint256) -func (_Polygondatacommittee *PolygondatacommitteeCaller) RequiredAmountOfSignatures(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Polygondatacommittee.contract.Call(opts, &out, "requiredAmountOfSignatures") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// RequiredAmountOfSignatures is a free data retrieval call binding the contract method 0x6beedd39. -// -// Solidity: function requiredAmountOfSignatures() view returns(uint256) -func (_Polygondatacommittee *PolygondatacommitteeSession) RequiredAmountOfSignatures() (*big.Int, error) { - return _Polygondatacommittee.Contract.RequiredAmountOfSignatures(&_Polygondatacommittee.CallOpts) -} - -// RequiredAmountOfSignatures is a free data retrieval call binding the contract method 0x6beedd39. -// -// Solidity: function requiredAmountOfSignatures() view returns(uint256) -func (_Polygondatacommittee *PolygondatacommitteeCallerSession) RequiredAmountOfSignatures() (*big.Int, error) { - return _Polygondatacommittee.Contract.RequiredAmountOfSignatures(&_Polygondatacommittee.CallOpts) -} - -// VerifyMessage is a free data retrieval call binding the contract method 0x3b51be4b. -// -// Solidity: function verifyMessage(bytes32 signedHash, bytes signaturesAndAddrs) view returns() -func (_Polygondatacommittee *PolygondatacommitteeCaller) VerifyMessage(opts *bind.CallOpts, signedHash [32]byte, signaturesAndAddrs []byte) error { - var out []interface{} - err := _Polygondatacommittee.contract.Call(opts, &out, "verifyMessage", signedHash, signaturesAndAddrs) - - if err != nil { - return err - } - - return err - -} - -// VerifyMessage is a free data retrieval call binding the contract method 0x3b51be4b. -// -// Solidity: function verifyMessage(bytes32 signedHash, bytes signaturesAndAddrs) view returns() -func (_Polygondatacommittee *PolygondatacommitteeSession) VerifyMessage(signedHash [32]byte, signaturesAndAddrs []byte) error { - return _Polygondatacommittee.Contract.VerifyMessage(&_Polygondatacommittee.CallOpts, signedHash, signaturesAndAddrs) -} - -// VerifyMessage is a free data retrieval call binding the contract method 0x3b51be4b. -// -// Solidity: function verifyMessage(bytes32 signedHash, bytes signaturesAndAddrs) view returns() -func (_Polygondatacommittee *PolygondatacommitteeCallerSession) VerifyMessage(signedHash [32]byte, signaturesAndAddrs []byte) error { - return _Polygondatacommittee.Contract.VerifyMessage(&_Polygondatacommittee.CallOpts, signedHash, signaturesAndAddrs) -} - -// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. -// -// Solidity: function initialize() returns() -func (_Polygondatacommittee *PolygondatacommitteeTransactor) Initialize(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Polygondatacommittee.contract.Transact(opts, "initialize") -} - -// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. -// -// Solidity: function initialize() returns() -func (_Polygondatacommittee *PolygondatacommitteeSession) Initialize() (*types.Transaction, error) { - return _Polygondatacommittee.Contract.Initialize(&_Polygondatacommittee.TransactOpts) -} - -// Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. -// -// Solidity: function initialize() returns() -func (_Polygondatacommittee *PolygondatacommitteeTransactorSession) Initialize() (*types.Transaction, error) { - return _Polygondatacommittee.Contract.Initialize(&_Polygondatacommittee.TransactOpts) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Polygondatacommittee *PolygondatacommitteeTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Polygondatacommittee.contract.Transact(opts, "renounceOwnership") -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Polygondatacommittee *PolygondatacommitteeSession) RenounceOwnership() (*types.Transaction, error) { - return _Polygondatacommittee.Contract.RenounceOwnership(&_Polygondatacommittee.TransactOpts) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_Polygondatacommittee *PolygondatacommitteeTransactorSession) RenounceOwnership() (*types.Transaction, error) { - return _Polygondatacommittee.Contract.RenounceOwnership(&_Polygondatacommittee.TransactOpts) -} - -// SetupCommittee is a paid mutator transaction binding the contract method 0x078fba2a. -// -// Solidity: function setupCommittee(uint256 _requiredAmountOfSignatures, string[] urls, bytes addrsBytes) returns() -func (_Polygondatacommittee *PolygondatacommitteeTransactor) SetupCommittee(opts *bind.TransactOpts, _requiredAmountOfSignatures *big.Int, urls []string, addrsBytes []byte) (*types.Transaction, error) { - return _Polygondatacommittee.contract.Transact(opts, "setupCommittee", _requiredAmountOfSignatures, urls, addrsBytes) -} - -// SetupCommittee is a paid mutator transaction binding the contract method 0x078fba2a. -// -// Solidity: function setupCommittee(uint256 _requiredAmountOfSignatures, string[] urls, bytes addrsBytes) returns() -func (_Polygondatacommittee *PolygondatacommitteeSession) SetupCommittee(_requiredAmountOfSignatures *big.Int, urls []string, addrsBytes []byte) (*types.Transaction, error) { - return _Polygondatacommittee.Contract.SetupCommittee(&_Polygondatacommittee.TransactOpts, _requiredAmountOfSignatures, urls, addrsBytes) -} - -// SetupCommittee is a paid mutator transaction binding the contract method 0x078fba2a. -// -// Solidity: function setupCommittee(uint256 _requiredAmountOfSignatures, string[] urls, bytes addrsBytes) returns() -func (_Polygondatacommittee *PolygondatacommitteeTransactorSession) SetupCommittee(_requiredAmountOfSignatures *big.Int, urls []string, addrsBytes []byte) (*types.Transaction, error) { - return _Polygondatacommittee.Contract.SetupCommittee(&_Polygondatacommittee.TransactOpts, _requiredAmountOfSignatures, urls, addrsBytes) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Polygondatacommittee *PolygondatacommitteeTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { - return _Polygondatacommittee.contract.Transact(opts, "transferOwnership", newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Polygondatacommittee *PolygondatacommitteeSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _Polygondatacommittee.Contract.TransferOwnership(&_Polygondatacommittee.TransactOpts, newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_Polygondatacommittee *PolygondatacommitteeTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _Polygondatacommittee.Contract.TransferOwnership(&_Polygondatacommittee.TransactOpts, newOwner) -} - -// PolygondatacommitteeCommitteeUpdatedIterator is returned from FilterCommitteeUpdated and is used to iterate over the raw logs and unpacked data for CommitteeUpdated events raised by the Polygondatacommittee contract. -type PolygondatacommitteeCommitteeUpdatedIterator struct { - Event *PolygondatacommitteeCommitteeUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *PolygondatacommitteeCommitteeUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(PolygondatacommitteeCommitteeUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(PolygondatacommitteeCommitteeUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *PolygondatacommitteeCommitteeUpdatedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *PolygondatacommitteeCommitteeUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// PolygondatacommitteeCommitteeUpdated represents a CommitteeUpdated event raised by the Polygondatacommittee contract. -type PolygondatacommitteeCommitteeUpdated struct { - CommitteeHash [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterCommitteeUpdated is a free log retrieval operation binding the contract event 0x831403fd381b3e6ac875d912ec2eee0e0203d0d29f7b3e0c96fc8f582d6db657. -// -// Solidity: event CommitteeUpdated(bytes32 committeeHash) -func (_Polygondatacommittee *PolygondatacommitteeFilterer) FilterCommitteeUpdated(opts *bind.FilterOpts) (*PolygondatacommitteeCommitteeUpdatedIterator, error) { - - logs, sub, err := _Polygondatacommittee.contract.FilterLogs(opts, "CommitteeUpdated") - if err != nil { - return nil, err - } - return &PolygondatacommitteeCommitteeUpdatedIterator{contract: _Polygondatacommittee.contract, event: "CommitteeUpdated", logs: logs, sub: sub}, nil -} - -// WatchCommitteeUpdated is a free log subscription operation binding the contract event 0x831403fd381b3e6ac875d912ec2eee0e0203d0d29f7b3e0c96fc8f582d6db657. -// -// Solidity: event CommitteeUpdated(bytes32 committeeHash) -func (_Polygondatacommittee *PolygondatacommitteeFilterer) WatchCommitteeUpdated(opts *bind.WatchOpts, sink chan<- *PolygondatacommitteeCommitteeUpdated) (event.Subscription, error) { - - logs, sub, err := _Polygondatacommittee.contract.WatchLogs(opts, "CommitteeUpdated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(PolygondatacommitteeCommitteeUpdated) - if err := _Polygondatacommittee.contract.UnpackLog(event, "CommitteeUpdated", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseCommitteeUpdated is a log parse operation binding the contract event 0x831403fd381b3e6ac875d912ec2eee0e0203d0d29f7b3e0c96fc8f582d6db657. -// -// Solidity: event CommitteeUpdated(bytes32 committeeHash) -func (_Polygondatacommittee *PolygondatacommitteeFilterer) ParseCommitteeUpdated(log types.Log) (*PolygondatacommitteeCommitteeUpdated, error) { - event := new(PolygondatacommitteeCommitteeUpdated) - if err := _Polygondatacommittee.contract.UnpackLog(event, "CommitteeUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// PolygondatacommitteeInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Polygondatacommittee contract. -type PolygondatacommitteeInitializedIterator struct { - Event *PolygondatacommitteeInitialized // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *PolygondatacommitteeInitializedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(PolygondatacommitteeInitialized) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(PolygondatacommitteeInitialized) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *PolygondatacommitteeInitializedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *PolygondatacommitteeInitializedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// PolygondatacommitteeInitialized represents a Initialized event raised by the Polygondatacommittee contract. -type PolygondatacommitteeInitialized struct { - Version uint8 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Polygondatacommittee *PolygondatacommitteeFilterer) FilterInitialized(opts *bind.FilterOpts) (*PolygondatacommitteeInitializedIterator, error) { - - logs, sub, err := _Polygondatacommittee.contract.FilterLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return &PolygondatacommitteeInitializedIterator{contract: _Polygondatacommittee.contract, event: "Initialized", logs: logs, sub: sub}, nil -} - -// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Polygondatacommittee *PolygondatacommitteeFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *PolygondatacommitteeInitialized) (event.Subscription, error) { - - logs, sub, err := _Polygondatacommittee.contract.WatchLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(PolygondatacommitteeInitialized) - if err := _Polygondatacommittee.contract.UnpackLog(event, "Initialized", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Polygondatacommittee *PolygondatacommitteeFilterer) ParseInitialized(log types.Log) (*PolygondatacommitteeInitialized, error) { - event := new(PolygondatacommitteeInitialized) - if err := _Polygondatacommittee.contract.UnpackLog(event, "Initialized", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// PolygondatacommitteeOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Polygondatacommittee contract. -type PolygondatacommitteeOwnershipTransferredIterator struct { - Event *PolygondatacommitteeOwnershipTransferred // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *PolygondatacommitteeOwnershipTransferredIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(PolygondatacommitteeOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(PolygondatacommitteeOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *PolygondatacommitteeOwnershipTransferredIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *PolygondatacommitteeOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// PolygondatacommitteeOwnershipTransferred represents a OwnershipTransferred event raised by the Polygondatacommittee contract. -type PolygondatacommitteeOwnershipTransferred struct { - PreviousOwner common.Address - NewOwner common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_Polygondatacommittee *PolygondatacommitteeFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*PolygondatacommitteeOwnershipTransferredIterator, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _Polygondatacommittee.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return &PolygondatacommitteeOwnershipTransferredIterator{contract: _Polygondatacommittee.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_Polygondatacommittee *PolygondatacommitteeFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PolygondatacommitteeOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _Polygondatacommittee.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(PolygondatacommitteeOwnershipTransferred) - if err := _Polygondatacommittee.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_Polygondatacommittee *PolygondatacommitteeFilterer) ParseOwnershipTransferred(log types.Log) (*PolygondatacommitteeOwnershipTransferred, error) { - event := new(PolygondatacommitteeOwnershipTransferred) - if err := _Polygondatacommittee.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/go.mod b/go.mod index e49b7df1..7e9f2a30 100644 --- a/go.mod +++ b/go.mod @@ -1,24 +1,25 @@ module github.com/0xPolygon/cdk-data-availability -go 1.19 +go 1.21.3 require ( + github.com/0xPolygon/cdk-contracts-tooling v0.0.0-20240826154954-f6182d2b17a2 github.com/DATA-DOG/go-sqlmock v1.5.1 github.com/didip/tollbooth/v6 v6.1.2 - github.com/ethereum/go-ethereum v1.13.11 - github.com/gobuffalo/packr/v2 v2.8.3 + github.com/ethereum/go-ethereum v1.13.14 github.com/gorilla/websocket v1.5.0 github.com/hermeznetwork/tracerr v0.3.2 + github.com/iden3/go-iden3-crypto v0.0.16 github.com/invopop/jsonschema v0.7.0 github.com/jmoiron/sqlx v1.2.0 github.com/lib/pq v1.10.7 github.com/miguelmota/go-solidity-sha3 v0.1.1 github.com/mitchellh/mapstructure v1.5.0 github.com/rubenv/sql-migrate v1.5.2 - github.com/spf13/viper v1.16.0 + github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.8.4 github.com/umbracle/ethgo v0.1.4-0.20230712173909-df37dddf16f0 - github.com/urfave/cli/v2 v2.25.7 + github.com/urfave/cli/v2 v2.27.1 go.uber.org/zap v1.24.0 ) @@ -32,11 +33,11 @@ require ( github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-pkgz/expirable-cache v0.0.3 // indirect @@ -44,34 +45,32 @@ require ( github.com/gobuffalo/packd v1.0.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect github.com/karrick/godirwalk v1.17.0 // indirect - github.com/klauspost/compress v1.15.15 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/markbates/errx v1.1.0 // indirect - github.com/markbates/oncer v1.0.0 // indirect - github.com/markbates/safe v1.0.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - github.com/spf13/afero v1.9.5 // indirect - github.com/spf13/cast v1.5.1 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.0 // indirect - github.com/subosito/gotenv v1.4.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect @@ -82,17 +81,15 @@ require ( github.com/valyala/fastjson v1.4.1 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.8.0 // indirect + go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.3.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.15.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index dcf076ac..78062e26 100644 --- a/go.sum +++ b/go.sum @@ -1,140 +1,100 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/0xPolygon/cdk-contracts-tooling v0.0.0-20240426091844-5cd6921eed9f h1:EiChBxSyJxMjgPdbYWujqD32r991Yhffrm78STAXB4k= +github.com/0xPolygon/cdk-contracts-tooling v0.0.0-20240426091844-5cd6921eed9f/go.mod h1:mFlcEjsm2YBBsu8atHJ3zyVnwM+Z/fMXpVmIJge+WVU= +github.com/0xPolygon/cdk-contracts-tooling v0.0.0-20240826154954-f6182d2b17a2 h1:N5qvWG4amhUt6d1F4Kf8AdJZs4z7/xZfE3v/Im2afNM= +github.com/0xPolygon/cdk-contracts-tooling v0.0.0-20240826154954-f6182d2b17a2/go.mod h1:mFlcEjsm2YBBsu8atHJ3zyVnwM+Z/fMXpVmIJge+WVU= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/DATA-DOG/go-sqlmock v1.5.1 h1:FK6RCIUSfmbnI/imIICmboyQBkOckutaa6R5YYlLZyo= github.com/DATA-DOG/go-sqlmock v1.5.1/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= 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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/errors v1.8.1 h1:A5+txlVZfOqFBDa4mGz2bUWSp0aHElvHX2bKkdbQu+Y= +github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw= +github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= 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= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/didip/tollbooth/v6 v6.1.2 h1:Kdqxmqw9YTv0uKajBUiWQg+GURL/k4vy9gmLCL01PjQ= github.com/didip/tollbooth/v6 v6.1.2/go.mod h1:xjcse6CTHCLuOkzsWrEgdy9WPJFv+p/x6v+MyfP+O9s= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.11 h1:b51Dsm+rEg7anFRUMGB8hODXHvNfcRKzz9vcj8wSdUs= -github.com/ethereum/go-ethereum v1.13.11/go.mod h1:gFtlVORuUcT+UUIcJ/veCNjkuOSujCi338uSHJrYAew= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/ethereum/go-ethereum v1.13.14 h1:EwiY3FZP94derMCIam1iW4HFVrSgIcpsu0HwTQtm6CQ= +github.com/ethereum/go-ethereum v1.13.14/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU= +github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= +github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -144,165 +104,96 @@ github.com/go-pkgz/expirable-cache v0.0.3 h1:rTh6qNPp78z0bQE6HDhXBHUwqnV9i09Vm6d github.com/go-pkgz/expirable-cache v0.0.3/go.mod h1:+IauqN00R2FqNRLCLA+X5YljQJrwB179PfiAoMPlTlQ= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= github.com/gobuffalo/logger v1.0.7 h1:LTLwWelETXDYyqF/ASf0nxaIcdEOIJNxRokPcfI/xbU= github.com/gobuffalo/logger v1.0.7/go.mod h1:u40u6Bq3VVvaMcy5sRBclD8SXhBYPS0Qk95ubt+1xJM= -github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= github.com/gobuffalo/packd v1.0.2 h1:Yg523YqnOxGIWCp69W12yYBKsoChwI7mtu6ceM9Bwfw= github.com/gobuffalo/packd v1.0.2/go.mod h1:sUc61tDqGMXON80zpKGp92lDb86Km28jfvX7IAyxFT8= github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +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= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hermeznetwork/tracerr v0.3.2 h1:QB3TlQxO/4XHyixsg+nRZPuoel/FFQlQ7oAoHDD5l1c= github.com/hermeznetwork/tracerr v0.3.2/go.mod h1:nsWC1+tc4qUEbUGRv4DcPJJTjLsedlPajlFmpJoohK4= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/iden3/go-iden3-crypto v0.0.16 h1:zN867xiz6HgErXVIV/6WyteGcOukE9gybYTorBMEdsk= +github.com/iden3/go-iden3-crypto v0.0.16/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy770So= github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/karrick/godirwalk v1.17.0 h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwSWoI= github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 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/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= @@ -311,37 +202,30 @@ github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miguelmota/go-solidity-sha3 v0.1.1 h1:3Y08sKZDtudtE5kbTBPC9RYJznoSYyWI9VD6mghU0CA= github.com/miguelmota/go-solidity-sha3 v0.1.1/go.mod h1:sax1FvQF+f71j8W1uUHMZn8NxKyl5rYLks2nqj8RFEw= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= @@ -352,88 +236,75 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +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/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= +github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 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/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0= github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= @@ -443,12 +314,13 @@ github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0h github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/umbracle/ethgo v0.1.4-0.20230712173909-df37dddf16f0 h1:wE2g4ydxJk8kdRIRq69zZvnhJ49ShS2BJSzFBFdMv6I= github.com/umbracle/ethgo v0.1.4-0.20230712173909-df37dddf16f0/go.mod h1:J+OZNfRCtbaYW3AEc0m47GhwAzlNJjcr9vO86nzOr6E= github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 h1:10Nbw6cACsnQm7r34zlpJky+IzxVLRk6MKTS2d3Vp0E= github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4= -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/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= +github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.40.0 h1:CRq/00MfruPGFLTQKY8b+8SfdK60TxNztjRMnH0t1Yc= @@ -458,212 +330,63 @@ github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7E github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 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.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -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= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/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-20190227155943-e225da77a7e6/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -675,77 +398,18 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -753,108 +417,12 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= @@ -862,33 +430,20 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw 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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/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= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/log/config.go b/log/config.go index f30be52b..763999ad 100644 --- a/log/config.go +++ b/log/config.go @@ -3,11 +3,13 @@ package log // Config for log type Config struct { // Environment defining the log format ("production" or "development"). - // In development mode enables development mode (which makes DPanicLevel logs panic), uses a console encoder, writes to standard error, and disables sampling. Stacktraces are automatically included on logs of WarnLevel and above. + // In development mode enables development mode (which makes DPanicLevel logs panic), + // uses a console encoder, writes to standard error, and disables sampling. + // Stacktraces are automatically included on logs of WarnLevel and above. // Check [here](https://pkg.go.dev/go.uber.org/zap@v1.24.0#NewDevelopmentConfig) Environment Environment `mapstructure:"Environment" jsonschema:"enum=production,enum=development"` // Level of log. As lower value more logs are going to be generated - Level string `mapstructure:"Level" jsonschema:"enum=debug,enum=info,enum=warn,enum=error,enum=dpanic,enum=panic,enum=fatal"` + Level string `mapstructure:"Level" jsonschema:"enum=debug,enum=info,enum=warn,enum=error,enum=dpanic,enum=panic,enum=fatal"` //nolint:lll // Outputs Outputs []string `mapstructure:"Outputs"` } diff --git a/log/log.go b/log/log.go index 4fe9c35d..a46ce5a6 100644 --- a/log/log.go +++ b/log/log.go @@ -91,10 +91,10 @@ func NewLogger(cfg Config) (*zap.SugaredLogger, *zap.AtomicLevel, error) { if err != nil { return nil, nil, err } - defer logger.Sync() //nolint:gosec,errcheck + defer logger.Sync() //nolint:errcheck // skip 2 callers: one for our wrapper methods and one for the package functions - withOptions := logger.WithOptions(zap.AddCallerSkip(2)) //nolint:gomnd + withOptions := logger.WithOptions(zap.AddCallerSkip(2)) //nolint:mnd return withOptions.Sugar(), &level, nil } @@ -104,7 +104,7 @@ func WithFields(keyValuePairs ...interface{}) *Logger { l := getDefaultLog().WithFields(keyValuePairs...) // since we are returning a new instance, remove one caller from the - // stack, because we'll be calling the retruned Logger methods + // stack, because we'll be calling the returned Logger methods // directly, not the package functions. x := l.x.WithOptions(zap.AddCallerSkip(-1)) l.x = x diff --git a/mocks/client.generated.go b/mocks/client.generated.go index 1bcf5872..9bee557b 100644 --- a/mocks/client.generated.go +++ b/mocks/client.generated.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks @@ -84,9 +84,126 @@ func (_c *Client_GetOffChainData_Call) RunAndReturn(run func(context.Context, co return _c } -// SignSequence provides a mock function with given fields: signedSequence -func (_m *Client) SignSequence(signedSequence types.SignedSequence) ([]byte, error) { - ret := _m.Called(signedSequence) +// GetStatus provides a mock function with given fields: ctx +func (_m *Client) GetStatus(ctx context.Context) (*types.DACStatus, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetStatus") + } + + var r0 *types.DACStatus + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*types.DACStatus, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *types.DACStatus); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.DACStatus) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_GetStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetStatus' +type Client_GetStatus_Call struct { + *mock.Call +} + +// GetStatus is a helper method to define mock.On call +// - ctx context.Context +func (_e *Client_Expecter) GetStatus(ctx interface{}) *Client_GetStatus_Call { + return &Client_GetStatus_Call{Call: _e.mock.On("GetStatus", ctx)} +} + +func (_c *Client_GetStatus_Call) Run(run func(ctx context.Context)) *Client_GetStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Client_GetStatus_Call) Return(_a0 *types.DACStatus, _a1 error) *Client_GetStatus_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_GetStatus_Call) RunAndReturn(run func(context.Context) (*types.DACStatus, error)) *Client_GetStatus_Call { + _c.Call.Return(run) + return _c +} + +// ListOffChainData provides a mock function with given fields: ctx, hashes +func (_m *Client) ListOffChainData(ctx context.Context, hashes []common.Hash) (map[common.Hash][]byte, error) { + ret := _m.Called(ctx, hashes) + + if len(ret) == 0 { + panic("no return value specified for ListOffChainData") + } + + var r0 map[common.Hash][]byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []common.Hash) (map[common.Hash][]byte, error)); ok { + return rf(ctx, hashes) + } + if rf, ok := ret.Get(0).(func(context.Context, []common.Hash) map[common.Hash][]byte); ok { + r0 = rf(ctx, hashes) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[common.Hash][]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []common.Hash) error); ok { + r1 = rf(ctx, hashes) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_ListOffChainData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListOffChainData' +type Client_ListOffChainData_Call struct { + *mock.Call +} + +// ListOffChainData is a helper method to define mock.On call +// - ctx context.Context +// - hashes []common.Hash +func (_e *Client_Expecter) ListOffChainData(ctx interface{}, hashes interface{}) *Client_ListOffChainData_Call { + return &Client_ListOffChainData_Call{Call: _e.mock.On("ListOffChainData", ctx, hashes)} +} + +func (_c *Client_ListOffChainData_Call) Run(run func(ctx context.Context, hashes []common.Hash)) *Client_ListOffChainData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]common.Hash)) + }) + return _c +} + +func (_c *Client_ListOffChainData_Call) Return(_a0 map[common.Hash][]byte, _a1 error) *Client_ListOffChainData_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_ListOffChainData_Call) RunAndReturn(run func(context.Context, []common.Hash) (map[common.Hash][]byte, error)) *Client_ListOffChainData_Call { + _c.Call.Return(run) + return _c +} + +// SignSequence provides a mock function with given fields: ctx, signedSequence +func (_m *Client) SignSequence(ctx context.Context, signedSequence types.SignedSequence) ([]byte, error) { + ret := _m.Called(ctx, signedSequence) if len(ret) == 0 { panic("no return value specified for SignSequence") @@ -94,19 +211,19 @@ func (_m *Client) SignSequence(signedSequence types.SignedSequence) ([]byte, err var r0 []byte var r1 error - if rf, ok := ret.Get(0).(func(types.SignedSequence) ([]byte, error)); ok { - return rf(signedSequence) + if rf, ok := ret.Get(0).(func(context.Context, types.SignedSequence) ([]byte, error)); ok { + return rf(ctx, signedSequence) } - if rf, ok := ret.Get(0).(func(types.SignedSequence) []byte); ok { - r0 = rf(signedSequence) + if rf, ok := ret.Get(0).(func(context.Context, types.SignedSequence) []byte); ok { + r0 = rf(ctx, signedSequence) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]byte) } } - if rf, ok := ret.Get(1).(func(types.SignedSequence) error); ok { - r1 = rf(signedSequence) + if rf, ok := ret.Get(1).(func(context.Context, types.SignedSequence) error); ok { + r1 = rf(ctx, signedSequence) } else { r1 = ret.Error(1) } @@ -120,14 +237,15 @@ type Client_SignSequence_Call struct { } // SignSequence is a helper method to define mock.On call +// - ctx context.Context // - signedSequence types.SignedSequence -func (_e *Client_Expecter) SignSequence(signedSequence interface{}) *Client_SignSequence_Call { - return &Client_SignSequence_Call{Call: _e.mock.On("SignSequence", signedSequence)} +func (_e *Client_Expecter) SignSequence(ctx interface{}, signedSequence interface{}) *Client_SignSequence_Call { + return &Client_SignSequence_Call{Call: _e.mock.On("SignSequence", ctx, signedSequence)} } -func (_c *Client_SignSequence_Call) Run(run func(signedSequence types.SignedSequence)) *Client_SignSequence_Call { +func (_c *Client_SignSequence_Call) Run(run func(ctx context.Context, signedSequence types.SignedSequence)) *Client_SignSequence_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.SignedSequence)) + run(args[0].(context.Context), args[1].(types.SignedSequence)) }) return _c } @@ -137,7 +255,66 @@ func (_c *Client_SignSequence_Call) Return(_a0 []byte, _a1 error) *Client_SignSe return _c } -func (_c *Client_SignSequence_Call) RunAndReturn(run func(types.SignedSequence) ([]byte, error)) *Client_SignSequence_Call { +func (_c *Client_SignSequence_Call) RunAndReturn(run func(context.Context, types.SignedSequence) ([]byte, error)) *Client_SignSequence_Call { + _c.Call.Return(run) + return _c +} + +// SignSequenceBanana provides a mock function with given fields: ctx, signedSequence +func (_m *Client) SignSequenceBanana(ctx context.Context, signedSequence types.SignedSequenceBanana) ([]byte, error) { + ret := _m.Called(ctx, signedSequence) + + if len(ret) == 0 { + panic("no return value specified for SignSequenceBanana") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, types.SignedSequenceBanana) ([]byte, error)); ok { + return rf(ctx, signedSequence) + } + if rf, ok := ret.Get(0).(func(context.Context, types.SignedSequenceBanana) []byte); ok { + r0 = rf(ctx, signedSequence) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, types.SignedSequenceBanana) error); ok { + r1 = rf(ctx, signedSequence) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_SignSequenceBanana_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SignSequenceBanana' +type Client_SignSequenceBanana_Call struct { + *mock.Call +} + +// SignSequenceBanana is a helper method to define mock.On call +// - ctx context.Context +// - signedSequence types.SignedSequenceBanana +func (_e *Client_Expecter) SignSequenceBanana(ctx interface{}, signedSequence interface{}) *Client_SignSequenceBanana_Call { + return &Client_SignSequenceBanana_Call{Call: _e.mock.On("SignSequenceBanana", ctx, signedSequence)} +} + +func (_c *Client_SignSequenceBanana_Call) Run(run func(ctx context.Context, signedSequence types.SignedSequenceBanana)) *Client_SignSequenceBanana_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.SignedSequenceBanana)) + }) + return _c +} + +func (_c *Client_SignSequenceBanana_Call) Return(_a0 []byte, _a1 error) *Client_SignSequenceBanana_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Client_SignSequenceBanana_Call) RunAndReturn(run func(context.Context, types.SignedSequenceBanana) ([]byte, error)) *Client_SignSequenceBanana_Call { _c.Call.Return(run) return _c } diff --git a/mocks/client_factory.generated.go b/mocks/client_factory.generated.go index 694661f4..6d22a522 100644 --- a/mocks/client_factory.generated.go +++ b/mocks/client_factory.generated.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/mocks/db.generated.go b/mocks/db.generated.go index 06e1b116..d21533c9 100644 --- a/mocks/db.generated.go +++ b/mocks/db.generated.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks @@ -7,12 +7,8 @@ import ( common "github.com/ethereum/go-ethereum/common" - db "github.com/0xPolygon/cdk-data-availability/db" - mock "github.com/stretchr/testify/mock" - sqlx "github.com/jmoiron/sqlx" - types "github.com/0xPolygon/cdk-data-availability/types" ) @@ -29,25 +25,23 @@ func (_m *DB) EXPECT() *DB_Expecter { return &DB_Expecter{mock: &_m.Mock} } -// BeginStateTransaction provides a mock function with given fields: ctx -func (_m *DB) BeginStateTransaction(ctx context.Context) (db.Tx, error) { +// CountOffchainData provides a mock function with given fields: ctx +func (_m *DB) CountOffchainData(ctx context.Context) (uint64, error) { ret := _m.Called(ctx) if len(ret) == 0 { - panic("no return value specified for BeginStateTransaction") + panic("no return value specified for CountOffchainData") } - var r0 db.Tx + var r0 uint64 var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (db.Tx, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { return rf(ctx) } - if rf, ok := ret.Get(0).(func(context.Context) db.Tx); ok { + if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { r0 = rf(ctx) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(db.Tx) - } + r0 = ret.Get(0).(uint64) } if rf, ok := ret.Get(1).(func(context.Context) error); ok { @@ -59,77 +53,135 @@ func (_m *DB) BeginStateTransaction(ctx context.Context) (db.Tx, error) { return r0, r1 } -// DB_BeginStateTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BeginStateTransaction' -type DB_BeginStateTransaction_Call struct { +// DB_CountOffchainData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CountOffchainData' +type DB_CountOffchainData_Call struct { *mock.Call } -// BeginStateTransaction is a helper method to define mock.On call +// CountOffchainData is a helper method to define mock.On call // - ctx context.Context -func (_e *DB_Expecter) BeginStateTransaction(ctx interface{}) *DB_BeginStateTransaction_Call { - return &DB_BeginStateTransaction_Call{Call: _e.mock.On("BeginStateTransaction", ctx)} +func (_e *DB_Expecter) CountOffchainData(ctx interface{}) *DB_CountOffchainData_Call { + return &DB_CountOffchainData_Call{Call: _e.mock.On("CountOffchainData", ctx)} } -func (_c *DB_BeginStateTransaction_Call) Run(run func(ctx context.Context)) *DB_BeginStateTransaction_Call { +func (_c *DB_CountOffchainData_Call) Run(run func(ctx context.Context)) *DB_CountOffchainData_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context)) }) return _c } -func (_c *DB_BeginStateTransaction_Call) Return(_a0 db.Tx, _a1 error) *DB_BeginStateTransaction_Call { +func (_c *DB_CountOffchainData_Call) Return(_a0 uint64, _a1 error) *DB_CountOffchainData_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *DB_BeginStateTransaction_Call) RunAndReturn(run func(context.Context) (db.Tx, error)) *DB_BeginStateTransaction_Call { +func (_c *DB_CountOffchainData_Call) RunAndReturn(run func(context.Context) (uint64, error)) *DB_CountOffchainData_Call { _c.Call.Return(run) return _c } -// Exists provides a mock function with given fields: ctx, key -func (_m *DB) Exists(ctx context.Context, key common.Hash) bool { - ret := _m.Called(ctx, key) +// DeleteUnresolvedBatchKeys provides a mock function with given fields: ctx, bks +func (_m *DB) DeleteUnresolvedBatchKeys(ctx context.Context, bks []types.BatchKey) error { + ret := _m.Called(ctx, bks) if len(ret) == 0 { - panic("no return value specified for Exists") + panic("no return value specified for DeleteUnresolvedBatchKeys") } - var r0 bool - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) bool); ok { - r0 = rf(ctx, key) + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []types.BatchKey) error); ok { + r0 = rf(ctx, bks) } else { - r0 = ret.Get(0).(bool) + r0 = ret.Error(0) } return r0 } -// DB_Exists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Exists' -type DB_Exists_Call struct { +// DB_DeleteUnresolvedBatchKeys_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteUnresolvedBatchKeys' +type DB_DeleteUnresolvedBatchKeys_Call struct { *mock.Call } -// Exists is a helper method to define mock.On call +// DeleteUnresolvedBatchKeys is a helper method to define mock.On call // - ctx context.Context -// - key common.Hash -func (_e *DB_Expecter) Exists(ctx interface{}, key interface{}) *DB_Exists_Call { - return &DB_Exists_Call{Call: _e.mock.On("Exists", ctx, key)} +// - bks []types.BatchKey +func (_e *DB_Expecter) DeleteUnresolvedBatchKeys(ctx interface{}, bks interface{}) *DB_DeleteUnresolvedBatchKeys_Call { + return &DB_DeleteUnresolvedBatchKeys_Call{Call: _e.mock.On("DeleteUnresolvedBatchKeys", ctx, bks)} } -func (_c *DB_Exists_Call) Run(run func(ctx context.Context, key common.Hash)) *DB_Exists_Call { +func (_c *DB_DeleteUnresolvedBatchKeys_Call) Run(run func(ctx context.Context, bks []types.BatchKey)) *DB_DeleteUnresolvedBatchKeys_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Hash)) + run(args[0].(context.Context), args[1].([]types.BatchKey)) }) return _c } -func (_c *DB_Exists_Call) Return(_a0 bool) *DB_Exists_Call { +func (_c *DB_DeleteUnresolvedBatchKeys_Call) Return(_a0 error) *DB_DeleteUnresolvedBatchKeys_Call { _c.Call.Return(_a0) return _c } -func (_c *DB_Exists_Call) RunAndReturn(run func(context.Context, common.Hash) bool) *DB_Exists_Call { +func (_c *DB_DeleteUnresolvedBatchKeys_Call) RunAndReturn(run func(context.Context, []types.BatchKey) error) *DB_DeleteUnresolvedBatchKeys_Call { + _c.Call.Return(run) + return _c +} + +// DetectOffchainDataGaps provides a mock function with given fields: ctx +func (_m *DB) DetectOffchainDataGaps(ctx context.Context) (map[uint64]uint64, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for DetectOffchainDataGaps") + } + + var r0 map[uint64]uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (map[uint64]uint64, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) map[uint64]uint64); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[uint64]uint64) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DB_DetectOffchainDataGaps_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DetectOffchainDataGaps' +type DB_DetectOffchainDataGaps_Call struct { + *mock.Call +} + +// DetectOffchainDataGaps is a helper method to define mock.On call +// - ctx context.Context +func (_e *DB_Expecter) DetectOffchainDataGaps(ctx interface{}) *DB_DetectOffchainDataGaps_Call { + return &DB_DetectOffchainDataGaps_Call{Call: _e.mock.On("DetectOffchainDataGaps", ctx)} +} + +func (_c *DB_DetectOffchainDataGaps_Call) Run(run func(ctx context.Context)) *DB_DetectOffchainDataGaps_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *DB_DetectOffchainDataGaps_Call) Return(_a0 map[uint64]uint64, _a1 error) *DB_DetectOffchainDataGaps_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DB_DetectOffchainDataGaps_Call) RunAndReturn(run func(context.Context) (map[uint64]uint64, error)) *DB_DetectOffchainDataGaps_Call { _c.Call.Return(run) return _c } @@ -191,29 +243,29 @@ func (_c *DB_GetLastProcessedBlock_Call) RunAndReturn(run func(context.Context, return _c } -// GetOffChainData provides a mock function with given fields: ctx, key, dbTx -func (_m *DB) GetOffChainData(ctx context.Context, key common.Hash, dbTx sqlx.QueryerContext) (types.ArgBytes, error) { - ret := _m.Called(ctx, key, dbTx) +// GetOffChainData provides a mock function with given fields: ctx, key +func (_m *DB) GetOffChainData(ctx context.Context, key common.Hash) (*types.OffChainData, error) { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for GetOffChainData") } - var r0 types.ArgBytes + var r0 *types.OffChainData var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, sqlx.QueryerContext) (types.ArgBytes, error)); ok { - return rf(ctx, key, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.OffChainData, error)); ok { + return rf(ctx, key) } - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, sqlx.QueryerContext) types.ArgBytes); ok { - r0 = rf(ctx, key, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.OffChainData); ok { + r0 = rf(ctx, key) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(types.ArgBytes) + r0 = ret.Get(0).(*types.OffChainData) } } - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, sqlx.QueryerContext) error); ok { - r1 = rf(ctx, key, dbTx) + if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { + r1 = rf(ctx, key) } else { r1 = ret.Error(1) } @@ -229,39 +281,156 @@ type DB_GetOffChainData_Call struct { // GetOffChainData is a helper method to define mock.On call // - ctx context.Context // - key common.Hash -// - dbTx sqlx.QueryerContext -func (_e *DB_Expecter) GetOffChainData(ctx interface{}, key interface{}, dbTx interface{}) *DB_GetOffChainData_Call { - return &DB_GetOffChainData_Call{Call: _e.mock.On("GetOffChainData", ctx, key, dbTx)} +func (_e *DB_Expecter) GetOffChainData(ctx interface{}, key interface{}) *DB_GetOffChainData_Call { + return &DB_GetOffChainData_Call{Call: _e.mock.On("GetOffChainData", ctx, key)} } -func (_c *DB_GetOffChainData_Call) Run(run func(ctx context.Context, key common.Hash, dbTx sqlx.QueryerContext)) *DB_GetOffChainData_Call { +func (_c *DB_GetOffChainData_Call) Run(run func(ctx context.Context, key common.Hash)) *DB_GetOffChainData_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Hash), args[2].(sqlx.QueryerContext)) + run(args[0].(context.Context), args[1].(common.Hash)) }) return _c } -func (_c *DB_GetOffChainData_Call) Return(_a0 types.ArgBytes, _a1 error) *DB_GetOffChainData_Call { +func (_c *DB_GetOffChainData_Call) Return(_a0 *types.OffChainData, _a1 error) *DB_GetOffChainData_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *DB_GetOffChainData_Call) RunAndReturn(run func(context.Context, common.Hash, sqlx.QueryerContext) (types.ArgBytes, error)) *DB_GetOffChainData_Call { +func (_c *DB_GetOffChainData_Call) RunAndReturn(run func(context.Context, common.Hash) (*types.OffChainData, error)) *DB_GetOffChainData_Call { _c.Call.Return(run) return _c } -// StoreLastProcessedBlock provides a mock function with given fields: ctx, task, block, dbTx -func (_m *DB) StoreLastProcessedBlock(ctx context.Context, task string, block uint64, dbTx sqlx.ExecerContext) error { - ret := _m.Called(ctx, task, block, dbTx) +// GetUnresolvedBatchKeys provides a mock function with given fields: ctx, limit +func (_m *DB) GetUnresolvedBatchKeys(ctx context.Context, limit uint) ([]types.BatchKey, error) { + ret := _m.Called(ctx, limit) + + if len(ret) == 0 { + panic("no return value specified for GetUnresolvedBatchKeys") + } + + var r0 []types.BatchKey + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint) ([]types.BatchKey, error)); ok { + return rf(ctx, limit) + } + if rf, ok := ret.Get(0).(func(context.Context, uint) []types.BatchKey); ok { + r0 = rf(ctx, limit) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]types.BatchKey) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint) error); ok { + r1 = rf(ctx, limit) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DB_GetUnresolvedBatchKeys_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUnresolvedBatchKeys' +type DB_GetUnresolvedBatchKeys_Call struct { + *mock.Call +} + +// GetUnresolvedBatchKeys is a helper method to define mock.On call +// - ctx context.Context +// - limit uint +func (_e *DB_Expecter) GetUnresolvedBatchKeys(ctx interface{}, limit interface{}) *DB_GetUnresolvedBatchKeys_Call { + return &DB_GetUnresolvedBatchKeys_Call{Call: _e.mock.On("GetUnresolvedBatchKeys", ctx, limit)} +} + +func (_c *DB_GetUnresolvedBatchKeys_Call) Run(run func(ctx context.Context, limit uint)) *DB_GetUnresolvedBatchKeys_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint)) + }) + return _c +} + +func (_c *DB_GetUnresolvedBatchKeys_Call) Return(_a0 []types.BatchKey, _a1 error) *DB_GetUnresolvedBatchKeys_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DB_GetUnresolvedBatchKeys_Call) RunAndReturn(run func(context.Context, uint) ([]types.BatchKey, error)) *DB_GetUnresolvedBatchKeys_Call { + _c.Call.Return(run) + return _c +} + +// ListOffChainData provides a mock function with given fields: ctx, keys +func (_m *DB) ListOffChainData(ctx context.Context, keys []common.Hash) ([]types.OffChainData, error) { + ret := _m.Called(ctx, keys) + + if len(ret) == 0 { + panic("no return value specified for ListOffChainData") + } + + var r0 []types.OffChainData + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []common.Hash) ([]types.OffChainData, error)); ok { + return rf(ctx, keys) + } + if rf, ok := ret.Get(0).(func(context.Context, []common.Hash) []types.OffChainData); ok { + r0 = rf(ctx, keys) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]types.OffChainData) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []common.Hash) error); ok { + r1 = rf(ctx, keys) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DB_ListOffChainData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListOffChainData' +type DB_ListOffChainData_Call struct { + *mock.Call +} + +// ListOffChainData is a helper method to define mock.On call +// - ctx context.Context +// - keys []common.Hash +func (_e *DB_Expecter) ListOffChainData(ctx interface{}, keys interface{}) *DB_ListOffChainData_Call { + return &DB_ListOffChainData_Call{Call: _e.mock.On("ListOffChainData", ctx, keys)} +} + +func (_c *DB_ListOffChainData_Call) Run(run func(ctx context.Context, keys []common.Hash)) *DB_ListOffChainData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]common.Hash)) + }) + return _c +} + +func (_c *DB_ListOffChainData_Call) Return(_a0 []types.OffChainData, _a1 error) *DB_ListOffChainData_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DB_ListOffChainData_Call) RunAndReturn(run func(context.Context, []common.Hash) ([]types.OffChainData, error)) *DB_ListOffChainData_Call { + _c.Call.Return(run) + return _c +} + +// StoreLastProcessedBlock provides a mock function with given fields: ctx, block, task +func (_m *DB) StoreLastProcessedBlock(ctx context.Context, block uint64, task string) error { + ret := _m.Called(ctx, block, task) if len(ret) == 0 { panic("no return value specified for StoreLastProcessedBlock") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, uint64, sqlx.ExecerContext) error); ok { - r0 = rf(ctx, task, block, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, uint64, string) error); ok { + r0 = rf(ctx, block, task) } else { r0 = ret.Error(0) } @@ -276,16 +445,15 @@ type DB_StoreLastProcessedBlock_Call struct { // StoreLastProcessedBlock is a helper method to define mock.On call // - ctx context.Context -// - task string // - block uint64 -// - dbTx sqlx.ExecerContext -func (_e *DB_Expecter) StoreLastProcessedBlock(ctx interface{}, task interface{}, block interface{}, dbTx interface{}) *DB_StoreLastProcessedBlock_Call { - return &DB_StoreLastProcessedBlock_Call{Call: _e.mock.On("StoreLastProcessedBlock", ctx, task, block, dbTx)} +// - task string +func (_e *DB_Expecter) StoreLastProcessedBlock(ctx interface{}, block interface{}, task interface{}) *DB_StoreLastProcessedBlock_Call { + return &DB_StoreLastProcessedBlock_Call{Call: _e.mock.On("StoreLastProcessedBlock", ctx, block, task)} } -func (_c *DB_StoreLastProcessedBlock_Call) Run(run func(ctx context.Context, task string, block uint64, dbTx sqlx.ExecerContext)) *DB_StoreLastProcessedBlock_Call { +func (_c *DB_StoreLastProcessedBlock_Call) Run(run func(ctx context.Context, block uint64, task string)) *DB_StoreLastProcessedBlock_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(uint64), args[3].(sqlx.ExecerContext)) + run(args[0].(context.Context), args[1].(uint64), args[2].(string)) }) return _c } @@ -295,22 +463,22 @@ func (_c *DB_StoreLastProcessedBlock_Call) Return(_a0 error) *DB_StoreLastProces return _c } -func (_c *DB_StoreLastProcessedBlock_Call) RunAndReturn(run func(context.Context, string, uint64, sqlx.ExecerContext) error) *DB_StoreLastProcessedBlock_Call { +func (_c *DB_StoreLastProcessedBlock_Call) RunAndReturn(run func(context.Context, uint64, string) error) *DB_StoreLastProcessedBlock_Call { _c.Call.Return(run) return _c } -// StoreOffChainData provides a mock function with given fields: ctx, od, dbTx -func (_m *DB) StoreOffChainData(ctx context.Context, od []types.OffChainData, dbTx sqlx.ExecerContext) error { - ret := _m.Called(ctx, od, dbTx) +// StoreOffChainData provides a mock function with given fields: ctx, od +func (_m *DB) StoreOffChainData(ctx context.Context, od []types.OffChainData) error { + ret := _m.Called(ctx, od) if len(ret) == 0 { panic("no return value specified for StoreOffChainData") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []types.OffChainData, sqlx.ExecerContext) error); ok { - r0 = rf(ctx, od, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, []types.OffChainData) error); ok { + r0 = rf(ctx, od) } else { r0 = ret.Error(0) } @@ -326,14 +494,13 @@ type DB_StoreOffChainData_Call struct { // StoreOffChainData is a helper method to define mock.On call // - ctx context.Context // - od []types.OffChainData -// - dbTx sqlx.ExecerContext -func (_e *DB_Expecter) StoreOffChainData(ctx interface{}, od interface{}, dbTx interface{}) *DB_StoreOffChainData_Call { - return &DB_StoreOffChainData_Call{Call: _e.mock.On("StoreOffChainData", ctx, od, dbTx)} +func (_e *DB_Expecter) StoreOffChainData(ctx interface{}, od interface{}) *DB_StoreOffChainData_Call { + return &DB_StoreOffChainData_Call{Call: _e.mock.On("StoreOffChainData", ctx, od)} } -func (_c *DB_StoreOffChainData_Call) Run(run func(ctx context.Context, od []types.OffChainData, dbTx sqlx.ExecerContext)) *DB_StoreOffChainData_Call { +func (_c *DB_StoreOffChainData_Call) Run(run func(ctx context.Context, od []types.OffChainData)) *DB_StoreOffChainData_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]types.OffChainData), args[2].(sqlx.ExecerContext)) + run(args[0].(context.Context), args[1].([]types.OffChainData)) }) return _c } @@ -343,7 +510,54 @@ func (_c *DB_StoreOffChainData_Call) Return(_a0 error) *DB_StoreOffChainData_Cal return _c } -func (_c *DB_StoreOffChainData_Call) RunAndReturn(run func(context.Context, []types.OffChainData, sqlx.ExecerContext) error) *DB_StoreOffChainData_Call { +func (_c *DB_StoreOffChainData_Call) RunAndReturn(run func(context.Context, []types.OffChainData) error) *DB_StoreOffChainData_Call { + _c.Call.Return(run) + return _c +} + +// StoreUnresolvedBatchKeys provides a mock function with given fields: ctx, bks +func (_m *DB) StoreUnresolvedBatchKeys(ctx context.Context, bks []types.BatchKey) error { + ret := _m.Called(ctx, bks) + + if len(ret) == 0 { + panic("no return value specified for StoreUnresolvedBatchKeys") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []types.BatchKey) error); ok { + r0 = rf(ctx, bks) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DB_StoreUnresolvedBatchKeys_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StoreUnresolvedBatchKeys' +type DB_StoreUnresolvedBatchKeys_Call struct { + *mock.Call +} + +// StoreUnresolvedBatchKeys is a helper method to define mock.On call +// - ctx context.Context +// - bks []types.BatchKey +func (_e *DB_Expecter) StoreUnresolvedBatchKeys(ctx interface{}, bks interface{}) *DB_StoreUnresolvedBatchKeys_Call { + return &DB_StoreUnresolvedBatchKeys_Call{Call: _e.mock.On("StoreUnresolvedBatchKeys", ctx, bks)} +} + +func (_c *DB_StoreUnresolvedBatchKeys_Call) Run(run func(ctx context.Context, bks []types.BatchKey)) *DB_StoreUnresolvedBatchKeys_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].([]types.BatchKey)) + }) + return _c +} + +func (_c *DB_StoreUnresolvedBatchKeys_Call) Return(_a0 error) *DB_StoreUnresolvedBatchKeys_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *DB_StoreUnresolvedBatchKeys_Call) RunAndReturn(run func(context.Context, []types.BatchKey) error) *DB_StoreUnresolvedBatchKeys_Call { _c.Call.Return(run) return _c } diff --git a/mocks/eth_client.generated.go b/mocks/eth_client.generated.go deleted file mode 100644 index 2cbfe779..00000000 --- a/mocks/eth_client.generated.go +++ /dev/null @@ -1,161 +0,0 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. - -package mocks - -import ( - big "math/big" - - common "github.com/ethereum/go-ethereum/common" - - context "context" - - mock "github.com/stretchr/testify/mock" - - types "github.com/ethereum/go-ethereum/core/types" -) - -// EthClient is an autogenerated mock type for the EthClient type -type EthClient struct { - mock.Mock -} - -type EthClient_Expecter struct { - mock *mock.Mock -} - -func (_m *EthClient) EXPECT() *EthClient_Expecter { - return &EthClient_Expecter{mock: &_m.Mock} -} - -// BlockByNumber provides a mock function with given fields: ctx, number -func (_m *EthClient) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - ret := _m.Called(ctx, number) - - if len(ret) == 0 { - panic("no return value specified for BlockByNumber") - } - - var r0 *types.Block - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Block, error)); ok { - return rf(ctx, number) - } - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *types.Block); ok { - r0 = rf(ctx, number) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Block) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { - r1 = rf(ctx, number) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EthClient_BlockByNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockByNumber' -type EthClient_BlockByNumber_Call struct { - *mock.Call -} - -// BlockByNumber is a helper method to define mock.On call -// - ctx context.Context -// - number *big.Int -func (_e *EthClient_Expecter) BlockByNumber(ctx interface{}, number interface{}) *EthClient_BlockByNumber_Call { - return &EthClient_BlockByNumber_Call{Call: _e.mock.On("BlockByNumber", ctx, number)} -} - -func (_c *EthClient_BlockByNumber_Call) Run(run func(ctx context.Context, number *big.Int)) *EthClient_BlockByNumber_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*big.Int)) - }) - return _c -} - -func (_c *EthClient_BlockByNumber_Call) Return(_a0 *types.Block, _a1 error) *EthClient_BlockByNumber_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EthClient_BlockByNumber_Call) RunAndReturn(run func(context.Context, *big.Int) (*types.Block, error)) *EthClient_BlockByNumber_Call { - _c.Call.Return(run) - return _c -} - -// CodeAt provides a mock function with given fields: ctx, account, blockNumber -func (_m *EthClient) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { - ret := _m.Called(ctx, account, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for CodeAt") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) ([]byte, error)); ok { - return rf(ctx, account, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) []byte); ok { - r0 = rf(ctx, account, blockNumber) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { - r1 = rf(ctx, account, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EthClient_CodeAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CodeAt' -type EthClient_CodeAt_Call struct { - *mock.Call -} - -// CodeAt is a helper method to define mock.On call -// - ctx context.Context -// - account common.Address -// - blockNumber *big.Int -func (_e *EthClient_Expecter) CodeAt(ctx interface{}, account interface{}, blockNumber interface{}) *EthClient_CodeAt_Call { - return &EthClient_CodeAt_Call{Call: _e.mock.On("CodeAt", ctx, account, blockNumber)} -} - -func (_c *EthClient_CodeAt_Call) Run(run func(ctx context.Context, account common.Address, blockNumber *big.Int)) *EthClient_CodeAt_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Address), args[2].(*big.Int)) - }) - return _c -} - -func (_c *EthClient_CodeAt_Call) Return(_a0 []byte, _a1 error) *EthClient_CodeAt_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EthClient_CodeAt_Call) RunAndReturn(run func(context.Context, common.Address, *big.Int) ([]byte, error)) *EthClient_CodeAt_Call { - _c.Call.Return(run) - return _c -} - -// NewEthClient creates a new instance of EthClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewEthClient(t interface { - mock.TestingT - Cleanup(func()) -}) *EthClient { - mock := &EthClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/mocks/eth_client_factory.generated.go b/mocks/eth_client_factory.generated.go deleted file mode 100644 index 6cbfd230..00000000 --- a/mocks/eth_client_factory.generated.go +++ /dev/null @@ -1,96 +0,0 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. - -package mocks - -import ( - context "context" - - types "github.com/0xPolygon/cdk-data-availability/types" - mock "github.com/stretchr/testify/mock" -) - -// EthClientFactory is an autogenerated mock type for the EthClientFactory type -type EthClientFactory struct { - mock.Mock -} - -type EthClientFactory_Expecter struct { - mock *mock.Mock -} - -func (_m *EthClientFactory) EXPECT() *EthClientFactory_Expecter { - return &EthClientFactory_Expecter{mock: &_m.Mock} -} - -// CreateEthClient provides a mock function with given fields: ctx, url -func (_m *EthClientFactory) CreateEthClient(ctx context.Context, url string) (types.EthClient, error) { - ret := _m.Called(ctx, url) - - if len(ret) == 0 { - panic("no return value specified for CreateEthClient") - } - - var r0 types.EthClient - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (types.EthClient, error)); ok { - return rf(ctx, url) - } - if rf, ok := ret.Get(0).(func(context.Context, string) types.EthClient); ok { - r0 = rf(ctx, url) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.EthClient) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, url) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EthClientFactory_CreateEthClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateEthClient' -type EthClientFactory_CreateEthClient_Call struct { - *mock.Call -} - -// CreateEthClient is a helper method to define mock.On call -// - ctx context.Context -// - url string -func (_e *EthClientFactory_Expecter) CreateEthClient(ctx interface{}, url interface{}) *EthClientFactory_CreateEthClient_Call { - return &EthClientFactory_CreateEthClient_Call{Call: _e.mock.On("CreateEthClient", ctx, url)} -} - -func (_c *EthClientFactory_CreateEthClient_Call) Run(run func(ctx context.Context, url string)) *EthClientFactory_CreateEthClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *EthClientFactory_CreateEthClient_Call) Return(_a0 types.EthClient, _a1 error) *EthClientFactory_CreateEthClient_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *EthClientFactory_CreateEthClient_Call) RunAndReturn(run func(context.Context, string) (types.EthClient, error)) *EthClientFactory_CreateEthClient_Call { - _c.Call.Return(run) - return _c -} - -// NewEthClientFactory creates a new instance of EthClientFactory. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewEthClientFactory(t interface { - mock.TestingT - Cleanup(func()) -}) *EthClientFactory { - mock := &EthClientFactory{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/mocks/etherman.generated.go b/mocks/etherman.generated.go index 2a94e12d..3b19727e 100644 --- a/mocks/etherman.generated.go +++ b/mocks/etherman.generated.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks @@ -16,7 +16,7 @@ import ( mock "github.com/stretchr/testify/mock" - polygonvalidium "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygonvalidium" + polygonvalidiumetrog "github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonvalidiumetrog" types "github.com/ethereum/go-ethereum/core/types" ) @@ -34,24 +34,143 @@ func (_m *Etherman) EXPECT() *Etherman_Expecter { return &Etherman_Expecter{mock: &_m.Mock} } +// BlockByNumber provides a mock function with given fields: ctx, number +func (_m *Etherman) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { + ret := _m.Called(ctx, number) + + if len(ret) == 0 { + panic("no return value specified for BlockByNumber") + } + + var r0 *types.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Block, error)); ok { + return rf(ctx, number) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *types.Block); ok { + r0 = rf(ctx, number) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(ctx, number) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Etherman_BlockByNumber_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockByNumber' +type Etherman_BlockByNumber_Call struct { + *mock.Call +} + +// BlockByNumber is a helper method to define mock.On call +// - ctx context.Context +// - number *big.Int +func (_e *Etherman_Expecter) BlockByNumber(ctx interface{}, number interface{}) *Etherman_BlockByNumber_Call { + return &Etherman_BlockByNumber_Call{Call: _e.mock.On("BlockByNumber", ctx, number)} +} + +func (_c *Etherman_BlockByNumber_Call) Run(run func(ctx context.Context, number *big.Int)) *Etherman_BlockByNumber_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int)) + }) + return _c +} + +func (_c *Etherman_BlockByNumber_Call) Return(_a0 *types.Block, _a1 error) *Etherman_BlockByNumber_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Etherman_BlockByNumber_Call) RunAndReturn(run func(context.Context, *big.Int) (*types.Block, error)) *Etherman_BlockByNumber_Call { + _c.Call.Return(run) + return _c +} + +// CodeAt provides a mock function with given fields: ctx, account, blockNumber +func (_m *Etherman) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { + ret := _m.Called(ctx, account, blockNumber) + + if len(ret) == 0 { + panic("no return value specified for CodeAt") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) ([]byte, error)); ok { + return rf(ctx, account, blockNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) []byte); ok { + r0 = rf(ctx, account, blockNumber) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { + r1 = rf(ctx, account, blockNumber) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Etherman_CodeAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CodeAt' +type Etherman_CodeAt_Call struct { + *mock.Call +} + +// CodeAt is a helper method to define mock.On call +// - ctx context.Context +// - account common.Address +// - blockNumber *big.Int +func (_e *Etherman_Expecter) CodeAt(ctx interface{}, account interface{}, blockNumber interface{}) *Etherman_CodeAt_Call { + return &Etherman_CodeAt_Call{Call: _e.mock.On("CodeAt", ctx, account, blockNumber)} +} + +func (_c *Etherman_CodeAt_Call) Run(run func(ctx context.Context, account common.Address, blockNumber *big.Int)) *Etherman_CodeAt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(common.Address), args[2].(*big.Int)) + }) + return _c +} + +func (_c *Etherman_CodeAt_Call) Return(_a0 []byte, _a1 error) *Etherman_CodeAt_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Etherman_CodeAt_Call) RunAndReturn(run func(context.Context, common.Address, *big.Int) ([]byte, error)) *Etherman_CodeAt_Call { + _c.Call.Return(run) + return _c +} + // FilterSequenceBatches provides a mock function with given fields: opts, numBatch -func (_m *Etherman) FilterSequenceBatches(opts *bind.FilterOpts, numBatch []uint64) (*polygonvalidium.PolygonvalidiumSequenceBatchesIterator, error) { +func (_m *Etherman) FilterSequenceBatches(opts *bind.FilterOpts, numBatch []uint64) (*polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatchesIterator, error) { ret := _m.Called(opts, numBatch) if len(ret) == 0 { panic("no return value specified for FilterSequenceBatches") } - var r0 *polygonvalidium.PolygonvalidiumSequenceBatchesIterator + var r0 *polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatchesIterator var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*polygonvalidium.PolygonvalidiumSequenceBatchesIterator, error)); ok { + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatchesIterator, error)); ok { return rf(opts, numBatch) } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *polygonvalidium.PolygonvalidiumSequenceBatchesIterator); ok { + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatchesIterator); ok { r0 = rf(opts, numBatch) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*polygonvalidium.PolygonvalidiumSequenceBatchesIterator) + r0 = ret.Get(0).(*polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatchesIterator) } } @@ -83,12 +202,12 @@ func (_c *Etherman_FilterSequenceBatches_Call) Run(run func(opts *bind.FilterOpt return _c } -func (_c *Etherman_FilterSequenceBatches_Call) Return(_a0 *polygonvalidium.PolygonvalidiumSequenceBatchesIterator, _a1 error) *Etherman_FilterSequenceBatches_Call { +func (_c *Etherman_FilterSequenceBatches_Call) Return(_a0 *polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatchesIterator, _a1 error) *Etherman_FilterSequenceBatches_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *Etherman_FilterSequenceBatches_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*polygonvalidium.PolygonvalidiumSequenceBatchesIterator, error)) *Etherman_FilterSequenceBatches_Call { +func (_c *Etherman_FilterSequenceBatches_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatchesIterator, error)) *Etherman_FilterSequenceBatches_Call { _c.Call.Return(run) return _c } @@ -332,9 +451,9 @@ func (_c *Etherman_HeaderByNumber_Call) RunAndReturn(run func(context.Context, * return _c } -// TrustedSequencer provides a mock function with given fields: -func (_m *Etherman) TrustedSequencer() (common.Address, error) { - ret := _m.Called() +// TrustedSequencer provides a mock function with given fields: ctx +func (_m *Etherman) TrustedSequencer(ctx context.Context) (common.Address, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for TrustedSequencer") @@ -342,19 +461,19 @@ func (_m *Etherman) TrustedSequencer() (common.Address, error) { var r0 common.Address var r1 error - if rf, ok := ret.Get(0).(func() (common.Address, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (common.Address, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() common.Address); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) common.Address); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(common.Address) } } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -368,13 +487,14 @@ type Etherman_TrustedSequencer_Call struct { } // TrustedSequencer is a helper method to define mock.On call -func (_e *Etherman_Expecter) TrustedSequencer() *Etherman_TrustedSequencer_Call { - return &Etherman_TrustedSequencer_Call{Call: _e.mock.On("TrustedSequencer")} +// - ctx context.Context +func (_e *Etherman_Expecter) TrustedSequencer(ctx interface{}) *Etherman_TrustedSequencer_Call { + return &Etherman_TrustedSequencer_Call{Call: _e.mock.On("TrustedSequencer", ctx)} } -func (_c *Etherman_TrustedSequencer_Call) Run(run func()) *Etherman_TrustedSequencer_Call { +func (_c *Etherman_TrustedSequencer_Call) Run(run func(ctx context.Context)) *Etherman_TrustedSequencer_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -384,14 +504,14 @@ func (_c *Etherman_TrustedSequencer_Call) Return(_a0 common.Address, _a1 error) return _c } -func (_c *Etherman_TrustedSequencer_Call) RunAndReturn(run func() (common.Address, error)) *Etherman_TrustedSequencer_Call { +func (_c *Etherman_TrustedSequencer_Call) RunAndReturn(run func(context.Context) (common.Address, error)) *Etherman_TrustedSequencer_Call { _c.Call.Return(run) return _c } -// TrustedSequencerURL provides a mock function with given fields: -func (_m *Etherman) TrustedSequencerURL() (string, error) { - ret := _m.Called() +// TrustedSequencerURL provides a mock function with given fields: ctx +func (_m *Etherman) TrustedSequencerURL(ctx context.Context) (string, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for TrustedSequencerURL") @@ -399,17 +519,17 @@ func (_m *Etherman) TrustedSequencerURL() (string, error) { var r0 string var r1 error - if rf, ok := ret.Get(0).(func() (string, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (string, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) string); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(string) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -423,13 +543,14 @@ type Etherman_TrustedSequencerURL_Call struct { } // TrustedSequencerURL is a helper method to define mock.On call -func (_e *Etherman_Expecter) TrustedSequencerURL() *Etherman_TrustedSequencerURL_Call { - return &Etherman_TrustedSequencerURL_Call{Call: _e.mock.On("TrustedSequencerURL")} +// - ctx context.Context +func (_e *Etherman_Expecter) TrustedSequencerURL(ctx interface{}) *Etherman_TrustedSequencerURL_Call { + return &Etherman_TrustedSequencerURL_Call{Call: _e.mock.On("TrustedSequencerURL", ctx)} } -func (_c *Etherman_TrustedSequencerURL_Call) Run(run func()) *Etherman_TrustedSequencerURL_Call { +func (_c *Etherman_TrustedSequencerURL_Call) Run(run func(ctx context.Context)) *Etherman_TrustedSequencerURL_Call { _c.Call.Run(func(args mock.Arguments) { - run() + run(args[0].(context.Context)) }) return _c } @@ -439,13 +560,13 @@ func (_c *Etherman_TrustedSequencerURL_Call) Return(_a0 string, _a1 error) *Ethe return _c } -func (_c *Etherman_TrustedSequencerURL_Call) RunAndReturn(run func() (string, error)) *Etherman_TrustedSequencerURL_Call { +func (_c *Etherman_TrustedSequencerURL_Call) RunAndReturn(run func(context.Context) (string, error)) *Etherman_TrustedSequencerURL_Call { _c.Call.Return(run) return _c } // WatchSetTrustedSequencer provides a mock function with given fields: ctx, events -func (_m *Etherman) WatchSetTrustedSequencer(ctx context.Context, events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer) (event.Subscription, error) { +func (_m *Etherman) WatchSetTrustedSequencer(ctx context.Context, events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer) (event.Subscription, error) { ret := _m.Called(ctx, events) if len(ret) == 0 { @@ -454,10 +575,10 @@ func (_m *Etherman) WatchSetTrustedSequencer(ctx context.Context, events chan *p var r0 event.Subscription var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer) (event.Subscription, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer) (event.Subscription, error)); ok { return rf(ctx, events) } - if rf, ok := ret.Get(0).(func(context.Context, chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer) event.Subscription); ok { + if rf, ok := ret.Get(0).(func(context.Context, chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer) event.Subscription); ok { r0 = rf(ctx, events) } else { if ret.Get(0) != nil { @@ -465,7 +586,7 @@ func (_m *Etherman) WatchSetTrustedSequencer(ctx context.Context, events chan *p } } - if rf, ok := ret.Get(1).(func(context.Context, chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer) error); ok { r1 = rf(ctx, events) } else { r1 = ret.Error(1) @@ -481,14 +602,14 @@ type Etherman_WatchSetTrustedSequencer_Call struct { // WatchSetTrustedSequencer is a helper method to define mock.On call // - ctx context.Context -// - events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer +// - events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer func (_e *Etherman_Expecter) WatchSetTrustedSequencer(ctx interface{}, events interface{}) *Etherman_WatchSetTrustedSequencer_Call { return &Etherman_WatchSetTrustedSequencer_Call{Call: _e.mock.On("WatchSetTrustedSequencer", ctx, events)} } -func (_c *Etherman_WatchSetTrustedSequencer_Call) Run(run func(ctx context.Context, events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer)) *Etherman_WatchSetTrustedSequencer_Call { +func (_c *Etherman_WatchSetTrustedSequencer_Call) Run(run func(ctx context.Context, events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer)) *Etherman_WatchSetTrustedSequencer_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer)) + run(args[0].(context.Context), args[1].(chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer)) }) return _c } @@ -498,13 +619,13 @@ func (_c *Etherman_WatchSetTrustedSequencer_Call) Return(_a0 event.Subscription, return _c } -func (_c *Etherman_WatchSetTrustedSequencer_Call) RunAndReturn(run func(context.Context, chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer) (event.Subscription, error)) *Etherman_WatchSetTrustedSequencer_Call { +func (_c *Etherman_WatchSetTrustedSequencer_Call) RunAndReturn(run func(context.Context, chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer) (event.Subscription, error)) *Etherman_WatchSetTrustedSequencer_Call { _c.Call.Return(run) return _c } // WatchSetTrustedSequencerURL provides a mock function with given fields: ctx, events -func (_m *Etherman) WatchSetTrustedSequencerURL(ctx context.Context, events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL) (event.Subscription, error) { +func (_m *Etherman) WatchSetTrustedSequencerURL(ctx context.Context, events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL) (event.Subscription, error) { ret := _m.Called(ctx, events) if len(ret) == 0 { @@ -513,10 +634,10 @@ func (_m *Etherman) WatchSetTrustedSequencerURL(ctx context.Context, events chan var r0 event.Subscription var r1 error - if rf, ok := ret.Get(0).(func(context.Context, chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL) (event.Subscription, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL) (event.Subscription, error)); ok { return rf(ctx, events) } - if rf, ok := ret.Get(0).(func(context.Context, chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL) event.Subscription); ok { + if rf, ok := ret.Get(0).(func(context.Context, chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL) event.Subscription); ok { r0 = rf(ctx, events) } else { if ret.Get(0) != nil { @@ -524,7 +645,7 @@ func (_m *Etherman) WatchSetTrustedSequencerURL(ctx context.Context, events chan } } - if rf, ok := ret.Get(1).(func(context.Context, chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL) error); ok { r1 = rf(ctx, events) } else { r1 = ret.Error(1) @@ -540,14 +661,14 @@ type Etherman_WatchSetTrustedSequencerURL_Call struct { // WatchSetTrustedSequencerURL is a helper method to define mock.On call // - ctx context.Context -// - events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL +// - events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL func (_e *Etherman_Expecter) WatchSetTrustedSequencerURL(ctx interface{}, events interface{}) *Etherman_WatchSetTrustedSequencerURL_Call { return &Etherman_WatchSetTrustedSequencerURL_Call{Call: _e.mock.On("WatchSetTrustedSequencerURL", ctx, events)} } -func (_c *Etherman_WatchSetTrustedSequencerURL_Call) Run(run func(ctx context.Context, events chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL)) *Etherman_WatchSetTrustedSequencerURL_Call { +func (_c *Etherman_WatchSetTrustedSequencerURL_Call) Run(run func(ctx context.Context, events chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL)) *Etherman_WatchSetTrustedSequencerURL_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL)) + run(args[0].(context.Context), args[1].(chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL)) }) return _c } @@ -557,7 +678,7 @@ func (_c *Etherman_WatchSetTrustedSequencerURL_Call) Return(_a0 event.Subscripti return _c } -func (_c *Etherman_WatchSetTrustedSequencerURL_Call) RunAndReturn(run func(context.Context, chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL) (event.Subscription, error)) *Etherman_WatchSetTrustedSequencerURL_Call { +func (_c *Etherman_WatchSetTrustedSequencerURL_Call) RunAndReturn(run func(context.Context, chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL) (event.Subscription, error)) *Etherman_WatchSetTrustedSequencerURL_Call { _c.Call.Return(run) return _c } diff --git a/mocks/gaps_detector.generated.go b/mocks/gaps_detector.generated.go new file mode 100644 index 00000000..a3f3f982 --- /dev/null +++ b/mocks/gaps_detector.generated.go @@ -0,0 +1,79 @@ +// Code generated by mockery v2.40.1. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// GapsDetector is an autogenerated mock type for the GapsDetector type +type GapsDetector struct { + mock.Mock +} + +type GapsDetector_Expecter struct { + mock *mock.Mock +} + +func (_m *GapsDetector) EXPECT() *GapsDetector_Expecter { + return &GapsDetector_Expecter{mock: &_m.Mock} +} + +// Gaps provides a mock function with given fields: +func (_m *GapsDetector) Gaps() map[uint64]uint64 { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Gaps") + } + + var r0 map[uint64]uint64 + if rf, ok := ret.Get(0).(func() map[uint64]uint64); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[uint64]uint64) + } + } + + return r0 +} + +// GapsDetector_Gaps_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Gaps' +type GapsDetector_Gaps_Call struct { + *mock.Call +} + +// Gaps is a helper method to define mock.On call +func (_e *GapsDetector_Expecter) Gaps() *GapsDetector_Gaps_Call { + return &GapsDetector_Gaps_Call{Call: _e.mock.On("Gaps")} +} + +func (_c *GapsDetector_Gaps_Call) Run(run func()) *GapsDetector_Gaps_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GapsDetector_Gaps_Call) Return(_a0 map[uint64]uint64) *GapsDetector_Gaps_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GapsDetector_Gaps_Call) RunAndReturn(run func() map[uint64]uint64) *GapsDetector_Gaps_Call { + _c.Call.Return(run) + return _c +} + +// NewGapsDetector creates a new instance of GapsDetector. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewGapsDetector(t interface { + mock.TestingT + Cleanup(func()) +}) *GapsDetector { + mock := &GapsDetector{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/sequencer_tracker.generated.go b/mocks/sequencer_tracker.generated.go index f821ca0e..5c21c7df 100644 --- a/mocks/sequencer_tracker.generated.go +++ b/mocks/sequencer_tracker.generated.go @@ -1,8 +1,10 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks import ( + context "context" + sequencer "github.com/0xPolygon/cdk-data-availability/sequencer" mock "github.com/stretchr/testify/mock" ) @@ -20,9 +22,9 @@ func (_m *SequencerTracker) EXPECT() *SequencerTracker_Expecter { return &SequencerTracker_Expecter{mock: &_m.Mock} } -// GetSequenceBatch provides a mock function with given fields: batchNum -func (_m *SequencerTracker) GetSequenceBatch(batchNum uint64) (*sequencer.SeqBatch, error) { - ret := _m.Called(batchNum) +// GetSequenceBatch provides a mock function with given fields: ctx, batchNum +func (_m *SequencerTracker) GetSequenceBatch(ctx context.Context, batchNum uint64) (*sequencer.SeqBatch, error) { + ret := _m.Called(ctx, batchNum) if len(ret) == 0 { panic("no return value specified for GetSequenceBatch") @@ -30,19 +32,19 @@ func (_m *SequencerTracker) GetSequenceBatch(batchNum uint64) (*sequencer.SeqBat var r0 *sequencer.SeqBatch var r1 error - if rf, ok := ret.Get(0).(func(uint64) (*sequencer.SeqBatch, error)); ok { - return rf(batchNum) + if rf, ok := ret.Get(0).(func(context.Context, uint64) (*sequencer.SeqBatch, error)); ok { + return rf(ctx, batchNum) } - if rf, ok := ret.Get(0).(func(uint64) *sequencer.SeqBatch); ok { - r0 = rf(batchNum) + if rf, ok := ret.Get(0).(func(context.Context, uint64) *sequencer.SeqBatch); ok { + r0 = rf(ctx, batchNum) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*sequencer.SeqBatch) } } - if rf, ok := ret.Get(1).(func(uint64) error); ok { - r1 = rf(batchNum) + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, batchNum) } else { r1 = ret.Error(1) } @@ -56,14 +58,15 @@ type SequencerTracker_GetSequenceBatch_Call struct { } // GetSequenceBatch is a helper method to define mock.On call +// - ctx context.Context // - batchNum uint64 -func (_e *SequencerTracker_Expecter) GetSequenceBatch(batchNum interface{}) *SequencerTracker_GetSequenceBatch_Call { - return &SequencerTracker_GetSequenceBatch_Call{Call: _e.mock.On("GetSequenceBatch", batchNum)} +func (_e *SequencerTracker_Expecter) GetSequenceBatch(ctx interface{}, batchNum interface{}) *SequencerTracker_GetSequenceBatch_Call { + return &SequencerTracker_GetSequenceBatch_Call{Call: _e.mock.On("GetSequenceBatch", ctx, batchNum)} } -func (_c *SequencerTracker_GetSequenceBatch_Call) Run(run func(batchNum uint64)) *SequencerTracker_GetSequenceBatch_Call { +func (_c *SequencerTracker_GetSequenceBatch_Call) Run(run func(ctx context.Context, batchNum uint64)) *SequencerTracker_GetSequenceBatch_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(uint64)) + run(args[0].(context.Context), args[1].(uint64)) }) return _c } @@ -73,7 +76,7 @@ func (_c *SequencerTracker_GetSequenceBatch_Call) Return(_a0 *sequencer.SeqBatch return _c } -func (_c *SequencerTracker_GetSequenceBatch_Call) RunAndReturn(run func(uint64) (*sequencer.SeqBatch, error)) *SequencerTracker_GetSequenceBatch_Call { +func (_c *SequencerTracker_GetSequenceBatch_Call) RunAndReturn(run func(context.Context, uint64) (*sequencer.SeqBatch, error)) *SequencerTracker_GetSequenceBatch_Call { _c.Call.Return(run) return _c } diff --git a/mocks/subscription.generated.go b/mocks/subscription.generated.go index 00f0a861..9119936e 100644 --- a/mocks/subscription.generated.go +++ b/mocks/subscription.generated.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/mocks/tx.generated.go b/mocks/tx.generated.go index 6ff9b243..2f3a0e6d 100644 --- a/mocks/tx.generated.go +++ b/mocks/tx.generated.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.40.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/packaging/deb/cdk-data-availability/DEBIAN/postinst b/packaging/deb/cdk-data-availability/DEBIAN/postinst new file mode 100755 index 00000000..77695dd7 --- /dev/null +++ b/packaging/deb/cdk-data-availability/DEBIAN/postinst @@ -0,0 +1,12 @@ +#!/bin/bash +# This is a postinstallation script so the service can be configured and started when requested +# +sudo adduser --disabled-password --disabled-login --shell /usr/sbin/nologin --quiet --system --no-create-home --home /nonexistent cdk-data-availability +if [ -d "/opt/cdk-data-availability" ] +then + echo "Directory /opt/cdk-data-availability exists." +else + sudo mkdir -p /opt/cdk-data-availability + sudo chown -R cdk-data-availability /opt/cdk-data-availability +fi +sudo systemctl daemon-reload diff --git a/packaging/deb/cdk-data-availability/DEBIAN/postrm b/packaging/deb/cdk-data-availability/DEBIAN/postrm new file mode 100755 index 00000000..e889b55c --- /dev/null +++ b/packaging/deb/cdk-data-availability/DEBIAN/postrm @@ -0,0 +1,8 @@ +#!/bin/bash +# +############### +# Remove cdk-data-availability installs +############## +sudo rm -rf /lib/systemd/system/cdk-data-availability.service +sudo deluser cdk-data-availability +sudo systemctl daemon-reload \ No newline at end of file diff --git a/packaging/package_scripts/systemd/cdk-data-availability.service b/packaging/package_scripts/systemd/cdk-data-availability.service new file mode 100644 index 00000000..e4c4cd26 --- /dev/null +++ b/packaging/package_scripts/systemd/cdk-data-availability.service @@ -0,0 +1,16 @@ +[Unit] + Description=cdk-data-availability-service + StartLimitIntervalSec=500 + StartLimitBurst=5 + +[Service] + Restart=on-failure + RestartSec=5s + ExecStart=/usr/bin/cdk-data-availability + Type=simple + KillSignal=SIGINT + User=cdk-data-availability + TimeoutStopSec=120 + +[Install] + WantedBy=multi-user.target \ No newline at end of file diff --git a/pkg/backoff/backoff.go b/pkg/backoff/backoff.go new file mode 100644 index 00000000..9476a2a9 --- /dev/null +++ b/pkg/backoff/backoff.go @@ -0,0 +1,16 @@ +package backoff + +import "time" + +// Exponential performs exponential backoff attempts on a given action +func Exponential(action func() error, attempts uint, wait time.Duration) error { + var err error + for i := uint(0); i < attempts; i++ { + if err = action(); err == nil { + return nil + } + time.Sleep(wait) + wait *= 2 + } + return err +} diff --git a/pkg/backoff/backoff_test.go b/pkg/backoff/backoff_test.go new file mode 100644 index 00000000..d22165b0 --- /dev/null +++ b/pkg/backoff/backoff_test.go @@ -0,0 +1,46 @@ +package backoff + +import ( + "errors" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestExponential(t *testing.T) { + t.Run("success", func(t *testing.T) { + i := 0 + outcomes := []bool{false, false, true} + t0 := time.Now() + err := Exponential(func() error { + outcome := outcomes[i] + i++ + if outcome { + return nil + } + return errors.New("bad") + }, 3, 150*time.Millisecond) + + elapsed := time.Since(t0) + + require.NoError(t, err) + require.Equal(t, i, 3) + require.True(t, elapsed >= 450*time.Millisecond) + }) + + t.Run("failed", func(t *testing.T) { + i := 0 + t0 := time.Now() + err := Exponential(func() error { + i++ + return errors.New("bad") + }, 3, 100*time.Millisecond) + + elapsed := time.Since(t0) + + require.Error(t, err) + require.Equal(t, i, 3) + require.True(t, elapsed >= 600*time.Millisecond) + }) +} diff --git a/rpc/client_test.go b/rpc/client_test.go index fc84f00e..c3178897 100644 --- a/rpc/client_test.go +++ b/rpc/client_test.go @@ -1,7 +1,6 @@ package rpc import ( - "context" "encoding/json" "errors" "fmt" @@ -13,6 +12,8 @@ import ( ) func Test_JSONRPCCallWithContext(t *testing.T) { + t.Parallel() + tests := []struct { name string result string @@ -53,7 +54,7 @@ func Test_JSONRPCCallWithContext(t *testing.T) { })) defer svr.Close() - got, err := JSONRPCCallWithContext(context.Background(), svr.URL, "test") + got, err := JSONRPCCall(svr.URL, "test") if tt.err != nil { require.Error(t, err) require.EqualError(t, tt.err, err.Error()) diff --git a/rpc/dbtxmanager.go b/rpc/dbtxmanager.go deleted file mode 100644 index 3475aeac..00000000 --- a/rpc/dbtxmanager.go +++ /dev/null @@ -1,36 +0,0 @@ -package rpc - -import ( - "context" - - "github.com/0xPolygon/cdk-data-availability/db" -) - -// DBTxManager allows to do scopped DB txs -type DBTxManager struct{} - -// DBTxScopedFn function to do scopped DB txs -type DBTxScopedFn func(ctx context.Context, dbTx db.Tx) (interface{}, Error) - -// NewDbTxScope function to initiate DB scopped txs -func (f *DBTxManager) NewDbTxScope(db db.DB, scopedFn DBTxScopedFn) (interface{}, Error) { - ctx := context.Background() - - dbTx, err := db.BeginStateTransaction(ctx) - if err != nil { - return RPCErrorResponse(DefaultErrorCode, "failed to connect to the state", err) - } - - v, rpcErr := scopedFn(ctx, dbTx) - if rpcErr != nil { - if txErr := dbTx.Rollback(); txErr != nil { - return RPCErrorResponse(DefaultErrorCode, "failed to rollback db transaction", txErr) - } - return v, rpcErr - } - - if txErr := dbTx.Commit(); txErr != nil { - return RPCErrorResponse(DefaultErrorCode, "failed to commit db transaction", txErr) - } - return v, rpcErr -} diff --git a/rpc/dbtxmanager_test.go b/rpc/dbtxmanager_test.go deleted file mode 100644 index 71c2bb01..00000000 --- a/rpc/dbtxmanager_test.go +++ /dev/null @@ -1,116 +0,0 @@ -package rpc_test - -import ( - "context" - "errors" - "testing" - - "github.com/0xPolygon/cdk-data-availability/db" - "github.com/0xPolygon/cdk-data-availability/mocks" - "github.com/0xPolygon/cdk-data-availability/rpc" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" -) - -func TestDBTxManager_NewDbTxScope(t *testing.T) { - testTable := []struct { - name string - db func(db *mocks.DB) *mocks.Tx - scopedFn rpc.DBTxScopedFn - expected interface{} - returnErr error - }{ - { - name: "successfully executed scoped function", - db: func(dbMock *mocks.DB) *mocks.Tx { - txMock := mocks.NewTx(t) - dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil) - txMock.On("Commit").Return(nil) - return txMock - }, - scopedFn: func(ctx context.Context, dbTx db.Tx) (interface{}, rpc.Error) { - return 123, nil - }, - expected: 123, - }, - { - name: "BeginStateTransaction returns error", - db: func(dbMock *mocks.DB) *mocks.Tx { - dbMock.On("BeginStateTransaction", mock.Anything). - Return(nil, errors.New("test")) - return nil - }, - scopedFn: func(ctx context.Context, dbTx db.Tx) (interface{}, rpc.Error) { - t.Fatal("unexpected scopedFn execution") - return nil, nil - }, - returnErr: errors.New("failed to connect to the state"), - }, - { - name: "scopedFn returns error", - db: func(dbMock *mocks.DB) *mocks.Tx { - txMock := mocks.NewTx(t) - dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil) - txMock.On("Rollback").Return(nil) - return txMock - }, - scopedFn: func(ctx context.Context, dbTx db.Tx) (interface{}, rpc.Error) { - return nil, rpc.NewRPCError(1, "test") - }, - returnErr: errors.New("test"), - }, - { - name: "Rollback returns error", - db: func(dbMock *mocks.DB) *mocks.Tx { - txMock := mocks.NewTx(t) - dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil) - txMock.On("Rollback").Return(errors.New("test")) - return txMock - }, - scopedFn: func(ctx context.Context, dbTx db.Tx) (interface{}, rpc.Error) { - return nil, rpc.NewRPCError(1, "test") - }, - returnErr: errors.New("failed to rollback db transaction"), - }, - { - name: "Commit returns error", - db: func(dbMock *mocks.DB) *mocks.Tx { - txMock := mocks.NewTx(t) - dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil) - txMock.On("Commit").Return(errors.New("test")) - return txMock - }, - scopedFn: func(ctx context.Context, dbTx db.Tx) (interface{}, rpc.Error) { - return 123, nil - }, - returnErr: errors.New("failed to commit db transaction"), - }, - } - - for _, tt := range testTable { - tt := tt - - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - dbMock := mocks.NewDB(t) - txMock := tt.db(dbMock) - - mgr := rpc.DBTxManager{} - - got, err := mgr.NewDbTxScope(dbMock, tt.scopedFn) - if tt.returnErr != nil { - require.Equal(t, tt.returnErr.Error(), err.Error()) - } else { - require.NoError(t, err) - require.Equal(t, tt.expected, got) - } - - dbMock.AssertExpectations(t) - - if txMock != nil { - txMock.AssertExpectations(t) - } - }) - } -} diff --git a/rpc/error.go b/rpc/error.go index a1d2d131..14c33eb2 100644 --- a/rpc/error.go +++ b/rpc/error.go @@ -25,8 +25,8 @@ const ( ) var ( - // invalidJSONReqErr denotes error that is returned when invalid JSON request is received - invalidJSONReqErr = errors.New("Invalid json request") + // errInvalidJSONReq denotes error that is returned when invalid JSON request is received + errInvalidJSONReq = errors.New("invalid json request") ) // Error interface diff --git a/rpc/handler.go b/rpc/handler.go index e95cd1b9..e21bb357 100644 --- a/rpc/handler.go +++ b/rpc/handler.go @@ -123,7 +123,11 @@ func (h *Handler) Handle(req handleRequest) Response { // check params passed by request match function params var testStruct []interface{} if err := json.Unmarshal(req.Params, &testStruct); err == nil && len(testStruct) > fd.numParams() { - return NewResponse(req.Request, nil, NewRPCError(InvalidParamsErrorCode, fmt.Sprintf("too many arguments, want at most %d", fd.numParams()))) + return NewResponse( + req.Request, + nil, + NewRPCError(InvalidParamsErrorCode, fmt.Sprintf("too many arguments, want at most %d", fd.numParams())), + ) } inputs := make([]interface{}, fd.numParams()-inArgsOffset) @@ -161,7 +165,7 @@ func (h *Handler) HandleWs(reqBody []byte, wsConn *websocket.Conn, httpReq *http log.Debugf("WS message received: %v", string(reqBody)) var req Request if err := json.Unmarshal(reqBody, &req); err != nil { - return NewResponse(req, nil, NewRPCError(InvalidRequestErrorCode, invalidJSONReqErr.Error())).Bytes() + return NewResponse(req, nil, NewRPCError(InvalidRequestErrorCode, errInvalidJSONReq.Error())).Bytes() } handleReq := handleRequest{ @@ -215,8 +219,8 @@ func (h *Handler) registerService(service Service) { func (h *Handler) getFnHandler(req Request) (*serviceData, *funcData, Error) { methodNotFoundErrorMessage := fmt.Sprintf("the method %s does not exist/is not available", req.Method) - callName := strings.SplitN(req.Method, "_", 2) //nolint:gomnd - if len(callName) != 2 { //nolint:gomnd + callName := strings.SplitN(req.Method, "_", 2) //nolint:mnd + if len(callName) != 2 { //nolint:mnd return nil, nil, NewRPCError(NotFoundErrorCode, methodNotFoundErrorMessage) } @@ -254,7 +258,12 @@ func validateFunc(funcName string, fv reflect.Value, isMethod bool) (inNum int, return } if !isRPCErrorType(ft.Out(1)) { - err = fmt.Errorf("unexpected type for the second return value of the function '%s': '%s'. Expected '%s'", funcName, ft.Out(1), rpcErrType) + err = fmt.Errorf( + "unexpected type for the second return value of the function '%s': '%s'. Expected '%s'", + funcName, + ft.Out(1), + rpcErrType, + ) return } diff --git a/rpc/server.go b/rpc/server.go index 2165d182..99ac23d7 100644 --- a/rpc/server.go +++ b/rpc/server.go @@ -108,7 +108,10 @@ func (s *Server) handle(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") + w.Header().Set( + "Access-Control-Allow-Headers", + "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization", + ) if (*req).Method == "OPTIONS" { // TODO(pg): need to count it in the metrics? @@ -156,7 +159,7 @@ func (s *Server) isSingleRequest(data []byte) (bool, Error) { x := bytes.TrimLeft(data, " \t\r\n") if len(x) == 0 { - return false, NewRPCError(InvalidRequestErrorCode, invalidJSONReqErr.Error()) + return false, NewRPCError(InvalidRequestErrorCode, errInvalidJSONReq.Error()) } return x[0] == '{', nil @@ -213,7 +216,7 @@ func (s *Server) parseRequest(data []byte) (Request, error) { var req Request if err := json.Unmarshal(data, &req); err != nil { - return Request{}, NewRPCError(InvalidRequestErrorCode, invalidJSONReqErr.Error()) + return Request{}, NewRPCError(InvalidRequestErrorCode, errInvalidJSONReq.Error()) } return req, nil @@ -223,7 +226,7 @@ func (s *Server) parseRequests(data []byte) ([]Request, error) { var requests []Request if err := json.Unmarshal(data, &requests); err != nil { - return nil, NewRPCError(InvalidRequestErrorCode, invalidJSONReqErr.Error()) + return nil, NewRPCError(InvalidRequestErrorCode, errInvalidJSONReq.Error()) } return requests, nil @@ -242,21 +245,6 @@ func handleError(w http.ResponseWriter, err error) { } } -// RPCErrorResponse formats error to be returned through RPC -func RPCErrorResponse(code int, message string, err error) (interface{}, Error) { - return RPCErrorResponseWithData(code, message, nil, err) -} - -// RPCErrorResponseWithData formats error to be returned through RPC -func RPCErrorResponseWithData(code int, message string, data *[]byte, err error) (interface{}, Error) { - if err != nil { - log.Errorf("%v: %v", message, err.Error()) - } else { - log.Error(message) - } - return nil, NewRPCErrorWithData(code, message, data) -} - func combinedLog(r *http.Request, start time.Time, httpStatus, dataLen int) { log.Infof("%s - - %s \"%s %s %s\" %d %d \"%s\" \"%s\"", r.RemoteAddr, diff --git a/rpc/server_test.go b/rpc/server_test.go index e821293e..a711967c 100644 --- a/rpc/server_test.go +++ b/rpc/server_test.go @@ -120,7 +120,7 @@ func Test_ServerHandleRequest(t *testing.T) { server.handle(respRecorder, httpReq) require.Equal(t, http.StatusInternalServerError, respRecorder.Result().StatusCode) - require.Equal(t, invalidJSONReqErr.Error(), respRecorder.Body.String()) + require.Equal(t, errInvalidJSONReq.Error(), respRecorder.Body.String()) }) t.Run("GET method request", func(t *testing.T) { diff --git a/sequencer/call.go b/sequencer/call.go index 75185610..3f1bcd96 100644 --- a/sequencer/call.go +++ b/sequencer/call.go @@ -1,6 +1,7 @@ package sequencer import ( + "context" "encoding/json" "fmt" @@ -17,8 +18,8 @@ type SeqBatch struct { } // GetData returns batch data from the trusted sequencer -func GetData(url string, batchNum uint64) (*SeqBatch, error) { - response, err := rpc.JSONRPCCall(url, "zkevm_getBatchByNumber", batchNum, true) +func GetData(ctx context.Context, url string, batchNum uint64) (*SeqBatch, error) { + response, err := rpc.JSONRPCCallWithContext(ctx, url, "zkevm_getBatchByNumber", batchNum, true) if err != nil { return nil, err } diff --git a/sequencer/call_test.go b/sequencer/call_test.go index 339e0021..cbd59575 100644 --- a/sequencer/call_test.go +++ b/sequencer/call_test.go @@ -1,6 +1,7 @@ package sequencer import ( + "context" "encoding/json" "errors" "fmt" @@ -15,6 +16,8 @@ import ( ) func Test_GetData(t *testing.T) { + t.Parallel() + tests := []struct { name string batchNum uint64 @@ -71,7 +74,10 @@ func Test_GetData(t *testing.T) { var params []interface{} require.NoError(t, json.Unmarshal(res.Params, ¶ms)) require.Equal(t, float64(tt.batchNum), params[0]) - require.True(t, params[1].(bool)) + + boolVal, ok := params[1].(bool) + require.True(t, ok, "params[1] is not of type bool") + require.True(t, boolVal) if tt.statusCode > 0 { w.WriteHeader(tt.statusCode) @@ -82,7 +88,7 @@ func Test_GetData(t *testing.T) { })) defer svr.Close() - got, err := GetData(svr.URL, tt.batchNum) + got, err := GetData(context.Background(), svr.URL, tt.batchNum) if tt.err != nil { require.Error(t, err) require.EqualError(t, tt.err, err.Error()) diff --git a/sequencer/tracker.go b/sequencer/tracker.go index 9c142ff3..339e8402 100644 --- a/sequencer/tracker.go +++ b/sequencer/tracker.go @@ -2,53 +2,56 @@ package sequencer import ( "context" + "strings" "sync" "time" + "github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonvalidiumetrog" "github.com/0xPolygon/cdk-data-availability/config" "github.com/0xPolygon/cdk-data-availability/etherman" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygonvalidium" "github.com/0xPolygon/cdk-data-availability/log" + "github.com/0xPolygon/cdk-data-availability/pkg/backoff" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/event" +) + +const ( + // maxConnectionRetries is the maximum number of retries to connect to the RPC node before failing. + maxConnectionRetries = 5 ) // Tracker watches the contract for relevant changes to the sequencer type Tracker struct { - client etherman.Etherman - stop chan struct{} - timeout time.Duration - retry time.Duration - addr common.Address - url string - lock sync.Mutex - startOnce sync.Once + em etherman.Etherman + stop chan struct{} + timeout time.Duration + retry time.Duration + addr common.Address + url string + trackChanges bool + usePolling bool + pollInterval time.Duration + wg sync.WaitGroup + lock sync.Mutex + startOnce sync.Once } // NewTracker creates a new Tracker -func NewTracker(cfg config.L1Config, ethClient etherman.Etherman) (*Tracker, error) { - log.Infof("starting sequencer address tracker") - addr, err := ethClient.TrustedSequencer() - if err != nil { - return nil, err +func NewTracker(cfg config.L1Config, em etherman.Etherman) *Tracker { + pollInterval := time.Minute + if cfg.TrackSequencerPollInterval.Seconds() > 0 { + pollInterval = cfg.TrackSequencerPollInterval.Duration } - log.Infof("current sequencer addr: %s", addr.Hex()) - url, err := ethClient.TrustedSequencerURL() - if err != nil { - return nil, err + return &Tracker{ + em: em, + stop: make(chan struct{}), + timeout: cfg.Timeout.Duration, + retry: cfg.RetryPeriod.Duration, + trackChanges: cfg.TrackSequencer, + usePolling: strings.HasPrefix(cfg.RpcURL, "http"), // If http(s), use polling instead of sockets + pollInterval: pollInterval, } - - log.Infof("current sequencer url: %s", url) - w := &Tracker{ - client: ethClient, - stop: make(chan struct{}), - timeout: cfg.Timeout.Duration, - retry: cfg.RetryPeriod.Duration, - addr: addr, - url: url, - } - - return w, nil } // GetAddr returns the last known address of the Sequencer @@ -60,8 +63,8 @@ func (st *Tracker) GetAddr() common.Address { func (st *Tracker) setAddr(addr common.Address) { st.lock.Lock() - defer st.lock.Unlock() st.addr = addr + st.lock.Unlock() } // GetUrl returns the last known URL of the Sequencer @@ -73,118 +76,240 @@ func (st *Tracker) GetUrl() string { func (st *Tracker) setUrl(url string) { st.lock.Lock() - defer st.lock.Unlock() st.url = url + st.lock.Unlock() } // Start starts the SequencerTracker -func (st *Tracker) Start(ctx context.Context) { +func (st *Tracker) Start(parentCtx context.Context) { st.startOnce.Do(func() { - go st.trackAddrChanges(ctx) - go st.trackUrlChanges(ctx) + ctx, cancel := context.WithTimeout(parentCtx, st.timeout) + defer cancel() + + addr, err := st.em.TrustedSequencer(ctx) + if err != nil { + log.Fatalf("failed to get sequencer addr: %v", err) + return + } + + log.Infof("current sequencer addr: %s", addr.Hex()) + st.setAddr(addr) + + url, err := st.em.TrustedSequencerURL(ctx) + if err != nil { + log.Fatalf("failed to get sequencer addr: %v", err) + return + } + + log.Infof("current sequencer url: %s", url) + st.setUrl(url) + + if st.trackChanges { + log.Info("sequencer tracking enabled") + + go st.trackAddrChanges(parentCtx) + go st.trackUrlChanges(parentCtx) + } }) } func (st *Tracker) trackAddrChanges(ctx context.Context) { - events := make(chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer) - defer close(events) + addrChan := make(chan common.Address, 1) + + if st.usePolling { + go st.pollAddrChanges(ctx, addrChan) + } else { + go st.subscribeOnAddrChanges(ctx, addrChan) + } for { select { + case addr := <-addrChan: + if st.GetAddr().Cmp(addr) != 0 { + log.Infof("new trusted sequencer address: %v", addr) + st.setAddr(addr) + } case <-ctx.Done(): if ctx.Err() != nil && ctx.Err() != context.DeadlineExceeded { log.Warnf("context cancelled: %v", ctx.Err()) } - default: - ctx, cancel := context.WithTimeout(ctx, st.timeout) + return + case <-st.stop: + return + } + } +} + +func (st *Tracker) subscribeOnAddrChanges(ctx context.Context, addrChan chan<- common.Address) { + st.wg.Add(1) + defer st.wg.Done() + + events := make(chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer) + defer close(events) + + var sub event.Subscription - sub, err := st.client.WatchSetTrustedSequencer(ctx, events) + initSubscription := func() { + if err := backoff.Exponential(func() (err error) { + if sub, err = st.em.WatchSetTrustedSequencer(ctx, events); err != nil { + log.Errorf("error subscribing to trusted sequencer event, retrying: %v", err) + } + + return err + }, maxConnectionRetries, st.retry); err != nil { + log.Fatalf("failed subscribing to trusted sequencer event: %v. Check ws(s) availability.", err) + } + } + + initSubscription() + + for { + select { + case e := <-events: + addrChan <- e.NewTrustedSequencer + case <-ctx.Done(): + return + case err := <-sub.Err(): + log.Warnf("subscription error, resubscribing: %v", err) + initSubscription() + case <-st.stop: + if sub != nil { + sub.Unsubscribe() + } + return + } + } +} - // if no subscription, retry until established - for err != nil { - <-time.After(st.retry) +func (st *Tracker) pollAddrChanges(ctx context.Context, addrChan chan<- common.Address) { + st.wg.Add(1) + defer st.wg.Done() - if sub, err = st.client.WatchSetTrustedSequencer(ctx, events); err != nil { - log.Errorf("error subscribing to trusted sequencer event, retrying: %v", err) - } + ticker := time.NewTicker(st.pollInterval) + for { + select { + case <-ticker.C: + addr, err := st.em.TrustedSequencer(ctx) + if err != nil { + log.Errorf("failed to get sequencer addr: %v", err) + break } - // wait on events, timeouts, and signals to stop - select { - case e := <-events: - log.Infof("new trusted sequencer address: %v", e.NewTrustedSequencer) - st.setAddr(e.NewTrustedSequencer) - case err := <-sub.Err(): - log.Warnf("subscription error, resubscribing: %v", err) - case <-ctx.Done(): - // Deadline exceeded is expected since we use finite context timeout - if ctx.Err() != nil && ctx.Err() != context.DeadlineExceeded { - log.Warnf("re-establishing subscription: %v", ctx.Err()) - } - case <-st.stop: - if sub != nil { - sub.Unsubscribe() - } - cancel() - return + if st.GetAddr().Cmp(addr) != 0 { + addrChan <- addr } + case <-ctx.Done(): + ticker.Stop() + return + case <-st.stop: + ticker.Stop() + return } } } func (st *Tracker) trackUrlChanges(ctx context.Context) { - events := make(chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL) - defer close(events) + urlChan := make(chan string, 1) + + if st.usePolling { + go st.pollUrlChanges(ctx, urlChan) + } else { + go st.subscribeOnUrlChanges(ctx, urlChan) + } for { select { + case url := <-urlChan: + if st.GetUrl() != url { + log.Infof("new trusted sequencer url: %v", url) + st.setUrl(url) + } case <-ctx.Done(): if ctx.Err() != nil && ctx.Err() != context.DeadlineExceeded { log.Warnf("context cancelled: %v", ctx.Err()) } - default: - ctx, cancel := context.WithTimeout(ctx, st.timeout) + return + case <-st.stop: + return + } + } +} + +func (st *Tracker) subscribeOnUrlChanges(ctx context.Context, urlChan chan<- string) { + st.wg.Add(1) + defer st.wg.Done() - sub, err := st.client.WatchSetTrustedSequencerURL(ctx, events) + events := make(chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL) + defer close(events) - // if no subscription, retry until established - for err != nil { - <-time.After(st.retry) + var sub event.Subscription - if sub, err = st.client.WatchSetTrustedSequencerURL(ctx, events); err != nil { - log.Errorf("error subscribing to trusted sequencer event, retrying: %v", err) - } + initSubscription := func() { + if err := backoff.Exponential(func() (err error) { + if sub, err = st.em.WatchSetTrustedSequencerURL(ctx, events); err != nil { + log.Errorf("error subscribing to trusted sequencer URL event, retrying: %v", err) } - // wait on events, timeouts, and signals to stop - select { - case e := <-events: - log.Infof("new trusted sequencer url: %v", e.NewTrustedSequencerURL) - st.setUrl(e.NewTrustedSequencerURL) - case err := <-sub.Err(): - log.Warnf("subscription error, resubscribing: %v", err) - case <-ctx.Done(): - // Deadline exceeded is expected since we use finite context timeout - if ctx.Err() != nil && ctx.Err() != context.DeadlineExceeded { - log.Warnf("re-establishing subscription: %v", ctx.Err()) - } - case <-st.stop: - if sub != nil { - sub.Unsubscribe() - } - cancel() - return + return err + }, maxConnectionRetries, st.retry); err != nil { + log.Fatalf("failed subscribing to trusted sequencer URL event: %v. Check ws(s) availability.", err) + } + } + + initSubscription() + + for { + select { + case e := <-events: + urlChan <- e.NewTrustedSequencerURL + case <-ctx.Done(): + return + case err := <-sub.Err(): + log.Warnf("subscription error, resubscribing: %v", err) + initSubscription() + case <-st.stop: + if sub != nil { + sub.Unsubscribe() } + return + } + } +} + +func (st *Tracker) pollUrlChanges(ctx context.Context, urlChan chan<- string) { + st.wg.Add(1) + defer st.wg.Done() + + ticker := time.NewTicker(st.pollInterval) + for { + select { + case <-ticker.C: + url, err := st.em.TrustedSequencerURL(ctx) + if err != nil { + log.Errorf("failed to get sequencer URL: %v", err) + break + } + + if st.GetUrl() != url { + urlChan <- url + } + case <-ctx.Done(): + ticker.Stop() + return + case <-st.stop: + ticker.Stop() + return } } } // GetSequenceBatch returns sequence batch for given batch number -func (st *Tracker) GetSequenceBatch(batchNum uint64) (*SeqBatch, error) { - return GetData(st.GetUrl(), batchNum) +func (st *Tracker) GetSequenceBatch(ctx context.Context, batchNum uint64) (*SeqBatch, error) { + return GetData(ctx, st.GetUrl(), batchNum) } // Stop stops the SequencerTracker func (st *Tracker) Stop() { close(st.stop) + st.wg.Wait() } diff --git a/sequencer/tracker_test.go b/sequencer/tracker_test.go index e76bb84a..eaa9511b 100644 --- a/sequencer/tracker_test.go +++ b/sequencer/tracker_test.go @@ -2,13 +2,12 @@ package sequencer_test import ( "context" - "errors" "testing" "time" + "github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonvalidiumetrog" "github.com/0xPolygon/cdk-data-availability/config" "github.com/0xPolygon/cdk-data-availability/config/types" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygonvalidium" "github.com/0xPolygon/cdk-data-availability/mocks" "github.com/0xPolygon/cdk-data-availability/sequencer" "github.com/ethereum/go-ethereum/common" @@ -16,145 +15,152 @@ import ( "github.com/stretchr/testify/require" ) -func Test_NewTracker(t *testing.T) { - testErr := errors.New("test error") - - testTable := []struct { - name string - initMock func(t *testing.T) *mocks.Etherman - err error - }{ - { - name: "successfully created tracker", - initMock: func(t *testing.T) *mocks.Etherman { - em := mocks.NewEtherman(t) - - em.On("TrustedSequencer").Return(common.Address{}, nil) - em.On("TrustedSequencerURL").Return("127.0.0.1", nil) - - return em - }, - }, - { - name: "TrustedSequencer returns error", - initMock: func(t *testing.T) *mocks.Etherman { - em := mocks.NewEtherman(t) - - em.On("TrustedSequencer").Return(common.Address{}, testErr) - - return em - }, - err: testErr, - }, - { - name: "TrustedSequencerURL returns error", - initMock: func(t *testing.T) *mocks.Etherman { - em := mocks.NewEtherman(t) - - em.On("TrustedSequencer").Return(common.Address{}, nil) - em.On("TrustedSequencerURL").Return("", testErr) - - return em - }, - err: testErr, - }, - } - - for _, tt := range testTable { - tt := tt - - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - em := tt.initMock(t) - defer em.AssertExpectations(t) - - _, err := sequencer.NewTracker(config.L1Config{ - Timeout: types.NewDuration(time.Second * 10), - RetryPeriod: types.NewDuration(time.Millisecond), - }, em) - if tt.err != nil { - require.Error(t, err) - require.EqualError(t, tt.err, err.Error()) - } else { - require.NoError(t, err) - } - }) - } -} - func TestTracker(t *testing.T) { var ( - addressesChan chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer - urlsChan chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL + initialAddress = common.BytesToAddress([]byte("initial")) + initialURL = "127.0.0.1:8585" + updatedAddress = common.BytesToAddress([]byte("updated")) + updatedURL = "127.0.0.1:9585" ) - ctx := context.Background() + t.Run("with enabled subscription tracker", func(t *testing.T) { + var ( + addressesChan chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer + urlsChan chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL + ) - etherman := mocks.NewEtherman(t) - defer etherman.AssertExpectations(t) + ctx := context.Background() - etherman.On("TrustedSequencer").Return(common.Address{}, nil) - etherman.On("TrustedSequencerURL").Return("127.0.0.1:8585", nil) + etherman := mocks.NewEtherman(t) - addressesSubscription := mocks.NewSubscription(t) - defer addressesSubscription.AssertExpectations(t) + etherman.On("TrustedSequencer", mock.Anything).Return(initialAddress, nil) + etherman.On("TrustedSequencerURL", mock.Anything).Return(initialURL, nil) - addressesSubscription.On("Err").Return(make(<-chan error)) - addressesSubscription.On("Unsubscribe").Return() + addressesSubscription := mocks.NewSubscription(t) - etherman.On("WatchSetTrustedSequencer", mock.Anything, mock.Anything). - Run(func(args mock.Arguments) { - var ok bool - addressesChan, ok = args[1].(chan *polygonvalidium.PolygonvalidiumSetTrustedSequencer) - require.True(t, ok) - }). - Return(addressesSubscription, nil) + addressesSubscription.On("Err").Return(make(<-chan error)) + addressesSubscription.On("Unsubscribe").Return() - urlsSubscription := mocks.NewSubscription(t) - defer urlsSubscription.AssertExpectations(t) + etherman.On("WatchSetTrustedSequencer", mock.Anything, mock.Anything). + Run(func(args mock.Arguments) { + var ok bool + addressesChan, ok = args[1].(chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer) + require.True(t, ok) + }). + Return(addressesSubscription, nil) - urlsSubscription.On("Err").Return(make(<-chan error)) - urlsSubscription.On("Unsubscribe").Return() + urlsSubscription := mocks.NewSubscription(t) - etherman.On("WatchSetTrustedSequencerURL", mock.Anything, mock.Anything). - Run(func(args mock.Arguments) { - var ok bool - urlsChan, ok = args[1].(chan *polygonvalidium.PolygonvalidiumSetTrustedSequencerURL) - require.True(t, ok) - }). - Return(urlsSubscription, nil) + urlsSubscription.On("Err").Return(make(<-chan error)) + urlsSubscription.On("Unsubscribe").Return() - tracker, err := sequencer.NewTracker(config.L1Config{ - Timeout: types.NewDuration(time.Second * 10), - RetryPeriod: types.NewDuration(time.Millisecond), - }, etherman) - require.NoError(t, err) + etherman.On("WatchSetTrustedSequencerURL", mock.Anything, mock.Anything). + Run(func(args mock.Arguments) { + var ok bool + urlsChan, ok = args[1].(chan *polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL) + require.True(t, ok) + }). + Return(urlsSubscription, nil) - tracker.Start(ctx) + tracker := sequencer.NewTracker(config.L1Config{ + Timeout: types.NewDuration(time.Second * 10), + RetryPeriod: types.NewDuration(time.Millisecond), + TrackSequencer: true, + }, etherman) - var ( - updatedAddress = common.BytesToAddress([]byte("updated")) - updatedURL = "127.0.0.1:9585" - ) + require.Equal(t, common.Address{}, tracker.GetAddr()) + require.Empty(t, tracker.GetUrl()) + + tracker.Start(ctx) + + require.Equal(t, initialAddress, tracker.GetAddr()) + require.Equal(t, initialURL, tracker.GetUrl()) + + eventually(t, 10, func() bool { + return addressesChan != nil && urlsChan != nil + }) + + addressesChan <- &polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencer{ + NewTrustedSequencer: updatedAddress, + } + + urlsChan <- &polygonvalidiumetrog.PolygonvalidiumetrogSetTrustedSequencerURL{ + NewTrustedSequencerURL: updatedURL, + } + + // Wait for values to be updated + eventually(t, 10, func() bool { + return tracker.GetAddr() == updatedAddress && tracker.GetUrl() == updatedURL + }) - eventually(t, 10, func() bool { - return addressesChan != nil && urlsChan != nil + tracker.Stop() + + urlsSubscription.AssertExpectations(t) + addressesSubscription.AssertExpectations(t) + etherman.AssertExpectations(t) }) - addressesChan <- &polygonvalidium.PolygonvalidiumSetTrustedSequencer{ - NewTrustedSequencer: updatedAddress, - } + t.Run("with enabled polling tracker", func(t *testing.T) { + ctx := context.Background() - urlsChan <- &polygonvalidium.PolygonvalidiumSetTrustedSequencerURL{ - NewTrustedSequencerURL: updatedURL, - } + etherman := mocks.NewEtherman(t) + + etherman.On("TrustedSequencer", mock.Anything).Return(initialAddress, nil) + etherman.On("TrustedSequencerURL", mock.Anything).Return(initialURL, nil) + + etherman.On("TrustedSequencer", mock.Anything).Return(updatedAddress, nil) + etherman.On("TrustedSequencerURL", mock.Anything).Return(updatedURL, nil) + + tracker := sequencer.NewTracker(config.L1Config{ + RpcURL: "http://127.0.0.1:8545", + Timeout: types.NewDuration(time.Second * 10), + RetryPeriod: types.NewDuration(time.Millisecond), + TrackSequencerPollInterval: types.NewDuration(time.Second), + TrackSequencer: true, + }, etherman) + + require.Equal(t, common.Address{}, tracker.GetAddr()) + require.Empty(t, tracker.GetUrl()) + + tracker.Start(ctx) + + require.Equal(t, initialAddress, tracker.GetAddr()) + require.Equal(t, initialURL, tracker.GetUrl()) + + // Wait for values to be updated + eventually(t, 10, func() bool { + return tracker.GetAddr() == updatedAddress && tracker.GetUrl() == updatedURL + }) + + tracker.Stop() + + etherman.AssertExpectations(t) + }) + + t.Run("with disabled tracker", func(t *testing.T) { + ctx := context.Background() + + etherman := mocks.NewEtherman(t) + + etherman.On("TrustedSequencer", mock.Anything).Return(initialAddress, nil) + etherman.On("TrustedSequencerURL", mock.Anything).Return(initialURL, nil) + + tracker := sequencer.NewTracker(config.L1Config{ + Timeout: types.NewDuration(time.Second * 10), + RetryPeriod: types.NewDuration(time.Millisecond), + }, etherman) + + require.Equal(t, common.Address{}, tracker.GetAddr()) + require.Empty(t, tracker.GetUrl()) + + tracker.Start(ctx) + + require.Equal(t, initialAddress, tracker.GetAddr()) + require.Equal(t, initialURL, tracker.GetUrl()) - tracker.Stop() + tracker.Stop() - // Wait for values to be updated - eventually(t, 10, func() bool { - return tracker.GetAddr() == updatedAddress && tracker.GetUrl() == updatedURL + etherman.AssertExpectations(t) }) } diff --git a/services/datacom/datacom.go b/services/datacom/datacom.go index 5e86d8c5..b347b41a 100644 --- a/services/datacom/datacom.go +++ b/services/datacom/datacom.go @@ -16,61 +16,64 @@ import ( // APIDATACOM is the namespace of the datacom service const APIDATACOM = "datacom" -// DataComEndpoints contains implementations for the "datacom" RPC endpoints -type DataComEndpoints struct { +// Endpoints contains implementations for the "datacom" RPC endpoints +type Endpoints struct { db db.DB - txMan rpc.DBTxManager privateKey *ecdsa.PrivateKey sequencerTracker *sequencer.Tracker permitApiAddress common.Address } -// NewDataComEndpoints returns DataComEndpoints -func NewDataComEndpoints( - db db.DB, privateKey *ecdsa.PrivateKey, sequencerTracker *sequencer.Tracker, - permitApiAddress common.Address, -) *DataComEndpoints { - return &DataComEndpoints{ +// NewEndpoints returns Endpoints +func NewEndpoints(db db.DB, pk *ecdsa.PrivateKey, st *sequencer.Tracker, permitApiAddress common.Address) *Endpoints { + return &Endpoints{ db: db, - privateKey: privateKey, - sequencerTracker: sequencerTracker, + privateKey: pk, + sequencerTracker: st, permitApiAddress: permitApiAddress, } } -// SignSequence generates the accumulated input hash aka accInputHash of the sequence and sign it. +// SignSequence generates the concatenation of hashes of the batch data of the sequence and sign it. // After storing the data that will be sent hashed to the contract, it returns the signature. // This endpoint is only accessible to the sequencer -func (d *DataComEndpoints) SignSequence(signedSequence types.SignedSequence) (interface{}, rpc.Error) { +func (d *Endpoints) SignSequence(signedSequence types.SignedSequence) (interface{}, rpc.Error) { + return d.signSequence(&signedSequence) +} + +// SignSequenceBanana generates the accumulated input hash aka accInputHash of the sequence and sign it. +// After storing the data that will be sent hashed to the contract, it returns the signature. +// This endpoint is only accessible to the sequencer +func (d *Endpoints) SignSequenceBanana(signedSequence types.SignedSequenceBanana) (interface{}, rpc.Error) { + log.Debugf("signing sequence, hash to sign: %s", common.BytesToHash(signedSequence.Sequence.HashToSign())) + return d.signSequence(&signedSequence) +} + +func (d *Endpoints) signSequence(signedSequence types.SignedSequenceInterface) (interface{}, rpc.Error) { // Verify that the request comes from the sequencer sender, err := signedSequence.Signer() if err != nil || d.isEmptyAddress(sender) { return "0x0", rpc.NewRPCError(rpc.DefaultErrorCode, "failed to verify sender") } - log.Infof("SignSequence, signedSequence sender: %v, sequencerTracker:%v, permitApiAddress:%s", sender.String(), d.sequencerTracker.GetAddr().String(), d.permitApiAddress.String()) + log.Infof("SignSequence, signedSequence sender: %v, sequencerTracker:%v, permitApiAddress:%s", + sender.String(), d.sequencerTracker.GetAddr().String(), d.permitApiAddress.String()) if sender != d.sequencerTracker.GetAddr() && sender != d.permitApiAddress { return "0x0", rpc.NewRPCError(rpc.DefaultErrorCode, "unauthorized") } // Store off-chain data by hash (hash(L2Data): L2Data) - _, err = d.txMan.NewDbTxScope(d.db, func(ctx context.Context, dbTx db.Tx) (interface{}, rpc.Error) { - err := d.db.StoreOffChainData(ctx, signedSequence.Sequence.OffChainData(), dbTx) - if err != nil { - return "0x0", rpc.NewRPCError(rpc.DefaultErrorCode, fmt.Errorf("failed to store offchain data. Error: %w", err).Error()) - } - - return nil, nil - }) - if err != nil { - return "0x0", rpc.NewRPCError(rpc.DefaultErrorCode, err.Error()) + if err = d.db.StoreOffChainData(context.Background(), signedSequence.OffChainData()); err != nil { + return "0x0", rpc.NewRPCError(rpc.DefaultErrorCode, + fmt.Errorf("failed to store offchain data. Error: %w", err).Error()) } + // Sign - signedSequenceByMe, err := signedSequence.Sequence.Sign(d.privateKey) + signature, err := signedSequence.Sign(d.privateKey) if err != nil { return "0x0", rpc.NewRPCError(rpc.DefaultErrorCode, fmt.Errorf("failed to sign. Error: %w", err).Error()) } // Return signature - return signedSequenceByMe.Signature, nil + return signature, nil } diff --git a/services/datacom/datacom_test.go b/services/datacom/datacom_test.go index 53cc5911..95353098 100644 --- a/services/datacom/datacom_test.go +++ b/services/datacom/datacom_test.go @@ -1,6 +1,7 @@ package datacom import ( + "context" "crypto/ecdsa" "errors" "testing" @@ -21,18 +22,11 @@ func TestDataCom_SignSequence(t *testing.T) { t.Parallel() type testConfig struct { - beginStateTransactionReturns []interface{} - storeOffChainDataReturns []interface{} - rollbackReturns []interface{} - commitReturns []interface{} - sender *ecdsa.PrivateKey - signer *ecdsa.PrivateKey - expectedError string - } - - sequence := types.Sequence{ - types.ArgBytes([]byte{0, 1}), - types.ArgBytes([]byte{2, 3}), + storeOffChainDataReturns []interface{} + sender *ecdsa.PrivateKey + signer *ecdsa.PrivateKey + sequence types.Sequence + expectedError string } privateKey, err := crypto.GenerateKey() @@ -41,46 +35,44 @@ func TestDataCom_SignSequence(t *testing.T) { otherPrivateKey, err := crypto.GenerateKey() require.NoError(t, err) - testFn := func(cfg testConfig) { + testFn := func(t *testing.T, cfg testConfig) { + t.Helper() + var ( signer = privateKey signedSequence *types.SignedSequence err error ) - txMock := mocks.NewTx(t) dbMock := mocks.NewDB(t) - if cfg.beginStateTransactionReturns != nil { - dbMock.On("BeginStateTransaction", mock.Anything).Return(cfg.beginStateTransactionReturns...).Once() - } else if cfg.storeOffChainDataReturns != nil { - dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil).Once() - dbMock.On("StoreOffChainData", mock.Anything, sequence.OffChainData(), txMock).Return( - cfg.storeOffChainDataReturns...).Once() - if cfg.rollbackReturns != nil { - txMock.On("Rollback").Return(cfg.rollbackReturns...).Once() - } else { - txMock.On("Commit").Return(cfg.commitReturns...).Once() - } + if len(cfg.storeOffChainDataReturns) > 0 { + dbMock.On("StoreOffChainData", mock.Anything, cfg.sequence.OffChainData()).Return( + cfg.storeOffChainDataReturns...).Once() } ethermanMock := mocks.NewEtherman(t) - ethermanMock.On("TrustedSequencer").Return(crypto.PubkeyToAddress(otherPrivateKey.PublicKey), nil).Once() - ethermanMock.On("TrustedSequencerURL").Return("http://some-url", nil).Once() + ethermanMock.On("TrustedSequencer", mock.Anything).Return(crypto.PubkeyToAddress(otherPrivateKey.PublicKey), nil).Once() + ethermanMock.On("TrustedSequencerURL", mock.Anything).Return("http://some-url", nil).Once() - sequencer, err := sequencer.NewTracker(config.L1Config{ + sqr := sequencer.NewTracker(config.L1Config{ Timeout: cfgTypes.Duration{Duration: time.Minute}, RetryPeriod: cfgTypes.Duration{Duration: time.Second}, }, ethermanMock) - require.NoError(t, err) + + sqr.Start(context.Background()) if cfg.sender != nil { - signedSequence, err = sequence.Sign(cfg.sender) + signature, err := cfg.sequence.Sign(cfg.sender) require.NoError(t, err) + signedSequence = &types.SignedSequence{ + Sequence: cfg.sequence, + Signature: signature, + } } else { signedSequence = &types.SignedSequence{ - Sequence: sequence, + Sequence: cfg.sequence, Signature: []byte{}, } } @@ -89,7 +81,7 @@ func TestDataCom_SignSequence(t *testing.T) { signer = cfg.signer } - dce := NewDataComEndpoints(dbMock, signer, sequencer, common.Address{}) + dce := NewEndpoints(dbMock, signer, sqr, common.Address{}) sig, err := dce.SignSequence(*signedSequence) if cfg.expectedError != "" { @@ -99,7 +91,8 @@ func TestDataCom_SignSequence(t *testing.T) { require.NotEmpty(t, sig) } - txMock.AssertExpectations(t) + sqr.Stop() + dbMock.AssertExpectations(t) ethermanMock.AssertExpectations(t) } @@ -107,69 +100,186 @@ func TestDataCom_SignSequence(t *testing.T) { t.Run("Failed to verify sender", func(t *testing.T) { t.Parallel() - testFn(testConfig{ + testFn(t, testConfig{ expectedError: "failed to verify sender", + sequence: types.Sequence{ + types.ArgBytes{0, 1}, + types.ArgBytes{2, 3}, + }, }) }) t.Run("Unauthorized sender", func(t *testing.T) { t.Parallel() - testFn(testConfig{ + testFn(t, testConfig{ sender: privateKey, expectedError: "unauthorized", + sequence: types.Sequence{ + types.ArgBytes{0, 1}, + types.ArgBytes{2, 3}, + }, }) }) - t.Run("Unauthorized sender", func(t *testing.T) { + t.Run("Fail to store off chain data", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - sender: privateKey, - expectedError: "unauthorized", + testFn(t, testConfig{ + sender: otherPrivateKey, + expectedError: "failed to store offchain data", + storeOffChainDataReturns: []interface{}{errors.New("error")}, + sequence: types.Sequence{ + types.ArgBytes{0, 1}, + types.ArgBytes{2, 3}, + }, }) }) - t.Run("Fail to begin state transaction", func(t *testing.T) { + t.Run("Fail to sign sequence", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - sender: otherPrivateKey, - expectedError: "failed to connect to the state", - beginStateTransactionReturns: []interface{}{nil, errors.New("error")}, + key, err := crypto.GenerateKey() + require.NoError(t, err) + + key.D = common.Big0 // alter the key so that signing does not pass + + testFn(t, testConfig{ + sender: otherPrivateKey, + signer: key, + storeOffChainDataReturns: []interface{}{nil}, + expectedError: "failed to sign", + sequence: types.Sequence{ + types.ArgBytes{0, 1}, + types.ArgBytes{2, 3}, + }, }) }) - t.Run("Fail to store off chain data - rollback fails", func(t *testing.T) { + t.Run("Happy path - sequence signed", func(t *testing.T) { t.Parallel() - testFn(testConfig{ + testFn(t, testConfig{ sender: otherPrivateKey, - expectedError: "failed to rollback db transaction", - storeOffChainDataReturns: []interface{}{errors.New("error")}, - rollbackReturns: []interface{}{errors.New("rollback fails")}, + storeOffChainDataReturns: []interface{}{nil}, + sequence: types.Sequence{ + types.ArgBytes{0, 1}, + types.ArgBytes{2, 3}, + }, }) }) +} - t.Run("Fail to store off chain data", func(t *testing.T) { +func TestDataCom_SignSequenceBanana(t *testing.T) { + t.Parallel() + + type testConfig struct { + storeOffChainDataReturns []interface{} + sender *ecdsa.PrivateKey + signer *ecdsa.PrivateKey + sequence types.SequenceBanana + expectedError string + } + + sequenceSignerKey, err := crypto.GenerateKey() + require.NoError(t, err) + + trustedSequencerKey, err := crypto.GenerateKey() + require.NoError(t, err) + + unknownKey, err := crypto.GenerateKey() + require.NoError(t, err) + + testFn := func(t *testing.T, cfg testConfig) { + t.Helper() + + var ( + signer = sequenceSignerKey + signedSequence *types.SignedSequenceBanana + err error + ) + + dbMock := mocks.NewDB(t) + + if len(cfg.storeOffChainDataReturns) > 0 { + dbMock.On("StoreOffChainData", mock.Anything, cfg.sequence.OffChainData()).Return( + cfg.storeOffChainDataReturns...).Once() + } + + ethermanMock := mocks.NewEtherman(t) + + ethermanMock.On("TrustedSequencer", mock.Anything).Return(crypto.PubkeyToAddress(trustedSequencerKey.PublicKey), nil).Once() + ethermanMock.On("TrustedSequencerURL", mock.Anything).Return("http://some-url", nil).Once() + + sqr := sequencer.NewTracker(config.L1Config{ + Timeout: cfgTypes.Duration{Duration: time.Minute}, + RetryPeriod: cfgTypes.Duration{Duration: time.Second}, + }, ethermanMock) + + sqr.Start(context.Background()) + + if cfg.sender != nil { + signature, err := cfg.sequence.Sign(cfg.sender) + require.NoError(t, err) + signedSequence = &types.SignedSequenceBanana{ + Sequence: cfg.sequence, + Signature: signature, + } + } else { + signedSequence = &types.SignedSequenceBanana{ + Sequence: cfg.sequence, + Signature: []byte{}, + } + } + + if cfg.signer != nil { + signer = cfg.signer + } + + dce := NewEndpoints(dbMock, signer, sqr, common.Address{}) + + sig, err := dce.SignSequenceBanana(*signedSequence) + if cfg.expectedError != "" { + require.ErrorContains(t, err, cfg.expectedError) + } else { + require.NoError(t, err) + require.NotEmpty(t, sig) + } + + sqr.Stop() + + dbMock.AssertExpectations(t) + ethermanMock.AssertExpectations(t) + } + + t.Run("Failed to verify sender", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - sender: otherPrivateKey, - expectedError: "failed to store offchain data", - storeOffChainDataReturns: []interface{}{errors.New("error")}, - rollbackReturns: []interface{}{nil}, + testFn(t, testConfig{ + expectedError: "failed to verify sender", + sequence: types.SequenceBanana{}, + }) + }) + + t.Run("Unauthorized sender", func(t *testing.T) { + t.Parallel() + + testFn(t, testConfig{ + sender: sequenceSignerKey, + expectedError: "unauthorized", + sequence: types.SequenceBanana{}, + signer: unknownKey, }) }) - t.Run("Fail to commit tx", func(t *testing.T) { + t.Run("Fail to store off chain data", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - sender: otherPrivateKey, - expectedError: "failed to commit db transaction", - storeOffChainDataReturns: []interface{}{nil}, - commitReturns: []interface{}{errors.New("error")}, + testFn(t, testConfig{ + sender: trustedSequencerKey, + expectedError: "failed to store offchain data", + storeOffChainDataReturns: []interface{}{errors.New("error")}, + sequence: types.SequenceBanana{}, }) }) @@ -181,22 +291,22 @@ func TestDataCom_SignSequence(t *testing.T) { key.D = common.Big0 // alter the key so that signing does not pass - testFn(testConfig{ - sender: otherPrivateKey, + testFn(t, testConfig{ + sender: trustedSequencerKey, signer: key, storeOffChainDataReturns: []interface{}{nil}, - commitReturns: []interface{}{nil}, expectedError: "failed to sign", + sequence: types.SequenceBanana{}, }) }) t.Run("Happy path - sequence signed", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - sender: otherPrivateKey, + testFn(t, testConfig{ + sender: trustedSequencerKey, storeOffChainDataReturns: []interface{}{nil}, - commitReturns: []interface{}{nil}, + sequence: types.SequenceBanana{}, }) }) } diff --git a/services/datacom/datacom_x1.go b/services/datacom/datacom_x1.go index 8894ad37..f0961c88 100644 --- a/services/datacom/datacom_x1.go +++ b/services/datacom/datacom_x1.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" ) -func (d *DataComEndpoints) isEmptyAddress(a common.Address) bool { +func (d *Endpoints) isEmptyAddress(a common.Address) bool { emptyAddress := common.Address{} return bytes.Equal(a[:], emptyAddress[:]) } diff --git a/services/status/status.go b/services/status/status.go new file mode 100644 index 00000000..6b3d2a2a --- /dev/null +++ b/services/status/status.go @@ -0,0 +1,62 @@ +package status + +import ( + "context" + "time" + + dataavailability "github.com/0xPolygon/cdk-data-availability" + "github.com/0xPolygon/cdk-data-availability/db" + "github.com/0xPolygon/cdk-data-availability/log" + "github.com/0xPolygon/cdk-data-availability/rpc" + "github.com/0xPolygon/cdk-data-availability/synchronizer" + "github.com/0xPolygon/cdk-data-availability/types" +) + +// APISTATUS is the namespace of the status service +const APISTATUS = "status" + +// GapsDetector is an interface for detecting gaps in the offchain data +type GapsDetector interface { + // Gaps returns a map of gaps in the offchain data + Gaps() map[uint64]uint64 +} + +// Endpoints contains implementations for the "status" RPC endpoints +type Endpoints struct { + db db.DB + startTime time.Time + gapsDetector GapsDetector +} + +// NewEndpoints returns Endpoints +func NewEndpoints(db db.DB, gapsDetector GapsDetector) *Endpoints { + return &Endpoints{ + db: db, + startTime: time.Now(), + gapsDetector: gapsDetector, + } +} + +// GetStatus returns the status of the service +func (s *Endpoints) GetStatus() (interface{}, rpc.Error) { + ctx := context.Background() + uptime := time.Since(s.startTime).String() + + rowCount, err := s.db.CountOffchainData(ctx) + if err != nil { + log.Errorf("failed to get the key count from the offchain_data table: %v", err) + } + + backfillProgress, err := s.db.GetLastProcessedBlock(ctx, string(synchronizer.L1SyncTask)) + if err != nil { + log.Errorf("failed to get last block processed by the synchronizer: %v", err) + } + + return types.DACStatus{ + Version: dataavailability.Version, + Uptime: uptime, + KeyCount: rowCount, + BackfillProgress: backfillProgress, + OffchainDataGapsExist: len(s.gapsDetector.Gaps()) > 0, + }, nil +} diff --git a/services/status/status_test.go b/services/status/status_test.go new file mode 100644 index 00000000..cc9b737f --- /dev/null +++ b/services/status/status_test.go @@ -0,0 +1,80 @@ +package status + +import ( + "errors" + "testing" + + "github.com/0xPolygon/cdk-data-availability/mocks" + "github.com/0xPolygon/cdk-data-availability/types" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func TestEndpoints_GetStatus(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + countOffchainData uint64 + countOffchainDataErr error + getLastProcessedBlock uint64 + getLastProcessedBlockErr error + expectedError error + }{ + { + name: "successfully got status", + countOffchainData: 1, + getLastProcessedBlock: 2, + }, + { + name: "failed to count offchain data", + countOffchainDataErr: errors.New("test error"), + getLastProcessedBlock: 2, + }, + { + name: "failed to count offchain data and last processed block", + countOffchainDataErr: errors.New("test error"), + getLastProcessedBlockErr: errors.New("test error"), + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + dbMock := mocks.NewDB(t) + + dbMock.On("CountOffchainData", mock.Anything). + Return(tt.countOffchainData, tt.countOffchainDataErr) + + dbMock.On("GetLastProcessedBlock", mock.Anything, mock.Anything). + Return(tt.getLastProcessedBlock, tt.getLastProcessedBlockErr) + + gapDetectorMock := mocks.NewGapsDetector(t) + + gapDetectorMock.On("Gaps").Return(map[uint64]uint64{1: 1}) + + statusEndpoints := NewEndpoints(dbMock, gapDetectorMock) + + actual, err := statusEndpoints.GetStatus() + + if tt.expectedError != nil { + require.Error(t, err) + require.EqualError(t, err, tt.expectedError.Error()) + } else { + require.NoError(t, err) + + dacStatus, ok := actual.(types.DACStatus) + require.True(t, ok, "actual is not of type types.DACStatus") + + require.NotEmpty(t, dacStatus.Uptime) + require.Equal(t, "v0.1.0", dacStatus.Version) + require.Equal(t, tt.countOffchainData, dacStatus.KeyCount) + require.Equal(t, tt.getLastProcessedBlock, dacStatus.BackfillProgress) + require.True(t, dacStatus.OffchainDataGapsExist) + } + }) + } +} diff --git a/services/sync/sync.go b/services/sync/sync.go index 8bed2474..f525d63f 100644 --- a/services/sync/sync.go +++ b/services/sync/sync.go @@ -7,33 +7,62 @@ import ( "github.com/0xPolygon/cdk-data-availability/log" "github.com/0xPolygon/cdk-data-availability/rpc" "github.com/0xPolygon/cdk-data-availability/types" + "github.com/ethereum/go-ethereum/common" ) -// APISYNC is the namespace of the sync service -const APISYNC = "sync" +const ( + // APISYNC is the namespace of the sync service + APISYNC = "sync" -// SyncEndpoints contains implementations for the "zkevm" RPC endpoints -type SyncEndpoints struct { - db db.DB - txMan rpc.DBTxManager + // maxListHashes is the maximum number of hashes that can be requested in a ListOffChainData call + maxListHashes = 100 +) + +// Endpoints contains implementations for the "zkevm" RPC endpoints +type Endpoints struct { + db db.DB } -// NewSyncEndpoints returns ZKEVMEndpoints -func NewSyncEndpoints(db db.DB) *SyncEndpoints { - return &SyncEndpoints{ +// NewEndpoints returns Endpoints +func NewEndpoints(db db.DB) *Endpoints { + return &Endpoints{ db: db, } } // GetOffChainData returns the image of the given hash -func (z *SyncEndpoints) GetOffChainData(hash types.ArgHash) (interface{}, rpc.Error) { - return z.txMan.NewDbTxScope(z.db, func(ctx context.Context, dbTx db.Tx) (interface{}, rpc.Error) { - data, err := z.db.GetOffChainData(ctx, hash.Hash(), dbTx) - if err != nil { - log.Errorf("failed to get the offchain requested data from the DB: %v", err) - return "0x0", rpc.NewRPCError(rpc.DefaultErrorCode, "failed to get the requested data") - } - - return data, nil - }) +func (z *Endpoints) GetOffChainData(hash types.ArgHash) (interface{}, rpc.Error) { + data, err := z.db.GetOffChainData(context.Background(), hash.Hash()) + if err != nil { + log.Errorf("failed to get the offchain requested data from the DB: %v", err) + return "0x0", rpc.NewRPCError(rpc.DefaultErrorCode, "failed to get the requested data") + } + + return types.ArgBytes(data.Value), nil +} + +// ListOffChainData returns the list of images of the given hashes +func (z *Endpoints) ListOffChainData(hashes []types.ArgHash) (interface{}, rpc.Error) { + if len(hashes) > maxListHashes { + log.Errorf("too many hashes requested in ListOffChainData: %d", len(hashes)) + return "0x0", rpc.NewRPCError(rpc.InvalidRequestErrorCode, "too many hashes requested") + } + + keys := make([]common.Hash, len(hashes)) + for i, hash := range hashes { + keys[i] = hash.Hash() + } + + list, err := z.db.ListOffChainData(context.Background(), keys) + if err != nil { + log.Errorf("failed to list the requested data from the DB: %v", err) + return "0x0", rpc.NewRPCError(rpc.DefaultErrorCode, "failed to list the requested data") + } + + listMap := make(map[common.Hash]types.ArgBytes) + for _, data := range list { + listMap[data.Key] = data.Value + } + + return listMap, nil } diff --git a/services/sync/sync_test.go b/services/sync/sync_test.go index 2b928715..0aa3ac9a 100644 --- a/services/sync/sync_test.go +++ b/services/sync/sync_test.go @@ -2,42 +2,47 @@ package sync import ( "context" + "crypto/rand" "errors" "testing" "github.com/0xPolygon/cdk-data-availability/mocks" "github.com/0xPolygon/cdk-data-availability/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" ) -func TestSyncEndpoints_GetOffChainData(t *testing.T) { +func TestEndpoints_GetOffChainData(t *testing.T) { + t.Parallel() + tests := []struct { name string hash types.ArgHash - data interface{} + data *types.OffChainData dbErr error - txErr error err error }{ { name: "successfully got offchain data", hash: types.ArgHash{}, - data: types.ArgBytes("offchaindata"), + data: &types.OffChainData{ + Key: common.Hash{}, + Value: types.ArgBytes("offchaindata"), + BatchNum: 0, + }, }, { - name: "db returns error", - hash: types.ArgHash{}, - data: types.ArgBytes("offchaindata"), + name: "db returns error", + hash: types.ArgHash{}, + data: &types.OffChainData{ + Key: common.Hash{}, + Value: types.ArgBytes("offchaindata"), + BatchNum: 0, + }, dbErr: errors.New("test error"), err: errors.New("failed to get the requested data"), }, - { - name: "tx returns error", - hash: types.ArgHash{}, - data: types.ArgBytes("offchaindata"), - txErr: errors.New("test error"), - err: errors.New("failed to connect to the state"), - }, } for _, tt := range tests { tt := tt @@ -45,28 +50,14 @@ func TestSyncEndpoints_GetOffChainData(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - txMock := mocks.NewTx(t) - dbMock := mocks.NewDB(t) - dbMock.On("BeginStateTransaction", context.Background()). - Return(txMock, tt.txErr) - if tt.txErr == nil { - dbMock.On("GetOffChainData", context.Background(), tt.hash.Hash(), txMock). - Return(tt.data, tt.dbErr) - if tt.err != nil { - txMock.On("Rollback"). - Return(nil) - } else { - txMock.On("Commit"). - Return(nil) - } - } + dbMock.On("GetOffChainData", context.Background(), tt.hash.Hash()). + Return(tt.data, tt.dbErr) - defer txMock.AssertExpectations(t) defer dbMock.AssertExpectations(t) - z := &SyncEndpoints{db: dbMock} + z := &Endpoints{db: dbMock} got, err := z.GetOffChainData(tt.hash) if tt.err != nil { @@ -74,8 +65,106 @@ func TestSyncEndpoints_GetOffChainData(t *testing.T) { require.EqualError(t, tt.err, err.Error()) } else { require.NoError(t, err) - require.Equal(t, tt.data, got) + require.Equal(t, types.ArgBytes(tt.data.Value), got) + } + }) + } +} + +func TestSyncEndpoints_ListOffChainData(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + hashes []types.ArgHash + data []types.OffChainData + dbErr error + err error + }{ + { + name: "successfully got offchain data", + hashes: generateRandomHashes(t, 1), + data: []types.OffChainData{{ + Key: common.BytesToHash(nil), + Value: types.ArgBytes("offchaindata"), + BatchNum: 0, + }}, + }, + { + name: "db returns error", + hashes: []types.ArgHash{}, + data: []types.OffChainData{{ + Key: common.BytesToHash(nil), + Value: types.ArgBytes("offchaindata"), + BatchNum: 0, + }}, + dbErr: errors.New("test error"), + err: errors.New("failed to list the requested data"), + }, + { + name: "too many hashes requested", + hashes: generateRandomHashes(t, maxListHashes+1), + err: errors.New("too many hashes requested"), + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + dbMock := mocks.NewDB(t) + + keys := make([]common.Hash, len(tt.hashes)) + for i, hash := range tt.hashes { + keys[i] = hash.Hash() + } + + if tt.data != nil { + dbMock.On("ListOffChainData", context.Background(), keys). + Return(tt.data, tt.dbErr) + + defer dbMock.AssertExpectations(t) + } + + z := &Endpoints{db: dbMock} + + got, err := z.ListOffChainData(tt.hashes) + if tt.err != nil { + require.Error(t, err) + require.ErrorContains(t, tt.err, err.Error()) + } else { + require.NoError(t, err) + + listMap := make(map[common.Hash]types.ArgBytes) + for _, data := range tt.data { + listMap[data.Key] = data.Value + } + + require.Equal(t, listMap, got) } }) } } + +func generateRandomHashes(t *testing.T, numOfHashes int) []types.ArgHash { + t.Helper() + + hashes := make([]types.ArgHash, numOfHashes) + for i := 0; i < numOfHashes; i++ { + hashes[i] = types.ArgHash(generateRandomHash(t)) + } + + return hashes +} + +func generateRandomHash(t *testing.T) common.Hash { + t.Helper() + + randomData := make([]byte, 32) + + _, err := rand.Read(randomData) + require.NoError(t, err) + + return crypto.Keccak256Hash(randomData) +} diff --git a/synchronizer/batches.go b/synchronizer/batches.go index b88a1e04..85e17388 100644 --- a/synchronizer/batches.go +++ b/synchronizer/batches.go @@ -1,17 +1,19 @@ package synchronizer import ( + "bytes" "context" "fmt" "math/rand" + "sort" "sync" "time" + "github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonvalidiumetrog" "github.com/0xPolygon/cdk-data-availability/client" "github.com/0xPolygon/cdk-data-availability/config" "github.com/0xPolygon/cdk-data-availability/db" "github.com/0xPolygon/cdk-data-availability/etherman" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygonvalidium" "github.com/0xPolygon/cdk-data-availability/log" "github.com/0xPolygon/cdk-data-availability/rpc" "github.com/0xPolygon/cdk-data-availability/sequencer" @@ -25,24 +27,27 @@ const defaultBlockBatchSize = 32 // SequencerTracker is an interface that defines functions that a sequencer tracker must implement type SequencerTracker interface { - GetSequenceBatch(batchNum uint64) (*sequencer.SeqBatch, error) + GetSequenceBatch(ctx context.Context, batchNum uint64) (*sequencer.SeqBatch, error) } -// BatchSynchronizer watches for number events, checks if they are "locally" stored, then retrieves and stores missing data +// BatchSynchronizer watches for number events, checks if they are +// "locally" stored, then retrieves and stores missing data type BatchSynchronizer struct { - client etherman.Etherman - stop chan struct{} - retry time.Duration - rpcTimeout time.Duration - blockBatchSize uint - self common.Address - db db.DB - committee map[common.Address]etherman.DataCommitteeMember - lock sync.Mutex - reorgs <-chan BlockReorg - events chan *polygonvalidium.PolygonvalidiumSequenceBatches - sequencer SequencerTracker - rpcClientFactory client.Factory + client etherman.Etherman + stop chan struct{} + retry time.Duration + rpcTimeout time.Duration + blockBatchSize uint + self common.Address + db db.DB + committee *CommitteeMapSafe + syncLock sync.Mutex + reorgs <-chan BlockReorg + events chan *polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatches + sequencer SequencerTracker + rpcClientFactory client.Factory + offchainDataGaps map[uint64]uint64 + offchainDataGapsLock sync.RWMutex } // NewBatchSynchronizer creates the BatchSynchronizer @@ -68,75 +73,96 @@ func NewBatchSynchronizer( self: self, db: db, reorgs: reorgs, - events: make(chan *polygonvalidium.PolygonvalidiumSequenceBatches), + events: make(chan *polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatches), sequencer: sequencer, rpcClientFactory: rpcClientFactory, + offchainDataGaps: make(map[uint64]uint64), } return synchronizer, synchronizer.resolveCommittee() } func (bs *BatchSynchronizer) resolveCommittee() error { - bs.lock.Lock() - defer bs.lock.Unlock() - - committee := make(map[common.Address]etherman.DataCommitteeMember) current, err := bs.client.GetCurrentDataCommittee() if err != nil { return err } - for _, member := range current.Members { - if bs.self != member.Addr { - committee[member.Addr] = member + + filteredMembers := make([]etherman.DataCommitteeMember, 0, len(current.Members)) + for _, m := range current.Members { + if m.Addr != bs.self { + filteredMembers = append(filteredMembers, m) } } - bs.committee = committee + + bs.committee = NewCommitteeMapSafe() + bs.committee.StoreBatch(filteredMembers) return nil } // Start starts the synchronizer -func (bs *BatchSynchronizer) Start() { - log.Infof("starting number synchronizer, DAC addr: %v", bs.self) - go bs.consumeEvents() - go bs.produceEvents() - go bs.handleReorgs() +func (bs *BatchSynchronizer) Start(ctx context.Context) { + log.Infof("starting batch synchronizer, DAC addr: %v", bs.self) + go bs.processUnresolvedBatches(ctx) + go bs.produceEvents(ctx) + go bs.handleReorgs(ctx) + go bs.startOffchainDataGapsDetection(ctx) } // Stop stops the synchronizer func (bs *BatchSynchronizer) Stop() { - close(bs.events) close(bs.stop) } -func (bs *BatchSynchronizer) handleReorgs() { +// Gaps returns the offchain data gaps +func (bs *BatchSynchronizer) Gaps() map[uint64]uint64 { + bs.offchainDataGapsLock.RLock() + gaps := make(map[uint64]uint64, len(bs.offchainDataGaps)) + for key, value := range bs.offchainDataGaps { + gaps[key] = value + } + bs.offchainDataGapsLock.RUnlock() + return gaps +} + +func (bs *BatchSynchronizer) handleReorgs(ctx context.Context) { + log.Info("starting reorgs handler") for { select { case r := <-bs.reorgs: - latest, err := getStartBlock(bs.db) + bs.syncLock.Lock() + + latest, err := getStartBlock(ctx, bs.db, L1SyncTask) if err != nil { log.Errorf("could not determine latest processed block: %v", err) + bs.syncLock.Unlock() + continue } + if latest < r.Number { // only reset start block if necessary + bs.syncLock.Unlock() continue } - err = setStartBlock(bs.db, r.Number) - if err != nil { + + if err = setStartBlock(ctx, bs.db, r.Number, L1SyncTask); err != nil { log.Errorf("failed to store new start block to %d: %v", r.Number, err) } + + bs.syncLock.Unlock() case <-bs.stop: return } } } -func (bs *BatchSynchronizer) produceEvents() { +func (bs *BatchSynchronizer) produceEvents(ctx context.Context) { log.Info("starting event producer") for { delay := time.NewTimer(bs.retry) select { case <-delay.C: - if err := bs.filterEvents(); err != nil { + if err := bs.filterEvents(ctx); err != nil { log.Errorf("error filtering events: %v", err) } case <-bs.stop: @@ -146,8 +172,11 @@ func (bs *BatchSynchronizer) produceEvents() { } // Start an iterator from last block processed, picking off SequenceBatches events -func (bs *BatchSynchronizer) filterEvents() error { - start, err := getStartBlock(bs.db) +func (bs *BatchSynchronizer) filterEvents(ctx context.Context) error { + bs.syncLock.Lock() + defer bs.syncLock.Unlock() + + start, err := getStartBlock(ctx, bs.db, L1SyncTask) if err != nil { return err } @@ -155,11 +184,12 @@ func (bs *BatchSynchronizer) filterEvents() error { end := start + uint64(bs.blockBatchSize) // get the latest block number - header, err := bs.client.HeaderByNumber(context.TODO(), nil) + header, err := bs.client.HeaderByNumber(ctx, nil) if err != nil { - log.Errorf("failed to determine latest block number", err) + log.Errorf("failed to determine latest block number: %v", err) return err } + // we don't want to scan beyond latest block if end > header.Number.Uint64() { end = header.Number.Uint64() @@ -167,172 +197,308 @@ func (bs *BatchSynchronizer) filterEvents() error { iter, err := bs.client.FilterSequenceBatches( &bind.FilterOpts{ + Context: ctx, Start: start, End: &end, - Context: context.TODO(), }, nil) if err != nil { + log.Errorf("failed to create SequenceBatches event iterator: %v", err) return err } + + // Collect events into the slice + var events []*polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatches for iter.Next() { if iter.Error() != nil { return iter.Error() } - bs.events <- iter.Event + + events = append(events, iter.Event) } - // advance start block - err = setStartBlock(bs.db, end) - if err != nil { - return err + if err = iter.Close(); err != nil { + log.Errorf("failed to close SequenceBatches event iterator: %v", err) } - return nil -} -func (bs *BatchSynchronizer) consumeEvents() { - log.Info("starting event consumer") - for { - select { - case sb := <-bs.events: - if err := bs.handleEvent(sb); err != nil { - log.Errorf("failed to handle event: %v", err) - } - case <-bs.stop: - return + // Sort events by block number ascending + sort.Slice(events, func(i, j int) bool { + return events[i].Raw.BlockNumber < events[j].Raw.BlockNumber + }) + + // Handle events + for _, event := range events { + if err = bs.handleEvent(ctx, event); err != nil { + log.Errorf("failed to handleEvent: %v", err) + return setStartBlock(ctx, bs.db, event.Raw.BlockNumber-1, L1SyncTask) } } -} -// batchKey is the pairing of batch number and data hash of a batch -type batchKey struct { - number uint64 - hash common.Hash + return setStartBlock(ctx, bs.db, end, L1SyncTask) } -func (bs *BatchSynchronizer) handleEvent(event *polygonvalidium.PolygonvalidiumSequenceBatches) error { - ctx, cancel := context.WithTimeout(context.Background(), bs.rpcTimeout) +func (bs *BatchSynchronizer) handleEvent( + parentCtx context.Context, + event *polygonvalidiumetrog.PolygonvalidiumetrogSequenceBatches, +) error { + ctx, cancel := context.WithTimeout(parentCtx, bs.rpcTimeout) defer cancel() tx, _, err := bs.client.GetTx(ctx, event.Raw.TxHash) if err != nil { return err } - txData := tx.Data() - keys, err := UnpackTxData(txData) + + keys, err := UnpackTxData(tx.Data()) if err != nil { return err } + // The event has the _last_ batch number & list of hashes. Each hash is // in order, so the batch number can be computed from position in array - var batchKeys []batchKey + var batchKeys []types.BatchKey for i, j := 0, len(keys)-1; i < len(keys); i, j = i+1, j-1 { - batchKeys = append(batchKeys, batchKey{ - number: event.NumBatch - uint64(i), - hash: keys[j], + batchKeys = append(batchKeys, types.BatchKey{ + Number: event.NumBatch - uint64(i), //nolint:gosec + Hash: keys[j], }) } - // Pick out any batches that are missing from storage - var missing []batchKey - for _, key := range batchKeys { - if !exists(bs.db, key.hash) { - missing = append(missing, key) + + // Store batch keys. Already handled batch keys are going to be ignored based on the DB logic. + return storeUnresolvedBatchKeys(ctx, bs.db, batchKeys) +} + +func (bs *BatchSynchronizer) processUnresolvedBatches(ctx context.Context) { + log.Info("starting handling unresolved batches") + for { + delay := time.NewTimer(bs.retry) + select { + case <-delay.C: + if err := bs.handleUnresolvedBatches(ctx); err != nil { + log.Error(err) + } + case <-bs.stop: + return } } - if len(missing) == 0 { +} + +// handleUnresolvedBatches handles unresolved batches that were collected by the event consumer +func (bs *BatchSynchronizer) handleUnresolvedBatches(ctx context.Context) error { + // Get unresolved batches + batchKeys, err := getUnresolvedBatchKeys(ctx, bs.db) + if err != nil { + return fmt.Errorf("failed to get unresolved batch keys: %v", err) + } + + if len(batchKeys) == 0 { return nil } - // Resolve the missing data - var data []types.OffChainData - for _, key := range missing { - var value *types.OffChainData - value, err = bs.resolve(key) + + // Collect list of keys + keys := make([]common.Hash, len(batchKeys)) + hashToKeys := make(map[common.Hash]types.BatchKey) + for i, key := range batchKeys { + keys[i] = key.Hash + hashToKeys[key.Hash] = key + } + + // Get the existing offchain data by the given list of keys + existingOffchainData, err := listOffchainData(ctx, bs.db, keys) + if err != nil { + return fmt.Errorf("failed to list offchain data: %v", err) + } + + // Resolve the unresolved data + data := make([]types.OffChainData, 0) + resolved := make([]types.BatchKey, 0) + + // Go over existing keys and mark them as resolved if they exist. + // Update the batch number if it is zero. + for _, extData := range existingOffchainData { + batchKey, ok := hashToKeys[extData.Key] + if !ok { + // This should not happen, but log it just in case + log.Errorf("unexpected key %s in the offchain data", extData.Key.Hex()) + continue + } + + // If the batch number is zero, update it + if extData.BatchNum == 0 { + extData.BatchNum = batchKey.Number + data = append(data, extData) + } + + // Mark the batch as resolved + resolved = append(resolved, batchKey) + + // Remove the key from the map + delete(hashToKeys, extData.Key) + } + + // Resolve the remaining unresolved data + for _, key := range hashToKeys { + value, err := bs.resolve(ctx, key) if err != nil { - return err + log.Errorf("failed to resolve batch %s: %v", key.Hash.Hex(), err) + continue } - log.Infof("resolved missing data for number %d, key %v", key.number, key.hash.Hex()) + + resolved = append(resolved, key) data = append(data, *value) } - // Finally, store the data - return store(bs.db, data) + + // Store data of the batches to the DB + if len(data) > 0 { + if err = storeOffchainData(ctx, bs.db, data); err != nil { + return fmt.Errorf("failed to store offchain data: %v", err) + } + } + + // Mark batches as resolved + if len(resolved) > 0 { + if err = deleteUnresolvedBatchKeys(ctx, bs.db, resolved); err != nil { + return fmt.Errorf("failed to delete successfully resolved batch keys: %v", err) + } + } + + return nil } -func (bs *BatchSynchronizer) resolve(batch batchKey) (*types.OffChainData, error) { +func (bs *BatchSynchronizer) resolve(ctx context.Context, batch types.BatchKey) (*types.OffChainData, error) { // First try to get the data from the trusted sequencer - data := bs.trySequencer(batch) + data := bs.trySequencer(ctx, batch) if data != nil { return data, nil } // If the sequencer failed to produce data, try the other nodes - if len(bs.committee) == 0 { + if bs.committee.Length() == 0 { // committee is resolved again once all members are evicted. They can be evicted // for not having data, or their config being malformed - err := bs.resolveCommittee() - if err != nil { + if err := bs.resolveCommittee(); err != nil { return nil, err } } // pull out the members, iterating will change the map on error - members := make([]etherman.DataCommitteeMember, len(bs.committee)) - for _, member := range bs.committee { - members = append(members, member) - } + members := bs.committee.AsSlice() + // iterate through them randomly until data is resolved for _, r := range rand.Perm(len(members)) { member := members[r] - if member.URL == "" || member.Addr == common.HexToAddress("0x0") || member.Addr == bs.self { - delete(bs.committee, member.Addr) + if member.URL == "" || + common.HexToAddress("0x0").Cmp(member.Addr) == 0 || + member.Addr.Cmp(bs.self) == 0 { + bs.committee.Delete(member.Addr) continue // malformed committee, skip what is known to be wrong } - value, err := bs.resolveWithMember(batch.hash, member) + + value, err := bs.resolveWithMember(ctx, batch, member) if err != nil { log.Warnf("error resolving, continuing: %v", err) - delete(bs.committee, member.Addr) + bs.committee.Delete(member.Addr) continue // did not have data or errored out } return value, nil } - return nil, rpc.NewRPCError(rpc.NotFoundErrorCode, "no data found for number %d, key %v", batch.number, batch.hash.Hex()) + + return nil, rpc.NewRPCError(rpc.NotFoundErrorCode, + "no data found for number %d, key %v", batch.Number, batch.Hash.Hex()) } // trySequencer returns L2Data from the trusted sequencer, but does not return errors, only logs warnings if not found. -func (bs *BatchSynchronizer) trySequencer(batch batchKey) *types.OffChainData { - seqBatch, err := bs.sequencer.GetSequenceBatch(batch.number) +func (bs *BatchSynchronizer) trySequencer(ctx context.Context, batch types.BatchKey) *types.OffChainData { + seqBatch, err := bs.sequencer.GetSequenceBatch(ctx, batch.Number) if err != nil { log.Warnf("failed to get data from sequencer: %v", err) return nil } expectKey := crypto.Keccak256Hash(seqBatch.BatchL2Data) - if batch.hash != expectKey { - log.Warnf("number %d: sequencer gave wrong data for key: %s", batch.number, batch.hash.Hex()) + if batch.Hash != expectKey { + log.Warnf("number %d: sequencer gave wrong data for key: %s", batch.Number, batch.Hash.Hex()) return nil } + return &types.OffChainData{ - Key: batch.hash, - Value: seqBatch.BatchL2Data, + Key: batch.Hash, + Value: seqBatch.BatchL2Data, + BatchNum: batch.Number, } } -func (bs *BatchSynchronizer) resolveWithMember(key common.Hash, member etherman.DataCommitteeMember) (*types.OffChainData, error) { +func (bs *BatchSynchronizer) resolveWithMember( + parentCtx context.Context, + batch types.BatchKey, + member etherman.DataCommitteeMember, +) (*types.OffChainData, error) { cm := bs.rpcClientFactory.New(member.URL) - ctx, cancel := context.WithTimeout(context.Background(), bs.rpcTimeout) + + ctx, cancel := context.WithTimeout(parentCtx, bs.rpcTimeout) defer cancel() - log.Debugf("trying member %v at %v for key %v", member.Addr.Hex(), member.URL, key.Hex()) + log.Debugf("trying member %v at %v for key %v", member.Addr.Hex(), member.URL, batch.Hash.Hex()) - bytes, err := cm.GetOffChainData(ctx, key) + bytes, err := cm.GetOffChainData(ctx, batch.Hash) if err != nil { return nil, err } + expectKey := crypto.Keccak256Hash(bytes) - if key != expectKey { + if batch.Hash.Cmp(expectKey) != 0 { return nil, fmt.Errorf("unexpected key gotten from member: %v. Key: %v", member.Addr.Hex(), expectKey.Hex()) } + return &types.OffChainData{ - Key: key, - Value: bytes, + Key: batch.Hash, + Value: bytes, + BatchNum: batch.Number, }, nil } + +func (bs *BatchSynchronizer) startOffchainDataGapsDetection(ctx context.Context) { + log.Info("starting handling unresolved batches") + for { + delay := time.NewTimer(time.Minute) + select { + case <-delay.C: + if err := bs.detectOffchainDataGaps(ctx); err != nil { + log.Error(err) + } + case <-bs.stop: + return + } + } +} + +// detectOffchainDataGaps detects offchain data gaps and reports them in logs and the service state. +func (bs *BatchSynchronizer) detectOffchainDataGaps(ctx context.Context) error { + // Detect offchain data gaps + gaps, err := detectOffchainDataGaps(ctx, bs.db) + if err != nil { + return fmt.Errorf("failed to detect offchain data gaps: %v", err) + } + + // No gaps found, all good + if len(gaps) == 0 { + return nil + } + + // Log the detected gaps and store the detected gaps in the service state + gapsRaw := new(bytes.Buffer) + bs.offchainDataGapsLock.Lock() + bs.offchainDataGaps = make(map[uint64]uint64, len(gaps)) + for key, value := range gaps { + bs.offchainDataGaps[key] = value + + if _, err = fmt.Fprintf(gapsRaw, "%d=>%d\n", key, value); err != nil { + log.Errorf("failed to write offchain data gaps: %v", err) + } + } + bs.offchainDataGapsLock.Unlock() + + log.Warnf("detected offchain data gaps (current batch number => expected batch number): %s", gapsRaw.String()) + + return nil +} diff --git a/synchronizer/batches_test.go b/synchronizer/batches_test.go index f56adf2a..bbb905a9 100644 --- a/synchronizer/batches_test.go +++ b/synchronizer/batches_test.go @@ -1,13 +1,15 @@ package synchronizer import ( + "context" "errors" "math/big" "strings" "testing" + elderberryValidium "github.com/0xPolygon/cdk-contracts-tooling/contracts/elderberry/polygonvalidiumetrog" + etrogValidium "github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonvalidiumetrog" "github.com/0xPolygon/cdk-data-availability/etherman" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygonvalidium" "github.com/0xPolygon/cdk-data-availability/mocks" "github.com/0xPolygon/cdk-data-availability/sequencer" "github.com/0xPolygon/cdk-data-availability/types" @@ -65,7 +67,7 @@ func TestBatchSynchronizer_ResolveCommittee(t *testing.T) { } require.NoError(t, batchSyncronizer.resolveCommittee()) - require.Len(t, batchSyncronizer.committee, len(committee.Members)) + require.Equal(t, len(committee.Members), batchSyncronizer.committee.Length()) ethermanMock.AssertExpectations(t) }) @@ -91,9 +93,9 @@ func TestBatchSynchronizer_Resolve(t *testing.T) { } data := common.HexToHash("0xFFFF").Bytes() - batchKey := batchKey{ - number: 1, - hash: crypto.Keccak256Hash(data), + batchKey := types.BatchKey{ + Number: 1, + Hash: crypto.Keccak256Hash(data), } testFn := func(config testConfig) { @@ -128,9 +130,10 @@ func TestBatchSynchronizer_Resolve(t *testing.T) { client: ethermanMock, sequencer: sequencerMock, rpcClientFactory: clientFactoryMock, + committee: NewCommitteeMapSafe(), } - offChainData, err := batchSyncronizer.resolve(batchKey) + offChainData, err := batchSyncronizer.resolve(context.Background(), batchKey) if config.isErrorExpected { if config.errorString != "" { require.ErrorContains(t, err, config.errorString) @@ -139,7 +142,7 @@ func TestBatchSynchronizer_Resolve(t *testing.T) { } } else { require.NoError(t, err) - require.Equal(t, batchKey.hash, offChainData.Key) + require.Equal(t, batchKey.Hash, offChainData.Key) require.Equal(t, data, offChainData.Value) } @@ -153,9 +156,9 @@ func TestBatchSynchronizer_Resolve(t *testing.T) { t.Parallel() testFn(testConfig{ - getSequenceBatchArgs: []interface{}{batchKey.number}, + getSequenceBatchArgs: []interface{}{context.Background(), batchKey.Number}, getSequenceBatchReturns: []interface{}{&sequencer.SeqBatch{ - Number: types.ArgUint64(batchKey.number), + Number: types.ArgUint64(batchKey.Number), BatchL2Data: types.ArgBytes(data), }, nil}, }) @@ -179,9 +182,9 @@ func TestBatchSynchronizer_Resolve(t *testing.T) { testFn(testConfig{ isErrorExpected: false, - getOffChainDataArgs: [][]interface{}{{mock.Anything, batchKey.hash}}, + getOffChainDataArgs: [][]interface{}{{mock.Anything, batchKey.Hash}}, getOffChainDataReturns: [][]interface{}{{data, nil}}, - getSequenceBatchArgs: []interface{}{batchKey.number}, + getSequenceBatchArgs: []interface{}{context.Background(), batchKey.Number}, getSequenceBatchReturns: []interface{}{nil, errors.New("error")}, getCurrentDataCommitteeReturns: []interface{}{committee, nil}, newArgs: [][]interface{}{{committee.Members[0].URL}}, @@ -205,15 +208,15 @@ func TestBatchSynchronizer_Resolve(t *testing.T) { } testFn(testConfig{ - getSequenceBatchArgs: []interface{}{batchKey.number}, + getSequenceBatchArgs: []interface{}{context.Background(), batchKey.Number}, getSequenceBatchReturns: []interface{}{nil, errors.New("error")}, getCurrentDataCommitteeReturns: []interface{}{committee, nil}, newArgs: [][]interface{}{ {committee.Members[0].URL}, {committee.Members[1].URL}}, getOffChainDataArgs: [][]interface{}{ - {mock.Anything, batchKey.hash}, - {mock.Anything, batchKey.hash}, + {mock.Anything, batchKey.Hash}, + {mock.Anything, batchKey.Hash}, }, getOffChainDataReturns: [][]interface{}{ {nil, errors.New("error")}, // member doesn't have batch @@ -247,14 +250,14 @@ func TestBatchSynchronizer_Resolve(t *testing.T) { {committee.Members[0].URL}, {committee.Members[1].URL}}, getOffChainDataArgs: [][]interface{}{ - {mock.Anything, batchKey.hash}, - {mock.Anything, batchKey.hash}, + {mock.Anything, batchKey.Hash}, + {mock.Anything, batchKey.Hash}, }, getOffChainDataReturns: [][]interface{}{ {[]byte{0, 0, 0, 1}, nil}, // member doesn't have batch {[]byte{0, 0, 0, 1}, nil}, // member doesn't have batch }, - getSequenceBatchArgs: []interface{}{batchKey.number}, + getSequenceBatchArgs: []interface{}{context.Background(), batchKey.Number}, getSequenceBatchReturns: []interface{}{nil, errors.New("error")}, getCurrentDataCommitteeReturns: []interface{}{committee, nil}, }) @@ -269,23 +272,14 @@ func TestBatchSynchronizer_HandleEvent(t *testing.T) { getTxArgs []interface{} getTxReturns []interface{} // db mock - existsArgs []interface{} - existsReturns []interface{} - beginStateTransactionArgs []interface{} - beginStateTransactionReturns []interface{} - storeOffChainDataArgs []interface{} - storeOffChainDataReturns []interface{} - commitReturns []interface{} - rollbackArgs []interface{} - // sequencer mocks - getSequenceBatchArgs []interface{} - getSequenceBatchReturns []interface{} + storeUnresolvedBatchKeysArgs []interface{} + storeUnresolvedBatchKeysReturns []interface{} isErrorExpected bool } to := common.HexToAddress("0xFFFF") - event := &polygonvalidium.PolygonvalidiumSequenceBatches{ + event := &etrogValidium.PolygonvalidiumetrogSequenceBatches{ Raw: ethTypes.Log{ TxHash: common.BytesToHash([]byte{0, 1, 2, 3}), }, @@ -294,19 +288,19 @@ func TestBatchSynchronizer_HandleEvent(t *testing.T) { batchL2Data := []byte{1, 2, 3, 4, 5, 6} txHash := crypto.Keccak256Hash(batchL2Data) - batchData := []polygonvalidium.PolygonValidiumEtrogValidiumBatchData{ + batchData := []etrogValidium.PolygonValidiumEtrogValidiumBatchData{ { TransactionsHash: txHash, }, } - a, err := abi.JSON(strings.NewReader(polygonvalidium.PolygonvalidiumABI)) + a, err := abi.JSON(strings.NewReader(etrogValidium.PolygonvalidiumetrogABI)) require.NoError(t, err) methodDefinition, ok := a.Methods["sequenceBatchesValidium"] require.True(t, ok) - data, err := methodDefinition.Inputs.Pack(batchData, uint64(0), uint64(0), common.HexToAddress("0xABCD"), []byte{22, 23, 24}) + data, err := methodDefinition.Inputs.Pack(batchData, common.HexToAddress("0xABCD"), []byte{22, 23, 24}) require.NoError(t, err) tx := ethTypes.NewTx( @@ -319,37 +313,182 @@ func TestBatchSynchronizer_HandleEvent(t *testing.T) { Data: append(methodDefinition.ID, data...), }) - testFn := func(config testConfig) { + testFn := func(t *testing.T, config testConfig) { + t.Helper() + dbMock := mocks.NewDB(t) - txMock := mocks.NewTx(t) ethermanMock := mocks.NewEtherman(t) - sequencerMock := mocks.NewSequencerTracker(t) if config.getTxArgs != nil && config.getTxReturns != nil { ethermanMock.On("GetTx", config.getTxArgs...).Return( config.getTxReturns...).Once() } - if config.existsArgs != nil && config.existsReturns != nil { - dbMock.On("Exists", config.existsArgs...).Return( - config.existsReturns...).Once() + if config.storeUnresolvedBatchKeysArgs != nil && config.storeUnresolvedBatchKeysReturns != nil { + dbMock.On("StoreUnresolvedBatchKeys", config.storeUnresolvedBatchKeysArgs...).Return( + config.storeUnresolvedBatchKeysReturns...).Once() } - if config.getSequenceBatchArgs != nil && config.getSequenceBatchReturns != nil { - sequencerMock.On("GetSequenceBatch", config.getSequenceBatchArgs...).Return( - config.getSequenceBatchReturns...).Once() + batchSynronizer := &BatchSynchronizer{ + db: dbMock, + client: ethermanMock, } - if config.beginStateTransactionArgs != nil { - var returnArgs []interface{} - if config.beginStateTransactionReturns != nil { - returnArgs = config.beginStateTransactionReturns - } else { - returnArgs = append(returnArgs, txMock, nil) - } + err := batchSynronizer.handleEvent(context.Background(), event) + if config.isErrorExpected { + require.Error(t, err) + } else { + require.NoError(t, err) + } + + dbMock.AssertExpectations(t) + ethermanMock.AssertExpectations(t) + } + + t.Run("could not get tx data", func(t *testing.T) { + t.Parallel() + + testFn(t, testConfig{ + getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, + getTxReturns: []interface{}{nil, false, errors.New("error")}, + isErrorExpected: true, + }) + }) + + t.Run("invalid tx data", func(t *testing.T) { + t.Parallel() + + testFn(t, testConfig{ + getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, + getTxReturns: []interface{}{ethTypes.NewTx( + ðTypes.LegacyTx{ + Nonce: 0, + GasPrice: big.NewInt(10_000), + Gas: 21_000, + To: &to, + Value: ethgo.Ether(1), + Data: []byte{0, 1, 3, 4, 5, 6, 7}, //some invalid data + }, + ), true, nil}, + isErrorExpected: true, + }) + }) + + t.Run("doesn't have batch in storage - successfully stored (Elderberry fork)", func(t *testing.T) { + t.Parallel() + + a, err := abi.JSON(strings.NewReader(elderberryValidium.PolygonvalidiumetrogABI)) + require.NoError(t, err) + + methodDefinition, ok := a.Methods["sequenceBatchesValidium"] + require.True(t, ok) + + data, err := methodDefinition.Inputs.Pack(batchData, uint64(10), uint64(20), common.HexToAddress("0xABCD"), []byte{22, 23, 24}) + require.NoError(t, err) + + localTx := ethTypes.NewTx( + ðTypes.LegacyTx{ + Nonce: 0, + GasPrice: big.NewInt(10_000), + Gas: 21_000, + To: &to, + Value: ethgo.Ether(1), + Data: append(methodDefinition.ID, data...), + }) + + testFn(t, testConfig{ + getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, + getTxReturns: []interface{}{localTx, true, nil}, + storeUnresolvedBatchKeysArgs: []interface{}{ + mock.Anything, + []types.BatchKey{{ + Number: 10, + Hash: txHash, + }}, + mock.Anything, + }, + storeUnresolvedBatchKeysReturns: []interface{}{nil}, + isErrorExpected: false, + }) + }) + + t.Run("doesn't have batch in storage - successfully stored (Etrog fork)", func(t *testing.T) { + t.Parallel() + + testFn(t, testConfig{ + getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, + getTxReturns: []interface{}{tx, true, nil}, + storeUnresolvedBatchKeysArgs: []interface{}{ + mock.Anything, + []types.BatchKey{{ + Number: 10, + Hash: txHash, + }}, + mock.Anything, + }, + storeUnresolvedBatchKeysReturns: []interface{}{nil}, + isErrorExpected: false, + }) + }) + + t.Run("doesn't have batch in storage - store fails", func(t *testing.T) { + t.Parallel() + + testFn(t, testConfig{ + isErrorExpected: true, + storeUnresolvedBatchKeysArgs: []interface{}{ + mock.Anything, + []types.BatchKey{{ + Number: 10, + Hash: txHash, + }}, + mock.Anything, + }, + storeUnresolvedBatchKeysReturns: []interface{}{errors.New("error")}, + getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, + getTxReturns: []interface{}{tx, true, nil}, + }) + }) +} + +func TestBatchSynchronizer_HandleUnresolvedBatches(t *testing.T) { + t.Parallel() + + type testConfig struct { + // db mock + getUnresolvedBatchKeysArgs []interface{} + getUnresolvedBatchKeysReturns []interface{} + listOffchainDataArgs []interface{} + listOffchainDataReturns []interface{} + storeOffChainDataArgs []interface{} + storeOffChainDataReturns []interface{} + deleteUnresolvedBatchKeysArgs []interface{} + deleteUnresolvedBatchKeysReturns []interface{} + // sequencer mocks + getSequenceBatchArgs []interface{} + getSequenceBatchReturns []interface{} + + isErrorExpected bool + } + + batchL2Data := []byte{1, 2, 3, 4, 5, 6} + txHash := crypto.Keccak256Hash(batchL2Data) + + testFn := func(t *testing.T, config testConfig) { + t.Helper() + + dbMock := mocks.NewDB(t) + ethermanMock := mocks.NewEtherman(t) + sequencerMock := mocks.NewSequencerTracker(t) - dbMock.On("BeginStateTransaction", config.beginStateTransactionArgs...).Return( - returnArgs...).Once() + if config.getUnresolvedBatchKeysArgs != nil && config.getUnresolvedBatchKeysReturns != nil { + dbMock.On("GetUnresolvedBatchKeys", config.getUnresolvedBatchKeysArgs...).Return( + config.getUnresolvedBatchKeysReturns...).Once() + } + + if config.listOffchainDataArgs != nil && config.listOffchainDataReturns != nil { + dbMock.On("ListOffChainData", config.listOffchainDataArgs...).Return( + config.listOffchainDataReturns...).Once() } if config.storeOffChainDataArgs != nil && config.storeOffChainDataReturns != nil { @@ -357,13 +496,14 @@ func TestBatchSynchronizer_HandleEvent(t *testing.T) { config.storeOffChainDataReturns...).Once() } - if config.commitReturns != nil { - txMock.On("Commit", mock.Anything).Return( - config.commitReturns...).Once() + if config.deleteUnresolvedBatchKeysArgs != nil && config.deleteUnresolvedBatchKeysReturns != nil { + dbMock.On("DeleteUnresolvedBatchKeys", config.deleteUnresolvedBatchKeysArgs...).Return( + config.deleteUnresolvedBatchKeysReturns...).Once() } - if config.rollbackArgs != nil { - txMock.On("Rollback", config.rollbackArgs...).Return(nil).Once() + if config.getSequenceBatchArgs != nil && config.getSequenceBatchReturns != nil { + sequencerMock.On("GetSequenceBatch", config.getSequenceBatchArgs...).Return( + config.getSequenceBatchReturns...).Once() } batchSynronizer := &BatchSynchronizer{ @@ -372,7 +512,7 @@ func TestBatchSynchronizer_HandleEvent(t *testing.T) { sequencer: sequencerMock, } - err := batchSynronizer.handleEvent(event) + err := batchSynronizer.handleUnresolvedBatches(context.Background()) if config.isErrorExpected { require.Error(t, err) } else { @@ -380,171 +520,226 @@ func TestBatchSynchronizer_HandleEvent(t *testing.T) { } dbMock.AssertExpectations(t) - txMock.AssertExpectations(t) ethermanMock.AssertExpectations(t) sequencerMock.AssertExpectations(t) } - t.Run("Could not get tx data", func(t *testing.T) { + t.Run("Could not get unresolved batch keys", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, - getTxReturns: []interface{}{nil, false, errors.New("error")}, - isErrorExpected: true, + testFn(t, testConfig{ + getUnresolvedBatchKeysArgs: []interface{}{mock.Anything, uint(100)}, + getUnresolvedBatchKeysReturns: []interface{}{nil, errors.New("error")}, + isErrorExpected: true, }) }) - t.Run("Invalid tx data", func(t *testing.T) { + t.Run("No unresolved batch keys found", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, - getTxReturns: []interface{}{ethTypes.NewTx( - ðTypes.LegacyTx{ - Nonce: 0, - GasPrice: big.NewInt(10_000), - Gas: 21_000, - To: &to, - Value: ethgo.Ether(1), - Data: []byte{0, 1, 3, 4, 5, 6, 7}, //some invalid data - }, - ), true, nil}, - isErrorExpected: true, + testFn(t, testConfig{ + getUnresolvedBatchKeysArgs: []interface{}{mock.Anything, uint(100)}, + getUnresolvedBatchKeysReturns: []interface{}{nil, nil}, + isErrorExpected: false, }) }) - t.Run("has batch in storage", func(t *testing.T) { + t.Run("Unresolved batch key already resolved", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, - getTxReturns: []interface{}{tx, true, nil}, - existsArgs: []interface{}{mock.Anything, common.Hash(batchData[0].TransactionsHash)}, - existsReturns: []interface{}{true}, - isErrorExpected: false, + testFn(t, testConfig{ + getUnresolvedBatchKeysArgs: []interface{}{mock.Anything, uint(100)}, + getUnresolvedBatchKeysReturns: []interface{}{ + []types.BatchKey{{ + Number: 10, + Hash: txHash, + }}, + nil, + }, + listOffchainDataArgs: []interface{}{mock.Anything, []common.Hash{txHash}}, + listOffchainDataReturns: []interface{}{[]types.OffChainData{{ + Key: txHash, + Value: batchL2Data, + BatchNum: 10, + }}, nil}, + deleteUnresolvedBatchKeysArgs: []interface{}{mock.Anything, + []types.BatchKey{{ + Number: 10, + Hash: txHash, + }}, + mock.Anything, + }, + deleteUnresolvedBatchKeysReturns: []interface{}{nil}, + isErrorExpected: false, }) }) - t.Run("doesn't have batch in storage - successfully stored", func(t *testing.T) { + t.Run("Unresolved batch key already resolved with no batch number", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, - getTxReturns: []interface{}{tx, true, nil}, - existsArgs: []interface{}{mock.Anything, txHash}, - existsReturns: []interface{}{false}, - getSequenceBatchArgs: []interface{}{event.NumBatch}, - getSequenceBatchReturns: []interface{}{&sequencer.SeqBatch{ - Number: types.ArgUint64(event.NumBatch), - BatchL2Data: types.ArgBytes(batchL2Data), - }, nil}, - beginStateTransactionArgs: []interface{}{mock.Anything}, + testFn(t, testConfig{ + getUnresolvedBatchKeysArgs: []interface{}{mock.Anything, uint(100)}, + getUnresolvedBatchKeysReturns: []interface{}{ + []types.BatchKey{{ + Number: 10, + Hash: txHash, + }}, + nil, + }, + listOffchainDataArgs: []interface{}{mock.Anything, []common.Hash{txHash}}, + listOffchainDataReturns: []interface{}{[]types.OffChainData{{ + Key: txHash, + Value: batchL2Data, + BatchNum: 0, + }}, nil}, storeOffChainDataArgs: []interface{}{mock.Anything, []types.OffChainData{{ - Key: txHash, - Value: batchL2Data, + Key: txHash, + Value: batchL2Data, + BatchNum: 10, }}, mock.Anything, }, storeOffChainDataReturns: []interface{}{nil}, - commitReturns: []interface{}{nil}, - isErrorExpected: false, + deleteUnresolvedBatchKeysArgs: []interface{}{mock.Anything, + []types.BatchKey{{ + Number: 10, + Hash: txHash, + }}, + mock.Anything, + }, + deleteUnresolvedBatchKeysReturns: []interface{}{nil}, + isErrorExpected: false, }) }) - t.Run("doesn't have batch in storage - begin state transaction fails", func(t *testing.T) { + t.Run("Unresolved batch key found", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - isErrorExpected: true, - beginStateTransactionArgs: []interface{}{mock.Anything}, - beginStateTransactionReturns: []interface{}{nil, errors.New("error")}, - getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, - getTxReturns: []interface{}{tx, true, nil}, - existsArgs: []interface{}{mock.Anything, txHash}, - existsReturns: []interface{}{false}, - getSequenceBatchArgs: []interface{}{event.NumBatch}, + testFn(t, testConfig{ + getUnresolvedBatchKeysArgs: []interface{}{mock.Anything, uint(100)}, + getUnresolvedBatchKeysReturns: []interface{}{ + []types.BatchKey{{ + Number: 10, + Hash: txHash, + }}, + nil, + }, + listOffchainDataArgs: []interface{}{mock.Anything, []common.Hash{txHash}}, + listOffchainDataReturns: []interface{}{nil, nil}, + storeOffChainDataArgs: []interface{}{mock.Anything, + []types.OffChainData{{ + Key: txHash, + Value: batchL2Data, + BatchNum: 10, + }}, + mock.Anything, + }, + storeOffChainDataReturns: []interface{}{nil}, + deleteUnresolvedBatchKeysArgs: []interface{}{mock.Anything, + []types.BatchKey{{ + Number: 10, + Hash: txHash, + }}, + mock.Anything, + }, + deleteUnresolvedBatchKeysReturns: []interface{}{nil}, + getSequenceBatchArgs: []interface{}{context.Background(), uint64(10)}, getSequenceBatchReturns: []interface{}{&sequencer.SeqBatch{ - Number: types.ArgUint64(event.NumBatch), + Number: types.ArgUint64(10), BatchL2Data: types.ArgBytes(batchL2Data), }, nil}, + isErrorExpected: false, }) }) - t.Run("doesn't have batch in storage - store fails", func(t *testing.T) { + /*t.Run("Invalid tx data", func(t *testing.T) { t.Parallel() testFn(testConfig{ + getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, + getTxReturns: []interface{}{ethTypes.NewTx( + ðTypes.LegacyTx{ + Nonce: 0, + GasPrice: big.NewInt(10_000), + Gas: 21_000, + To: &to, + Value: ethgo.Ether(1), + Data: []byte{0, 1, 3, 4, 5, 6, 7}, //some invalid data + }, + ), true, nil}, isErrorExpected: true, - storeOffChainDataArgs: []interface{}{mock.Anything, + }) + }) + + t.Run("doesn't have batch in storage - successfully stored", func(t *testing.T) { + t.Parallel() + + testFn(testConfig{ + getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, + getTxReturns: []interface{}{tx, true, nil}, + getSequenceBatchArgs: []interface{}{event.NumBatch}, + getSequenceBatchReturns: []interface{}{&sequencer.SeqBatch{ + Number: types.ArgUint64(event.NumBatch), + BatchL2Data: types.ArgBytes(batchL2Data), + }, nil}, + beginStateTransactionArgs: []interface{}{mock.Anything}, + storeUnresolvedBatchKeysArgs: []interface{}{mock.Anything, []types.OffChainData{{ Key: txHash, Value: batchL2Data, }}, mock.Anything, }, - storeOffChainDataReturns: []interface{}{errors.New("error")}, - beginStateTransactionArgs: []interface{}{mock.Anything}, - rollbackArgs: []interface{}{mock.Anything}, - getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, - getTxReturns: []interface{}{tx, true, nil}, - existsArgs: []interface{}{mock.Anything, txHash}, - existsReturns: []interface{}{false}, - getSequenceBatchArgs: []interface{}{event.NumBatch}, - getSequenceBatchReturns: []interface{}{&sequencer.SeqBatch{ - Number: types.ArgUint64(event.NumBatch), - BatchL2Data: types.ArgBytes(batchL2Data), - }, nil}, + storeUnresolvedBatchKeysReturns: []interface{}{nil}, + commitReturns: []interface{}{nil}, + isErrorExpected: false, }) }) - t.Run("doesn't have batch in storage - commit fails", func(t *testing.T) { + t.Run("doesn't have batch in storage - store fails", func(t *testing.T) { t.Parallel() testFn(testConfig{ - isErrorExpected: true, - beginStateTransactionArgs: []interface{}{mock.Anything}, - storeOffChainDataArgs: []interface{}{mock.Anything, - []types.OffChainData{{ - Key: txHash, - Value: batchL2Data, + isErrorExpected: true, + storeUnresolvedBatchKeysArgs: []interface{}{mock.Anything, + []types.BatchKey{{ + Number: 1, + Hash: txHash, }}, mock.Anything, }, - storeOffChainDataReturns: []interface{}{nil}, - commitReturns: []interface{}{errors.New("error")}, - getSequenceBatchArgs: []interface{}{event.NumBatch}, + storeUnresolvedBatchKeysReturns: []interface{}{errors.New("error")}, + beginStateTransactionArgs: []interface{}{mock.Anything}, + rollbackArgs: []interface{}{mock.Anything}, + getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, + getTxReturns: []interface{}{tx, true, nil}, + getSequenceBatchArgs: []interface{}{event.NumBatch}, getSequenceBatchReturns: []interface{}{&sequencer.SeqBatch{ Number: types.ArgUint64(event.NumBatch), BatchL2Data: types.ArgBytes(batchL2Data), }, nil}, - getTxArgs: []interface{}{mock.Anything, event.Raw.TxHash}, - getTxReturns: []interface{}{tx, true, nil}, - existsArgs: []interface{}{mock.Anything, txHash}, - existsReturns: []interface{}{false}, }) }) + })*/ } -func TestBatchSyncronizer_HandleReorgs(t *testing.T) { +func TestBatchSynchronizer_HandleReorgs(t *testing.T) { t.Parallel() type testConfig struct { - getLastProcessedBlockReturns []interface{} - commitReturns []interface{} - reorg BlockReorg + getLastProcessedBlockReturns []interface{} + storeLastProcessedBlockReturns []interface{} + reorg BlockReorg } testFn := func(config testConfig) { dbMock := mocks.NewDB(t) - txMock := mocks.NewTx(t) - dbMock.On("GetLastProcessedBlock", mock.Anything, l1SyncTask).Return(config.getLastProcessedBlockReturns...).Once() - if config.commitReturns != nil { - dbMock.On("BeginStateTransaction", mock.Anything).Return(txMock, nil).Once() - dbMock.On("StoreLastProcessedBlock", mock.Anything, l1SyncTask, mock.Anything, txMock).Return(nil).Once() - txMock.On("Commit").Return(config.commitReturns...).Once() + dbMock.On("GetLastProcessedBlock", mock.Anything, string(L1SyncTask)).Return(config.getLastProcessedBlockReturns...).Once() + if config.storeLastProcessedBlockReturns != nil { + dbMock.On("StoreLastProcessedBlock", mock.Anything, mock.Anything, string(L1SyncTask)). + Return(config.storeLastProcessedBlockReturns...).Once() } reorgChan := make(chan BlockReorg) @@ -554,14 +749,13 @@ func TestBatchSyncronizer_HandleReorgs(t *testing.T) { reorgs: reorgChan, } - go batchSynchronizer.handleReorgs() + go batchSynchronizer.handleReorgs(context.Background()) reorgChan <- config.reorg batchSynchronizer.stop <- struct{}{} dbMock.AssertExpectations(t) - txMock.AssertExpectations(t) } t.Run("Getting last processed block fails", func(t *testing.T) { @@ -590,8 +784,8 @@ func TestBatchSyncronizer_HandleReorgs(t *testing.T) { t.Parallel() testFn(testConfig{ - getLastProcessedBlockReturns: []interface{}{uint64(15), nil}, - commitReturns: []interface{}{errors.New("error")}, + getLastProcessedBlockReturns: []interface{}{uint64(15), nil}, + storeLastProcessedBlockReturns: []interface{}{errors.New("error")}, reorg: BlockReorg{ Number: 10, }, @@ -602,11 +796,82 @@ func TestBatchSyncronizer_HandleReorgs(t *testing.T) { t.Parallel() testFn(testConfig{ - getLastProcessedBlockReturns: []interface{}{uint64(25), nil}, - commitReturns: []interface{}{nil}, + getLastProcessedBlockReturns: []interface{}{uint64(25), nil}, + storeLastProcessedBlockReturns: []interface{}{nil}, reorg: BlockReorg{ Number: 15, }, }) }) } + +func TestBatchSynchronizer_detectOffchainDataGaps(t *testing.T) { + t.Parallel() + + type testConfig struct { + // db mock + detectOffchainDataGapsArgs []interface{} + detectOffchainDataGapsReturns []interface{} + + expectedGaps map[uint64]uint64 + isErrorExpected bool + } + + testFn := func(t *testing.T, config testConfig) { + t.Helper() + + dbMock := mocks.NewDB(t) + + if config.detectOffchainDataGapsArgs != nil && config.detectOffchainDataGapsReturns != nil { + dbMock.On("DetectOffchainDataGaps", config.detectOffchainDataGapsArgs...).Return( + config.detectOffchainDataGapsReturns...).Once() + } + + batchSynronizer := &BatchSynchronizer{ + db: dbMock, + } + + err := batchSynronizer.detectOffchainDataGaps(context.Background()) + if config.isErrorExpected { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, config.expectedGaps, batchSynronizer.Gaps()) + } + + dbMock.AssertExpectations(t) + } + + t.Run("no gaps detected", func(t *testing.T) { + t.Parallel() + + testFn(t, testConfig{ + detectOffchainDataGapsArgs: []interface{}{mock.Anything}, + detectOffchainDataGapsReturns: []interface{}{map[uint64]uint64{}, nil}, + expectedGaps: map[uint64]uint64{}, + isErrorExpected: false, + }) + }) + + t.Run("one gap detected", func(t *testing.T) { + t.Parallel() + + testFn(t, testConfig{ + detectOffchainDataGapsArgs: []interface{}{mock.Anything}, + detectOffchainDataGapsReturns: []interface{}{map[uint64]uint64{1: 3}, nil}, + expectedGaps: map[uint64]uint64{1: 3}, + isErrorExpected: false, + }) + }) + + t.Run("failed to detect gaps", func(t *testing.T) { + t.Parallel() + + testFn(t, testConfig{ + detectOffchainDataGapsArgs: []interface{}{mock.Anything}, + detectOffchainDataGapsReturns: []interface{}{nil, errors.New("test error")}, + expectedGaps: map[uint64]uint64{}, + isErrorExpected: true, + }) + }) +} diff --git a/synchronizer/committee_map.go b/synchronizer/committee_map.go new file mode 100644 index 00000000..28adc976 --- /dev/null +++ b/synchronizer/committee_map.go @@ -0,0 +1,70 @@ +package synchronizer + +import ( + "sync" + "sync/atomic" + + "github.com/0xPolygon/cdk-data-availability/etherman" + "github.com/ethereum/go-ethereum/common" +) + +// CommitteeMapSafe represents a thread-safe implementation for the data availability committee members map. +type CommitteeMapSafe struct { + members sync.Map + membersCount int32 +} + +// NewCommitteeMapSafe creates a new CommitteeMapSafe. +func NewCommitteeMapSafe() *CommitteeMapSafe { + return &CommitteeMapSafe{members: sync.Map{}} +} + +// Store sets the value for a key. +func (t *CommitteeMapSafe) Store(member etherman.DataCommitteeMember) { + _, exists := t.members.LoadOrStore(member.Addr, member) + if !exists { + atomic.AddInt32(&t.membersCount, 1) + } else { + t.members.Store(member.Addr, member) + } +} + +// StoreBatch sets the range of values and keys. +func (t *CommitteeMapSafe) StoreBatch(members []etherman.DataCommitteeMember) { + for _, m := range members { + t.Store(m) + } +} + +// Load returns the value stored in the map for a key, or false if no value is present. +func (t *CommitteeMapSafe) Load(addr common.Address) (etherman.DataCommitteeMember, bool) { + rawValue, exists := t.members.Load(addr) + if !exists { + return etherman.DataCommitteeMember{}, false + } + return rawValue.(etherman.DataCommitteeMember), exists //nolint:forcetypeassert +} + +// Delete deletes the value for a key. +func (t *CommitteeMapSafe) Delete(key common.Address) { + _, exists := t.members.LoadAndDelete(key) + if exists { + atomic.AddInt32(&t.membersCount, -1) + } +} + +// AsSlice returns a slice of etherman.DataCommitteeMembers. +func (t *CommitteeMapSafe) AsSlice() []etherman.DataCommitteeMember { + membersSlice := make([]etherman.DataCommitteeMember, 0, atomic.LoadInt32(&t.membersCount)) + t.members.Range(func(_, rawMember any) bool { + membersSlice = append(membersSlice, rawMember.(etherman.DataCommitteeMember)) //nolint:forcetypeassert + + return true + }) + return membersSlice +} + +// Length returns the current length of the map. +func (t *CommitteeMapSafe) Length() int { + return int(atomic.LoadInt32(&t.membersCount)) +} diff --git a/synchronizer/committee_map_test.go b/synchronizer/committee_map_test.go new file mode 100644 index 00000000..1f9990f4 --- /dev/null +++ b/synchronizer/committee_map_test.go @@ -0,0 +1,139 @@ +package synchronizer + +import ( + "sync" + "testing" + + "github.com/0xPolygon/cdk-data-availability/etherman" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestStoreAndLoad(t *testing.T) { + committee := NewCommitteeMapSafe() + + members := []etherman.DataCommitteeMember{ + {Addr: common.HexToAddress("0x1"), URL: "Member 1"}, + {Addr: common.HexToAddress("0x2"), URL: "Member 2"}, + {Addr: common.HexToAddress("0x3"), URL: "Member 3"}, + {Addr: common.HexToAddress("0x4"), URL: "Member 4"}, + {Addr: common.HexToAddress("0x5"), URL: "Member 5"}, + {Addr: common.HexToAddress("0x6"), URL: "Member 6"}, + } + + var wg sync.WaitGroup + wg.Add(2) + + ch := make(chan etherman.DataCommitteeMember) + + go func() { + defer wg.Done() + + for _, m := range members { + committee.Store(m) + ch <- m + } + close(ch) + }() + + var actualMembers []etherman.DataCommitteeMember + go func() { + defer wg.Done() + + for m := range ch { + member, ok := committee.Load(m.Addr) + require.True(t, ok) + actualMembers = append(actualMembers, member) + } + }() + + wg.Wait() + + require.Len(t, actualMembers, len(members)) + for i, m := range members { + require.Equal(t, m, actualMembers[i]) + } + + // replace the single committee member + replacedMember := etherman.DataCommitteeMember{Addr: members[0].Addr, URL: "New Member 1"} + committee.Store(replacedMember) + require.Equal(t, len(members), committee.Length()) + actualReplacedMember, exists := committee.Load(replacedMember.Addr) + require.True(t, exists) + require.Equal(t, replacedMember, actualReplacedMember) + // skip the first member, because it is replaced and already asserted + for i, m := range members[1:] { + require.Equal(t, m, actualMembers[i+1]) + } +} + +func TestDelete(t *testing.T) { + committee := NewCommitteeMapSafe() + + member := etherman.DataCommitteeMember{Addr: common.HexToAddress("0x1"), URL: "Member 1"} + + committee.Store(member) + committee.Delete(member.Addr) + + _, ok := committee.Load(member.Addr) + require.False(t, ok) +} + +func TestStoreBatch(t *testing.T) { + committee := NewCommitteeMapSafe() + + members := []etherman.DataCommitteeMember{ + {Addr: common.HexToAddress("0x1"), URL: "http://localhost:1001"}, + {Addr: common.HexToAddress("0x2"), URL: "http://localhost:1002"}, + {Addr: common.HexToAddress("0x3"), URL: "http://localhost:1003"}, + } + + var wg sync.WaitGroup + wg.Add(1) + + go func() { + defer wg.Done() + committee.StoreBatch(members) + }() + + wg.Wait() + + for _, member := range members { + loadedMember, ok := committee.Load(member.Addr) + require.True(t, ok) + require.Equal(t, member, loadedMember) + } +} + +func TestAsSlice(t *testing.T) { + committee := NewCommitteeMapSafe() + committee.StoreBatch( + []etherman.DataCommitteeMember{ + {Addr: common.HexToAddress("0x1"), URL: "Member 1"}, + {Addr: common.HexToAddress("0x2"), URL: "Member 2"}, + {Addr: common.HexToAddress("0x3"), URL: "Member 3"}, + {Addr: common.HexToAddress("0x4"), URL: "Member 4"}, + }) + + membersSlice := committee.AsSlice() + + require.Equal(t, committee.Length(), len(membersSlice)) + for _, member := range membersSlice { + foundMember, ok := committee.Load(member.Addr) + require.True(t, ok) + require.Equal(t, foundMember, member) + } +} + +func TestLength(t *testing.T) { + committee := NewCommitteeMapSafe() + + members := []etherman.DataCommitteeMember{ + {Addr: common.HexToAddress("0x1"), URL: "http://localhost:1001"}, + {Addr: common.HexToAddress("0x2"), URL: "http://localhost:1002"}, + } + + committee.StoreBatch(members) + + require.Equal(t, len(members), committee.Length()) +} diff --git a/synchronizer/init.go b/synchronizer/init.go index 929e5ba0..6ac169bd 100644 --- a/synchronizer/init.go +++ b/synchronizer/init.go @@ -5,74 +5,77 @@ import ( "math/big" "time" - "github.com/0xPolygon/cdk-data-availability/config" "github.com/0xPolygon/cdk-data-availability/db" + "github.com/0xPolygon/cdk-data-availability/etherman" "github.com/0xPolygon/cdk-data-availability/log" - "github.com/0xPolygon/cdk-data-availability/types" "github.com/ethereum/go-ethereum/common" ) const ( - initBlockTimeout = 15 * time.Second - minCodeLen = 2 + initBlockTimeout = 15 * time.Second + minCodeLen = 2 + maxUnprocessedBatch = 100 ) // InitStartBlock initializes the L1 sync task by finding the inception block for the CDKValidium contract -func InitStartBlock(db db.DB, ethClientFactory types.EthClientFactory, l1 config.L1Config) error { - ctx, cancel := context.WithTimeout(context.Background(), initBlockTimeout) +func InitStartBlock( + parentCtx context.Context, + db db.DB, em etherman.Etherman, + genesisBlock uint64, + validiumAddr common.Address, +) error { + ctx, cancel := context.WithTimeout(parentCtx, initBlockTimeout) defer cancel() - current, err := getStartBlock(db) + current, err := getStartBlock(ctx, db, L1SyncTask) if err != nil { return err } + if current > 0 { // no need to resolve start block, it's already been set return nil } - log.Info("starting search for start block of contract ", l1.PolygonValidiumAddress) - ethClient, err := ethClientFactory.CreateEthClient(ctx, l1.RpcURL) - if err != nil { - log.Errorf("failed to create eth client: %v", err) - return err - } + log.Info("starting search for start block of contract ", validiumAddr) - startBlock, err := findContractDeploymentBlock(ctx, ethClient, common.HexToAddress(l1.PolygonValidiumAddress)) - if err != nil { - log.Errorf("failed to find contract deployment block: %v", err) - return err + startBlock := new(big.Int) + if genesisBlock != 0 { + startBlock.SetUint64(genesisBlock) + } else { + startBlock, err = findContractDeploymentBlock(ctx, em, validiumAddr) + if err != nil { + return err + } } - return setStartBlock(db, startBlock.Uint64()) + return setStartBlock(ctx, db, startBlock.Uint64(), L1SyncTask) } -func findContractDeploymentBlock(ctx context.Context, eth types.EthClient, contract common.Address) (*big.Int, error) { - latestBlock, err := eth.BlockByNumber(ctx, nil) +func findContractDeploymentBlock(ctx context.Context, em etherman.Etherman, contract common.Address) (*big.Int, error) { + latestHeader, err := em.HeaderByNumber(ctx, nil) if err != nil { return nil, err } - firstBlock := findCode(ctx, eth, contract, 0, latestBlock.Number().Int64()) + firstBlock := findCode(ctx, em, contract, 0, latestHeader.Number.Int64()) return big.NewInt(firstBlock), nil } // findCode is an O(log(n)) search for the inception block of a contract at the given address -func findCode(ctx context.Context, eth types.EthClient, address common.Address, startBlock, endBlock int64) int64 { - log.Infof("searching for contract code at block %d", startBlock) - time.Sleep(50 * time.Millisecond) //nolint:gomnd +func findCode(ctx context.Context, em etherman.Etherman, address common.Address, startBlock, endBlock int64) int64 { if startBlock == endBlock { return startBlock } - midBlock := (startBlock + endBlock) / 2 //nolint:gomnd - if codeLen := codeLen(ctx, eth, address, midBlock); codeLen > minCodeLen { - return findCode(ctx, eth, address, startBlock, midBlock) + midBlock := (startBlock + endBlock) / 2 //nolint:mnd + if codeLen := codeLen(ctx, em, address, midBlock); codeLen > minCodeLen { + return findCode(ctx, em, address, startBlock, midBlock) } else { - return findCode(ctx, eth, address, midBlock+1, endBlock) + return findCode(ctx, em, address, midBlock+1, endBlock) } } -func codeLen(ctx context.Context, eth types.EthClient, address common.Address, blockNumber int64) int64 { - data, err := eth.CodeAt(ctx, address, big.NewInt(blockNumber)) +func codeLen(ctx context.Context, em etherman.Etherman, address common.Address, blockNumber int64) int64 { + data, err := em.CodeAt(ctx, address, big.NewInt(blockNumber)) if err != nil { return 0 } diff --git a/synchronizer/init_test.go b/synchronizer/init_test.go index 249b1a68..dc232369 100644 --- a/synchronizer/init_test.go +++ b/synchronizer/init_test.go @@ -1,6 +1,7 @@ package synchronizer import ( + "context" "errors" "math/big" "testing" @@ -22,26 +23,20 @@ func Test_InitStartBlock(t *testing.T) { // store mocks getLastProcessedBlockArgs []interface{} getLastProcessedBlockReturns []interface{} - beginStateTransactionArgs []interface{} - beginStateTransactionReturns []interface{} storeLastProcessedBlockArgs []interface{} storeLastProcessedBlockReturns []interface{} - commitReturns []interface{} - // eth client factory mocks - createEthClientArgs []interface{} - createEthClientReturns []interface{} // eth client mocks - blockByNumberArgs []interface{} - blockByNumberReturns []interface{} - codeAtArgs [][]interface{} - codeAtReturns [][]interface{} + headerByNumberArgs []interface{} + headerByNumberReturns []interface{} + codeAtArgs [][]interface{} + codeAtReturns [][]interface{} isErrorExpected bool } l1Config := config.L1Config{ - WsURL: "ws://localhost:8080/ws", - RpcURL: "http://localhost:8081", + RpcURL: "ws://localhost:8080/ws", + // RpcURL: "http://localhost:8081", PolygonValidiumAddress: "0xCDKValidium", DataCommitteeAddress: "0xDAC", Timeout: types.NewDuration(time.Minute), @@ -49,11 +44,11 @@ func Test_InitStartBlock(t *testing.T) { BlockBatchSize: 10, } - testFn := func(config testConfig) { + testFn := func(t *testing.T, config testConfig) { + t.Helper() + dbMock := mocks.NewDB(t) - txMock := mocks.NewTx(t) - ethClientMock := mocks.NewEthClient(t) - ethClientFactoryMock := mocks.NewEthClientFactory(t) + emMock := mocks.NewEtherman(t) if config.getLastProcessedBlockArgs != nil && config.getLastProcessedBlockReturns != nil { dbMock.On("GetLastProcessedBlock", config.getLastProcessedBlockArgs...).Return( @@ -65,63 +60,39 @@ func Test_InitStartBlock(t *testing.T) { config.storeLastProcessedBlockReturns...).Once() } - if config.commitReturns != nil { - txMock.On("Commit", mock.Anything).Return(config.commitReturns...).Once() - } - - if config.beginStateTransactionArgs != nil { - var returnArgs []interface{} - if config.beginStateTransactionReturns != nil { - returnArgs = config.beginStateTransactionReturns - } else { - returnArgs = append(returnArgs, txMock, nil) - } - - dbMock.On("BeginStateTransaction", config.beginStateTransactionArgs...).Return( - returnArgs...).Once() - } - - if config.createEthClientArgs != nil { - var returnArgs []interface{} - if config.createEthClientReturns != nil { - returnArgs = config.createEthClientReturns - } else { - returnArgs = append(returnArgs, ethClientMock, nil) - } - - ethClientFactoryMock.On("CreateEthClient", config.createEthClientArgs...).Return( - returnArgs...).Once() - } - - if config.blockByNumberArgs != nil && config.blockByNumberReturns != nil { - ethClientMock.On("BlockByNumber", config.blockByNumberArgs...).Return( - config.blockByNumberReturns...).Once() + if config.headerByNumberArgs != nil && config.headerByNumberReturns != nil { + emMock.On("HeaderByNumber", config.headerByNumberArgs...).Return( + config.headerByNumberReturns...).Once() } if config.codeAtArgs != nil && config.codeAtReturns != nil { for i, args := range config.codeAtArgs { - ethClientMock.On("CodeAt", args...).Return( + emMock.On("CodeAt", args...).Return( config.codeAtReturns[i]...).Once() } } + err := InitStartBlock( + context.Background(), + dbMock, + emMock, + l1Config.GenesisBlock, + common.HexToAddress(l1Config.PolygonValidiumAddress), + ) if config.isErrorExpected { - require.Error(t, InitStartBlock(dbMock, ethClientFactoryMock, l1Config)) + require.Error(t, err) } else { - require.NoError(t, InitStartBlock(dbMock, ethClientFactoryMock, l1Config)) + require.NoError(t, err) } dbMock.AssertExpectations(t) - txMock.AssertExpectations(t) - ethClientMock.AssertExpectations(t) - ethClientFactoryMock.AssertExpectations(t) } t.Run("GetLastProcessedBlock returns an error", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - getLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask}, + testFn(t, testConfig{ + getLastProcessedBlockArgs: []interface{}{mock.Anything, string(L1SyncTask)}, getLastProcessedBlockReturns: []interface{}{uint64(1), errors.New("can't get last processed block")}, isErrorExpected: true, }) @@ -130,53 +101,21 @@ func Test_InitStartBlock(t *testing.T) { t.Run("no need to resolve start block", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - getLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask}, + testFn(t, testConfig{ + getLastProcessedBlockArgs: []interface{}{mock.Anything, string(L1SyncTask)}, getLastProcessedBlockReturns: []interface{}{uint64(10), nil}, isErrorExpected: false, }) }) - t.Run("can not create eth client", func(t *testing.T) { - t.Parallel() - - testFn(testConfig{ - getLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask}, - getLastProcessedBlockReturns: []interface{}{uint64(0), nil}, - createEthClientArgs: []interface{}{mock.Anything, l1Config.RpcURL}, - createEthClientReturns: []interface{}{nil, errors.New("error")}, - isErrorExpected: true, - }) - }) - t.Run("can not get block from eth client", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - getLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask}, + testFn(t, testConfig{ + getLastProcessedBlockArgs: []interface{}{mock.Anything, string(L1SyncTask)}, getLastProcessedBlockReturns: []interface{}{uint64(0), nil}, - createEthClientArgs: []interface{}{mock.Anything, l1Config.RpcURL}, - blockByNumberArgs: []interface{}{mock.Anything, mock.Anything}, - blockByNumberReturns: []interface{}{nil, errors.New("error")}, - isErrorExpected: true, - }) - }) - - t.Run("BeginStateTransaction fails", func(t *testing.T) { - t.Parallel() - - block := ethTypes.NewBlockWithHeader(ðTypes.Header{ - Number: big.NewInt(0), - }) - - testFn(testConfig{ - getLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask}, - getLastProcessedBlockReturns: []interface{}{uint64(0), nil}, - beginStateTransactionArgs: []interface{}{mock.Anything}, - beginStateTransactionReturns: []interface{}{nil, errors.New("error")}, - createEthClientArgs: []interface{}{mock.Anything, l1Config.RpcURL}, - blockByNumberArgs: []interface{}{mock.Anything, mock.Anything}, - blockByNumberReturns: []interface{}{block, nil}, + headerByNumberArgs: []interface{}{mock.Anything, mock.Anything}, + headerByNumberReturns: []interface{}{nil, errors.New("error")}, isErrorExpected: true, }) }) @@ -184,39 +123,15 @@ func Test_InitStartBlock(t *testing.T) { t.Run("Store off-chain data fails", func(t *testing.T) { t.Parallel() - block := ethTypes.NewBlockWithHeader(ðTypes.Header{ - Number: big.NewInt(0), - }) - - testFn(testConfig{ - getLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask}, + testFn(t, testConfig{ + getLastProcessedBlockArgs: []interface{}{mock.Anything, string(L1SyncTask)}, getLastProcessedBlockReturns: []interface{}{uint64(0), nil}, - beginStateTransactionArgs: []interface{}{mock.Anything}, - storeLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask, uint64(0), mock.Anything}, + storeLastProcessedBlockArgs: []interface{}{mock.Anything, uint64(0), string(L1SyncTask)}, storeLastProcessedBlockReturns: []interface{}{errors.New("error")}, - createEthClientArgs: []interface{}{mock.Anything, l1Config.RpcURL}, - blockByNumberArgs: []interface{}{mock.Anything, mock.Anything}, - blockByNumberReturns: []interface{}{block, nil}, - isErrorExpected: true, - }) - }) - - t.Run("Commit fails", func(t *testing.T) { - t.Parallel() - - testFn(testConfig{ - blockByNumberArgs: []interface{}{mock.Anything, mock.Anything}, - blockByNumberReturns: []interface{}{ethTypes.NewBlockWithHeader(ðTypes.Header{ + headerByNumberArgs: []interface{}{mock.Anything, mock.Anything}, + headerByNumberReturns: []interface{}{ethTypes.NewBlockWithHeader(ðTypes.Header{ Number: big.NewInt(0), - }), nil}, - createEthClientArgs: []interface{}{mock.Anything, l1Config.RpcURL}, - getLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask}, - getLastProcessedBlockReturns: []interface{}{uint64(0), nil}, - storeLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask, uint64(0), mock.Anything}, - storeLastProcessedBlockReturns: []interface{}{nil}, - beginStateTransactionArgs: []interface{}{mock.Anything}, - commitReturns: []interface{}{errors.New("error")}, - + }).Header(), nil}, isErrorExpected: true, }) }) @@ -224,18 +139,15 @@ func Test_InitStartBlock(t *testing.T) { t.Run("Successful init", func(t *testing.T) { t.Parallel() - testFn(testConfig{ - getLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask}, + testFn(t, testConfig{ + getLastProcessedBlockArgs: []interface{}{mock.Anything, string(L1SyncTask)}, getLastProcessedBlockReturns: []interface{}{uint64(0), nil}, - beginStateTransactionArgs: []interface{}{mock.Anything}, - storeLastProcessedBlockArgs: []interface{}{mock.Anything, l1SyncTask, uint64(2), mock.Anything}, + storeLastProcessedBlockArgs: []interface{}{mock.Anything, uint64(2), string(L1SyncTask)}, storeLastProcessedBlockReturns: []interface{}{nil}, - commitReturns: []interface{}{nil}, - createEthClientArgs: []interface{}{mock.Anything, l1Config.RpcURL}, - blockByNumberArgs: []interface{}{mock.Anything, mock.Anything}, - blockByNumberReturns: []interface{}{ethTypes.NewBlockWithHeader(ðTypes.Header{ + headerByNumberArgs: []interface{}{mock.Anything, mock.Anything}, + headerByNumberReturns: []interface{}{ethTypes.NewBlockWithHeader(ðTypes.Header{ Number: big.NewInt(3), - }), nil}, + }).Header(), nil}, codeAtArgs: [][]interface{}{ {mock.Anything, common.HexToAddress(l1Config.PolygonValidiumAddress), big.NewInt(1)}, {mock.Anything, common.HexToAddress(l1Config.PolygonValidiumAddress), big.NewInt(2)}, diff --git a/synchronizer/reorg.go b/synchronizer/reorg.go index d3176c56..af2d79d4 100644 --- a/synchronizer/reorg.go +++ b/synchronizer/reorg.go @@ -41,15 +41,14 @@ func (rd *ReorgDetector) Subscribe() <-chan BlockReorg { } // Start starts the ReorgDetector tracking for reorg events -func (rd *ReorgDetector) Start() error { +func (rd *ReorgDetector) Start(ctx context.Context) error { log.Info("starting block reorganization detector") - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(ctx) rd.cancel = cancel blocks := make(chan *ethgo.Block) - err := rd.trackBlocks(ctx, blocks) - if err != nil { + if err := rd.trackBlocks(ctx, blocks); err != nil { return err } diff --git a/synchronizer/store.go b/synchronizer/store.go index d75355ef..3ba53734 100644 --- a/synchronizer/store.go +++ b/synchronizer/store.go @@ -10,82 +10,77 @@ import ( "github.com/ethereum/go-ethereum/common" ) -const dbTimeout = 2 * time.Second +// SyncTask is the type of the sync task +type SyncTask string -const l1SyncTask = "L1" +const ( + // L1SyncTask is the name of the L1 sync task + L1SyncTask SyncTask = "L1" -func getStartBlock(db dbTypes.DB) (uint64, error) { - ctx, cancel := context.WithTimeout(context.Background(), dbTimeout) + dbTimeout = 2 * time.Second +) + +func getStartBlock(parentCtx context.Context, db dbTypes.DB, syncTask SyncTask) (uint64, error) { + ctx, cancel := context.WithTimeout(parentCtx, dbTimeout) defer cancel() - start, err := db.GetLastProcessedBlock(ctx, l1SyncTask) + start, err := db.GetLastProcessedBlock(ctx, string(syncTask)) if err != nil { - log.Errorf("error retrieving last processed block, starting from 0: %v", err) + log.Errorf("error retrieving last processed block for %s task, starting from 0: %v", syncTask, err) } + if start > 0 { start = start - 1 // since a block may have been partially processed } + return start, err } -func setStartBlock(db dbTypes.DB, block uint64) error { - ctx, cancel := context.WithTimeout(context.Background(), dbTimeout) +func setStartBlock(parentCtx context.Context, db dbTypes.DB, block uint64, syncTask SyncTask) error { + ctx, cancel := context.WithTimeout(parentCtx, dbTimeout) defer cancel() - var ( - dbTx dbTypes.Tx - err error - ) - - if dbTx, err = db.BeginStateTransaction(ctx); err != nil { - return err - } - - if err = db.StoreLastProcessedBlock(ctx, l1SyncTask, block, dbTx); err != nil { - return err - } + return db.StoreLastProcessedBlock(ctx, block, string(syncTask)) +} - if err = dbTx.Commit(); err != nil { - return err - } +func storeUnresolvedBatchKeys(parentCtx context.Context, db dbTypes.DB, keys []types.BatchKey) error { + ctx, cancel := context.WithTimeout(parentCtx, dbTimeout) + defer cancel() - return nil + return db.StoreUnresolvedBatchKeys(ctx, keys) } -func exists(db dbTypes.DB, key common.Hash) bool { - ctx, cancel := context.WithTimeout(context.Background(), dbTimeout) +func getUnresolvedBatchKeys(parentCtx context.Context, db dbTypes.DB) ([]types.BatchKey, error) { + ctx, cancel := context.WithTimeout(parentCtx, dbTimeout) defer cancel() - return db.Exists(ctx, key) + return db.GetUnresolvedBatchKeys(ctx, maxUnprocessedBatch) } -func store(db dbTypes.DB, data []types.OffChainData) error { - ctx, cancel := context.WithTimeout(context.Background(), dbTimeout) +func deleteUnresolvedBatchKeys(parentCtx context.Context, db dbTypes.DB, keys []types.BatchKey) error { + ctx, cancel := context.WithTimeout(parentCtx, dbTimeout) defer cancel() - var ( - dbTx dbTypes.Tx - err error - ) + return db.DeleteUnresolvedBatchKeys(ctx, keys) +} - if dbTx, err = db.BeginStateTransaction(ctx); err != nil { - return err - } +func listOffchainData(parentCtx context.Context, db dbTypes.DB, keys []common.Hash) ([]types.OffChainData, error) { + ctx, cancel := context.WithTimeout(parentCtx, dbTimeout) + defer cancel() - if err = db.StoreOffChainData(ctx, data, dbTx); err != nil { - rollback(err, dbTx) - return err - } + return db.ListOffChainData(ctx, keys) +} - if err = dbTx.Commit(); err != nil { - return err - } +func storeOffchainData(parentCtx context.Context, db dbTypes.DB, data []types.OffChainData) error { + ctx, cancel := context.WithTimeout(parentCtx, dbTimeout) + defer cancel() - return nil + return db.StoreOffChainData(ctx, data) } -func rollback(err error, dbTx dbTypes.Tx) { - if txErr := dbTx.Rollback(); txErr != nil { - log.Errorf("failed to roll back transaction after error %v : %v", err, txErr) - } +func detectOffchainDataGaps(parentCtx context.Context, db dbTypes.DB) (map[uint64]uint64, error) { + ctx, cancel := context.WithTimeout(parentCtx, dbTimeout) + defer cancel() + + return db.DetectOffchainDataGaps(ctx) } diff --git a/synchronizer/store_test.go b/synchronizer/store_test.go index 5a72bfa4..c32091e1 100644 --- a/synchronizer/store_test.go +++ b/synchronizer/store_test.go @@ -1,6 +1,7 @@ package synchronizer import ( + "context" "errors" "testing" @@ -12,7 +13,9 @@ import ( "github.com/stretchr/testify/require" ) -func Test_setStartBlock(t *testing.T) { +func Test_getStartBlock(t *testing.T) { + t.Parallel() + testError := errors.New("test error") tests := []struct { @@ -22,28 +25,68 @@ func Test_setStartBlock(t *testing.T) { wantErr bool }{ { - name: "BeginStateTransaction returns error", + name: "GetLastProcessedBlock returns error", db: func(t *testing.T) db.DB { + t.Helper() mockDB := mocks.NewDB(t) - mockDB.On("BeginStateTransaction", mock.Anything). - Return(nil, testError) + mockDB.On("GetLastProcessedBlock", mock.Anything, "L1"). + Return(uint64(0), testError) return mockDB }, - block: 1, + block: 0, wantErr: true, }, { - name: "StoreLastProcessedBlock returns error", + name: "all good", db: func(t *testing.T) db.DB { + t.Helper() mockDB := mocks.NewDB(t) - mockTx := mocks.NewTx(t) + mockDB.On("GetLastProcessedBlock", mock.Anything, "L1").Return(uint64(5), nil) + + return mockDB + }, + block: 4, + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + testDB := tt.db(t) - mockDB.On("BeginStateTransaction", mock.Anything).Return(mockTx, nil) + if block, err := getStartBlock(context.Background(), testDB, L1SyncTask); tt.wantErr { + require.ErrorIs(t, err, testError) + } else { + require.NoError(t, err) + require.Equal(t, tt.block, block) + } + }) + } +} - mockDB.On("StoreLastProcessedBlock", mock.Anything, "L1", uint64(2), mockTx). +func Test_setStartBlock(t *testing.T) { + t.Parallel() + + testError := errors.New("test error") + + tests := []struct { + name string + db func(t *testing.T) db.DB + block uint64 + wantErr bool + }{ + { + name: "StoreLastProcessedBlock returns error", + db: func(t *testing.T) db.DB { + t.Helper() + mockDB := mocks.NewDB(t) + + mockDB.On("StoreLastProcessedBlock", mock.Anything, uint64(2), "L1"). Return(testError) return mockDB @@ -52,50 +95,88 @@ func Test_setStartBlock(t *testing.T) { wantErr: true, }, { - name: "Commit returns error", + name: "all good", db: func(t *testing.T) db.DB { + t.Helper() mockDB := mocks.NewDB(t) - mockTx := mocks.NewTx(t) + mockDB.On("StoreLastProcessedBlock", mock.Anything, uint64(4), "L1"). + Return(nil) - mockDB.On("BeginStateTransaction", mock.Anything).Return(mockTx, nil) + return mockDB + }, + block: 4, + }, + } + for _, tt := range tests { + tt := tt - mockDB.On("StoreLastProcessedBlock", mock.Anything, "L1", uint64(3), mockTx). - Return(nil) + t.Run(tt.name, func(t *testing.T) { + t.Parallel() - mockTx.On("Commit"). - Return(testError) + testDB := tt.db(t) + + if err := setStartBlock(context.Background(), testDB, tt.block, L1SyncTask); tt.wantErr { + require.ErrorIs(t, err, testError) + } else { + require.NoError(t, err) + } + }) + } +} + +func Test_storeUnresolvedBatchKeys(t *testing.T) { + t.Parallel() + + testError := errors.New("test error") + testData := []types.BatchKey{ + { + Number: 1, + Hash: common.HexToHash("0x01"), + }, + } + + tests := []struct { + name string + db func(t *testing.T) db.DB + keys []types.BatchKey + wantErr bool + }{ + { + name: "StoreUnresolvedBatchKeys returns error", + db: func(t *testing.T) db.DB { + t.Helper() + mockDB := mocks.NewDB(t) + + mockDB.On("StoreUnresolvedBatchKeys", mock.Anything, testData).Return(testError) return mockDB }, - block: 3, + keys: testData, wantErr: true, }, { name: "all good", db: func(t *testing.T) db.DB { + t.Helper() mockDB := mocks.NewDB(t) - mockTx := mocks.NewTx(t) - - mockDB.On("BeginStateTransaction", mock.Anything).Return(mockTx, nil) - - mockDB.On("StoreLastProcessedBlock", mock.Anything, "L1", uint64(4), mockTx). - Return(nil) - - mockTx.On("Commit"). - Return(nil) + mockDB.On("StoreUnresolvedBatchKeys", mock.Anything, testData).Return(nil) return mockDB }, - block: 4, + keys: testData, }, } for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + testDB := tt.db(t) - if err := setStartBlock(testDB, tt.block); tt.wantErr { + if err := storeUnresolvedBatchKeys(context.Background(), testDB, tt.keys); tt.wantErr { require.ErrorIs(t, err, testError) } else { require.NoError(t, err) @@ -104,89 +185,150 @@ func Test_setStartBlock(t *testing.T) { } } -func Test_exists(t *testing.T) { +func Test_getUnresolvedBatchKeys(t *testing.T) { + t.Parallel() + + testError := errors.New("test error") + testData := []types.BatchKey{ + { + Number: 1, + Hash: common.HexToHash("0x01"), + }, + } + tests := []struct { - name string - db func(t *testing.T) db.DB - key common.Hash - want bool + name string + db func(t *testing.T) db.DB + keys []types.BatchKey + wantErr bool }{ { - name: "Exists returns true", + name: "GetUnresolvedBatchKeys returns error", db: func(t *testing.T) db.DB { + t.Helper() mockDB := mocks.NewDB(t) - mockDB.On("Exists", mock.Anything, common.HexToHash("0x01")). - Return(true) + mockDB.On("GetUnresolvedBatchKeys", mock.Anything, uint(100)). + Return(nil, testError) return mockDB }, - key: common.HexToHash("0x01"), - want: true, + wantErr: true, }, { - name: "Exists returns false", + name: "all good", db: func(t *testing.T) db.DB { + t.Helper() mockDB := mocks.NewDB(t) - mockDB.On("Exists", mock.Anything, common.HexToHash("0x02")). - Return(false) + mockDB.On("GetUnresolvedBatchKeys", mock.Anything, uint(100)).Return(testData, nil) return mockDB }, - key: common.HexToHash("0x02"), - want: false, + keys: testData, }, } for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + testDB := tt.db(t) - got := exists(testDB, tt.key) - require.Equal(t, tt.want, got) + if keys, err := getUnresolvedBatchKeys(context.Background(), testDB); tt.wantErr { + require.ErrorIs(t, err, testError) + } else { + require.NoError(t, err) + require.Equal(t, tt.keys, keys) + } }) } } -func Test_store(t *testing.T) { +func Test_deleteUnresolvedBatchKeys(t *testing.T) { + t.Parallel() + testError := errors.New("test error") - testData := []types.OffChainData{ + testData := []types.BatchKey{ { - Key: common.HexToHash("0x01"), - Value: []byte("test data 1"), + Number: 1, + Hash: common.HexToHash("0x01"), }, } tests := []struct { name string db func(t *testing.T) db.DB - data []types.OffChainData wantErr bool }{ { - name: "BeginStateTransaction returns error", + name: "DeleteUnresolvedBatchKeys returns error", db: func(t *testing.T) db.DB { + t.Helper() mockDB := mocks.NewDB(t) - mockDB.On("BeginStateTransaction", mock.Anything).Return(nil, testError) + mockDB.On("DeleteUnresolvedBatchKeys", mock.Anything, testData). + Return(testError) return mockDB }, - data: testData, wantErr: true, }, { - name: "StoreOffChainData returns error", + name: "all good", db: func(t *testing.T) db.DB { + t.Helper() mockDB := mocks.NewDB(t) - mockTx := mocks.NewTx(t) + mockDB.On("DeleteUnresolvedBatchKeys", mock.Anything, testData). + Return(nil) + + return mockDB + }, + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + testDB := tt.db(t) + + if err := deleteUnresolvedBatchKeys(context.Background(), testDB, testData); tt.wantErr { + require.ErrorIs(t, err, testError) + } else { + require.NoError(t, err) + } + }) + } +} - mockDB.On("BeginStateTransaction", mock.Anything).Return(mockTx, nil) +func Test_storeOffchainData(t *testing.T) { + t.Parallel() - mockDB.On("StoreOffChainData", mock.Anything, testData, mockTx).Return(testError) + testError := errors.New("test error") + testData := []types.OffChainData{ + { + Key: common.HexToHash("0x01"), + Value: []byte("test data 1"), + }, + } + + tests := []struct { + name string + db func(t *testing.T) db.DB + data []types.OffChainData + wantErr bool + }{ + { + name: "StoreOffChainData returns error", + db: func(t *testing.T) db.DB { + t.Helper() + mockDB := mocks.NewDB(t) - mockTx.On("Rollback").Return(nil) + mockDB.On("StoreOffChainData", mock.Anything, testData).Return(testError) return mockDB }, @@ -194,49 +336,88 @@ func Test_store(t *testing.T) { wantErr: true, }, { - name: "Commit returns error", + name: "all good", db: func(t *testing.T) db.DB { + t.Helper() mockDB := mocks.NewDB(t) - mockTx := mocks.NewTx(t) + mockDB.On("StoreOffChainData", mock.Anything, testData).Return(nil) + + return mockDB + }, + data: testData, + }, + } + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + testDB := tt.db(t) + + if err := storeOffchainData(context.Background(), testDB, tt.data); tt.wantErr { + require.ErrorIs(t, err, testError) + } else { + require.NoError(t, err) + } + }) + } +} + +func Test_detectOffchainDataGaps(t *testing.T) { + t.Parallel() - mockDB.On("BeginStateTransaction", mock.Anything).Return(mockTx, nil) + testError := errors.New("test error") - mockDB.On("StoreOffChainData", mock.Anything, testData, mockTx).Return(nil) + tests := []struct { + name string + db func(t *testing.T) db.DB + gaps map[uint64]uint64 + wantErr bool + }{ + { + name: "DetectOffchainDataGaps returns error", + db: func(t *testing.T) db.DB { + t.Helper() + + mockDB := mocks.NewDB(t) - mockTx.On("Commit").Return(testError) + mockDB.On("DetectOffchainDataGaps", mock.Anything).Return(nil, testError) return mockDB }, - data: testData, + gaps: nil, wantErr: true, }, { name: "all good", db: func(t *testing.T) db.DB { - mockDB := mocks.NewDB(t) - - mockTx := mocks.NewTx(t) + t.Helper() - mockDB.On("BeginStateTransaction", mock.Anything).Return(mockTx, nil) - - mockDB.On("StoreOffChainData", mock.Anything, testData, mockTx).Return(nil) + mockDB := mocks.NewDB(t) - mockTx.On("Commit").Return(nil) + mockDB.On("DetectOffchainDataGaps", mock.Anything).Return(map[uint64]uint64{1: 3}, nil) return mockDB }, - data: testData, + gaps: map[uint64]uint64{1: 3}, + wantErr: false, }, } for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + testDB := tt.db(t) - if err := store(testDB, tt.data); tt.wantErr { + if gaps, err := detectOffchainDataGaps(context.Background(), testDB); tt.wantErr { require.ErrorIs(t, err, testError) } else { require.NoError(t, err) + require.Equal(t, tt.gaps, gaps) } }) } diff --git a/synchronizer/util.go b/synchronizer/util.go index e51d1234..b389b6b8 100644 --- a/synchronizer/util.go +++ b/synchronizer/util.go @@ -1,38 +1,90 @@ package synchronizer import ( + "bytes" + "encoding/hex" "encoding/json" + "fmt" "strings" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygonvalidium" + bananaValidium "github.com/0xPolygon/cdk-contracts-tooling/contracts/banana/polygonvalidiumetrog" + elderberryValidium "github.com/0xPolygon/cdk-contracts-tooling/contracts/elderberry/polygonvalidiumetrog" + etrogValidium "github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonvalidiumetrog" + "github.com/0xPolygon/cdk-data-availability/log" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +var ( + // methodIDSequenceBatchesValidiumEtrog is sequenceBatchesValidium method id in Etrog fork (0x2d72c248) + methodIDSequenceBatchesValidiumEtrog = crypto.Keccak256( + []byte("sequenceBatchesValidium((bytes32,bytes32,uint64,bytes32)[],address,bytes)"), + )[:methodIDLen] + + // methodIDSequenceBatchesValidiumElderberry is sequenceBatchesValidium method id in Elderberry fork (0xdb5b0ed7) + methodIDSequenceBatchesValidiumElderberry = crypto.Keccak256( + []byte("sequenceBatchesValidium((bytes32,bytes32,uint64,bytes32)[],uint64,uint64,address,bytes)"), + )[:methodIDLen] + // methodIDSequenceBatchesValidiumBanana is sequenceBatchesValidium method id in Banana fork (0x165e8a8d) + methodIDSequenceBatchesValidiumBanana = crypto.Keccak256( + []byte("sequenceBatchesValidium((bytes32,bytes32,uint64,bytes32)[],uint32,uint64,bytes32,address,bytes)"), + )[:methodIDLen] +) + +const ( + // methodIDLen represents method id size in bytes + methodIDLen = 4 ) // UnpackTxData unpacks the keys in a SequenceBatches event func UnpackTxData(txData []byte) ([]common.Hash, error) { - a, err := abi.JSON(strings.NewReader(polygonvalidium.PolygonvalidiumMetaData.ABI)) - if err != nil { - return nil, err + methodID := txData[:methodIDLen] + + var ( + a abi.ABI + err error + ) + + if bytes.Equal(methodID, methodIDSequenceBatchesValidiumEtrog) { + a, err = abi.JSON(strings.NewReader(etrogValidium.PolygonvalidiumetrogMetaData.ABI)) + if err != nil { + return nil, err + } + } else if bytes.Equal(methodID, methodIDSequenceBatchesValidiumElderberry) { + a, err = abi.JSON(strings.NewReader(elderberryValidium.PolygonvalidiumetrogMetaData.ABI)) + if err != nil { + return nil, err + } + } else if bytes.Equal(methodID, methodIDSequenceBatchesValidiumBanana) { + a, err = abi.JSON(strings.NewReader(bananaValidium.PolygonvalidiumetrogMetaData.ABI)) + if err != nil { + return nil, err + } + } else { + return nil, fmt.Errorf("unrecognized method id: %s", hex.EncodeToString(methodID)) } - method, err := a.MethodById(txData[:4]) + method, err := a.MethodById(methodID) if err != nil { return nil, err } - data, err := method.Inputs.Unpack(txData[4:]) + data, err := method.Inputs.Unpack(txData[methodIDLen:]) if err != nil { + log.Errorf("error Unpack data: %v", err) return nil, err } - var batches []polygonvalidium.PolygonValidiumEtrogValidiumBatchData bytes, err := json.Marshal(data[0]) if err != nil { + log.Errorf("error marshalling data: %v", err) return nil, err } + var batches []etrogValidium.PolygonValidiumEtrogValidiumBatchData if err = json.Unmarshal(bytes, &batches); err != nil { + log.Errorf("error Unmarshal data: %v", err) return nil, err } diff --git a/synchronizer/util_test.go b/synchronizer/util_test.go new file mode 100644 index 00000000..741cb44c --- /dev/null +++ b/synchronizer/util_test.go @@ -0,0 +1,20 @@ +package synchronizer + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_SequenceBatchesValidiumMethodIDs_Equality(t *testing.T) { + var ( + expectedSequenceBatchesValidiumEtrog = "2d72c248" + expectedSequenceBatchesValidiumElderberry = "db5b0ed7" + expectedSequenceBatchesValidiumBanana = "165e8a8d" + ) + + require.Equal(t, expectedSequenceBatchesValidiumEtrog, hex.EncodeToString(methodIDSequenceBatchesValidiumEtrog)) + require.Equal(t, expectedSequenceBatchesValidiumElderberry, hex.EncodeToString(methodIDSequenceBatchesValidiumElderberry)) + require.Equal(t, expectedSequenceBatchesValidiumBanana, hex.EncodeToString(methodIDSequenceBatchesValidiumBanana)) +} diff --git a/test/Makefile b/test/Makefile index fb90e468..967eb54f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,14 +2,10 @@ STOP := docker compose down .PHONY: run run: stop ## Runs a full node for e2e - docker compose up -d xlayer-state-db - docker compose up -d xlayer-pool-db - docker compose up -d xlayer-data-availability-db - docker compose up -d xlayer-mock-l1-network + docker compose up -d cdk-data-availability-db + docker compose up -d l1 sleep 1 - docker compose up -d xlayer-data-availability - docker compose up -d xlayer-prover - docker compose up -d xlayer-node + docker compose up -d cdk-data-availability .PHONY: stop stop: ## Stop a full data node @@ -22,7 +18,7 @@ stop-dacs: .PHONY: test-e2e test-e2e: run ## Runs the E2E tests - trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 600s ./e2e/... + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 900s ./e2e/... .PHONY: test-unit test-unit: ## Runs the unit tests, skips e2e @@ -41,28 +37,20 @@ help: ## Prints this help ### node commands called by testing operations ### -.PHONY: run-node -run-node: ## Runs the node - docker compose up -d xlayer-node - -.PHONY: stop-node -stop-node: ## Stops the node - docker compose stop xlayer-node && docker compose rm -f xlayer-node - .PHONY: run-network -run-network: ## Runs the xlayer-mock-l1-network network - docker compose up -d xlayer-mock-l1-network +run-network: ## Runs the l1 network + docker compose up -d l1 .PHONY: stop-network -stop-network: ## Stops the xlayer-mock-l1-network network - docker compose stop xlayer-mock-l1-network && docker compose rm -f xlayer-mock-l1-network +stop-network: ## Stops the l1 network + docker compose stop l1 && docker compose rm -f l1 .PHONY: run-local run-local: run-network ## Run network and db for local instance - docker compose up -d xlayer-data-availability-db + docker compose up -d cdk-data-availability-db .PHONY: stop-local stop-local: stop-network ## Run network and db for local instance - docker compose stop xlayer-data-availability-db && docker compose rm -f xlayer-data-availability-db + docker compose stop cdk-data-availability-db && docker compose rm -f cdk-data-availability-db diff --git a/test/config/aggregator.keystore b/test/config/aggregator.keystore deleted file mode 100644 index 36adf8bc..00000000 --- a/test/config/aggregator.keystore +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"id":"71b028b6-9b1d-4f4c-9e66-31c94a6eb679","address":"70997970c51812dc3a010c7d01b50e0d17dc79c8","crypto":{"ciphertext":"985d5dc5f7750fc4ad0ad0d370486870016bb97e00ef1f7b146d6ad95d456861","cipherparams":{"iv":"f51b18b9f45872f71c3578513fca6cb0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"6253e2d8a71e4808dd11143329cfea467cabb37ac1e1e55dbc0dd90ff22524a7","n":8192,"r":8,"p":1},"mac":"922f741e84201fc7c17bbf9fae5dba6c04a2a99a7268998b5a0268aa690004be"}} \ No newline at end of file diff --git a/test/config/genesis.json b/test/config/genesis.json deleted file mode 100644 index 0188b472..00000000 --- a/test/config/genesis.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "l1Config": { - "chainId": 1337, - "polygonZkEVMAddress": "0x975725832B4909Aab87D3604A0b501569dbBE7A9", - "polygonRollupManagerAddress": "0xF5336Cb12989c0673071dF0c8a930900D7DF8D3e", - "polTokenAddress": "0xcFE6D77a653b988203BfAc9C6a69eA9D583bdC2b", - "polygonZkEVMGlobalExitRootAddress": "0x6Ae5b0863dBF3477335c0102DBF432aFf04ceb22" - }, - "genesisBlockNumber": 199, - "root": "0xe6ae9579cda5787ab533bf97a8a5aa4ca1e0d40c8890b01f2d714fce71a5873c", - "genesis": [ - { - "contractName": "PolygonZkEVMDeployer", - "balance": "0", - "nonce": "4", - "address": "0xb169BC523B5399B94c7BDe7108fc543004F09aad", - "bytecode": "0x6080604052600436106100705760003560e01c8063715018a61161004e578063715018a6146100e65780638da5cb5b146100fb578063e11ae6cb14610126578063f2fde38b1461013957600080fd5b80632b79805a146100755780634a94d4871461008a5780636d07dbf81461009d575b600080fd5b610088610083366004610927565b610159565b005b6100886100983660046109c7565b6101cb565b3480156100a957600080fd5b506100bd6100b8366004610a1e565b61020d565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b50610088610220565b34801561010757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100bd565b610088610134366004610a40565b610234565b34801561014557600080fd5b50610088610154366004610a90565b61029b565b610161610357565b600061016e8585856103d8565b905061017a8183610537565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101d3610357565b6101de83838361057b565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b90600090a1505050565b600061021983836105a9565b9392505050565b610228610357565b61023260006105b6565b565b61023c610357565b60006102498484846103d8565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b6102a3610357565b73ffffffffffffffffffffffffffffffffffffffff811661034b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610354816105b6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610342565b600083471015610444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610342565b81516000036104af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610342565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff8116610219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610342565b6060610219838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061062b565b60606105a1848484604051806060016040528060298152602001610b3d6029913961062b565b949350505050565b6000610219838330610744565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610342565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516106e69190610acf565b60006040518083038185875af1925050503d8060008114610723576040519150601f19603f3d011682016040523d82523d6000602084013e610728565b606091505b50915091506107398783838761076e565b979650505050505050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156108045782516000036107fd5773ffffffffffffffffffffffffffffffffffffffff85163b6107fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610342565b50816105a1565b6105a183838151156108195781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103429190610aeb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261088d57600080fd5b813567ffffffffffffffff808211156108a8576108a861084d565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108ee576108ee61084d565b8160405283815286602085880101111561090757600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561093d57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561096357600080fd5b61096f8883890161087c565b9350606087013591508082111561098557600080fd5b506109928782880161087c565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff811681146109c257600080fd5b919050565b6000806000606084860312156109dc57600080fd5b6109e58461099e565b9250602084013567ffffffffffffffff811115610a0157600080fd5b610a0d8682870161087c565b925050604084013590509250925092565b60008060408385031215610a3157600080fd5b50508035926020909101359150565b600080600060608486031215610a5557600080fd5b8335925060208401359150604084013567ffffffffffffffff811115610a7a57600080fd5b610a868682870161087c565b9150509250925092565b600060208284031215610aa257600080fd5b6102198261099e565b60005b83811015610ac6578181015183820152602001610aae565b50506000910152565b60008251610ae1818460208701610aab565b9190910192915050565b6020815260008251806020840152610b0a816040850160208701610aab565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220964619cee0e0baf94c6f8763f013be157da5d54c89e5cff4a8caf4266e13f13a64736f6c63430008140033", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000002ecf31ece36ccac2d3222a303b1409233ecbb225" - } - }, - { - "contractName": "ProxyAdmin", - "balance": "0", - "nonce": "1", - "address": "0xa6791C91168866769273e6AFFe603e00269b16ae", - "bytecode": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461012b57806399a88ec41461013e578063f2fde38b1461015e578063f3b7dead1461017e57600080fd5b8063204e1c7a14610080578063715018a6146100c95780637eff275e146100e05780638da5cb5b14610100575b600080fd5b34801561008c57600080fd5b506100a061009b366004610608565b61019e565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100de610255565b005b3480156100ec57600080fd5b506100de6100fb36600461062c565b610269565b34801561010c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100a0565b6100de610139366004610694565b6102f7565b34801561014a57600080fd5b506100de61015936600461062c565b61038c565b34801561016a57600080fd5b506100de610179366004610608565b6103e8565b34801561018a57600080fd5b506100a0610199366004610608565b6104a4565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610225576040519150601f19603f3d011682016040523d82523d6000602084013e61022a565b606091505b50915091508161023957600080fd5b8080602001905181019061024d9190610788565b949350505050565b61025d6104f0565b6102676000610571565b565b6102716104f0565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b600060405180830381600087803b1580156102db57600080fd5b505af11580156102ef573d6000803e3d6000fd5b505050505050565b6102ff6104f0565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061035590869086906004016107a5565b6000604051808303818588803b15801561036e57600080fd5b505af1158015610382573d6000803e3d6000fd5b5050505050505050565b6103946104f0565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102c1565b6103f06104f0565b73ffffffffffffffffffffffffffffffffffffffff8116610498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6104a181610571565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b60005473ffffffffffffffffffffffffffffffffffffffff163314610267576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161048f565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146104a157600080fd5b60006020828403121561061a57600080fd5b8135610625816105e6565b9392505050565b6000806040838503121561063f57600080fd5b823561064a816105e6565b9150602083013561065a816105e6565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156106a957600080fd5b83356106b4816105e6565b925060208401356106c4816105e6565b9150604084013567ffffffffffffffff808211156106e157600080fd5b818601915086601f8301126106f557600080fd5b81358181111561070757610707610665565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561074d5761074d610665565b8160405282815289602084870101111561076657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561079a57600080fd5b8151610625816105e6565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b818110156107ef578581018301518582016060015282016107d3565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010192505050939250505056fea2646970667358221220c9867ffac53151bdb1305d8f5e3e883cd83e5270c7ec09cdc24e837b2e65239064736f6c63430008140033", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000d4289c477602498dff4d0a7024f5dd4e060d531b" - } - }, - { - "contractName": "PolygonZkEVMBridge implementation", - "balance": "0", - "nonce": "1", - "address": "0x611732751B6857dFc02974cD019771b190E2e84C", - "bytecode": "0x6080604052600436106101e35760003560e01c806383f2440311610102578063ccaa2d1111610095578063ee25560b11610064578063ee25560b146105ce578063f5efcd79146105fb578063f811bff71461061b578063fb5708341461063b57600080fd5b8063ccaa2d111461055d578063cd5865791461057d578063d02103ca14610590578063dbc16976146105b957600080fd5b8063bab161bf116100d1578063bab161bf146104d7578063be5831c7146104f9578063c00f14ab1461051d578063cc4616321461053d57600080fd5b806383f24403146104575780638ed7e3f214610477578063aaa13cc214610497578063b8b284d0146104b757600080fd5b80633cbc795b1161017a5780637843298b116101495780637843298b146103d757806379e2cf97146103f757806381b1c1741461040c57806383c43a551461044257600080fd5b80633cbc795b146103495780633e197043146103825780634b2f336d146103a25780635ca1e165146103c257600080fd5b806327aef4e8116101b657806327aef4e8146102795780632dfdf0b51461029b578063318aee3d146102bf5780633c351e101461032957600080fd5b806315064c96146101e85780632072f6c51461021757806322e95f2c1461022e578063240ff37814610266575b600080fd5b3480156101f457600080fd5b506068546102029060ff1681565b60405190151581526020015b60405180910390f35b34801561022357600080fd5b5061022c61065b565b005b34801561023a57600080fd5b5061024e61024936600461307c565b610690565b6040516001600160a01b03909116815260200161020e565b61022c61027436600461310a565b6106fb565b34801561028557600080fd5b5061028e610784565b60405161020e91906131d4565b3480156102a757600080fd5b506102b160535481565b60405190815260200161020e565b3480156102cb57600080fd5b506103056102da3660046131ee565b606b6020526000908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b0390911660208301520161020e565b34801561033557600080fd5b50606d5461024e906001600160a01b031681565b34801561035557600080fd5b50606d5461036d90600160a01b900463ffffffff1681565b60405163ffffffff909116815260200161020e565b34801561038e57600080fd5b506102b161039d36600461321a565b610812565b3480156103ae57600080fd5b50606f5461024e906001600160a01b031681565b3480156103ce57600080fd5b506102b16108bc565b3480156103e357600080fd5b5061024e6103f2366004613299565b610999565b34801561040357600080fd5b5061022c6109c3565b34801561041857600080fd5b5061024e6104273660046132e2565b606a602052600090815260409020546001600160a01b031681565b34801561044e57600080fd5b5061028e6109e4565b34801561046357600080fd5b506102b161047236600461330d565b610a03565b34801561048357600080fd5b50606c5461024e906001600160a01b031681565b3480156104a357600080fd5b5061024e6104b2366004613419565b610ad9565b3480156104c357600080fd5b5061022c6104d23660046134b5565b610c1a565b3480156104e357600080fd5b5060685461036d90610100900463ffffffff1681565b34801561050557600080fd5b5060685461036d90600160c81b900463ffffffff1681565b34801561052957600080fd5b5061028e6105383660046131ee565b610cfa565b34801561054957600080fd5b50610202610558366004613538565b610d3f565b34801561056957600080fd5b5061022c61057836600461356b565b610dc9565b61022c61058b366004613657565b61131c565b34801561059c57600080fd5b5060685461024e906501000000000090046001600160a01b031681565b3480156105c557600080fd5b5061022c61179f565b3480156105da57600080fd5b506102b16105e93660046132e2565b60696020526000908152604090205481565b34801561060757600080fd5b5061022c61061636600461356b565b6117d2565b34801561062757600080fd5b5061022c6106363660046136ed565b611aa5565b34801561064757600080fd5b50610202610656366004613796565b611dc7565b606c546001600160a01b0316331461068657604051631736745960e31b815260040160405180910390fd5b61068e611ddf565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091206000908152606a90915220546001600160a01b03165b92915050565b60685460ff161561071f57604051630bc011ff60e21b815260040160405180910390fd5b34158015906107385750606f546001600160a01b031615155b1561076f576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61077d858534868686611e3b565b5050505050565b606e8054610791906137de565b80601f01602080910402602001604051908101604052809291908181526020018280546107bd906137de565b801561080a5780601f106107df5761010080835404028352916020019161080a565b820191906000526020600020905b8154815290600101906020018083116107ed57829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b605354600090819081805b6020811015610990578083901c60011660010361092457603381602081106108f1576108f1613818565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610951565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b6040805160208101849052908101839052606001604051602081830303815290604052805190602001209150808061098890613844565b9150506108c7565b50919392505050565b60006109bb84846109a985611f05565b6109b286611ff3565b6104b2876120d8565b949350505050565b605354606854600160c81b900463ffffffff16101561068e5761068e6121a9565b60405180611ba00160405280611b668152602001613ec4611b66913981565b600083815b6020811015610ad057600163ffffffff8516821c81169003610a7357848160208110610a3657610a36613818565b602002013582604051602001610a56929190918252602082015260400190565b604051602081830303815290604052805190602001209150610abe565b81858260208110610a8657610a86613818565b6020020135604051602001610aa5929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610ac881613844565b915050610a08565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201526000908190603801604051602081830303815290604052805190602001209050600060ff60f81b308360405180611ba00160405280611b668152602001613ec4611b669139898989604051602001610b639392919061385d565b60408051601f1981840301815290829052610b819291602001613896565b60405160208183030381529060405280519060200120604051602001610bf694939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c3e57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c80576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54604051632770a7eb60e21b8152336004820152602481018690526001600160a01b0390911690639dc29fac90604401600060405180830381600087803b158015610ccc57600080fd5b505af1158015610ce0573d6000803e3d6000fd5b50505050610cf2868686868686611e3b565b505050505050565b6060610d0582611f05565b610d0e83611ff3565b610d17846120d8565b604051602001610d299392919061385d565b6040516020818303038152906040529050919050565b6068546000908190610100900463ffffffff16158015610d65575063ffffffff83166001145b15610d77575063ffffffff8316610d9f565b610d8c64010000000063ffffffff85166138c5565b610d9c9063ffffffff86166138dc565b90505b600881901c600090815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610ded57604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610e1d576040516302caf51760e11b815260040160405180910390fd5b610e518c8c8c8c8c610e4c60008e8e8e8e8e8e8e604051610e3f9291906138ef565b6040518091039020610812565b61225c565b6001600160a01b038616610fa457606f546001600160a01b0316610f395760006001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610ea8576020820181803683370190505b50604051610eb691906138ff565b60006040518083038185875af1925050503d8060008114610ef3576040519150601f19603f3d011682016040523d82523d6000602084013e610ef8565b606091505b5050905080610f33576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506112b2565b606f546040516340c10f1960e01b81526001600160a01b03868116600483015260248201869052909116906340c10f1990604401600060405180830381600087803b158015610f8757600080fd5b505af1158015610f9b573d6000803e3d6000fd5b505050506112b2565b606d546001600160a01b038781169116148015610fd25750606d5463ffffffff888116600160a01b90920416145b15610fea5760006001600160a01b0385168482610e7e565b60685463ffffffff61010090910481169088160361101b576110166001600160a01b03871685856123f4565b6112b2565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b16602482015260009060380160408051601f1981840301815291815281516020928301206000818152606a9093529120549091506001600160a01b03168061124c5760006110c98386868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061247592505050565b6040516340c10f1960e01b81526001600160a01b03898116600483015260248201899052919250908216906340c10f1990604401600060405180830381600087803b15801561111757600080fd5b505af115801561112b573d6000803e3d6000fd5b5050505080606a600085815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b6000836001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a83888860405161123e959493929190613944565b60405180910390a1506112af565b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528216906340c10f1990604401600060405180830381600087803b15801561129657600080fd5b505af11580156112aa573d6000803e3d6000fd5b505050505b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff161561134057604051630bc011ff60e21b815260040160405180910390fd5b61134861250a565b60685463ffffffff610100909104811690881603611379576040516302caf51760e11b815260040160405180910390fd5b6000806060876001600160a01b038816611478578834146113c6576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff169450906113f3906137de565b80601f016020809104026020016040519081016040528092919081815260200182805461141f906137de565b801561146c5780601f106114415761010080835404028352916020019161146c565b820191906000526020600020905b81548152906001019060200180831161144f57829003601f168201915b50505050509150611714565b34156114b0576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b039081169089160361152b57604051632770a7eb60e21b8152336004820152602481018a90526001600160a01b03891690639dc29fac90604401600060405180830381600087803b15801561150e57600080fd5b505af1158015611522573d6000803e3d6000fd5b50505050611714565b6001600160a01b038089166000908152606b602090815260409182902082518084019093525463ffffffff81168352640100000000900490921691810182905290156115e457604051632770a7eb60e21b8152336004820152602481018b90526001600160a01b038a1690639dc29fac90604401600060405180830381600087803b1580156115b957600080fd5b505af11580156115cd573d6000803e3d6000fd5b505050508060200151945080600001519350611707565b85156115f6576115f6898b8989612563565b6040516370a0823160e01b81523060048201526000906001600160a01b038b16906370a0823190602401602060405180830381865afa15801561163d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611661919061397d565b90506116786001600160a01b038b1633308e61290d565b6040516370a0823160e01b81523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa1580156116bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e3919061397d565b90506116ef8282613996565b6068548c9850610100900463ffffffff169650935050505b61171089610cfa565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b600084868e8e86886053546040516117549897969594939291906139a9565b60405180910390a161177b611776600085878f8f878980519060200120610812565b61295e565b8615611789576117896121a9565b5050505061179660018055565b50505050505050565b606c546001600160a01b031633146117ca57604051631736745960e31b815260040160405180910390fd5b61068e612a62565b60685460ff16156117f657604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614611826576040516302caf51760e11b815260040160405180910390fd5b6118488c8c8c8c8c610e4c60018e8e8e8e8e8e8e604051610e3f9291906138ef565b606f546000906001600160a01b03166118ff57846001600160a01b031684888a868660405160240161187d9493929190613a13565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b179052516118b291906138ff565b60006040518083038185875af1925050503d80600081146118ef576040519150601f19603f3d011682016040523d82523d6000602084013e6118f4565b606091505b505080915050611a03565b606f546040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052909116906340c10f1990604401600060405180830381600087803b15801561194d57600080fd5b505af1158015611961573d6000803e3d6000fd5b50505050846001600160a01b0316878985856040516024016119869493929190613a13565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b179052516119bb91906138ff565b6000604051808303816000865af19150503d80600081146119f8576040519150601f19603f3d011682016040523d82523d6000602084013e6119fd565b606091505b50909150505b80611a3a576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b600054610100900460ff1615808015611ac55750600054600160ff909116105b80611adf5750303b158015611adf575060005460ff166001145b611b565760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff191660011790558015611b79576000805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff19168583161790558616611c545763ffffffff851615611c4f576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d71565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e611ca38382613a92565b50611d436000801b6012604051602001611d2f91906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b604051602081830303815290604052612475565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611d79612ad3565b8015611796576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b600081611dd5868686610a03565b1495945050505050565b60685460ff1615611e0357604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b60685463ffffffff610100909104811690871603611e6c576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611ec099989796959493929190613b52565b60405180910390a1611ef76117766001606860019054906101000a900463ffffffff16338a8a8a8989604051610e3f9291906138ef565b8215610cf257610cf26121a9565b60408051600481526024810182526020810180516001600160e01b03167f06fdde0300000000000000000000000000000000000000000000000000000000179052905160609160009182916001600160a01b03861691611f6591906138ff565b600060405180830381855afa9150503d8060008114611fa0576040519150601f19603f3d011682016040523d82523d6000602084013e611fa5565b606091505b509150915081611fea576040518060400160405280600781526020017f4e4f5f4e414d45000000000000000000000000000000000000000000000000008152506109bb565b6109bb81612b46565b60408051600481526024810182526020810180516001600160e01b03167f95d89b4100000000000000000000000000000000000000000000000000000000179052905160609160009182916001600160a01b0386169161205391906138ff565b600060405180830381855afa9150503d806000811461208e576040519150601f19603f3d011682016040523d82523d6000602084013e612093565b606091505b509150915081611fea576040518060400160405280600981526020017f4e4f5f53594d424f4c00000000000000000000000000000000000000000000008152506109bb565b60408051600481526024810182526020810180516001600160e01b03167f313ce567000000000000000000000000000000000000000000000000000000001790529051600091829182916001600160a01b0386169161213791906138ff565b600060405180830381855afa9150503d8060008114612172576040519150601f19603f3d011682016040523d82523d6000602084013e612177565b606091505b509150915081801561218a575080516020145b6121955760126109bb565b808060200190518101906109bb9190613bbe565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d61220a6108bc565b6040518263ffffffff1660e01b815260040161222891815260200190565b600060405180830381600087803b15801561224257600080fd5b505af1158015612256573d6000803e3d6000fd5b50505050565b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091526000916501000000000090046001600160a01b03169063257b3632906084016020604051808303816000875af11580156122f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612315919061397d565b905080600003612350576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806801000000000000000087161561239557869150612373848a8489611dc7565b612390576040516338105f3b60e21b815260040160405180910390fd5b6123df565b602087901c6123a5816001613bdb565b91508792506123c06123b8868c86610a03565b8a8389611dc7565b6123dd576040516338105f3b60e21b815260040160405180910390fd5b505b6123e98282612d1b565b505050505050505050565b6040516001600160a01b0383166024820152604481018290526124709084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612ddd565b505050565b60008060405180611ba00160405280611b668152602001613ec4611b669139836040516020016124a6929190613896565b6040516020818303038152906040529050838151602083016000f591506001600160a01b038216612503576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b60026001540361255c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611b4d565b6002600155565b60006125726004828486613bf8565b61257b91613c22565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b031982160161275a5760008080808080806125c3896004818d613bf8565b8101906125d09190613c52565b9650965096509650965096509650336001600160a01b0316876001600160a01b0316146126105760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03861630146126395760405163750643af60e01b815260040160405180910390fd5b8a8514612672576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161270991906138ff565b6000604051808303816000865af19150503d8060008114612746576040519150601f19603f3d011682016040523d82523d6000602084013e61274b565b606091505b5050505050505050505061077d565b6001600160e01b031981166323f2ebc360e21b146127a4576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808080808080806127ba8a6004818e613bf8565b8101906127c79190613ca6565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146128095760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03871630146128325760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f16916128b991906138ff565b6000604051808303816000865af19150503d80600081146128f6576040519150601f19603f3d011682016040523d82523d6000602084013e6128fb565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526122569085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612439565b80600161296d60206002613e0d565b6129779190613996565b605354106129b1576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006053600081546129c290613844565b9182905550905060005b6020811015612a53578082901c6001166001036129ff5782603382602081106129f7576129f7613818565b015550505050565b60338160208110612a1257612a12613818565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092508080612a4b90613844565b9150506129cc565b50612470613e19565b60018055565b60685460ff16612a9e576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b600054610100900460ff16612b3e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611b4d565b61068e612ec2565b60606040825110612b6557818060200190518101906106f59190613e2f565b8151602003612cdd5760005b602081108015612bb85750828181518110612b8e57612b8e613818565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15612bcf5780612bc781613844565b915050612b71565b80600003612c1257505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b60008167ffffffffffffffff811115612c2d57612c2d61334c565b6040519080825280601f01601f191660200182016040528015612c57576020820181803683370190505b50905060005b82811015612cd557848181518110612c7757612c77613818565b602001015160f81c60f81b828281518110612c9457612c94613818565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080612ccd81613844565b915050612c5d565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b606854600090610100900463ffffffff16158015612d3f575063ffffffff82166001145b15612d51575063ffffffff8216612d79565b612d6664010000000063ffffffff84166138c5565b612d769063ffffffff85166138dc565b90505b600881901c60008181526069602052604081208054600160ff861690811b91821892839055929091908183169003611796576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612e32826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f2d9092919063ffffffff16565b8051909150156124705780806020019051810190612e509190613ea6565b6124705760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611b4d565b600054610100900460ff16612a5c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611b4d565b60606109bb848460008585600080866001600160a01b03168587604051612f5491906138ff565b60006040518083038185875af1925050503d8060008114612f91576040519150601f19603f3d011682016040523d82523d6000602084013e612f96565b606091505b5091509150612fa787838387612fb2565b979650505050505050565b6060831561302157825160000361301a576001600160a01b0385163b61301a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611b4d565b50816109bb565b6109bb83838151156130365781518083602001fd5b8060405162461bcd60e51b8152600401611b4d91906131d4565b803563ffffffff81168114612d1657600080fd5b6001600160a01b038116811461307957600080fd5b50565b6000806040838503121561308f57600080fd5b61309883613050565b915060208301356130a881613064565b809150509250929050565b801515811461307957600080fd5b60008083601f8401126130d357600080fd5b50813567ffffffffffffffff8111156130eb57600080fd5b60208301915083602082850101111561310357600080fd5b9250929050565b60008060008060006080868803121561312257600080fd5b61312b86613050565b9450602086013561313b81613064565b9350604086013561314b816130b3565b9250606086013567ffffffffffffffff81111561316757600080fd5b613173888289016130c1565b969995985093965092949392505050565b60005b8381101561319f578181015183820152602001613187565b50506000910152565b600081518084526131c0816020860160208601613184565b601f01601f19169290920160200192915050565b6020815260006131e760208301846131a8565b9392505050565b60006020828403121561320057600080fd5b81356131e781613064565b60ff8116811461307957600080fd5b600080600080600080600060e0888a03121561323557600080fd5b87356132408161320b565b965061324e60208901613050565b9550604088013561325e81613064565b945061326c60608901613050565b9350608088013561327c81613064565b9699959850939692959460a0840135945060c09093013592915050565b6000806000606084860312156132ae57600080fd5b6132b784613050565b925060208401356132c781613064565b915060408401356132d781613064565b809150509250925092565b6000602082840312156132f457600080fd5b5035919050565b8061040081018310156106f557600080fd5b6000806000610440848603121561332357600080fd5b8335925061333485602086016132fb565b91506133436104208501613050565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561338b5761338b61334c565b604052919050565b600067ffffffffffffffff8211156133ad576133ad61334c565b50601f01601f191660200190565b60006133ce6133c984613393565b613362565b90508281528383830111156133e257600080fd5b828260208301376000602084830101529392505050565b600082601f83011261340a57600080fd5b6131e7838335602085016133bb565b600080600080600060a0868803121561343157600080fd5b61343a86613050565b9450602086013561344a81613064565b9350604086013567ffffffffffffffff8082111561346757600080fd5b61347389838a016133f9565b9450606088013591508082111561348957600080fd5b50613496888289016133f9565b92505060808601356134a78161320b565b809150509295509295909350565b60008060008060008060a087890312156134ce57600080fd5b6134d787613050565b955060208701356134e781613064565b94506040870135935060608701356134fe816130b3565b9250608087013567ffffffffffffffff81111561351a57600080fd5b61352689828a016130c1565b979a9699509497509295939492505050565b6000806040838503121561354b57600080fd5b61355483613050565b915061356260208401613050565b90509250929050565b6000806000806000806000806000806000806109208d8f03121561358e57600080fd5b6135988e8e6132fb565b9b506135a88e6104008f016132fb565b9a506108008d013599506108208d013598506108408d013597506135cf6108608e01613050565b96506135df6108808e0135613064565b6108808d013595506135f46108a08e01613050565b94506136046108c08e0135613064565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e0135111561362e57600080fd5b61363f8e6109008f01358f016130c1565b81935080925050509295989b509295989b509295989b565b600080600080600080600060c0888a03121561367257600080fd5b61367b88613050565b9650602088013561368b81613064565b95506040880135945060608801356136a281613064565b935060808801356136b2816130b3565b925060a088013567ffffffffffffffff8111156136ce57600080fd5b6136da8a828b016130c1565b989b979a50959850939692959293505050565b60008060008060008060c0878903121561370657600080fd5b61370f87613050565b9550602087013561371f81613064565b945061372d60408801613050565b9350606087013561373d81613064565b9250608087013561374d81613064565b915060a087013567ffffffffffffffff81111561376957600080fd5b8701601f8101891361377a57600080fd5b613789898235602084016133bb565b9150509295509295509295565b60008060008061046085870312156137ad57600080fd5b843593506137be86602087016132fb565b92506137cd6104208601613050565b939692955092936104400135925050565b600181811c908216806137f257607f821691505b60208210810361381257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016138565761385661382e565b5060010190565b60608152600061387060608301866131a8565b828103602084015261388281866131a8565b91505060ff83166040830152949350505050565b600083516138a8818460208801613184565b8351908301906138bc818360208801613184565b01949350505050565b80820281158282048414176106f5576106f561382e565b808201808211156106f5576106f561382e565b8183823760009101908152919050565b60008251613911818460208701613184565b9190910192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b63ffffffff8616815260006001600160a01b03808716602084015280861660408401525060806060830152612fa760808301848661391b565b60006020828403121561398f57600080fd5b5051919050565b818103818111156106f5576106f561382e565b600061010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c08501526139fa828501876131a8565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201526000613a4260608301848661391b565b9695505050505050565b601f82111561247057600081815260208120601f850160051c81016020861015613a735750805b601f850160051c820191505b81811015610cf257828155600101613a7f565b815167ffffffffffffffff811115613aac57613aac61334c565b613ac081613aba84546137de565b84613a4c565b602080601f831160018114613af55760008415613add5750858301515b600019600386901b1c1916600185901b178555610cf2565b600085815260208120601f198616915b82811015613b2457888601518255948401946001909101908401613b05565b5085821015613b425787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600061010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c0850152613ba4828501878961391b565b925080851660e085015250509a9950505050505050505050565b600060208284031215613bd057600080fd5b81516131e78161320b565b63ffffffff8181168382160190808211156125035761250361382e565b60008085851115613c0857600080fd5b83861115613c1557600080fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015613c4a5780818660040360031b1b83161692505b505092915050565b600080600080600080600060e0888a031215613c6d57600080fd5b8735613c7881613064565b96506020880135613c8881613064565b95506040880135945060608801359350608088013561327c8161320b565b600080600080600080600080610100898b031215613cc357600080fd5b8835613cce81613064565b97506020890135613cde81613064565b965060408901359550606089013594506080890135613cfc816130b3565b935060a0890135613d0c8161320b565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613d64578160001904821115613d4a57613d4a61382e565b80851615613d5757918102915b93841c9390800290613d2e565b509250929050565b600082613d7b575060016106f5565b81613d88575060006106f5565b8160018114613d9e5760028114613da857613dc4565b60019150506106f5565b60ff841115613db957613db961382e565b50506001821b6106f5565b5060208310610133831016604e8410600b8410161715613de7575081810a6106f5565b613df18383613d29565b8060001904821115613e0557613e0561382e565b029392505050565b60006131e78383613d6c565b634e487b7160e01b600052600160045260246000fd5b600060208284031215613e4157600080fd5b815167ffffffffffffffff811115613e5857600080fd5b8201601f81018413613e6957600080fd5b8051613e776133c982613393565b818152856020838501011115613e8c57600080fd5b613e9d826020830160208601613184565b95945050505050565b600060208284031215613eb857600080fd5b81516131e7816130b356fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a264697066735822122078dbdc367e7857d7cdf8e3cb8d3102a00d09ea40655a67a85436f80d2c7ba06664736f6c63430008140033" - }, - { - "contractName": "PolygonZkEVMBridge proxy", - "balance": "340282366920938463463374607431768211455", - "nonce": "1", - "address": "0x1dDA31e2F009E7479dE78445C1540f55627a85f4", - "bytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461086f565b610135565b61006b6100a336600461088a565b61017f565b3480156100b457600080fd5b506100bd6101f3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461086f565b610231565b34801561011257600080fd5b506100bd61025e565b61012361028c565b61013361012e610363565b61036d565b565b61013d610391565b73ffffffffffffffffffffffffffffffffffffffff16330361017757610174816040518060200160405280600081525060006103d1565b50565b61017461011b565b610187610391565b73ffffffffffffffffffffffffffffffffffffffff1633036101eb576101e68383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506103d1915050565b505050565b6101e661011b565b60006101fd610391565b73ffffffffffffffffffffffffffffffffffffffff16330361022657610221610363565b905090565b61022e61011b565b90565b610239610391565b73ffffffffffffffffffffffffffffffffffffffff16330361017757610174816103fc565b6000610268610391565b73ffffffffffffffffffffffffffffffffffffffff16330361022657610221610391565b610294610391565b73ffffffffffffffffffffffffffffffffffffffff163303610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b600061022161045d565b3660008037600080366000845af43d6000803e80801561038c573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6103da83610485565b6000825111806103e75750805b156101e6576103f683836104d2565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610425610391565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a1610174816104fe565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103b5565b61048e8161060a565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606104f7838360405180606001604052806027815260200161099f602791396106d5565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81166105a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161035a565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b73ffffffffffffffffffffffffffffffffffffffff81163b6106ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161035a565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105c4565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516106ff9190610931565b600060405180830381855af49150503d806000811461073a576040519150601f19603f3d011682016040523d82523d6000602084013e61073f565b606091505b50915091506107508683838761075a565b9695505050505050565b606083156107f05782516000036107e95773ffffffffffffffffffffffffffffffffffffffff85163b6107e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161035a565b50816107fa565b6107fa8383610802565b949350505050565b8151156108125781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035a919061094d565b803573ffffffffffffffffffffffffffffffffffffffff8116811461086a57600080fd5b919050565b60006020828403121561088157600080fd5b6104f782610846565b60008060006040848603121561089f57600080fd5b6108a884610846565b9250602084013567ffffffffffffffff808211156108c557600080fd5b818601915086601f8301126108d957600080fd5b8135818111156108e857600080fd5b8760208285010111156108fa57600080fd5b6020830194508093505050509250925092565b60005b83811015610928578181015183820152602001610910565b50506000910152565b6000825161094381846020870161090d565b9190910192915050565b602081526000825180602084015261096c81604085016020870161090d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220701a0c26bdd76686e63fc3c65e4f28a20ba3ecc8a60246733c0627e679c9804e64736f6c63430008140033", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000a6791c91168866769273e6affe603e00269b16ae", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000611732751b6857dfc02974cd019771b190e2e84c" - } - }, - { - "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", - "balance": "0", - "nonce": "1", - "address": "0x6C71cb798D098f8Aa3C1c13286A2EB4A7c4fa2a9", - "bytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806301fd904414610051578063257b36321461006d57806333d6247d1461008d578063a3c573eb146100a2575b600080fd5b61005a60015481565b6040519081526020015b60405180910390f35b61005a61007b366004610162565b60006020819052908152604090205481565b6100a061009b366004610162565b6100ee565b005b6100c97f0000000000000000000000001dda31e2f009e7479de78445c1540f55627a85f481565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610064565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001dda31e2f009e7479de78445c1540f55627a85f4161461015d576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b60006020828403121561017457600080fd5b503591905056fea2646970667358221220ea2171e2c85c8bff947affc409ef6fc6a8fe82fb8c174ddeda988651e595d66564736f6c63430008140033" - }, - { - "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", - "balance": "0", - "nonce": "1", - "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", - "bytecode": "0x60806040523661001357610011610017565b005b6100115b61001f6101b7565b6001600160a01b0316336001600160a01b0316141561016f5760606001600160e01b031960003516631b2ce7f360e11b8114156100655761005e6101ea565b9150610167565b6001600160e01b0319811663278f794360e11b14156100865761005e610241565b6001600160e01b031981166308f2839760e41b14156100a75761005e610287565b6001600160e01b031981166303e1469160e61b14156100c85761005e6102b8565b6001600160e01b03198116635c60da1b60e01b14156100e95761005e6102f8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b61017761030c565b565b606061019e83836040518060600160405280602781526020016108576027913961031c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101f4610394565b600061020336600481846106a2565b81019061021091906106e8565b905061022d8160405180602001604052806000815250600061039f565b505060408051602081019091526000815290565b606060008061025336600481846106a2565b8101906102609190610719565b915091506102708282600161039f565b604051806020016040528060008152509250505090565b6060610291610394565b60006102a036600481846106a2565b8101906102ad91906106e8565b905061022d816103cb565b60606102c2610394565b60006102cc6101b7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b6060610302610394565b60006102cc610422565b610177610317610422565b610431565b6060600080856001600160a01b0316856040516103399190610807565b600060405180830381855af49150503d8060008114610374576040519150601f19603f3d011682016040523d82523d6000602084013e610379565b606091505b509150915061038a86838387610455565b9695505050505050565b341561017757600080fd5b6103a8836104d3565b6000825111806103b55750805b156103c6576103c48383610179565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103f46101b7565b604080516001600160a01b03928316815291841660208301520160405180910390a161041f81610513565b50565b600061042c6105bc565b905090565b3660008037600080366000845af43d6000803e808015610450573d6000f35b3d6000fd5b606083156104c15782516104ba576001600160a01b0385163b6104ba5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161015e565b50816104cb565b6104cb83836105e4565b949350505050565b6104dc8161060e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105785760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161015e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101db565b8151156105f45781518083602001fd5b8060405162461bcd60e51b815260040161015e9190610823565b6001600160a01b0381163b61067b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161015e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61059b565b600080858511156106b257600080fd5b838611156106bf57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106e357600080fd5b919050565b6000602082840312156106fa57600080fd5b61019e826106cc565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561072c57600080fd5b610735836106cc565b9150602083013567ffffffffffffffff8082111561075257600080fd5b818501915085601f83011261076657600080fd5b81358181111561077857610778610703565b604051601f8201601f19908116603f011681019083821181831017156107a0576107a0610703565b816040528281528860208487010111156107b957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107f65781810151838201526020016107de565b838111156103c45750506000910152565b600082516108198184602087016107db565b9190910192915050565b60208152600082518060208401526108428160408501602087016107db565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122012bb4f564f73959a03513dc74fc3c6e40e8386e6f02c16b78d6db00ce0aa16af64736f6c63430008090033", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000a6791c91168866769273e6affe603e00269b16ae", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000006c71cb798d098f8aa3c1c13286a2eb4a7c4fa2a9" - } - }, - { - "contractName": "PolygonZkEVMTimelock", - "balance": "0", - "nonce": "1", - "address": "0xD4289C477602498Dff4d0A7024f5DD4E060d531b", - "bytecode": "0x6080604052600436106101c65760003560e01c806364d62353116100f7578063b1c5f42711610095578063d547741f11610064578063d547741f14610661578063e38335e514610681578063f23a6e6114610694578063f27a0c92146106d957600080fd5b8063b1c5f427146105af578063bc197c81146105cf578063c4d252f514610614578063d45c44351461063457600080fd5b80638f61f4f5116100d15780638f61f4f5146104e157806391d1485414610515578063a217fddf14610566578063b08e51c01461057b57600080fd5b806364d62353146104815780638065657f146104a15780638f2a0bb0146104c157600080fd5b8063248a9ca31161016457806331d507501161013e57806331d50750146103c857806336568abe146103e85780633a6aae7214610408578063584b153e1461046157600080fd5b8063248a9ca3146103475780632ab0f529146103775780632f2ff15d146103a857600080fd5b80630d3cf6fc116101a05780630d3cf6fc1461026b578063134008d31461029f57806313bc9f20146102b2578063150b7a02146102d257600080fd5b806301d5062a146101d257806301ffc9a7146101f457806307bd02651461022957600080fd5b366101cd57005b600080fd5b3480156101de57600080fd5b506101f26101ed366004611c52565b6106ee565b005b34801561020057600080fd5b5061021461020f366004611cc7565b610783565b60405190151581526020015b60405180910390f35b34801561023557600080fd5b5061025d7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610220565b34801561027757600080fd5b5061025d7f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101f26102ad366004611d09565b6107df565b3480156102be57600080fd5b506102146102cd366004611d75565b6108d7565b3480156102de57600080fd5b506103166102ed366004611e9a565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610220565b34801561035357600080fd5b5061025d610362366004611d75565b60009081526020819052604090206001015490565b34801561038357600080fd5b50610214610392366004611d75565b6000908152600160208190526040909120541490565b3480156103b457600080fd5b506101f26103c3366004611f02565b6108fd565b3480156103d457600080fd5b506102146103e3366004611d75565b610927565b3480156103f457600080fd5b506101f2610403366004611f02565b610940565b34801561041457600080fd5b5061043c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610220565b34801561046d57600080fd5b5061021461047c366004611d75565b6109f8565b34801561048d57600080fd5b506101f261049c366004611d75565b610a0e565b3480156104ad57600080fd5b5061025d6104bc366004611d09565b610ade565b3480156104cd57600080fd5b506101f26104dc366004611f73565b610b1d565b3480156104ed57600080fd5b5061025d7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b34801561052157600080fd5b50610214610530366004611f02565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561057257600080fd5b5061025d600081565b34801561058757600080fd5b5061025d7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156105bb57600080fd5b5061025d6105ca366004612025565b610d4f565b3480156105db57600080fd5b506103166105ea36600461214e565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b34801561062057600080fd5b506101f261062f366004611d75565b610d94565b34801561064057600080fd5b5061025d61064f366004611d75565b60009081526001602052604090205490565b34801561066d57600080fd5b506101f261067c366004611f02565b610e8f565b6101f261068f366004612025565b610eb4565b3480156106a057600080fd5b506103166106af3660046121f8565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106e557600080fd5b5061025d611161565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161071881611244565b6000610728898989898989610ade565b90506107348184611251565b6000817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a604051610770969594939291906122a6565b60405180910390a3505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107d957506107d98261139e565b92915050565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661085c5761085c8133611435565b600061086c888888888888610ade565b905061087881856114ed565b6108848888888861162a565b6000817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516108bc94939291906122f1565b60405180910390a36108cd8161172e565b5050505050505050565b6000818152600160205260408120546001811180156108f65750428111155b9392505050565b60008281526020819052604090206001015461091881611244565b61092283836117d7565b505050565b60008181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109f482826118c7565b5050565b6000818152600160208190526040822054610939565b333014610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109e1565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b6000868686868686604051602001610afb969594939291906122a6565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b4781611244565b888714610bd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b888514610c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b6000610c778b8b8b8b8b8b8b8b610d4f565b9050610c838184611251565b60005b8a811015610d415780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610cc357610cc3612331565b9050602002016020810190610cd89190612360565b8d8d86818110610cea57610cea612331565b905060200201358c8c87818110610d0357610d03612331565b9050602002810190610d15919061237b565b8c8b604051610d29969594939291906122a6565b60405180910390a3610d3a8161240f565b9050610c86565b505050505050505050505050565b60008888888888888888604051602001610d709897969594939291906124f7565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610dbe81611244565b610dc7826109f8565b610e53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109e1565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b600082815260208190526040902060010154610eaa81611244565b61092283836118c7565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610f3157610f318133611435565b878614610fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b87841461104f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b60006110618a8a8a8a8a8a8a8a610d4f565b905061106d81856114ed565b60005b8981101561114b5760008b8b8381811061108c5761108c612331565b90506020020160208101906110a19190612360565b905060008a8a848181106110b7576110b7612331565b9050602002013590503660008a8a868181106110d5576110d5612331565b90506020028101906110e7919061237b565b915091506110f78484848461162a565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588686868660405161112e94939291906122f1565b60405180910390a350505050806111449061240f565b9050611070565b506111558161172e565b50505050505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff161580159061123257507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa15801561120e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123291906125be565b1561123d5750600090565b5060025490565b61124e8133611435565b50565b61125a82610927565b156112e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109e1565b6112ef611161565b81101561137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109e1565b61138881426125e0565b6000928352600160205260409092209190915550565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107d957507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107d9565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f4576114738161197e565b61147e83602061199d565b60405160200161148f929190612617565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109e191600401612698565b6114f6826108d7565b611582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b80158061159e5750600081815260016020819052604090912054145b6109f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109e1565b60008473ffffffffffffffffffffffffffffffffffffffff168484846040516116549291906126e9565b60006040518083038185875af1925050503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b5050905080611727576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109e1565b5050505050565b611737816108d7565b6117c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b600090815260016020819052604090912055565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556118693390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107d973ffffffffffffffffffffffffffffffffffffffff831660145b606060006119ac8360026126f9565b6119b79060026125e0565b67ffffffffffffffff8111156119cf576119cf611d8e565b6040519080825280601f01601f1916602001820160405280156119f9576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110611a3057611a30612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a9357611a93612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000611acf8460026126f9565b611ada9060016125e0565b90505b6001811115611b77577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611b1b57611b1b612331565b1a60f81b828281518110611b3157611b31612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93611b7081612710565b9050611add565b5083156108f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109e1565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c0457600080fd5b919050565b60008083601f840112611c1b57600080fd5b50813567ffffffffffffffff811115611c3357600080fd5b602083019150836020828501011115611c4b57600080fd5b9250929050565b600080600080600080600060c0888a031215611c6d57600080fd5b611c7688611be0565b965060208801359550604088013567ffffffffffffffff811115611c9957600080fd5b611ca58a828b01611c09565b989b979a50986060810135976080820135975060a09091013595509350505050565b600060208284031215611cd957600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108f657600080fd5b60008060008060008060a08789031215611d2257600080fd5b611d2b87611be0565b955060208701359450604087013567ffffffffffffffff811115611d4e57600080fd5b611d5a89828a01611c09565b979a9699509760608101359660809091013595509350505050565b600060208284031215611d8757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611e0457611e04611d8e565b604052919050565b600082601f830112611e1d57600080fd5b813567ffffffffffffffff811115611e3757611e37611d8e565b611e6860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611dbd565b818152846020838601011115611e7d57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611eb057600080fd5b611eb985611be0565b9350611ec760208601611be0565b925060408501359150606085013567ffffffffffffffff811115611eea57600080fd5b611ef687828801611e0c565b91505092959194509250565b60008060408385031215611f1557600080fd5b82359150611f2560208401611be0565b90509250929050565b60008083601f840112611f4057600080fd5b50813567ffffffffffffffff811115611f5857600080fd5b6020830191508360208260051b8501011115611c4b57600080fd5b600080600080600080600080600060c08a8c031215611f9157600080fd5b893567ffffffffffffffff80821115611fa957600080fd5b611fb58d838e01611f2e565b909b50995060208c0135915080821115611fce57600080fd5b611fda8d838e01611f2e565b909950975060408c0135915080821115611ff357600080fd5b506120008c828d01611f2e565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b03121561204157600080fd5b883567ffffffffffffffff8082111561205957600080fd5b6120658c838d01611f2e565b909a50985060208b013591508082111561207e57600080fd5b61208a8c838d01611f2e565b909850965060408b01359150808211156120a357600080fd5b506120b08b828c01611f2e565b999c989b509699959896976060870135966080013595509350505050565b600082601f8301126120df57600080fd5b8135602067ffffffffffffffff8211156120fb576120fb611d8e565b8160051b61210a828201611dbd565b928352848101820192828101908785111561212457600080fd5b83870192505b848310156121435782358252918301919083019061212a565b979650505050505050565b600080600080600060a0868803121561216657600080fd5b61216f86611be0565b945061217d60208701611be0565b9350604086013567ffffffffffffffff8082111561219a57600080fd5b6121a689838a016120ce565b945060608801359150808211156121bc57600080fd5b6121c889838a016120ce565b935060808801359150808211156121de57600080fd5b506121eb88828901611e0c565b9150509295509295909350565b600080600080600060a0868803121561221057600080fd5b61221986611be0565b945061222760208701611be0565b93506040860135925060608601359150608086013567ffffffffffffffff81111561225157600080fd5b6121eb88828901611e0c565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a0604082015260006122dc60a08301868861225d565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152600061232760608301848661225d565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561237257600080fd5b6108f682611be0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126123b057600080fd5b83018035915067ffffffffffffffff8211156123cb57600080fd5b602001915036819003821315611c4b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612440576124406123e0565b5060010190565b81835260006020808501808196508560051b810191508460005b878110156124ea57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126124a057600080fd5b8701858101903567ffffffffffffffff8111156124bc57600080fd5b8036038213156124cb57600080fd5b6124d686828461225d565b9a87019a9550505090840190600101612461565b5091979650505050505050565b60a0808252810188905260008960c08301825b8b8110156125455773ffffffffffffffffffffffffffffffffffffffff61253084611be0565b1682526020928301929091019060010161250a565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89111561257e57600080fd5b8860051b9150818a602083013701828103602090810160408501526125a69082018789612447565b60608401959095525050608001529695505050505050565b6000602082840312156125d057600080fd5b815180151581146108f657600080fd5b808201808211156107d9576107d96123e0565b60005b8381101561260e5781810151838201526020016125f6565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161264f8160178501602088016125f3565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161268c8160288401602088016125f3565b01602801949350505050565b60208152600082518060208401526126b78160408501602087016125f3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b8183823760009101908152919050565b80820281158282048414176107d9576107d96123e0565b60008161271f5761271f6123e0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220d4ff1a49185b3c2eaf58aefd333a2a50a107fd10a8faba8e2063893453ad0e1c64736f6c63430008140033", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000e10", - "0xd52c425d569449de3ea8e96b6f4f0056c8b90231a08ce274f929eac5ca5b70c5": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xc9d8eca0788029234fc9f7531913a7be3fed1b0438d68195b63e370bf6ac88b7": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", - "0x0dbd82eed89d73822865d402eb9d73d4609cb01c0aa3d785a17d7a9d0cb5ee06": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", - "0x9d38bd476745c975feef1b204358c9d3e7719e09369f43fb65a1097848fb43d1": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", - "0x89eab0dbc58be726d54f3116480f80e75a19870aa9750471514a47a86f365aef": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" - } - }, - { - "accountName": "keyless Deployer", - "balance": "0", - "nonce": "1", - "address": "0xc0124DeE8494E155eFf900100D2AF4CC0BC9a76e" - }, - { - "accountName": "deployer", - "balance": "100000000000000000000000", - "nonce": "8", - "address": "0x2ECF31eCe36ccaC2d3222A303b1409233ECBB225" - } - ] -} diff --git a/test/config/node.toml b/test/config/node.toml deleted file mode 100644 index f28d43c9..00000000 --- a/test/config/node.toml +++ /dev/null @@ -1,196 +0,0 @@ -IsTrustedSequencer = true - -[Log] -Environment = "development" # "production" or "development" -Level = "debug" -Outputs = ["stderr"] - -[State] -[State.DB] -User = "state_user" -Password = "state_password" -Name = "state_db" -Host = "xlayer-state-db" -Port = "5432" -EnableLog = false -MaxConns = 200 -[State.Batch] -[State.Batch.Constraints] -MaxTxsPerBatch = 300 -MaxBatchBytesSize = 120000 -MaxCumulativeGasUsed = 1125899906842624 -MaxKeccakHashes = 2145 -MaxPoseidonHashes = 252357 -MaxPoseidonPaddings = 135191 -MaxMemAligns = 236585 -MaxArithmetics = 236585 -MaxBinaries = 473170 -MaxSteps = 7570538 -MaxSHA256Hashes = 1596 - -[Pool] -FreeClaimGasLimit = 1500000 -IntervalToRefreshBlockedAddresses = "5m" -EnableWhitelist = false -IntervalToRefreshWhiteAddresses = "1m" -IntervalToRefreshGasPrices = "5s" -MaxTxBytesSize=100132 -MaxTxDataBytesSize=100000 -DefaultMinGasPriceAllowed = 1000000000 -MinAllowedGasPriceInterval = "5m" -PollMinAllowedGasPriceInterval = "15s" -AccountQueue = 64 -GlobalQueue = 1024 -[Pool.EffectiveGasPrice] -Enabled = false -L1GasPriceFactor = 0.25 -ByteGasCost = 16 -ZeroByteGasCost = 4 -NetProfit = 1 -BreakEvenFactor = 1.1 -FinalDeviationPct = 10 -EthTransferGasPrice = 0 -EthTransferL1GasPriceFactor = 0 -L2GasPriceSuggesterFactor = 0.5 -[Pool.DB] -User = "pool_user" -Password = "pool_password" -Name = "pool_db" -Host = "xlayer-pool-db" -Port = "5432" -EnableLog = false -MaxConns = 200 - -[Etherman] -URL = "http://xlayer-mock-l1-network:8545" -ForkIDChunkSize = 20000 -MultiGasProvider = false -[Etherscan] -ApiKey = "" - -[RPC] -Host = "0.0.0.0" -Port = 8123 -ReadTimeout = "60s" -WriteTimeout = "60s" -MaxRequestsPerIPAndSecond = 5000 -SequencerNodeURI = "" -EnableL2SuggestedGasPricePolling = true -GasLimitFactor = 1 -DisableAPIs = [] -[RPC.WebSockets] -Enabled = true -Port = 8133 - -[Synchronizer] -SyncInterval = "1s" -SyncChunkSize = 100 -TrustedSequencerURL = "" # If it is empty or not specified, then the value is read from the smc. -L1SynchronizationMode = "sequential" -[Synchronizer.L1ParallelSynchronization] -MaxClients = 10 -MaxPendingNoProcessedBlocks = 25 -RequestLastBlockPeriod = "5s" -RequestLastBlockTimeout = "5s" -RequestLastBlockMaxRetries = 3 -StatisticsPeriod = "5m" -TimeoutMainLoop = "5m" -RollupInfoRetriesSpacing= "5s" -FallbackToSequentialModeOnSynchronized = false -[Synchronizer.L1ParallelSynchronization.PerformanceWarning] -AceptableInacctivityTime = "5s" -ApplyAfterNumRollupReceived = 10 - -[Sequencer] -DeletePoolTxsL1BlockConfirmations = 100 -DeletePoolTxsCheckInterval = "12h" -TxLifetimeCheckInterval = "10m" -TxLifetimeMax = "3h" -LoadPoolTxsCheckInterval = "500ms" -StateConsistencyCheckInterval = "5s" -[Sequencer.Finalizer] -NewTxsWaitInterval = "100ms" -ForcedBatchesTimeout = "5s" -ForcedBatchesL1BlockConfirmations = 0 -ForcedBatchesCheckInterval = "10s" -L1InfoTreeL1BlockConfirmations = 0 -L1InfoTreeCheckInterval = "10s" -BatchMaxDeltaTimestamp = "20s" -L2BlockMaxDeltaTimestamp = "4s" -ResourceExhaustedMarginPct = 10 -HaltOnBatchNumber = 0 -SequentialBatchSanityCheck = false -SequentialProcessL2Block = true -[Sequencer.Finalizer.Metrics] -Interval = "60m" -EnableLog = true -[Sequencer.StreamServer] -Port = 6900 -Filename = "/datastreamer/datastream.bin" -Version = 1 -ChainID = 1337 -Enabled = false - -[SequenceSender] -WaitPeriodSendSequence = "15s" -LastBatchVirtualizationTimeMaxWaitPeriod = "10s" -L1BlockTimestampMargin = "5s" -MaxTxSizeForL1 = 131072 -MaxBatchesForL1 = 10 -SenderAddress = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" -L2Coinbase = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" -PrivateKey = {Path = "/pk/sequencer.keystore", Password = "testonly"} -[SequenceSender.StreamClient] -Server = "xlayer-sequencer:6900" - -[Aggregator] -Host = "0.0.0.0" -Port = 50081 -RetryTime = "5s" -VerifyProofInterval = "10s" -TxProfitabilityCheckerType = "acceptall" -TxProfitabilityMinReward = "1.1" -ProofStatePollingInterval = "5s" -SenderAddress = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" -CleanupLockedProofsInterval = "2m" -GeneratingProofCleanupThreshold = "10m" -UpgradeEtrogBatchNumber = 0 -BatchProofL1BlockConfirmations = 2 - -[EthTxManager] -ForcedGas = 0 -PrivateKeys = [ - {Path = "/pk/sequencer.keystore", Password = "testonly"}, - {Path = "/pk/aggregator.keystore", Password = "testonly"} -] - -[L2GasPriceSuggester] -Type = "default" -UpdatePeriod = "10s" -Factor = 0.5 -DefaultGasPriceWei = 1000000000 -MaxGasPriceWei = 0 - -[MTClient] -URI = "xlayer-prover:50061" - -[Executor] -URI = "xlayer-prover:50071" -MaxGRPCMessageSize = 100000000 - -[Metrics] -Host = "0.0.0.0" -Port = 9091 -Enabled = true -ProfilingHost = "0.0.0.0" -ProfilingPort = 6060 -ProfilingEnabled = true - -[HashDB] -User = "prover_user" -Password = "prover_pass" -Name = "prover_db" -Host = "xlayer-state-db" -Port = "5432" -EnableLog = false -MaxConns = 200 diff --git a/test/config/prover.json b/test/config/prover.json deleted file mode 100644 index a98ef8c7..00000000 --- a/test/config/prover.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "runExecutorServer": true, - "runExecutorClient": false, - "runExecutorClientMultithread": false, - - "runHashDBServer": true, - "runHashDBTest": false, - - "runAggregatorServer": false, - "runAggregatorClient": false, - "runAggregatorClientMock": true, - "aggregatorClientMockTimeout": 1, - "proverName": "test-prover", - - "runFileGenBatchProof": false, - "runFileGenAggregatedProof": false, - "runFileGenFinalProof": false, - "runFileProcessBatch": false, - "runFileProcessBatchMultithread": false, - - "runKeccakScriptGenerator": false, - "runKeccakTest": false, - "runStorageSMTest": false, - "runBinarySMTest": false, - "runMemAlignSMTest": false, - "runSHA256Test": false, - "runBlakeTest": false, - - "executeInParallel": true, - "useMainExecGenerated": true, - "saveRequestToFile": false, - "saveInputToFile": false, - "saveDbReadsToFile": false, - "saveDbReadsToFileOnChange": false, - "saveOutputToFile": true, - "saveProofToFile": true, - "saveResponseToFile": false, - "loadDBToMemCache": true, - "opcodeTracer": false, - "logRemoteDbReads": false, - "logExecutorServerResponses": false, - - "proverServerPort": 50051, - "proverServerMockPort": 50052, - "proverServerMockTimeout": 10000000, - "proverClientPort": 50051, - "proverClientHost": "127.0.0.1", - - "executorServerPort": 50071, - "executorROMLineTraces": false, - "executorClientPort": 50071, - "executorClientHost": "127.0.0.1", - - "hashDBServerPort": 50061, - "hashDBURL": "local", - - "aggregatorServerPort": 50081, - "aggregatorClientPort": 50081, - "aggregatorClientHost": "xlayer-aggregator", - - "mapConstPolsFile": false, - "mapConstantsTreeFile": false, - - "inputFile": "input_executor_0.json", - "inputFile2": "input_executor_1.json", - - "keccakScriptFile": "config/scripts/keccak_script.json", - "storageRomFile": "config/scripts/storage_sm_rom.json", - - "outputPath": "output", - - "databaseURL": "postgresql://prover_user:prover_pass@xlayer-state-db:5432/prover_db", - "dbNodesTableName": "state.nodes", - "dbProgramTableName": "state.program", - "dbMultiWrite": true, - "dbFlushInParallel": false, - "dbMTCacheSize": 1024, - "dbProgramCacheSize": 512, - "dbNumberOfPoolConnections": 30, - "dbGetTree": true, - "cleanerPollingPeriod": 600, - "requestsPersistence": 3600, - "maxExecutorThreads": 20, - "maxProverThreads": 8, - "maxHashDBThreads": 8, - "ECRecoverPrecalc": false, - "ECRecoverPrecalcNThreads": 4, - "stateManager": true, - "useAssociativeCache" : false -} - diff --git a/test/config/sql/init_event_db.sql b/test/config/sql/init_event_db.sql deleted file mode 100644 index c45a6ba1..00000000 --- a/test/config/sql/init_event_db.sql +++ /dev/null @@ -1,14 +0,0 @@ -CREATE TYPE level_t AS ENUM ('emerg', 'alert', 'crit', 'err', 'warning', 'notice', 'info', 'debug'); - -CREATE TABLE public.event ( - id BIGSERIAL PRIMARY KEY, - received_at timestamp WITH TIME ZONE default CURRENT_TIMESTAMP, - ip_address inet, - source varchar(32) not null, - component varchar(32), - level level_t not null, - event_id varchar(32) not null, - description text, - data bytea, - json jsonb -); diff --git a/test/config/sql/init_prover_db.sql b/test/config/sql/init_prover_db.sql deleted file mode 100644 index a4f8616c..00000000 --- a/test/config/sql/init_prover_db.sql +++ /dev/null @@ -1,15 +0,0 @@ -CREATE DATABASE prover_db; -\connect prover_db; - -CREATE SCHEMA state; - -CREATE TABLE state.nodes (hash BYTEA PRIMARY KEY, data BYTEA NOT NULL); -CREATE TABLE state.program (hash BYTEA PRIMARY KEY, data BYTEA NOT NULL); - -CREATE USER prover_user with password 'prover_pass'; -ALTER DATABASE prover_db OWNER TO prover_user; -ALTER SCHEMA state OWNER TO prover_user; -ALTER SCHEMA public OWNER TO prover_user; -ALTER TABLE state.nodes OWNER TO prover_user; -ALTER TABLE state.program OWNER TO prover_user; -ALTER USER prover_user SET SEARCH_PATH=state; diff --git a/test/config/test-member.keystore b/test/config/test-member.keystore index 96b662b7..36adf8bc 100644 --- a/test/config/test-member.keystore +++ b/test/config/test-member.keystore @@ -1 +1 @@ -{"address":"f39fd6e51aad88f6f4ce6ab8827279cfffb92266","crypto":{"cipher":"aes-128-ctr","ciphertext":"d005030a7684f3adad2447cbb27f63039eec2224c451eaa445de0d90502b9f3d","cipherparams":{"iv":"dc07a54bc7e388efa89c34d42f2ebdb4"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"cf2ec55ecae11171de575112cfb16963570533a9c46fb774473ceb11519eb24a"},"mac":"3eb180d405a5da6e462b2adc00091c14856c91d574bf27348714506357d6e177"},"id":"035454db-6b6d-477f-8a79-ce24c10b185f","version":3} \ No newline at end of file +{"version":3,"id":"71b028b6-9b1d-4f4c-9e66-31c94a6eb679","address":"70997970c51812dc3a010c7d01b50e0d17dc79c8","crypto":{"ciphertext":"985d5dc5f7750fc4ad0ad0d370486870016bb97e00ef1f7b146d6ad95d456861","cipherparams":{"iv":"f51b18b9f45872f71c3578513fca6cb0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"6253e2d8a71e4808dd11143329cfea467cabb37ac1e1e55dbc0dd90ff22524a7","n":8192,"r":8,"p":1},"mac":"922f741e84201fc7c17bbf9fae5dba6c04a2a99a7268998b5a0268aa690004be"}} \ No newline at end of file diff --git a/test/config/test.dev.toml b/test/config/test.dev.toml index 26ec5efc..5e08237b 100644 --- a/test/config/test.dev.toml +++ b/test/config/test.dev.toml @@ -1,13 +1,13 @@ PrivateKey = {Path = "config/test-member.keystore", Password = "testonly"} [L1] -WsURL = "wss://rootchain.hardfork.dev/ws" -RpcURL = "https://rootchain.hardfork.dev/" +RpcURL = "wss://rootchain.hardfork.dev/ws" PolygonValidiumAddress = "0x0775AAFB6dD38417581F7C583053Fa3B78FD4FD1" DataCommitteeAddress = "0xE660928f13F51bEbb553063A1317EDC0e7038949" Timeout = "1m" RetryPeriod = "5s" - +TrackSequencer = true +TrackSequencerPollInterval = "1m" [Log] Environment = "development" # "production" or "development" diff --git a/test/config/test.docker.toml b/test/config/test.docker.toml index 0d159678..8a74271b 100644 --- a/test/config/test.docker.toml +++ b/test/config/test.docker.toml @@ -1,13 +1,14 @@ PrivateKey = {Path = "/pk/test-member.keystore", Password = "testonly"} [L1] -WsURL = "ws://xlayer-mock-l1-network:8546" -RpcURL = "http://xlayer-mock-l1-network:8545" -PolygonValidiumAddress = "0x975725832B4909Aab87D3604A0b501569dbBE7A9" -DataCommitteeAddress = "0x2f08F654B896208dD968aFdAEf733edC5FF62c03" +RpcURL = "ws://l1:8546" +PolygonValidiumAddress = "0x8dAF17A20c9DBA35f005b6324F493785D239719d" +DataCommitteeAddress = "0x68B1D87F95878fE05B998F19b66F4baba5De1aed" Timeout = "3m" RetryPeriod = "5s" BlockBatchSize = 32 +TrackSequencer = true +TrackSequencerPollInterval = "1m" [Log] Environment = "development" # "production" or "development" @@ -18,7 +19,7 @@ Outputs = ["stderr"] User = "committee_user" Password = "committee_password" Name = "committee_db" -Host = "xlayer-data-availability-db" +Host = "cdk-data-availability-db" Port = "5432" EnableLog = false MaxConns = 200 diff --git a/test/config/test.local.toml b/test/config/test.local.toml index 6e408764..b19a167b 100644 --- a/test/config/test.local.toml +++ b/test/config/test.local.toml @@ -1,13 +1,14 @@ PrivateKey = {Path = "config/test-member.keystore", Password = "testonly"} [L1] -WsURL = "ws://127.0.0.1:8546" -RpcURL = "http://127.0.0.1:8545" -PolygonValidiumAddress = "0x975725832B4909Aab87D3604A0b501569dbBE7A9" -DataCommitteeAddress = "0x2f08F654B896208dD968aFdAEf733edC5FF62c03" +RpcURL = "ws://127.0.0.1:8546" +PolygonValidiumAddress = "0x8dAF17A20c9DBA35f005b6324F493785D239719d" +DataCommitteeAddress = "0x68B1D87F95878fE05B998F19b66F4baba5De1aed" Timeout = "3m" RetryPeriod = "5s" BlockBatchSize = 8 +TrackSequencer = true +TrackSequencerPollInterval = "1m" [Log] Environment = "development" # "production" or "development" diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 66085095..87e02ca5 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -1,15 +1,15 @@ version: "3.5" networks: default: - name: xlayer + name: cdk-data-availability services: - xlayer-data-availability: - container_name: xlayer-data-availability + cdk-data-availability: + container_name: cdk-data-availability restart: unless-stopped depends_on: - xlayer-data-availability-db: + cdk-data-availability-db: condition: service_healthy image: xlayer-data-availability deploy: @@ -28,8 +28,8 @@ services: - "-c" - "/app/xlayer-data-availability run --cfg /app/config.toml" - xlayer-data-availability-db: - container_name: xlayer-data-availability-db + cdk-data-availability-db: + container_name: cdk-data-availability-db restart: unless-stopped image: postgres healthcheck: @@ -48,9 +48,9 @@ services: - "-N" - "500" - xlayer-mock-l1-network: - container_name: xlayer-mock-l1-network - image: zjg555543/geth:v0.3.0_20240320_00 + l1: + container_name: l1 + image: hermeznetwork/geth-cdk-validium-contracts:v0.0.4 healthcheck: test: [ "CMD-SHELL", "geth attach --datadir /geth_data --exec eth.blockNumber" ] interval: 10s @@ -80,72 +80,3 @@ services: - "--syncmode" - "full" - "--rpc.allow-unprotected-txs" - -##### xlayer-node components ##### - - xlayer-state-db: - container_name: xlayer-state-db - image: postgres - deploy: - resources: - limits: - memory: 2G - reservations: - memory: 1G - ports: - - 5432:5432 - volumes: - - ./config/sql/init_prover_db.sql:/docker-entrypoint-initdb.d/init.sql - environment: - - POSTGRES_USER=state_user - - POSTGRES_PASSWORD=state_password - - POSTGRES_DB=state_db - command: ["postgres", "-N", "500"] - - xlayer-pool-db: - container_name: xlayer-pool-db - image: postgres - deploy: - resources: - limits: - memory: 2G - reservations: - memory: 1G - ports: - - 5433:5432 - environment: - - POSTGRES_USER=pool_user - - POSTGRES_PASSWORD=pool_password - - POSTGRES_DB=pool_db - command: ["postgres", "-N", "500"] - - xlayer-prover: - container_name: xlayer-prover - platform: linux/amd64 - image: hermeznetwork/zkevm-prover:v5.0.3 - ports: - - 50061:50061 # MT - - 50071:50071 # Executor - environment: - - EXPERIMENTAL_DOCKER_DESKTOP_FORCE_QEMU=1 - volumes: - - ./config/prover.json:/usr/src/app/config.json - command: > - zkProver -c /usr/src/app/config.json - - xlayer-node: - container_name: xlayer-node - image: okexchain/x1-node:origin_zjg_rebranding-xlayer_20240320035849_c631dc6e - ports: - - 8123:8123 - - 61090:61090 - volumes: - - ./config/sequencer.keystore:/pk/sequencer.keystore - - ./config/aggregator.keystore:/pk/aggregator.keystore - - ./config/node.toml:/app/config.toml - - ./config/genesis.json:/app/genesis.json - command: - - "/bin/sh" - - "-c" - - "/app/xlayer-node approve --network custom --custom-network-file /app/genesis.json --am 115792089237316195423570985008687907853269984665640564039457584007913129639935 -y --cfg /app/config.toml --key-store-path /pk/sequencer.keystore --password testonly && - /app/xlayer-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components \"synchronizer,rpc,sequencer,sequence-sender,aggregator,eth-tx-manager,l2gaspricer\"" diff --git a/test/e2e/datacommittee_test.go b/test/e2e/datacommittee_test.go deleted file mode 100644 index f4381f60..00000000 --- a/test/e2e/datacommittee_test.go +++ /dev/null @@ -1,380 +0,0 @@ -package e2e - -import ( - "context" - "crypto/ecdsa" - "encoding/json" - "fmt" - "math/big" - "os" - "os/exec" - "sort" - "strconv" - "strings" - "testing" - "time" - - "github.com/0xPolygon/cdk-data-availability/config" - cTypes "github.com/0xPolygon/cdk-data-availability/config/types" - "github.com/0xPolygon/cdk-data-availability/db" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygondatacommittee" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygonvalidium" - "github.com/0xPolygon/cdk-data-availability/log" - "github.com/0xPolygon/cdk-data-availability/rpc" - "github.com/0xPolygon/cdk-data-availability/synchronizer" - "github.com/0xPolygon/cdk-data-availability/test/operations" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - eTypes "github.com/ethereum/go-ethereum/core/types" - - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const ( - nSignatures = 2 - dacMembersCount = 3 - ksFile = "/tmp/pkey" - cfgFile = "/tmp/dacnodeconfigfile.json" - ksPass = "pass" - dacNodeContainer = "xlayer-data-availability" - stopDacs = true -) - -func TestDataCommittee(t *testing.T) { - // Setup - var err error - if testing.Short() { - t.Skip() - } - ctx := context.Background() - defer func() { - if stopDacs { - require.NoError(t, operations.Teardown()) - } - }() - err = operations.Teardown() - require.NoError(t, err) - require.NoError(t, err) - err = operations.Setup() - require.NoError(t, err) - time.Sleep(5 * time.Second) - authL2, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL2ChainID) - require.NoError(t, err) - authL1, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) - require.NoError(t, err) - clientL2, err := ethclient.Dial(operations.DefaultL2NetworkURL) - require.NoError(t, err) - clientL1, err := ethclient.Dial(operations.DefaultL1NetworkURL) - require.NoError(t, err) - - // The default sequencer URL is incorrect, set it to match the docker container - validiumContract, err := polygonvalidium.NewPolygonvalidium( - common.HexToAddress(operations.DefaultL1CDKValidiumSmartContract), - clientL1, - ) - require.NoError(t, err) - _, err = validiumContract.SetTrustedSequencerURL(authL1, "http://xlayer-node:8123") - require.NoError(t, err) - - dacSC, err := polygondatacommittee.NewPolygondatacommittee( - common.HexToAddress(operations.DefaultL1DataCommitteeContract), - clientL1, - ) - require.NoError(t, err) - - // Register committe with N / M signatures - membs := members{} - addrsBytes := []byte{} - urls := []string{} - for i := 0; i < dacMembersCount; i++ { - pk, err := crypto.GenerateKey() - require.NoError(t, err) - membs = append(membs, member{ - addr: crypto.PubkeyToAddress(pk.PublicKey), - pk: pk, - url: fmt.Sprintf("http://xlayer-data-availability-%d:420%d", i, i), - i: i, - }) - } - sort.Sort(membs) - for _, m := range membs { - addrsBytes = append(addrsBytes, m.addr.Bytes()...) - urls = append(urls, m.url) - } - tx, err := dacSC.SetupCommittee(authL1, big.NewInt(nSignatures), urls, addrsBytes) - if err != nil { - for _, m := range membs { - fmt.Println(m.addr) - } - } - require.NoError(t, err) - err = operations.WaitTxToBeMined(ctx, clientL1, tx, operations.DefaultTimeoutTxToBeMined) - require.NoError(t, err) - - var runningDacs []member - - defer func() { - if !stopDacs { - return - } - for _, m := range runningDacs { - stopDACMember(t, m) - } - // Remove tmp files - assert.NoError(t, - exec.Command("rm", cfgFile).Run(), - ) - assert.NoError(t, - exec.Command("rm", ksFile).Run(), - ) - // FIXME: for some reason rmdir is failing - _ = exec.Command("rmdir", "-rf", ksFile+"_").Run() - }() - - // pick one to start later - startCount := len(membs) - 1 - delayedMember := membs[startCount] - - // Start DAC nodes & DBs (except for delayed member) - for i := 0; i < startCount; i++ { - startDACMember(t, membs[i]) - runningDacs = append(runningDacs, membs[i]) - } - - // Send txs - nTxs := 10 - amount := big.NewInt(10000) - toAddress := common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8") - _, err = clientL2.BalanceAt(ctx, authL2.From, nil) - require.NoError(t, err) - _, err = clientL2.PendingNonceAt(ctx, authL2.From) - require.NoError(t, err) - - gasLimit, err := clientL2.EstimateGas(ctx, ethereum.CallMsg{From: authL2.From, To: &toAddress, Value: amount}) - require.NoError(t, err) - - gasPrice, err := clientL2.SuggestGasPrice(ctx) - require.NoError(t, err) - - nonce, err := clientL2.PendingNonceAt(ctx, authL2.From) - require.NoError(t, err) - - txs := make([]*eTypes.Transaction, 0, nTxs) - for i := 0; i < nTxs; i++ { - tx := eTypes.NewTransaction(nonce+uint64(i), toAddress, amount, gasLimit, gasPrice, nil) - log.Infof("generating tx %d / %d: %s", i+1, nTxs, tx.Hash().Hex()) - txs = append(txs, tx) - } - - startedIndices := []int{} - for i := 0; i < len(membs); i++ { - startedIndices = append(startedIndices, membs[i].i) - } - - // Wait for verification - // FIXME: Confirmation level should be higher here, but somehow the zkevm-node container is currently - // having issues sync'ing during github CI. Increase the confirmation level when this is solved. - _, err = operations.ApplyL2Txs(ctx, txs, authL2, clientL2, operations.TrustedConfirmationLevel) - if err != nil { - operations.CollectDockerLogs(startedIndices) - } - require.NoError(t, err) - - startDACMember(t, delayedMember) // start the delayed one, it should catch up through synchronization - runningDacs = append(runningDacs, delayedMember) - - // allow the member to startup and synchronize - log.Infof("waiting for delayed member %d to synchronize...", delayedMember.i) - <-time.After(20 * time.Second) - - iter, err := getSequenceBatchesEventIterator(clientL1) - require.NoError(t, err) - defer func() { _ = iter.Close() }() - - // All the events should be present in DACs - for iter.Next() { - expectedKeys, err := getSequenceBatchesKeys(clientL1, iter.Event) - require.NoError(t, err) - for _, m := range membs { - // Each member (including m0) should have all the keys - for _, expected := range expectedKeys { - actual, err := getOffchainDataKeys(m, expected) - require.NoError(t, err) - require.Equal(t, expected, actual) - } - } - } -} - -func getSequenceBatchesEventIterator(clientL1 *ethclient.Client) (*polygonvalidium.PolygonvalidiumSequenceBatchesIterator, error) { - // Get the expected data keys of the batches from what was submitted to L1 - cdkValidium, err := polygonvalidium.NewPolygonvalidium(common.HexToAddress(operations.DefaultL1CDKValidiumSmartContract), clientL1) - if err != nil { - return nil, err - } - // iterate over all events that were generated - iter, err := cdkValidium.FilterSequenceBatches(&bind.FilterOpts{Start: 0, Context: context.Background()}, nil) - if err != nil { - return nil, err - } - return iter, nil -} - -func getSequenceBatchesKeys(clientL1 *ethclient.Client, event *polygonvalidium.PolygonvalidiumSequenceBatches) ([]common.Hash, error) { - ctx := context.Background() - tx, _, err := clientL1.TransactionByHash(ctx, event.Raw.TxHash) - if err != nil { - return nil, err - } - txData := tx.Data() - keys, err := synchronizer.UnpackTxData(txData) - return keys, err -} - -func getOffchainDataKeys(m member, tx common.Hash) (common.Hash, error) { - testUrl := fmt.Sprintf("http://127.0.0.1:420%d", m.i) - mc := newTestClient(testUrl, m.addr) - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - data, err := mc.client.GetOffChainData(ctx, tx) - if err != nil { - return common.Hash{}, err - } - return crypto.Keccak256Hash(data), nil -} - -type member struct { - addr common.Address - pk *ecdsa.PrivateKey - url string - i int -} -type members []member - -func (s members) Len() int { return len(s) } -func (s members) Less(i, j int) bool { - return strings.ToUpper(s[i].addr.Hex()) < strings.ToUpper(s[j].addr.Hex()) -} -func (s members) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -func createKeyStore(pk *ecdsa.PrivateKey, outputDir, password string) error { - ks := keystore.NewKeyStore(outputDir+"_", keystore.StandardScryptN, keystore.StandardScryptP) - _, err := ks.ImportECDSA(pk, password) - if err != nil { - return err - } - fileNameB, err := exec.Command("ls", outputDir+"_/").CombinedOutput() - fileName := strings.TrimSuffix(string(fileNameB), "\n") - if err != nil { - fmt.Println(fileName) - return err - } - out, err := exec.Command("mv", outputDir+"_/"+fileName, outputDir).CombinedOutput() - if err != nil { - fmt.Println(string(out)) - return err - } - return nil -} - -func startDACMember(t *testing.T, m member) { - dacNodeConfig := config.Config{ - L1: config.L1Config{ - WsURL: "ws://xlayer-mock-l1-network:8546", - RpcURL: "http://xlayer-mock-l1-network:8545", - PolygonValidiumAddress: operations.DefaultL1CDKValidiumSmartContract, - DataCommitteeAddress: operations.DefaultL1DataCommitteeContract, - Timeout: cTypes.Duration{Duration: time.Second}, - RetryPeriod: cTypes.Duration{Duration: time.Second}, - }, - PrivateKey: cTypes.KeystoreFileConfig{ - Path: ksFile, - Password: ksPass, - }, - DB: db.Config{ - Name: "committee_db", - User: "committee_user", - Password: "committee_password", - Host: "xlayer-data-availability-db-" + strconv.Itoa(m.i), - Port: "5432", - EnableLog: false, - MaxConns: 10, - }, - RPC: rpc.Config{ - Host: "0.0.0.0", - MaxRequestsPerIPAndSecond: 100, - }, - Log: log.Config{ - Level: "debug", - }, - } - - // Run the DB - dbCmd := exec.Command( - "docker", "run", "-d", - "--name", dacNodeConfig.DB.Host, - "-e", "POSTGRES_DB=committee_db", - "-e", "POSTGRES_PASSWORD=committee_password", - "-e", "POSTGRES_USER=committee_user", - "-p", fmt.Sprintf("553%d:5432", m.i), - "--network", "xlayer", - "postgres", "-N", "500", - ) - out, err := dbCmd.CombinedOutput() - require.NoError(t, err, string(out)) - log.Infof("DAC DB %d started", m.i) - time.Sleep(time.Second * 2) - - // Set correct port - port := 4200 + m.i - dacNodeConfig.RPC.Port = port - - // Write config file - file, err := json.MarshalIndent(dacNodeConfig, "", " ") - require.NoError(t, err) - err = os.WriteFile(cfgFile, file, 0644) - require.NoError(t, err) - // Write private key keystore file - err = createKeyStore(m.pk, ksFile, ksPass) - require.NoError(t, err) - // Run DAC node - cmd := exec.Command( - "docker", "run", "-d", - "-p", fmt.Sprintf("%d:%d", port, port), - "--name", "xlayer-data-availability-"+strconv.Itoa(m.i), - "-v", cfgFile+":/app/config.json", - "-v", ksFile+":"+ksFile, - "--network", "xlayer", - dacNodeContainer, - "/bin/sh", "-c", - "/app/xlayer-data-availability run --cfg /app/config.json", - ) - out, err = cmd.CombinedOutput() - require.NoError(t, err, string(out)) - log.Infof("DAC node %d started", m.i) - time.Sleep(time.Second * 5) -} - -func stopDACMember(t *testing.T, m member) { - out, err := exec.Command( - "docker", "kill", "xlayer-data-availability-"+strconv.Itoa(m.i), - ).CombinedOutput() - assert.NoError(t, err, string(out)) - out, err = exec.Command( - "docker", "rm", "xlayer-data-availability-"+strconv.Itoa(m.i), - ).CombinedOutput() - assert.NoError(t, err, string(out)) - out, err = exec.Command( - "docker", "kill", "xlayer-data-availability-db-"+strconv.Itoa(m.i), - ).CombinedOutput() - assert.NoError(t, err, string(out)) - out, err = exec.Command( - "docker", "rm", "xlayer-data-availability-db-"+strconv.Itoa(m.i), - ).CombinedOutput() - assert.NoError(t, err, string(out)) -} diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 4e98a9cc..f6d9c9fc 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -19,7 +19,7 @@ import ( func initTest(t *testing.T) (*testClient, *ecdsa.PrivateKey) { const ( url = "http://localhost:8444" - memberAddr = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + memberAddr = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" privKeyPath = "../config/sequencer.keystore" privKeyPass = "testonly" ) @@ -49,7 +49,7 @@ func TestSignSequence(t *testing.T) { unexpectedSenderPrivKey, err := crypto.GenerateKey() require.NoError(t, err) - unexpectedSenderSignedSequence, err := expectedSequence.Sign(unexpectedSenderPrivKey) + unexpectedSenderSignature, err := expectedSequence.Sign(unexpectedSenderPrivKey) require.NoError(t, err) tSequences := []testSequences{ { @@ -64,7 +64,7 @@ func TestSignSequence(t *testing.T) { name: "signature_not_from_sender", sequence: types.SignedSequence{ Sequence: expectedSequence, - Signature: unexpectedSenderSignedSequence.Signature, + Signature: unexpectedSenderSignature, }, expectedErr: errors.New("-32000 unauthorized"), }, @@ -85,9 +85,12 @@ func TestSignSequence(t *testing.T) { for _, ts := range tSequences { t.Run(ts.name, func(t *testing.T) { if ts.sequence.Signature == nil { - signedBatch, err := ts.sequence.Sequence.Sign(pk) + signature, err := ts.sequence.Sequence.Sign(pk) require.NoError(t, err) - ts.sequence = *signedBatch + ts.sequence = types.SignedSequence{ + Sequence: ts.sequence.Sequence, + Signature: signature, + } } tc.signSequence(t, &ts.sequence, ts.expectedErr) }) @@ -107,7 +110,7 @@ func newTestClient(url string, addr common.Address) *testClient { } func (tc *testClient) signSequence(t *testing.T, expected *types.SignedSequence, expectedErr error) { - if signature, err := tc.client.SignSequence(*expected); err != nil { + if signature, err := tc.client.SignSequence(context.Background(), *expected); err != nil { assert.Equal(t, expectedErr.Error(), err.Error()) } else { // Verify signature @@ -116,6 +119,7 @@ func (tc *testClient) signSequence(t *testing.T, expected *types.SignedSequence, actualAddr, err := expected.Signer() require.NoError(t, err) assert.Equal(t, tc.dacMemberAddr, actualAddr) + // Check that offchain data has been stored expectedOffchainData := expected.Sequence.OffChainData() for _, od := range expectedOffchainData { @@ -126,5 +130,17 @@ func (tc *testClient) signSequence(t *testing.T, expected *types.SignedSequence, require.NoError(t, err) assert.Equal(t, od.Value, actualData) } + + hashes := make([]common.Hash, len(expectedOffchainData)) + for i, od := range expectedOffchainData { + hashes[i] = od.Key + } + + actualData, err := tc.client.ListOffChainData(context.Background(), hashes) + require.NoError(t, err) + + for _, od := range expectedOffchainData { + assert.Equal(t, od.Value, actualData[od.Key]) + } } } diff --git a/test/e2e/e2ebanana_test.go b/test/e2e/e2ebanana_test.go new file mode 100644 index 00000000..6efa6264 --- /dev/null +++ b/test/e2e/e2ebanana_test.go @@ -0,0 +1,132 @@ +package e2e + +import ( + "context" + "errors" + "testing" + + "github.com/0xPolygon/cdk-data-availability/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSignSequenceBanana(t *testing.T) { + if testing.Short() { + t.Skip() + } + + tc, pk := initTest(t) + type testSequences struct { + name string + sequence types.SignedSequenceBanana + expectedErr error + } + expectedSequence := types.SequenceBanana{ + Batches: []types.Batch{ + { + L2Data: common.FromHex("723473475757adadaddada"), + ForcedGER: common.Hash{}, + ForcedTimestamp: 0, + Coinbase: common.HexToAddress("aabbccddee"), + ForcedBlockHashL1: common.Hash{}, + }, + { + L2Data: common.FromHex("723473475757adadaddada723473475757adadaddada"), + ForcedGER: common.Hash{}, + ForcedTimestamp: 0, + Coinbase: common.HexToAddress("aabbccddee"), + ForcedBlockHashL1: common.Hash{}, + }, + }, + OldAccInputHash: common.HexToHash("abcdef0987654321"), + L1InfoRoot: common.HexToHash("ffddeeaabb09876"), + MaxSequenceTimestamp: 78945, + } + + unexpectedSenderPrivKey, err := crypto.GenerateKey() + require.NoError(t, err) + unexpectedSenderSignature, err := expectedSequence.Sign(unexpectedSenderPrivKey) + require.NoError(t, err) + tSequences := []testSequences{ + { + name: "invalid_signature", + sequence: types.SignedSequenceBanana{ + Sequence: types.SequenceBanana{}, + Signature: common.Hex2Bytes("f00"), + }, + expectedErr: errors.New("-32000 failed to verify sender"), + }, + { + name: "signature_not_from_sender", + sequence: types.SignedSequenceBanana{ + Sequence: expectedSequence, + Signature: unexpectedSenderSignature, + }, + expectedErr: errors.New("-32000 unauthorized"), + }, + { + name: "empty_batch", + sequence: types.SignedSequenceBanana{}, + expectedErr: nil, + }, + { + name: "success", + sequence: types.SignedSequenceBanana{ + Sequence: expectedSequence, + Signature: nil, + }, + expectedErr: nil, + }, + } + for _, ts := range tSequences { + t.Run(ts.name, func(t *testing.T) { + if ts.sequence.Signature == nil { + signature, err := ts.sequence.Sequence.Sign(pk) + require.NoError(t, err) + ts.sequence = types.SignedSequenceBanana{ + Sequence: ts.sequence.Sequence, + Signature: signature, + } + } + tc.signSequenceBanana(t, &ts.sequence, ts.expectedErr) + }) + } +} + +func (tc *testClient) signSequenceBanana(t *testing.T, expected *types.SignedSequenceBanana, expectedErr error) { + if signature, err := tc.client.SignSequenceBanana(context.Background(), *expected); err != nil { + assert.Equal(t, expectedErr.Error(), err.Error()) + } else { + // Verify signature + require.NoError(t, expectedErr) + expected.Signature = signature + actualAddr, err := expected.Signer() + require.NoError(t, err) + assert.Equal(t, tc.dacMemberAddr, actualAddr) + + // Check that offchain data has been stored + expectedOffchainData := expected.Sequence.OffChainData() + for _, od := range expectedOffchainData { + actualData, err := tc.client.GetOffChainData( + context.Background(), + od.Key, + ) + require.NoError(t, err) + assert.Equal(t, od.Value, actualData) + } + + hashes := make([]common.Hash, len(expectedOffchainData)) + for i, od := range expectedOffchainData { + hashes[i] = od.Key + } + + actualData, err := tc.client.ListOffChainData(context.Background(), hashes) + require.NoError(t, err) + + for _, od := range expectedOffchainData { + assert.Equal(t, od.Value, actualData[od.Key]) + } + } +} diff --git a/test/e2e/sequencer_tracker_test.go b/test/e2e/sequencer_tracker_test.go index 75a39a44..9e7907ea 100644 --- a/test/e2e/sequencer_tracker_test.go +++ b/test/e2e/sequencer_tracker_test.go @@ -6,9 +6,10 @@ import ( "testing" "time" + "github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonvalidiumetrog" "github.com/0xPolygon/cdk-data-availability/config" + "github.com/0xPolygon/cdk-data-availability/config/types" "github.com/0xPolygon/cdk-data-availability/etherman" - "github.com/0xPolygon/cdk-data-availability/etherman/smartcontracts/polygonvalidium" "github.com/0xPolygon/cdk-data-availability/sequencer" "github.com/0xPolygon/cdk-data-availability/test/operations" "github.com/ethereum/go-ethereum/common" @@ -20,30 +21,16 @@ import ( func TestSequencerAddrExists(t *testing.T) { err := operations.StartComponent("network") require.NoError(t, err) + defer operations.StopComponent("network") <-time.After(3 * time.Second) // wait for component to start ctx := cli.NewContext(cli.NewApp(), nil, nil) - cfg, err := config.Load(ctx) - require.NoError(t, err) - etm, err := etherman.New(ctx.Context, cfg.L1) - require.NoError(t, err) - - tracker, err := sequencer.NewTracker(cfg.L1, etm) - require.NoError(t, err) - - go tracker.Start(ctx.Context) - defer tracker.Stop() - - addr := tracker.GetAddr() - require.Equal(t, common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"), addr) - - url := tracker.GetUrl() - require.Equal(t, "http://x1-json-rpc:8123", url) // the default clientL1, err := ethclient.Dial(operations.DefaultL1NetworkURL) require.NoError(t, err) - validiumContract, err := polygonvalidium.NewPolygonvalidium( + + validiumContract, err := polygonvalidiumetrog.NewPolygonvalidiumetrog( common.HexToAddress(operations.DefaultL1CDKValidiumSmartContract), clientL1, ) @@ -53,11 +40,44 @@ func TestSequencerAddrExists(t *testing.T) { require.NoError(t, err) newUrl := fmt.Sprintf("http://something-else:%d", rand.Intn(10000)) + + initTracker := func(rpcUrl string) *sequencer.Tracker { + cfg, err := config.Load(ctx) + require.NoError(t, err) + + // Make sure ws is used + cfg.L1.RpcURL = rpcUrl + cfg.L1.TrackSequencerPollInterval = types.NewDuration(100 * time.Millisecond) + + etm, err := etherman.New(ctx.Context, cfg.L1) + require.NoError(t, err) + + tracker := sequencer.NewTracker(cfg.L1, etm) + + tracker.Start(ctx.Context) + + addr := tracker.GetAddr() + require.Equal(t, common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"), addr) + + url := tracker.GetUrl() + require.Equal(t, "http://zkevm-json-rpc:8123", url) // the default + + return tracker + } + + wsTracker := initTracker("ws://127.0.0.1:8546") + defer wsTracker.Stop() + + httpTracker := initTracker("http://127.0.0.1:8545") + defer httpTracker.Stop() + + // Update URL on L1 contract _, err = validiumContract.SetTrustedSequencerURL(authL1, newUrl) require.NoError(t, err) - // give the tracker a sec to get the event + // Give the tracker a sec to get the event <-time.After(2500 * time.Millisecond) - require.Equal(t, newUrl, tracker.GetUrl()) + require.Equal(t, newUrl, wsTracker.GetUrl()) + require.Equal(t, newUrl, httpTracker.GetUrl()) } diff --git a/test/operations/operations.go b/test/operations/operations.go index 405ddd0c..3d78fbc6 100644 --- a/test/operations/operations.go +++ b/test/operations/operations.go @@ -41,22 +41,22 @@ const ( DefaultL2NetworkURL = "http://localhost:8123" // DefaultSequencerPrivateKey is the sequencer private key - DefaultSequencerPrivateKey = "0xde3ca643a52f5543e84ba984c4419ff40dbabd0e483c31c1d09fee8168d68e38" + DefaultSequencerPrivateKey = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" // DefaultL2ChainID is the l2 chain id - DefaultL2ChainID uint64 = 195 + DefaultL2ChainID uint64 = 1001 // DefaultL1ChainID is the l1 chain id DefaultL1ChainID uint64 = 1337 // DefaultL1DataCommitteeContract is the l1 data committee contract address - DefaultL1DataCommitteeContract = "0x2f08F654B896208dD968aFdAEf733edC5FF62c03" + DefaultL1DataCommitteeContract = "0x68B1D87F95878fE05B998F19b66F4baba5De1aed" // DefaultTimeoutTxToBeMined is the timeout for blocks to be mined DefaultTimeoutTxToBeMined = 1 * time.Minute // DefaultL1CDKValidiumSmartContract is the l1 CDK validium contract address - DefaultL1CDKValidiumSmartContract = "0x975725832B4909Aab87D3604A0b501569dbBE7A9" + DefaultL1CDKValidiumSmartContract = "0x8dAF17A20c9DBA35f005b6324F493785D239719d" ) var ( @@ -391,18 +391,32 @@ func ApplyL2Txs(ctx context.Context, txs []*ethTypes.Transaction, auth *bind.Tra // CollectDockerLogs retrieves the logs from Docker containers and writes them into the logger func CollectDockerLogs(dacIndices []int) { - cmd := exec.Command("docker", "logs", "xlayer-node") - out, _ := cmd.CombinedOutput() - log.Debug("DOCKER LOGS ZKEVM-NODE: ", string(out)) - + ReportContainerLogs("zkevm-node", -1) + ReportContainerLogs("l1", 100) + ReportContainerLogs("zkevm-prover", 100) for i := 0; i < len(dacIndices); i++ { idx := dacIndices[i] - nodeName := fmt.Sprintf("xlayer-data-availability-%d", idx) - cmd = exec.Command("docker", "logs", "--tail", "1000", nodeName) + nodeName := fmt.Sprintf("cdk-data-availability-%d", idx) + ReportContainerLogs(nodeName, 100) + } +} - out, _ = cmd.CombinedOutput() - log.Debug(fmt.Sprintf("DOCKER LOGS DAN-%d: ", idx), string(out)) +func ReportContainerLogs(name string, max int) { + args := []string{"logs"} + if max > 0 { + args = append(args, "--tail", fmt.Sprintf("%d", max)) } + args = append(args, name) + + cmd := exec.Command("docker", args...) + out, _ := cmd.CombinedOutput() + log.Debugf("CONTAINER LOG %s:\n%s", name, string(out)) +} + +func ShowRunningDockerContainers() { + cmd := exec.Command("docker", "ps") + out, _ := cmd.CombinedOutput() + log.Debug("CURRENT DOCKER CONTAINERS: \n", string(out)) } // WaitL2BlockToBeVirtualized waits until a L2 Block has been virtualized or the given timeout expires. diff --git a/test/stop-dacs b/test/stop-dacs index 72f5ce3e..3f2dd72c 100755 --- a/test/stop-dacs +++ b/test/stop-dacs @@ -1,6 +1,6 @@ #!/bin/sh -for x in xlayer-data-availability xlayer-data-availability-db; do +for x in cdk-data-availability cdk-validium-data-node-db; do echo $x for i in 0 1 2 3 4; do docker kill $x-$i || true diff --git a/types/factories.go b/types/factories.go deleted file mode 100644 index 097f3fa7..00000000 --- a/types/factories.go +++ /dev/null @@ -1,34 +0,0 @@ -package types - -import ( - "context" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" -) - -// EthClient defines functions that an ethereum rpc client should implement -type EthClient interface { - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) - CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) -} - -// EthClientFactory defines functions for a EthClient factory -type EthClientFactory interface { - CreateEthClient(ctx context.Context, url string) (EthClient, error) -} - -// ethClientFactory is the implementation of EthClientFactory interface -type ethClientFactory struct{} - -// NewEthClientFactory is the constructor of ethClientFactory -func NewEthClientFactory() EthClientFactory { - return ðClientFactory{} -} - -// CreateEthClient creates a new eth client -func (e *ethClientFactory) CreateEthClient(ctx context.Context, url string) (EthClient, error) { - return ethclient.DialContext(ctx, url) -} diff --git a/types/interfaces.go b/types/interfaces.go new file mode 100644 index 00000000..00c8f294 --- /dev/null +++ b/types/interfaces.go @@ -0,0 +1,16 @@ +package types + +import ( + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/common" +) + +// SignedSequenceInterface is the interface that defines the methods that a signed sequence must implement +type SignedSequenceInterface interface { + Signer() (common.Address, error) + OffChainData() []OffChainData + Sign(privateKey *ecdsa.PrivateKey) (ArgBytes, error) + SetSignature([]byte) + GetSignature() []byte +} diff --git a/types/sequence.go b/types/sequence.go index 91258ba7..a8ad10a1 100644 --- a/types/sequence.go +++ b/types/sequence.go @@ -3,8 +3,6 @@ package types import ( "crypto/ecdsa" "errors" - "math/big" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -39,40 +37,9 @@ func (s *Sequence) HashToSign() []byte { // Sign returns a signed sequence by the private key. // Note that what's being signed is the accumulated input hash -func (s *Sequence) Sign(privateKey *ecdsa.PrivateKey) (*SignedSequence, error) { +func (s *Sequence) Sign(privateKey *ecdsa.PrivateKey) ([]byte, error) { hashToSign := s.HashToSign() - sig, err := crypto.Sign(hashToSign, privateKey) - if err != nil { - return nil, err - } - - rBytes := sig[:32] - sBytes := sig[32:64] - vByte := sig[64] - - if strings.ToUpper(common.Bytes2Hex(sBytes)) > "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0" { - magicNumber := common.Hex2Bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141") - sBig := big.NewInt(0).SetBytes(sBytes) - magicBig := big.NewInt(0).SetBytes(magicNumber) - s1 := magicBig.Sub(magicBig, sBig) - sBytes = s1.Bytes() - if vByte == 0 { - vByte = 1 - } else { - vByte = 0 - } - } - vByte += 27 - - actualSignature := []byte{} - actualSignature = append(actualSignature, rBytes...) - actualSignature = append(actualSignature, sBytes...) - actualSignature = append(actualSignature, vByte) - - return &SignedSequence{ - Sequence: *s, - Signature: actualSignature, - }, nil + return Sign(privateKey, hashToSign) } // OffChainData returns the data that needs to be stored off chain from a given sequence @@ -107,3 +74,23 @@ func (s *SignedSequence) Signer() (common.Address, error) { } return crypto.PubkeyToAddress(*pubKey), nil } + +// OffChainData returns the data to be stored of the sequence +func (s *SignedSequence) OffChainData() []OffChainData { + return s.Sequence.OffChainData() +} + +// Sign signs the sequence using the privateKey +func (s *SignedSequence) Sign(privateKey *ecdsa.PrivateKey) (ArgBytes, error) { + return s.Sequence.Sign(privateKey) +} + +// SetSignature set signature +func (s *SignedSequence) SetSignature(sign []byte) { + s.Signature = sign +} + +// GetSignature returns signature +func (s *SignedSequence) GetSignature() []byte { + return s.Signature +} diff --git a/types/sequence_test.go b/types/sequence_test.go index 40c2b2b2..1e8eaa66 100644 --- a/types/sequence_test.go +++ b/types/sequence_test.go @@ -43,8 +43,12 @@ func TestSigning(t *testing.T) { } for _, c := range testSequenceCases { for _, pk := range privKeys { - signedSequence, err := c.s.Sign(pk) + signature, err := c.s.Sign(pk) require.NoError(t, err) + signedSequence := &SignedSequence{ + Sequence: c.s, + Signature: signature, + } actualAddr, err := signedSequence.Signer() require.NoError(t, err) expectedAddr := crypto.PubkeyToAddress(pk.PublicKey) @@ -52,3 +56,10 @@ func TestSigning(t *testing.T) { } } } + +func TestGetSetSignature(t *testing.T) { + sut := SignedSequence{} + signature := []byte{1, 2, 3} + sut.SetSignature(signature) + assert.Equal(t, signature, sut.GetSignature()) +} diff --git a/types/sequencebanana.go b/types/sequencebanana.go new file mode 100644 index 00000000..c4d3ea69 --- /dev/null +++ b/types/sequencebanana.go @@ -0,0 +1,129 @@ +package types + +import ( + "crypto/ecdsa" + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/iden3/go-iden3-crypto/keccak256" +) + +// Batch represents the batch data that the sequencer will send to L1 +type Batch struct { + L2Data ArgBytes `json:"L2Data"` + ForcedGER common.Hash `json:"forcedGlobalExitRoot"` + ForcedTimestamp ArgUint64 `json:"forcedTimestamp"` + Coinbase common.Address `json:"coinbase"` + ForcedBlockHashL1 common.Hash `json:"forcedBlockHashL1"` +} + +// SequenceBanana represents the data that the sequencer will send to L1 +// and other metadata needed to build the accumulated input hash aka accInputHash +type SequenceBanana struct { + Batches []Batch `json:"batches"` + OldAccInputHash common.Hash `json:"oldAccInputhash"` + L1InfoRoot common.Hash `json:"l1InfoRoot"` + MaxSequenceTimestamp ArgUint64 `json:"maxSequenceTimestamp"` +} + +// HashToSign returns the accumulated input hash of the sequence. +// Note that this is equivalent to what happens on the smart contract +func (s *SequenceBanana) HashToSign() []byte { + v1 := s.OldAccInputHash.Bytes() + for _, b := range s.Batches { + v2 := b.L2Data + var v3, v4 []byte + if b.ForcedTimestamp > 0 { + v3 = b.ForcedGER.Bytes() + v4 = big.NewInt(0).SetUint64(uint64(b.ForcedTimestamp)).Bytes() + } else { + v3 = s.L1InfoRoot.Bytes() + v4 = big.NewInt(0).SetUint64(uint64(s.MaxSequenceTimestamp)).Bytes() + } + v5 := b.Coinbase.Bytes() + v6 := b.ForcedBlockHashL1.Bytes() + + // Add 0s to make values 32 bytes long + for len(v1) < 32 { + v1 = append([]byte{0}, v1...) + } + v2 = keccak256.Hash(v2) + for len(v3) < 32 { + v3 = append([]byte{0}, v3...) + } + for len(v4) < 8 { + v4 = append([]byte{0}, v4...) + } + for len(v5) < 20 { + v5 = append([]byte{0}, v5...) + } + for len(v6) < 32 { + v6 = append([]byte{0}, v6...) + } + v1 = keccak256.Hash(v1, v2, v3, v4, v5, v6) + } + + return v1 +} + +// Sign returns a signed sequence by the private key. +// Note that what's being signed is the accumulated input hash +func (s *SequenceBanana) Sign(privateKey *ecdsa.PrivateKey) ([]byte, error) { + hashToSign := s.HashToSign() + return Sign(privateKey, hashToSign) +} + +// OffChainData returns the data that needs to be stored off chain from a given sequence +func (s *SequenceBanana) OffChainData() []OffChainData { + od := []OffChainData{} + for _, b := range s.Batches { + od = append(od, OffChainData{ + Key: crypto.Keccak256Hash(b.L2Data), + Value: b.L2Data, + }) + } + return od +} + +// SignedSequenceBanana is a sequence but signed +type SignedSequenceBanana struct { + Sequence SequenceBanana `json:"sequence"` + Signature ArgBytes `json:"signature"` +} + +// Signer returns the address of the signer +func (s *SignedSequenceBanana) Signer() (common.Address, error) { + if len(s.Signature) != signatureLen { + return common.Address{}, errors.New("invalid signature") + } + sig := make([]byte, signatureLen) + copy(sig, s.Signature) + sig[64] -= 27 + pubKey, err := crypto.SigToPub(s.Sequence.HashToSign(), sig) + if err != nil { + return common.Address{}, err + } + return crypto.PubkeyToAddress(*pubKey), nil +} + +// OffChainData returns the data to be stored of the sequence +func (s *SignedSequenceBanana) OffChainData() []OffChainData { + return s.Sequence.OffChainData() +} + +// Sign signs the sequence using the privateKey +func (s *SignedSequenceBanana) Sign(privateKey *ecdsa.PrivateKey) (ArgBytes, error) { + return s.Sequence.Sign(privateKey) +} + +// SetSignature set signature +func (s *SignedSequenceBanana) SetSignature(sign []byte) { + s.Signature = sign +} + +// GetSignature returns signature +func (s *SignedSequenceBanana) GetSignature() []byte { + return s.Signature +} diff --git a/types/sequencebanana_test.go b/types/sequencebanana_test.go new file mode 100644 index 00000000..349cb5aa --- /dev/null +++ b/types/sequencebanana_test.go @@ -0,0 +1,14 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetSetSignatureBanana(t *testing.T) { + sut := SignedSequenceBanana{} + signature := []byte{1, 2, 3} + sut.SetSignature(signature) + assert.Equal(t, signature, sut.GetSignature()) +} diff --git a/types/sign.go b/types/sign.go new file mode 100644 index 00000000..0eb2472c --- /dev/null +++ b/types/sign.go @@ -0,0 +1,31 @@ +package types + +import ( + "crypto/ecdsa" + "errors" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +var ( + // ErrNonCanonicalSignature is returned when the signature is not canonical. + ErrNonCanonicalSignature = errors.New("received non-canonical signature") +) + +// Sign the hashToSIgn with the given privateKey. +func Sign(privateKey *ecdsa.PrivateKey, hashToSign []byte) ([]byte, error) { + sig, err := crypto.Sign(hashToSign, privateKey) + if err != nil { + return nil, err + } + + if strings.ToUpper(common.Bytes2Hex(sig[32:64])) > "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0" { + return nil, ErrNonCanonicalSignature + } + + sig[64] += 27 + + return sig, nil +} diff --git a/types/types.go b/types/types.go index 7474bdb7..6d262d7f 100644 --- a/types/types.go +++ b/types/types.go @@ -15,10 +15,39 @@ const ( hexBitSize64 = 64 ) +// DACStatus contains DAC status info +type DACStatus struct { + Uptime string `json:"uptime"` + Version string `json:"version"` + KeyCount uint64 `json:"key_count"` + BackfillProgress uint64 `json:"backfill_progress"` + OffchainDataGapsExist bool `json:"offchain_data_gaps_exist"` +} + +// BatchKey is the pairing of batch number and data hash of a batch +type BatchKey struct { + Number uint64 + Hash common.Hash +} + // OffChainData represents some data that is not stored on chain and should be preserved type OffChainData struct { - Key common.Hash - Value []byte + Key common.Hash + Value []byte + BatchNum uint64 +} + +// RemoveDuplicateOffChainData removes duplicate off chain data +func RemoveDuplicateOffChainData(ods []OffChainData) []OffChainData { + seen := make(map[common.Hash]struct{}) + result := []OffChainData{} + for _, od := range ods { + if _, ok := seen[od.Key]; !ok { + seen[od.Key] = struct{}{} + result = append(result, od) + } + } + return result } // ArgUint64 helps to marshal uint64 values provided in the RPC requests @@ -26,7 +55,7 @@ type ArgUint64 uint64 // MarshalText marshals into text func (b ArgUint64) MarshalText() ([]byte, error) { - buf := make([]byte, 2) //nolint:gomnd + buf := make([]byte, 2) //nolint:mnd copy(buf, `0x`) buf = strconv.AppendUint(buf, uint64(b), hexBase) return buf, nil diff --git a/types/types_test.go b/types/types_test.go index f49bd2ec..c8e3493b 100644 --- a/types/types_test.go +++ b/types/types_test.go @@ -3,6 +3,8 @@ package types import ( "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -39,3 +41,59 @@ func TestIsHexValid(t *testing.T) { }) } } + +func TestRemoveDuplicateOffChainData(t *testing.T) { + type args struct { + ods []OffChainData + } + tests := []struct { + name string + args args + want []OffChainData + }{ + { + name: "no duplicates", + args: args{ + ods: []OffChainData{ + { + Key: common.BytesToHash([]byte("key1")), + }, + { + Key: common.BytesToHash([]byte("key2")), + }, + }, + }, + want: []OffChainData{ + { + Key: common.BytesToHash([]byte("key1")), + }, + { + Key: common.BytesToHash([]byte("key2")), + }, + }, + }, + { + name: "with duplicates", + args: args{ + ods: []OffChainData{ + { + Key: common.BytesToHash([]byte("key1")), + }, + { + Key: common.BytesToHash([]byte("key1")), + }, + }, + }, + want: []OffChainData{ + { + Key: common.BytesToHash([]byte("key1")), + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, RemoveDuplicateOffChainData(tt.args.ods), "RemoveDuplicateOffChainData(%v)", tt.args.ods) + }) + } +} diff --git a/version.go b/version.go index 8b92bb1c..67d32258 100644 --- a/version.go +++ b/version.go @@ -16,10 +16,16 @@ var ( // PrintVersion prints version info into the provided io.Writer. func PrintVersion(w io.Writer) { - fmt.Fprintf(w, "Version: %s\n", Version) - fmt.Fprintf(w, "Git revision: %s\n", GitRev) - fmt.Fprintf(w, "Git branch: %s\n", GitBranch) - fmt.Fprintf(w, "Go version: %s\n", runtime.Version()) - fmt.Fprintf(w, "Built: %s\n", BuildDate) - fmt.Fprintf(w, "OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH) + fmt.Fprint(w, GetVersionInfo()) +} + +// GetVersionInfo returns version information as a formatted string. +func GetVersionInfo() string { + versionInfo := fmt.Sprintf("Version: %s\n", Version) + versionInfo += fmt.Sprintf("Git revision: %s\n", GitRev) + versionInfo += fmt.Sprintf("Git branch: %s\n", GitBranch) + versionInfo += fmt.Sprintf("Go version: %s\n", runtime.Version()) + versionInfo += fmt.Sprintf("Built: %s\n", BuildDate) + versionInfo += fmt.Sprintf("OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH) + return versionInfo }