diff --git a/.envrc b/.envrc new file mode 100644 index 0000000000..2d576c8ac3 --- /dev/null +++ b/.envrc @@ -0,0 +1,10 @@ +# - Will execute on entry to the containing directory only if authorized with `direnv allow` +# - Requires a recent version of direnv (https://direnv.net/) +# - For quieter direnv output, set `export DIRENV_LOG_FORMAT=` + +# Determine AVALANCHE_VERSION +source ./scripts/versions.sh + +# - Starts an avalanchego dev shell +# - Requires nix (https://github.com/DeterminateSystems/nix-installer?tab=readme-ov-file#install-nix) +use flake "github:ava-labs/avalanchego?ref=${AVALANCHE_VERSION}" diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b444581e62..ee80e2a8b4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: directory: "/" # Location of package manifests schedule: interval: "daily" + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9112587cdc..9047fa9159 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -44,7 +44,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@1b549b9259bda1cb5ddde3b41741a82a2d15a841 #v3.28.13 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -55,7 +55,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@1b549b9259bda1cb5ddde3b41741a82a2d15a841 #v3.28.13 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -69,4 +69,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@1b549b9259bda1cb5ddde3b41741a82a2d15a841 #v3.28.13 diff --git a/.github/workflows/publish_antithesis_images.yml b/.github/workflows/publish_antithesis_images.yml index d941f2fad4..51b8ae5986 100644 --- a/.github/workflows/publish_antithesis_images.yml +++ b/.github/workflows/publish_antithesis_images.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v4 - name: Login to GAR - uses: docker/login-action@v3 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0 with: registry: ${{ env.REGISTRY }} username: _json_key diff --git a/.github/workflows/publish_docker.yml b/.github/workflows/publish_docker.yml index 407b373739..761c4f9bd8 100644 --- a/.github/workflows/publish_docker.yml +++ b/.github/workflows/publish_docker.yml @@ -25,8 +25,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: docker/setup-qemu-action@v3 - - uses: docker/setup-buildx-action@v3 + - uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 #v3.6.0 + - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 #v3.10.0 - name: Build and publish images to DockerHub env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 86fc3de66f..a625bf7981 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,12 +42,17 @@ jobs: echo cd4f08a75577145b8f05245a2975f7c81401d75e9535dcffbb879ee1deefcbf4 tarballs/MacOSX11.3.sdk.tar.xz | sha256sum -c - UNATTENDED=1 ./build.sh echo "$PWD/target/bin" >> "$GITHUB_PATH" + - name: Git checkout workflow event ref for .goreleaser.yml only + uses: actions/checkout@v4 + with: + fetch-depth: 0 + path: goreleaser - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v3 + uses: goreleaser/goreleaser-action@90a3faa9d0182683851fbfa97ca1a2cb983bfca3 #v6.2.1 with: distribution: goreleaser version: v2.5.1 - args: release --clean + args: release --clean --config ../goreleaser/.goreleaser.yml workdir: ./subnet-evm/ env: # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 92f3f6a62f..9f033883f5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,7 +22,7 @@ jobs: with: go-version-file: "go.mod" - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc #v3 with: version: v1.63 working-directory: . @@ -38,6 +38,11 @@ jobs: run: | go mod tidy git diff --exit-code + - name: Ensure consistent avalanchego version + shell: bash + run: | + bash -x ./scripts/update_avalanchego_version.sh + git diff --exit-code unit_test: name: Golang Unit Tests (${{ matrix.os }}) @@ -152,18 +157,15 @@ jobs: shell: bash run: ./scripts/build.sh - name: Run Warp E2E Tests - uses: ava-labs/avalanchego/.github/actions/run-monitored-tmpnet-cmd@v1.11.13 + uses: ava-labs/avalanchego/.github/actions/run-monitored-tmpnet-cmd@3a6bfac46f43ac2d7cc1e3fc8576ff6a8594bafa with: - run: AVALANCHEGO_BUILD_PATH=/tmp/e2e-test/avalanchego ./scripts/run_ginkgo_warp.sh - prometheus_id: ${{ secrets.PROMETHEUS_ID || '' }} + run: ./scripts/run_ginkgo_warp.sh + run_env: AVALANCHEGO_BUILD_PATH=/tmp/e2e-test/avalanchego + artifact_prefix: warp + prometheus_username: ${{ secrets.PROMETHEUS_ID || '' }} prometheus_password: ${{ secrets.PROMETHEUS_PASSWORD || '' }} - loki_id: ${{ secrets.LOKI_ID || '' }} + loki_username: ${{ secrets.LOKI_ID || '' }} loki_password: ${{ secrets.LOKI_PASSWORD || '' }} - - name: Upload tmpnet network dir for warp testing - uses: ava-labs/avalanchego/.github/actions/upload-tmpnet-artifact@v1-actions - if: always() - with: - name: warp-tmpnet-data e2e_load: name: e2e load tests runs-on: ubuntu-latest @@ -183,18 +185,15 @@ jobs: shell: bash run: ./scripts/build.sh - name: Run E2E Load Tests - uses: ava-labs/avalanchego/.github/actions/run-monitored-tmpnet-cmd@v1.11.13 + uses: ava-labs/avalanchego/.github/actions/run-monitored-tmpnet-cmd@3a6bfac46f43ac2d7cc1e3fc8576ff6a8594bafa with: - run: AVALANCHEGO_BUILD_PATH=/tmp/e2e-test/avalanchego ./scripts/run_ginkgo_load.sh - prometheus_id: ${{ secrets.PROMETHEUS_ID || '' }} + run: ./scripts/run_ginkgo_load.sh + run_env: AVALANCHEGO_BUILD_PATH=/tmp/e2e-test/avalanchego + artifact_prefix: load + prometheus_username: ${{ secrets.PROMETHEUS_ID || '' }} prometheus_password: ${{ secrets.PROMETHEUS_PASSWORD || '' }} - loki_id: ${{ secrets.LOKI_ID || '' }} + loki_username: ${{ secrets.LOKI_ID || '' }} loki_password: ${{ secrets.LOKI_PASSWORD || '' }} - - name: Upload tmpnet network dir for load testing - uses: ava-labs/avalanchego/.github/actions/upload-tmpnet-artifact@v1-actions - if: always() - with: - name: load-tmpnet-data test_build_image: name: Image build runs-on: ubuntu-latest diff --git a/.github/workflows/trigger-antithesis.yml b/.github/workflows/trigger-antithesis.yml index f957d26ed6..7afcbdc972 100644 --- a/.github/workflows/trigger-antithesis.yml +++ b/.github/workflows/trigger-antithesis.yml @@ -30,7 +30,7 @@ jobs: name: Run Antithesis runs-on: ubuntu-latest steps: - - uses: antithesishq/antithesis-trigger-action@v0.5 + - uses: antithesishq/antithesis-trigger-action@b7d0c9d1d9316bd4de73a44144c56636ea3a64ba #v0.8 with: notebook_name: avalanche tenant: avalanche diff --git a/.gitignore b/.gitignore index 1ba452b444..d845c24558 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ diffs/ # clone used for antithesis image builds avalanchego/ + +.direnv diff --git a/.goreleaser.yml b/.goreleaser.yml index 62808b512d..e7b4684897 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,3 +1,4 @@ +version: 2 # ref. https://goreleaser.com/customization/build/ builds: - id: subnet-evm @@ -37,3 +38,8 @@ release: github: owner: ava-labs name: subnet-evm + +git: + # Avoid picking the wrong tag when there is an RC tag and a non-RC tag + # pointing to the same commit. + prerelease_suffix: "-rc" diff --git a/Dockerfile b/Dockerfile index 5afa01d5f0..77b3d258e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ ARG AVALANCHEGO_NODE_IMAGE="invalid-image" # ============= Compilation Stage ================ -FROM --platform=$BUILDPLATFORM golang:1.23.6-bullseye AS builder +FROM --platform=$BUILDPLATFORM golang:1.23.6-bookworm AS builder WORKDIR /build diff --git a/README.md b/README.md index 6af11e89ce..8a3acb4c26 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ The Subnet EVM runs in a separate process from the main AvalancheGo process and [v0.7.0] AvalancheGo@v1.12.0-v1.12.1 (Protocol Version: 38) [v0.7.1] AvalancheGo@v1.12.2 (Protocol Version: 39) [v0.7.2] AvalancheGo@v1.12.2/1.13.0-fuji (Protocol Version: 39) +[v0.7.3] AvalancheGo@v1.12.2/1.13.0 (Protocol Version: 39) ``` ## API diff --git a/bin/ginkgo b/bin/ginkgo new file mode 100755 index 0000000000..195b899896 --- /dev/null +++ b/bin/ginkgo @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Ensure the go command is run from the root of the repository so that its go.mod file is used +REPO_ROOT=$(cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd ) +cd "${REPO_ROOT}" + +# If an explicit version is not specified, go run uses the ginkgo version from go.mod +go run github.com/onsi/ginkgo/v2/ginkgo "${@}" diff --git a/bin/tmpnetctl b/bin/tmpnetctl new file mode 100755 index 0000000000..593c4feea4 --- /dev/null +++ b/bin/tmpnetctl @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Ensure the go command is run from the root of the repository +REPO_ROOT=$(cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd ) +cd "${REPO_ROOT}" + +# Set AVALANCHE_VERSION +. ./scripts/versions.sh + +echo "Running tmpnetctl @ ${AVALANCHE_VERSION}" +go run github.com/ava-labs/avalanchego/tests/fixture/tmpnet/tmpnetctl@"${AVALANCHE_VERSION}" "${@}" diff --git a/compatibility.json b/compatibility.json index e2c9603394..c7bc8c4921 100644 --- a/compatibility.json +++ b/compatibility.json @@ -1,5 +1,6 @@ { "rpcChainVMProtocolVersion": { + "v0.7.3": 39, "v0.7.2": 39, "v0.7.1": 39, "v0.7.0": 38 diff --git a/contracts/package-lock.json b/contracts/package-lock.json index b8e16b42a0..105aa55643 100644 --- a/contracts/package-lock.json +++ b/contracts/package-lock.json @@ -2247,10 +2247,11 @@ } }, "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "follow-redirects": "^1.15.6", @@ -7119,10 +7120,11 @@ } }, "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", "dev": true, + "license": "MIT", "dependencies": { "@fastify/busboy": "^2.0.0" }, diff --git a/go.mod b/go.mod index 693b964ec7..6c8c40a695 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.6 require ( github.com/VictoriaMetrics/fastcache v1.12.1 github.com/antithesishq/antithesis-sdk-go v0.3.8 - github.com/ava-labs/avalanchego v1.12.3-rc.1.0.20250326132201-73294af08342 + github.com/ava-labs/avalanchego v1.13.1-0.20250327151600-3a6bfac46f43 github.com/ava-labs/libevm v1.13.14-0.2.0.rc.4 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set/v2 v2.1.0 @@ -32,10 +32,10 @@ require ( go.uber.org/goleak v1.3.0 go.uber.org/mock v0.5.0 go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.32.0 + golang.org/x/crypto v0.35.0 golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e golang.org/x/mod v0.22.0 - golang.org/x/sync v0.10.0 + golang.org/x/sync v0.11.0 golang.org/x/time v0.3.0 golang.org/x/tools v0.29.0 google.golang.org/protobuf v1.35.2 @@ -46,8 +46,8 @@ require ( github.com/DataDog/zstd v1.5.2 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/StephenButtolph/canoto v0.10.0 // indirect - github.com/ava-labs/coreth v0.14.1-rc.3.0.20250326124329-8ee70dc0f37c // indirect + github.com/StephenButtolph/canoto v0.15.0 // indirect + github.com/ava-labs/coreth v0.15.0-rc.1.0.20250331083503-0d68be6b92be // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -101,6 +101,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/huin/goupnp v1.3.0 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -140,7 +141,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect - github.com/supranational/blst v0.3.13 // indirect + github.com/supranational/blst v0.3.14 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect @@ -155,11 +156,11 @@ require ( go.opentelemetry.io/otel/trace v1.22.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.34.0 // indirect + golang.org/x/net v0.36.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/term v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/term v0.29.0 // indirect + golang.org/x/text v0.22.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed // indirect diff --git a/go.sum b/go.sum index 25432615d0..7379242c7c 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5 github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/StephenButtolph/canoto v0.10.0 h1:KdW85TYQXH+gwR8vOxfOUf28TRpkLU+X06Kycg1IR7s= -github.com/StephenButtolph/canoto v0.10.0/go.mod h1:MxppdgKRApRBvIg4ZgO2e14m/NSBjFMuydy97OB/gYY= +github.com/StephenButtolph/canoto v0.15.0 h1:3iGdyTSQZ7/y09WaJCe0O/HIi53ZyTrnmVzfCqt64mM= +github.com/StephenButtolph/canoto v0.15.0/go.mod h1:IcnAHC6nJUfQFVR9y60ko2ecUqqHHSB6UwI9NnBFZnE= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -64,10 +64,10 @@ github.com/antithesishq/antithesis-sdk-go v0.3.8/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/ava-labs/avalanchego v1.12.3-rc.1.0.20250326132201-73294af08342 h1:/LjSP3FxGOzqqfhrgJWIJiPyKOuD7MrvbMpPEvpiAGw= -github.com/ava-labs/avalanchego v1.12.3-rc.1.0.20250326132201-73294af08342/go.mod h1:i93h2n7XHM+Kr+Hqdr8I58sr3KwkpTq7fgL3z3gX2tk= -github.com/ava-labs/coreth v0.14.1-rc.3.0.20250326124329-8ee70dc0f37c h1:02pdeALkBYh6DLGvPrdDzZ2vGpnV8rqcMVdI2SWfm8k= -github.com/ava-labs/coreth v0.14.1-rc.3.0.20250326124329-8ee70dc0f37c/go.mod h1:v0wH5c0rrcVMBFa1NaRGy5AU6EoiL8Dr75C2bedJrew= +github.com/ava-labs/avalanchego v1.13.1-0.20250327151600-3a6bfac46f43 h1:N7C2AEHTSme0+MMa6n0TPDD11VbTqSNeT4eG2UKg610= +github.com/ava-labs/avalanchego v1.13.1-0.20250327151600-3a6bfac46f43/go.mod h1:jSJtHEp/1AGaruY53bQhDxbc/8UXh0n01yNTlggX3wk= +github.com/ava-labs/coreth v0.15.0-rc.1.0.20250331083503-0d68be6b92be h1:CQ4v84fgsxab1a1LVFBUPmZx37eOkeezWjEfjcLcbZY= +github.com/ava-labs/coreth v0.15.0-rc.1.0.20250331083503-0d68be6b92be/go.mod h1:yiTX4Xamyw6vRFZbpFiLsCtxmD+Nb1z8pJ6JJhAufVo= github.com/ava-labs/libevm v1.13.14-0.2.0.rc.4 h1:wnq3x3OE8DnBTBeKFjiywRO/MfnEXWjoSgnZtTQ1LS8= github.com/ava-labs/libevm v1.13.14-0.2.0.rc.4/go.mod h1:+Iol+sVQ1KyoBsHf3veyrBmHCXr3xXRWq6ZXkgVfNLU= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -380,6 +380,8 @@ github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:q 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/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= @@ -604,8 +606,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= -github.com/supranational/blst v0.3.13 h1:AYeSxdOMacwu7FBmpfloBz5pbFXDmJL33RuwnKtmTjk= -github.com/supranational/blst v0.3.13/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= +github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= @@ -690,8 +692,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= 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= @@ -776,8 +778,8 @@ golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qx 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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= +golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= 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= @@ -801,8 +803,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ 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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -870,12 +872,12 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.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= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= 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= @@ -886,8 +888,8 @@ 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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= 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= diff --git a/plugin/evm/client/client.go b/plugin/evm/client/client.go index 53a2122e6a..7d8a73e934 100644 --- a/plugin/evm/client/client.go +++ b/plugin/evm/client/client.go @@ -50,12 +50,17 @@ type client struct { // NewClient returns a Client for interacting with EVM [chain] func NewClient(uri, chain string) Client { requestUri := fmt.Sprintf("%s/ext/bc/%s", uri, chain) + return NewClientWithURL(requestUri) +} + +// NewClientWithURL returns a Client for interacting with EVM [chain] +func NewClientWithURL(url string) Client { return &client{ adminRequester: rpc.NewEndpointRequester( - requestUri + "/admin", + url + "/admin", ), validatorsRequester: rpc.NewEndpointRequester( - requestUri + "/validators", + url + "/validators", ), } } diff --git a/plugin/evm/customrawdb/accessors_metadata_ext.go b/plugin/evm/customrawdb/accessors_metadata_ext.go index 094974c0a2..f4c644bee0 100644 --- a/plugin/evm/customrawdb/accessors_metadata_ext.go +++ b/plugin/evm/customrawdb/accessors_metadata_ext.go @@ -85,7 +85,7 @@ func WritePruningDisabled(db ethdb.KeyValueStore) error { } // HasPruningDisabled returns true if there is a marker present indicating that -// the node has run with pruning disabled at some pooint. +// the node has run with pruning disabled at some point. func HasPruningDisabled(db ethdb.KeyValueStore) (bool, error) { return db.Has(pruningDisabledKey) } diff --git a/plugin/evm/service.md b/plugin/evm/service.md new file mode 100644 index 0000000000..1e102280e8 --- /dev/null +++ b/plugin/evm/service.md @@ -0,0 +1,321 @@ +--- +title: Subnet-EVM API +--- + +[Subnet-EVM](https://github.com/ava-labs/subnet-evm) APIs are identical to +[Coreth](/docs/api-reference/c-chain/api) C-Chain APIs, except Avalanche Specific APIs +starting with `avax`. Subnet-EVM also supports standard Ethereum APIs as well. For more +information about Coreth APIs see [GitHub](https://github.com/ava-labs/coreth). + +Subnet-EVM has some additional APIs that are not available in Coreth. + +## `eth_feeConfig` + +Subnet-EVM comes with an API request for getting fee config at a specific block. You can use this +API to check your activated fee config. + +**Signature:** + +```bash +eth_feeConfig([blk BlkNrOrHash]) -> {feeConfig: json} +``` + +- `blk` is the block number or hash at which to retrieve the fee config. Defaults to the latest block if omitted. + +**Example Call:** + +```bash +curl -X POST --data '{ + "jsonrpc": "2.0", + "method": "eth_feeConfig", + "params": [ + "latest" + ], + "id": 1 +}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt/rpc +``` + +**Example Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "feeConfig": { + "gasLimit": 15000000, + "targetBlockRate": 2, + "minBaseFee": 33000000000, + "targetGas": 15000000, + "baseFeeChangeDenominator": 36, + "minBlockGasCost": 0, + "maxBlockGasCost": 1000000, + "blockGasCostStep": 200000 + }, + "lastChangedAt": 0 + } +} +``` + +## `eth_getChainConfig` + +`eth_getChainConfig` returns the Chain Config of the blockchain. This API is enabled by default with +`internal-blockchain` namespace. + +This API exists on the C-Chain as well, but in addition to the normal Chain Config returned by the +C-Chain `eth_getChainConfig` on `subnet-evm` additionally returns the upgrade config, which specifies +network upgrades activated after the genesis. **Signature:** + +```bash +eth_getChainConfig({}) -> {chainConfig: json} +``` + +**Example Call:** + +```bash +curl -X POST --data '{ + "jsonrpc":"2.0", + "id" :1, + "method" :"eth_getChainConfig", + "params" :[] +}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/Nvqcm33CX2XABS62iZsAcVUkavfnzp1Sc5k413wn5Nrf7Qjt7/rpc +``` + +**Example Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "chainId": 43214, + "feeConfig": { + "gasLimit": 8000000, + "targetBlockRate": 2, + "minBaseFee": 33000000000, + "targetGas": 15000000, + "baseFeeChangeDenominator": 36, + "minBlockGasCost": 0, + "maxBlockGasCost": 1000000, + "blockGasCostStep": 200000 + }, + "allowFeeRecipients": true, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "subnetEVMTimestamp": 0, + "contractDeployerAllowListConfig": { + "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], + "blockTimestamp": 0 + }, + "contractNativeMinterConfig": { + "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], + "blockTimestamp": 0 + }, + "feeManagerConfig": { + "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], + "blockTimestamp": 0 + }, + "upgrades": { + "precompileUpgrades": [ + { + "feeManagerConfig": { + "adminAddresses": null, + "blockTimestamp": 1661541259, + "disable": true + } + }, + { + "feeManagerConfig": { + "adminAddresses": null, + "blockTimestamp": 1661541269 + } + } + ] + } + } +} +``` + +## `eth_getActivePrecompilesAt` + +**DEPRECATED—instead use** [`eth_getActiveRulesAt`](#eth_getactiveprecompilesat). + +`eth_getActivePrecompilesAt` returns activated precompiles at a specific timestamp. If no +timestamp is provided it returns the latest block timestamp. This API is enabled by default with +`internal-blockchain` namespace. + +**Signature:** + +```bash +eth_getActivePrecompilesAt([timestamp uint]) -> {precompiles: []Precompile} +``` + +- `timestamp` specifies the timestamp to show the precompiles active at this time. If omitted it shows precompiles activated at the latest block timestamp. + +**Example Call:** + +```bash +curl -X POST --data '{ + "jsonrpc": "2.0", + "method": "eth_getActivePrecompilesAt", + "params": [], + "id": 1 +}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/Nvqcm33CX2XABS62iZsAcVUkavfnzp1Sc5k413wn5Nrf7Qjt7/rpc +``` + +**Example Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "contractDeployerAllowListConfig": { + "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], + "blockTimestamp": 0 + }, + "contractNativeMinterConfig": { + "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], + "blockTimestamp": 0 + }, + "feeManagerConfig": { + "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], + "blockTimestamp": 0 + } + } +} +``` + +## `eth_getActiveRulesAt` + +`eth_getActiveRulesAt` returns activated rules (precompiles, upgrades) at a specific timestamp. If no +timestamp is provided it returns the latest block timestamp. This API is enabled by default with +`internal-blockchain` namespace. + +**Signature:** + +```bash +eth_getActiveRulesAt([timestamp uint]) -> {rules: json} +``` + +- `timestamp` specifies the timestamp to show the rules active at this time. If omitted it shows rules activated at the latest block timestamp. + +**Example Call:** + +```bash +curl -X POST --data '{ + "jsonrpc": "2.0", + "method": "eth_getActiveRulesAt", + "params": [], + "id": 1 +}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/Nvqcm33CX2XABS62iZsAcVUkavfnzp1Sc5k413wn5Nrf7Qjt7/rpc +``` + +**Example Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "ethRules": { + "IsHomestead": true, + "IsEIP150": true, + "IsEIP155": true, + "IsEIP158": true, + "IsByzantium": true, + "IsConstantinople": true, + "IsPetersburg": true, + "IsIstanbul": true, + "IsCancun": true + }, + "avalancheRules": { + "IsSubnetEVM": true, + "IsDurango": true, + "IsEUpgrade": true + }, + "precompiles": { + "contractNativeMinterConfig": { + "timestamp": 0 + }, + "rewardManagerConfig": { + "timestamp": 1712918700 + }, + "warpConfig": { + "timestamp": 1714158045 + } + } + } +} +``` + +## `validators.getCurrentValidators` + +This API retrieves the list of current validators for the Subnet/L1. It provides detailed information about each validator, including their ID, status, weight, connection, and uptime. + +URL: `http:///ext/bc//validators` + +**Signature:** + +```bash +validators.getCurrentValidators({nodeIDs: []string}) -> {validators: []Validator} +``` + +- `nodeIDs` is an optional parameter that specifies the node IDs of the validators to retrieve. If omitted, all validators are returned. + +**Example Call:** + +```bash +curl -X POST --data '{ + "jsonrpc": "2.0", + "method": "validators.getCurrentValidators", + "params": { + "nodeIDs": [] + }, + "id": 1 +}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/C49rHzk3vLr1w9Z8sY7scrZ69TU4WcD2pRS6ZyzaSn9xA2U9F/validators +``` + +**Example Response:** + +```json +{ + "jsonrpc": "2.0", + "result": { + "validators": [ + { + "validationID": "nESqWkcNXihfdZESS2idWbFETMzatmkoTCktjxG1qryaQXfS6", + "nodeID": "NodeID-P7oB2McjBGgW2NXXWVYjV8JEDFoW9xDE5", + "weight": 20, + "startTimestamp": 1732025492, + "isActive": true, + "isL1Validator": false, + "isConnected": true, + "uptimeSeconds": 36, + "uptimePercentage": 100 + } + ] + }, + "id": 1 +} +``` + +**Response Fields:** + +- `validationID`: (string) Unique identifier for the validation. This returns validation ID for L1s, AddSubnetValidator txID for Subnets. +- `nodeID`: (string) Node identifier for the validator. +- `weight`: (integer) The weight of the validator, often representing stake. +- `startTimestamp`: (integer) UNIX timestamp for when validation started. +- `isActive`: (boolean) Indicates if the validator is active. This returns true if this is L1 validator and has enough continuous subnet staking fees in P-Chain. It always returns true for subnet validators. +- `isL1Validator`: (boolean) Indicates if the validator is a L1 validator or a subnet validator. +- `isConnected`: (boolean) Indicates if the validator node is currently connected to the callee node. +- `uptimeSeconds`: (integer) The number of seconds the validator has been online. +- `uptimePercentage`: (float) The percentage of time the validator has been online. diff --git a/plugin/evm/version.go b/plugin/evm/version.go index d6ccf8d553..1cd4b951a9 100644 --- a/plugin/evm/version.go +++ b/plugin/evm/version.go @@ -11,7 +11,7 @@ var ( // GitCommit is set by the build script GitCommit string // Version is the version of Subnet EVM - Version string = "v0.7.2" + Version string = "v0.7.3" ) func init() { diff --git a/precompile/allowlist/allowlist.go b/precompile/allowlist/allowlist.go index e443f4a204..8cf8425cf3 100644 --- a/precompile/allowlist/allowlist.go +++ b/precompile/allowlist/allowlist.go @@ -82,7 +82,7 @@ func UnpackModifyAllowListInput(input []byte, r Role, useStrictMode bool) (commo } // createAllowListRoleSetter returns an execution function for setting the allow list status of the input address argument to [role]. -// This execution function is speciifc to [precompileAddr]. +// This execution function is specific to [precompileAddr]. func createAllowListRoleSetter(precompileAddr common.Address, role Role) contract.RunStatefulPrecompileFunc { return func(evm contract.AccessibleState, callerAddr, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) { if remainingGas, err = contract.DeductGas(suppliedGas, ModifyAllowListGasCost); err != nil { diff --git a/precompile/contracts/rewardmanager/contract.go b/precompile/contracts/rewardmanager/contract.go index 6af586f0d7..9f405e5b9a 100644 --- a/precompile/contracts/rewardmanager/contract.go +++ b/precompile/contracts/rewardmanager/contract.go @@ -73,7 +73,7 @@ func EnableAllowFeeRecipients(stateDB contract.StateDB) { stateDB.SetState(ContractAddress, rewardAddressStorageKey, allowFeeRecipientsAddressValue) } -// DisableRewardAddress disables rewards and burns them by sending to Blackhole Address. +// DisableFeeRewards disables rewards and burns them by sending to Blackhole Address. func DisableFeeRewards(stateDB contract.StateDB) { stateDB.SetState(ContractAddress, rewardAddressStorageKey, common.BytesToHash(constants.BlackholeAddr.Bytes())) } diff --git a/precompile/contracts/warp/README.md b/precompile/contracts/warp/README.md index f346ed0170..809c44294c 100644 --- a/precompile/contracts/warp/README.md +++ b/precompile/contracts/warp/README.md @@ -77,27 +77,35 @@ Since the predicate is encoded into the [Transaction Access List](https://eips.e Therefore, we use the [Predicate Utils](https://github.com/ava-labs/subnet-evm/blob/master/predicate/Predicate.md) package to encode the actual byte slice of size N into the access list. -### Performance Optimization: C-Chain to Avalanche L1 +### Performance Optimization: Primary Network to Avalanche L1 -For communication between the C-Chain and an L1, as well as broader interactions between the Primary Network and Avalanche L1s, we have implemented special handling for the C-Chain. +The Primary Network has a large validator set compared to most Subnets and L1s, which makes Warp signature collection and verification from the entire Primary Network validator set costly. All Subnets and L1s track at least one blockchain of the Primary Network, so we can instead optimize this by using the validator set of the receiving L1 instead of the Primary Network for certain Warp messages. -The Primary Network has a large validator set, which creates a unique challenge for Avalanche Warp messages. To reach the required stake threshold, numerous signatures would need to be collected and verifying messages from the Primary Network would be computationally costly. However, we have developed a more efficient solution. +#### Subnets -When an Avalanche L1 receives a message from a blockchain on the Primary Network, we use the validator set of the receiving L1 instead of the entire network when validating the message. Note this is NOT possible if an L1 does not validate the Primary Network, in which case the Warp precompile must be configured with `requirePrimaryNetworkSigners`. +Recall that Avalanche Subnet validators must also validate the Primary Network, so it tracks all of the blockchains in the Primary Network (X, C, and P-Chains). -Sending messages from the C-Chain remains unchanged. -However, when L1 XYZ receives a message from the C-Chain, it changes the semantics to the following: +When an Avalanche Subnet receives a message from a blockchain on the Primary Network, we use the validator set of the receiving Subnet instead of the entire network when validating the message. -1. Read the `SourceChainID` of the signed message (C-Chain) -2. Look up the `SubnetID` that validates C-Chain: Primary Network -3. Look up the validator set of L1 XYZ (instead of the Primary Network) and the registered BLS Public Keys of L1 XYZ at the P-Chain height specified by the ProposerVM header -4. Continue Warp Message verification using the validator set of L1 XYZ instead of the Primary Network +Sending messages from the X, C, or P-Chain remains unchanged. +However, when the Subnet receives the message, it changes the semantics to the following: -This means that C-Chain to L1 communication only requires a threshold of stake on the receiving L1 to sign the message instead of a threshold of stake for the entire Primary Network. +1. Read the `SourceChainID` of the signed message +2. Look up the `SubnetID` that validates `SourceChainID`. In this case it will be the Primary Network's `SubnetID` +3. Look up the validator set of the Subnet (instead of the Primary Network) and the registered BLS Public Keys of the Subnet validators at the P-Chain height specified by the ProposerVM header +4. Continue Warp Message verification using the validator set of the Subnet instead of the Primary Network -This assumes that the security of L1 XYZ already depends on the validators of L1 XYZ to behave virtuously. Therefore, requiring a threshold of stake from the receiving L1's validator set instead of the whole Primary Network does not meaningfully change security of the receiving L1. +This means that Primary Network to Subnet communication only requires a threshold of stake on the receiving Subnet to sign the message instead of a threshold of stake for the entire Primary Network. -Note: this special case is ONLY applied during Warp Message verification. The message sent by the Primary Network will still contain the Avalanche C-Chain's blockchainID as the sourceChainID and signatures will be served by querying the C-Chain directly. +Since the security of the Subnet is provided by trust in its validator set, requiring a threshold of stake from the receiving Subnet's validator set instead of the whole Primary Network does not meaningfully change the security of the receiving L1. + +Note: this special case is ONLY applied during Warp Message verification. The message sent by the Primary Network will still contain the blockchainID of the Primary Network chain that sent the message as the sourceChainID and signatures will be served by querying the source chain directly. + +#### L1s + +Avalanche L1s are only required to sync the P-Chain, but are not required to validate the Primary Network. Therefore, **for L1s, this optimization only applies to Warp messages sent by the P-Chain.** The rest of the description of this optimization in the above section applies to L1s. + +Note that **in order to properly verify messages from the C-Chain and X-Chain, the Warp precompile must be configured with `requirePrimaryNetworkSigners` set to `true`**. Otherwise, we will attempt to verify the message signature against the receiving L1's validator set, which is not required to track the C-Chain or X-Chain, and therefore will not in general be able to produce a valid Warp message. ## Design Considerations diff --git a/scripts/actionlint.sh b/scripts/actionlint.sh index bdc3083e6b..dd0a90527a 100755 --- a/scripts/actionlint.sh +++ b/scripts/actionlint.sh @@ -2,6 +2,4 @@ set -euo pipefail -go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.1 - -actionlint +go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.1 "${@}" diff --git a/scripts/dev_shell.sh b/scripts/dev_shell.sh new file mode 100755 index 0000000000..98929e3f80 --- /dev/null +++ b/scripts/dev_shell.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Requires nix to be installed. The determinate systems installer is recommended: +# +# https://github.com/DeterminateSystems/nix-installer?tab=readme-ov-file#install-nix +# + +# Load AVALANCHE_VERSION +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +# shellcheck source=/scripts/versions.sh +source "$SCRIPT_DIR"/versions.sh + +# Start a dev shell with the avalanchego flake +FLAKE="github:ava-labs/avalanchego?ref=${AVALANCHE_VERSION}" +echo "Starting nix shell for ${FLAKE}" +nix develop "${FLAKE}" "${@}" diff --git a/scripts/run_ginkgo_load.sh b/scripts/run_ginkgo_load.sh index 6dd6c58757..208211a067 100755 --- a/scripts/run_ginkgo_load.sh +++ b/scripts/run_ginkgo_load.sh @@ -15,10 +15,6 @@ source "$SUBNET_EVM_PATH"/scripts/constants.sh source "$SUBNET_EVM_PATH"/scripts/versions.sh -# Build ginkgo -# to install the ginkgo binary (required for test build and run) -go install -v github.com/onsi/ginkgo/v2/ginkgo@"${GINKGO_VERSION}" - EXTRA_ARGS=() AVALANCHEGO_BUILD_PATH="${AVALANCHEGO_BUILD_PATH:-}" if [[ -n "${AVALANCHEGO_BUILD_PATH}" ]]; then @@ -26,4 +22,4 @@ if [[ -n "${AVALANCHEGO_BUILD_PATH}" ]]; then echo "Running with extra args:" "${EXTRA_ARGS[@]}" fi -ginkgo -vv --label-filter="${GINKGO_LABEL_FILTER:-}" ./tests/load -- "${EXTRA_ARGS[@]}" +"${SUBNET_EVM_PATH}"/bin/ginkgo -vv --label-filter="${GINKGO_LABEL_FILTER:-}" ./tests/load -- "${EXTRA_ARGS[@]}" diff --git a/scripts/run_ginkgo_precompile.sh b/scripts/run_ginkgo_precompile.sh index 9e626445c3..35d48765b0 100755 --- a/scripts/run_ginkgo_precompile.sh +++ b/scripts/run_ginkgo_precompile.sh @@ -15,15 +15,11 @@ source "$SUBNET_EVM_PATH"/scripts/constants.sh source "$SUBNET_EVM_PATH"/scripts/versions.sh -# Build ginkgo -# to install the ginkgo binary (required for test build and run) -go install -v github.com/onsi/ginkgo/v2/ginkgo@"${GINKGO_VERSION}" - TEST_SOURCE_ROOT=$(pwd) # By default, it runs all e2e test cases! # Use "--ginkgo.skip" to skip tests. # Use "--ginkgo.focus" to select tests. -TEST_SOURCE_ROOT="$TEST_SOURCE_ROOT" ginkgo run -procs=5 tests/precompile \ +TEST_SOURCE_ROOT="$TEST_SOURCE_ROOT" "${SUBNET_EVM_PATH}"/bin/ginkgo run -procs=5 tests/precompile \ --ginkgo.vv \ --ginkgo.label-filter="${GINKGO_LABEL_FILTER:-""}" diff --git a/scripts/run_ginkgo_warp.sh b/scripts/run_ginkgo_warp.sh index 0d7c3abd3a..11e40ffec6 100755 --- a/scripts/run_ginkgo_warp.sh +++ b/scripts/run_ginkgo_warp.sh @@ -16,10 +16,6 @@ source "$SUBNET_EVM_PATH"/scripts/constants.sh source "$SUBNET_EVM_PATH"/scripts/versions.sh -# Build ginkgo -# to install the ginkgo binary (required for test build and run) -go install -v github.com/onsi/ginkgo/v2/ginkgo@"${GINKGO_VERSION}" - EXTRA_ARGS=() AVALANCHEGO_BUILD_PATH="${AVALANCHEGO_BUILD_PATH:-}" if [[ -n "${AVALANCHEGO_BUILD_PATH}" ]]; then @@ -27,4 +23,4 @@ if [[ -n "${AVALANCHEGO_BUILD_PATH}" ]]; then echo "Running with extra args:" "${EXTRA_ARGS[@]}" fi -ginkgo -vv --label-filter="${GINKGO_LABEL_FILTER:-}" ./tests/warp -- "${EXTRA_ARGS[@]}" +"${SUBNET_EVM_PATH}"/bin/ginkgo -vv --label-filter="${GINKGO_LABEL_FILTER:-}" ./tests/warp -- "${EXTRA_ARGS[@]}" diff --git a/scripts/run_prometheus.sh b/scripts/run_prometheus.sh deleted file mode 100755 index dce9ef1e30..0000000000 --- a/scripts/run_prometheus.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Starts a prometheus instance in agent-mode, forwarding to a central -# instance. Intended to enable metrics collection from temporary networks running -# locally and in CI. -# -# The prometheus instance will remain running in the background and will forward -# metrics to the central instance for all tmpnet networks. -# -# To stop it: -# -# $ kill -9 `cat ~/.tmpnet/prometheus/run.pid` && rm ~/.tmpnet/prometheus/run.pid -# - -# e.g., -# PROMETHEUS_ID= PROMETHEUS_PASSWORD= ./scripts/run_prometheus.sh -if ! [[ "$0" =~ scripts/run_prometheus.sh ]]; then - echo "must be run from repository root" - exit 255 -fi - -PROMETHEUS_WORKING_DIR="${HOME}/.tmpnet/prometheus" -PIDFILE="${PROMETHEUS_WORKING_DIR}"/run.pid - -# First check if an agent-mode prometheus is already running. A single instance can collect -# metrics from all local temporary networks. -if pgrep --pidfile="${PIDFILE}" -f 'prometheus.*enable-feature=agent' &> /dev/null; then - echo "prometheus is already running locally with --enable-feature=agent" - exit 0 -fi - -PROMETHEUS_URL="${PROMETHEUS_URL:-https://prometheus-poc.avax-dev.network}" -if [[ -z "${PROMETHEUS_URL}" ]]; then - echo "Please provide a value for PROMETHEUS_URL" - exit 1 -fi - -PROMETHEUS_ID="${PROMETHEUS_ID:-}" -if [[ -z "${PROMETHEUS_ID}" ]]; then - echo "Please provide a value for PROMETHEUS_ID" - exit 1 -fi - -PROMETHEUS_PASSWORD="${PROMETHEUS_PASSWORD:-}" -if [[ -z "${PROMETHEUS_PASSWORD}" ]]; then - echo "Plase provide a value for PROMETHEUS_PASSWORD" - exit 1 -fi - -# This was the LTS version when this script was written. Probably not -# much reason to update it unless something breaks since the usage -# here is only to collect metrics from temporary networks. -VERSION="2.45.3" - -# Ensure the prometheus command is locally available -CMD=prometheus -if ! command -v "${CMD}" &> /dev/null; then - # Try to use a local version - CMD="${PWD}/bin/prometheus" - if ! command -v "${CMD}" &> /dev/null; then - echo "prometheus not found, attempting to install..." - - # Determine the arch - if which sw_vers &> /dev/null; then - echo "on macos, only amd64 binaries are available so rosetta is required on apple silicon machines." - echo "to avoid using rosetta, install via homebrew: brew install prometheus" - DIST=darwin - else - ARCH="$(uname -i)" - if [[ "${ARCH}" != "x86_64" ]]; then - echo "on linux, only amd64 binaries are available. manual installation of prometheus is required." - exit 1 - else - DIST="linux" - fi - fi - - # Install the specified release - PROMETHEUS_FILE="prometheus-${VERSION}.${DIST}-amd64" - URL="https://github.com/prometheus/prometheus/releases/download/v${VERSION}/${PROMETHEUS_FILE}.tar.gz" - curl -s -L "${URL}" | tar zxv -C /tmp > /dev/null - mkdir -p "$(dirname "${CMD}")" - cp /tmp/"${PROMETHEUS_FILE}/prometheus" "${CMD}" - fi -fi - -# Configure prometheus -FILE_SD_PATH="${PROMETHEUS_WORKING_DIR}/file_sd_configs" -mkdir -p "${FILE_SD_PATH}" - -echo "writing configuration..." -cat >"${PROMETHEUS_WORKING_DIR}"/prometheus.yaml < prometheus.log 2>&1 & -echo $! > "${PIDFILE}" -echo "running with pid $(cat "${PIDFILE}")" diff --git a/scripts/run_promtail.sh b/scripts/run_promtail.sh deleted file mode 100755 index 5811dcf06f..0000000000 --- a/scripts/run_promtail.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Starts a promtail instance to collect logs from temporary networks -# running locally and in CI. -# -# The promtail instance will remain running in the background and will forward -# logs to the central instance for all tmpnet networks. -# -# To stop it: -# -# $ kill -9 `cat ~/.tmpnet/promtail/run.pid` && rm ~/.tmpnet/promtail/run.pid -# - -# e.g., -# LOKI_ID= LOKI_PASSWORD= ./scripts/run_promtail.sh -if ! [[ "$0" =~ scripts/run_promtail.sh ]]; then - echo "must be run from repository root" - exit 255 -fi - -PROMTAIL_WORKING_DIR="${HOME}/.tmpnet/promtail" -PIDFILE="${PROMTAIL_WORKING_DIR}"/run.pid - -# First check if promtail is already running. A single instance can -# collect logs from all local temporary networks. -if pgrep --pidfile="${PIDFILE}" &> /dev/null; then - echo "promtail is already running" - exit 0 -fi - -LOKI_URL="${LOKI_URL:-https://loki-poc.avax-dev.network}" -if [[ -z "${LOKI_URL}" ]]; then - echo "Please provide a value for LOKI_URL" - exit 1 -fi - -LOKI_ID="${LOKI_ID:-}" -if [[ -z "${LOKI_ID}" ]]; then - echo "Please provide a value for LOKI_ID" - exit 1 -fi - -LOKI_PASSWORD="${LOKI_PASSWORD:-}" -if [[ -z "${LOKI_PASSWORD}" ]]; then - echo "Plase provide a value for LOKI_PASSWORD" - exit 1 -fi - -# Version as of this writing -VERSION="v2.9.5" - -# Ensure the promtail command is locally available -CMD=promtail -if ! command -v "${CMD}" &> /dev/null; then - # Try to use a local version - CMD="${PWD}/bin/promtail" - if ! command -v "${CMD}" &> /dev/null; then - echo "promtail not found, attempting to install..." - # Determine the arch - if which sw_vers &> /dev/null; then - DIST="darwin-$(uname -m)" - else - ARCH="$(uname -i)" - if [[ "${ARCH}" == "aarch64" ]]; then - ARCH="arm64" - elif [[ "${ARCH}" == "x86_64" ]]; then - ARCH="amd64" - fi - DIST="linux-${ARCH}" - fi - - # Install the specified release - PROMTAIL_FILE="promtail-${DIST}" - ZIP_PATH="/tmp/${PROMTAIL_FILE}.zip" - BIN_DIR="$(dirname "${CMD}")" - URL="https://github.com/grafana/loki/releases/download/${VERSION}/promtail-${DIST}.zip" - curl -L -o "${ZIP_PATH}" "${URL}" - unzip "${ZIP_PATH}" -d "${BIN_DIR}" - mv "${BIN_DIR}/${PROMTAIL_FILE}" "${CMD}" - fi -fi - -# Configure promtail -FILE_SD_PATH="${PROMTAIL_WORKING_DIR}/file_sd_configs" -mkdir -p "${FILE_SD_PATH}" - -echo "writing configuration..." -cat >"${PROMTAIL_WORKING_DIR}"/promtail.yaml < promtail.log 2>&1 & -echo $! > "${PIDFILE}" -echo "running with pid $(cat "${PIDFILE}")" diff --git a/scripts/update_avalanchego_version.sh b/scripts/update_avalanchego_version.sh new file mode 100755 index 0000000000..9ee79ac379 --- /dev/null +++ b/scripts/update_avalanchego_version.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if ! [[ "$0" =~ scripts/update_avalanchego_version.sh ]]; then + echo "must be run from repository root, but got $0" + exit 255 +fi + +# If version is not provided, the existing version in go.mod is assumed +VERSION="${1:-}" + +if [[ -n "${VERSION}" ]]; then + echo "Ensuring AvalancheGo version $VERSION in go.mod" + go get "github.com/ava-labs/avalanchego@${VERSION}" + go mod tidy +fi + +# Discover AVALANCHE_VERSION +. scripts/versions.sh + +# The full SHA is required for versioning custom actions. +CURL_ARGS=(curl -s) +if [[ -n "${GITHUB_TOKEN:-}" ]]; then + # Using an auth token avoids being rate limited when run in CI + CURL_ARGS+=(-H "Authorization: token ${GITHUB_TOKEN}") +fi +CURL_URL="https://api.github.com/repos/ava-labs/avalanchego/commits/${AVALANCHE_VERSION}" +FULL_AVALANCHE_VERSION="$("${CURL_ARGS[@]}" "${CURL_URL}" | grep '"sha":' | head -n1 | cut -d'"' -f4)" + +# Ensure the custom action version matches the avalanche version +WORKFLOW_PATH=".github/workflows/tests.yml" +CUSTOM_ACTION="ava-labs/avalanchego/.github/actions/run-monitored-tmpnet-cmd" +echo "Ensuring AvalancheGo version ${FULL_AVALANCHE_VERSION} for ${CUSTOM_ACTION} custom action in ${WORKFLOW_PATH} " +sed -i.bak "s|\(uses: ${CUSTOM_ACTION}\)@.*|\1@${FULL_AVALANCHE_VERSION}|g" "${WORKFLOW_PATH}" && rm -f "${WORKFLOW_PATH}.bak" diff --git a/scripts/versions.sh b/scripts/versions.sh index 25fa377aab..710885ae37 100755 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -24,5 +24,3 @@ if [[ -z ${AVALANCHE_VERSION:-} ]]; then AVALANCHE_VERSION="${MODULE_HASH::8}" fi fi - -GINKGO_VERSION=${GINKGO_VERSION:-'v2.2.0'} diff --git a/sync/statesync/code_syncer.go b/sync/statesync/code_syncer.go index e08a74bc20..18b1c2b497 100644 --- a/sync/statesync/code_syncer.go +++ b/sync/statesync/code_syncer.go @@ -40,7 +40,7 @@ type CodeSyncerConfig struct { DB ethdb.Database } -// codeSyncer syncs code bytes from the network in a seprate thread. +// codeSyncer syncs code bytes from the network in a separate thread. // Tracks outstanding requests in the DB, so that it will still fulfill them if interrupted. type codeSyncer struct { lock sync.Mutex @@ -194,7 +194,7 @@ func (c *codeSyncer) fulfillCodeRequest(ctx context.Context, codeHashes []common c.lock.Unlock() // Release the lock before writing the batch if err := batch.Write(); err != nil { - return fmt.Errorf("faild to write batch for fulfilled code requests: %w", err) + return fmt.Errorf("failed to write batch for fulfilled code requests: %w", err) } return nil } @@ -224,7 +224,7 @@ func (c *codeSyncer) addCode(codeHashes []common.Hash) error { } // notifyAccountTrieCompleted notifies the code syncer that there will be no more incoming -// code hashes from syncing the account trie, so it only needs to compelete its outstanding +// code hashes from syncing the account trie, so it only needs to complete its outstanding // work. // Note: this allows the worker threads to exit and return a nil error. func (c *codeSyncer) notifyAccountTrieCompleted() { diff --git a/tests/README.md b/tests/README.md index f434f45592..54cc0497d0 100644 --- a/tests/README.md +++ b/tests/README.md @@ -35,3 +35,20 @@ viewed in grafana. The details of configuration and usage for subnet-evm mirror those of avalanchego and the same [documentation](https://github.com/ava-labs/avalanchego/blob/master/tests/fixture/tmpnet/README.md#Monitoring) applies. + +## Optional Dev Shell + +Some activities, such as collecting metrics and logs from the nodes targeted by an e2e +test run, require binary dependencies. One way of making these dependencies available is +to use a nix shell which will give access to the dependencies expected by the test +tooling: + + - Install [nix](https://nixos.org/). The [determinate systems + installer](https://github.com/DeterminateSystems/nix-installer?tab=readme-ov-file#install-nix) + is recommended. + - Use ./scripts/dev_shell.sh to start a nix shell + - Execute the dependency-requiring command (e.g. `ginkgo -v ./tests/warp -- --start-collectors`) + +This repo also defines a `.envrc` file to configure [devenv](https://direnv.net/). With `devenv` +and `nix` installed, a shell at the root of the repo will automatically start a nix dev +shell. diff --git a/utils/metered_cache.go b/utils/metered_cache.go index ee1807e36f..31c47e22b0 100644 --- a/utils/metered_cache.go +++ b/utils/metered_cache.go @@ -56,7 +56,7 @@ func NewMeteredCache(size int, namespace string, updateFrequency uint64) *Metere return mc } -// updateStats updates metrics from fastcache +// updateStatsIfNeeded updates metrics from fastcache func (mc *MeteredCache) updateStatsIfNeeded() { if mc.namespace == "" { return