From 6ce5230f273f34c677550441f8b20cd44762c2b7 Mon Sep 17 00:00:00 2001 From: Maru Newby Date: Mon, 6 May 2024 19:06:30 -0700 Subject: [PATCH] [antithesis] Propose initial test setup --- .../workflows/publish_antithesis_images.yml | 32 ++++++ .github/workflows/tests.yml | 8 ++ .gitignore | 3 + Dockerfile | 6 +- go.mod | 13 ++- go.sum | 26 ++++- scripts/build_antithesis_images.sh | 86 ++++++++++++++ scripts/build_antithesis_workload.sh | 11 ++ scripts/build_docker_image.sh | 5 +- scripts/install_avalanchego_release.sh | 2 +- scripts/tests.build_antithesis_images.sh | 68 +++++++++++ scripts/versions.sh | 2 +- tests/antithesis/Dockerfile.config | 53 +++++++++ tests/antithesis/Dockerfile.node | 65 +++++++++++ tests/antithesis/Dockerfile.workload | 30 +++++ tests/antithesis/gencomposeconfig/main.go | 65 +++++++++++ tests/antithesis/main.go | 106 ++++++++++++++++++ 17 files changed, 569 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/publish_antithesis_images.yml create mode 100755 scripts/build_antithesis_images.sh create mode 100755 scripts/build_antithesis_workload.sh create mode 100755 scripts/tests.build_antithesis_images.sh create mode 100644 tests/antithesis/Dockerfile.config create mode 100644 tests/antithesis/Dockerfile.node create mode 100644 tests/antithesis/Dockerfile.workload create mode 100644 tests/antithesis/gencomposeconfig/main.go create mode 100644 tests/antithesis/main.go diff --git a/.github/workflows/publish_antithesis_images.yml b/.github/workflows/publish_antithesis_images.yml new file mode 100644 index 0000000000..5a835e40a6 --- /dev/null +++ b/.github/workflows/publish_antithesis_images.yml @@ -0,0 +1,32 @@ +name: Publish Antithesis Images + +on: + workflow_dispatch: + push: + branches: + - master + +env: + REGISTRY: us-central1-docker.pkg.dev + REPOSITORY: molten-verve-216720/avalanche-repository + +jobs: + antithesis: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Login to GAR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: _json_key + password: ${{ secrets.ANTITHESIS_GAR_JSON_KEY }} + + - name: Build and publish images + run: bash -x ./scripts/build_antithesis_images.sh + env: + IMAGE_PREFIX: ${{ env.REGISTRY }}/${{ env.REPOSITORY }} + TAG: latest diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7b7299762f..3f0c3a2177 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -253,3 +253,11 @@ jobs: run: scripts/mock.gen.sh - shell: bash run: .github/workflows/check-clean-branch.sh + test_build_antithesis_images: + name: Build Antithesis images + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Check image build for antithesis test setup + shell: bash + run: bash -x scripts/tests.build_antithesis_images.sh diff --git a/.gitignore b/.gitignore index 65fe98d2e3..3d35c8fd93 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,6 @@ cmd/simulator/simulator # goreleaser dist/ + +# clone used for antithesis image builds +avalanchego/ diff --git a/Dockerfile b/Dockerfile index ff30c90589..fb9abab4a5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ # syntax=docker/dockerfile:experimental # ============= Setting up base Stage ================ -# Set required AVALANCHE_VERSION parameter in build image script -ARG AVALANCHE_VERSION +# AVALANCHEGO_NODE_IMAGE needs to identify an existing node image and should include the tag +ARG AVALANCHEGO_NODE_IMAGE # ============= Compilation Stage ================ FROM golang:1.21.9-bullseye AS builder @@ -26,7 +26,7 @@ ARG CURRENT_BRANCH RUN export SUBNET_EVM_COMMIT=$SUBNET_EVM_COMMIT && export CURRENT_BRANCH=$CURRENT_BRANCH && ./scripts/build.sh /build/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy # ============= Cleanup Stage ================ -FROM avaplatform/avalanchego:$AVALANCHE_VERSION AS builtImage +FROM $AVALANCHEGO_NODE_IMAGE AS builtImage # Copy the evm binary into the correct location in the container COPY --from=builder /build/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy /avalanchego/build/plugins/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy diff --git a/go.mod b/go.mod index 4a36447809..e74b9eeb52 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21.9 require ( github.com/VictoriaMetrics/fastcache v1.10.0 - github.com/ava-labs/avalanchego v1.11.5 + github.com/ava-labs/avalanchego v1.11.6-0.20240506185313-bcac3aef13ad github.com/cespare/cp v0.1.0 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set/v2 v2.1.0 @@ -54,7 +54,7 @@ require ( require ( github.com/DataDog/zstd v1.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/ava-labs/coreth v0.13.3-rc.2 // indirect + github.com/ava-labs/coreth v0.13.4-0.20240506124912-82b6c4e91557 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -65,12 +65,16 @@ require ( github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06 // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/compose-spec/compose-go v1.20.2 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/distribution/reference v0.5.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/ethereum/c-kzg-4844 v0.3.1 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.4.1 // indirect @@ -91,6 +95,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/inconshreveable/mousetrap v1.0.0 // indirect github.com/jackpal/gateway v1.0.6 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/klauspost/compress v1.15.15 // indirect @@ -98,12 +103,14 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-shellwords v1.0.12 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pires/go-proxyproto v0.6.2 // indirect @@ -114,7 +121,9 @@ require ( github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/rs/cors v1.7.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/cobra v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/supranational/blst v0.3.11 // indirect diff --git a/go.sum b/go.sum index d62a4975ac..9e87330338 100644 --- a/go.sum +++ b/go.sum @@ -56,10 +56,10 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/avalanchego v1.11.5 h1:3HCE6I1/9BOSrIvwXXuOhVuMGMi926jKhQ+sgU3LEX8= -github.com/ava-labs/avalanchego v1.11.5/go.mod h1:XPNUEh0ezPEW1IV6yo6AwvqjTZSG1twGskDb7dVcIRA= -github.com/ava-labs/coreth v0.13.3-rc.2 h1:lhyQwln6at1DTs1O586dMSAtGtSfQWlt2WH+Z2kgYdQ= -github.com/ava-labs/coreth v0.13.3-rc.2/go.mod h1:4l15XGak3FklhIb7CtlC/1YVwGAfMl83R2zd2N0hNE0= +github.com/ava-labs/avalanchego v1.11.6-0.20240506185313-bcac3aef13ad h1:jyoQE9jlda2CkJrTWZEsGpwlTZLIy2OvVFg7KqWXU5M= +github.com/ava-labs/avalanchego v1.11.6-0.20240506185313-bcac3aef13ad/go.mod h1:kIad6DhZYRRpzssQXdgF9gNuiwLiATVcTiY3cg42XtQ= +github.com/ava-labs/coreth v0.13.4-0.20240506124912-82b6c4e91557 h1:92JWd4u2pqpO551gXUIZ/qDZu3l7vn8jIxX2qRyyFwM= +github.com/ava-labs/coreth v0.13.4-0.20240506124912-82b6c4e91557/go.mod h1:yMIxezDyB/5moKt8LlATlfwR/Z5cmipY3gUQ1SqHvQ0= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -120,6 +120,8 @@ github.com/cockroachdb/pebble v0.0.0-20230906160148-46873a6a7a06/go.mod h1:bynZ3 github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ= +github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= 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= @@ -147,11 +149,17 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2U github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +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.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= @@ -342,6 +350,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: 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/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 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= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= @@ -407,6 +416,8 @@ github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peK github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= +github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -459,6 +470,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +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/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -503,6 +516,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +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.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -512,6 +527,8 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -795,6 +812,7 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/scripts/build_antithesis_images.sh b/scripts/build_antithesis_images.sh new file mode 100755 index 0000000000..2f455acff5 --- /dev/null +++ b/scripts/build_antithesis_images.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Builds docker images for antithesis testing. + +# e.g., +# ./scripts/build_antithesis_images.sh # Build local images +# IMAGE_PREFIX=/ TAG=latest ./scripts/build_antithesis_images.sh # Specify a prefix to enable image push and use a specific tag + +# Directory above this script +SUBNET_EVM_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd ) + +# Allow configuring the clone path to point to a shared and/or existing clone of the avalanchego repo +AVALANCHEGO_CLONE_PATH="${AVALANCHEGO_CLONE_PATH:-${SUBNET_EVM_PATH}/avalanchego}" + +# Specifying an image prefix will ensure the image is pushed after build +IMAGE_PREFIX="${IMAGE_PREFIX:-}" + +TAG="${TAG:-}" +if [[ -z "${TAG}" ]]; then + # Default to tagging with the commit hash + source "${SUBNET_EVM_PATH}"/scripts/constants.sh + TAG="${SUBNET_EVM_COMMIT::8}" +fi + +# The dockerfiles don't specify the golang version to minimize the changes required to bump +# the version. Instead, the golang version is provided as an argument. +GO_VERSION="$(go list -m -f '{{.GoVersion}}')" + +function build_images { + local base_image_name=$1 + local uninstrumented_node_dockerfile=$2 + local avalanche_node_image=$3 + + # Define image names + if [[ -n "${IMAGE_PREFIX}" ]]; then + base_image_name="${IMAGE_PREFIX}/${base_image_name}" + fi + local node_image_name="${base_image_name}-node:${TAG}" + local workload_image_name="${base_image_name}-workload:${TAG}" + local config_image_name="${base_image_name}-config:${TAG}" + + # Define dockerfiles + local base_dockerfile="${SUBNET_EVM_PATH}/tests/antithesis/Dockerfile" + local node_dockerfile="${base_dockerfile}.node" + if [[ "$(go env GOARCH)" == "arm64" ]]; then + # Antithesis instrumentation is only supported on amd64. On apple silicon (arm64), the + # uninstrumented Dockerfile will be used to build the node image to enable local test + # development. + node_dockerfile="${uninstrumented_node_dockerfile}" + fi + + # Define default build command + local docker_cmd="docker buildx build --build-arg GO_VERSION=${GO_VERSION} --build-arg NODE_IMAGE=${node_image_name}" + + # Build node image first to allow the config and workload image builds to use it. + ${docker_cmd} --build-arg AVALANCHEGO_NODE_IMAGE="${avalanche_node_image}" -t "${node_image_name}" \ + -f "${node_dockerfile}" "${SUBNET_EVM_PATH}" + ${docker_cmd} --build-arg IMAGE_TAG="${TAG}" -t "${config_image_name}" -f "${base_dockerfile}.config" "${SUBNET_EVM_PATH}" + ${docker_cmd} -t "${workload_image_name}" -f "${base_dockerfile}.workload" "${SUBNET_EVM_PATH}" +} + +# Assume it's necessary to build the avalanchego node image from source +# TODO(marun) Support use of a released node image if using a release version of avalanchego + +source "${SUBNET_EVM_PATH}"/scripts/versions.sh + +echo "checking out target avalanchego version ${AVALANCHE_VERSION}" +if [[ -d "${AVALANCHEGO_CLONE_PATH}" ]]; then + echo "updating existing clone" + cd "${AVALANCHEGO_CLONE_PATH}" + git fetch +else + echo "creating new clone" + git clone https://github.com/ava-labs/avalanchego.git "${AVALANCHEGO_CLONE_PATH}" + cd "${AVALANCHEGO_CLONE_PATH}" +fi +# Branch will be reset to $AVALANCHE_VERSION if it already exists +git checkout -B "test-${AVALANCHE_VERSION}" "${AVALANCHE_VERSION}" +cd "${SUBNET_EVM_PATH}" + +# Build avalanchego node image +NODE_ONLY=1 TEST_SETUP=avalanchego IMAGE_PREFIX="${IMAGE_PREFIX}" TAG= bash -x "${AVALANCHEGO_CLONE_PATH}"/scripts/build_antithesis_images.sh + +build_images antithesis-subnet-evm "${SUBNET_EVM_PATH}/Dockerfile" "antithesis-avalanchego-node:${AVALANCHE_VERSION::8}" diff --git a/scripts/build_antithesis_workload.sh b/scripts/build_antithesis_workload.sh new file mode 100755 index 0000000000..942e91c0ac --- /dev/null +++ b/scripts/build_antithesis_workload.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Directory above this script +SUBNET_EVM_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd ) +# Load the constants +source "$SUBNET_EVM_PATH"/scripts/constants.sh + +echo "Building Workload..." +go build -o "$SUBNET_EVM_PATH/build/workload" "$SUBNET_EVM_PATH/tests/antithesis/"*.go diff --git a/scripts/build_docker_image.sh b/scripts/build_docker_image.sh index 8124ea9cdb..5a881e0f69 100755 --- a/scripts/build_docker_image.sh +++ b/scripts/build_docker_image.sh @@ -14,8 +14,11 @@ source "$SUBNET_EVM_PATH"/scripts/versions.sh # WARNING: this will use the most recent commit even if there are un-committed changes present BUILD_IMAGE_ID=${BUILD_IMAGE_ID:-"${CURRENT_BRANCH}"} +# Default to the release image. Will need to be overridden when testing against unreleased versions. +AVALANCHE_NODE_IMAGE=${AVALANCHE_NODE_IMAGE:-"avaplatform/avalanchego:${AVALANCHE_VERSION}"} + echo "Building Docker Image: $DOCKERHUB_REPO:$BUILD_IMAGE_ID based of AvalancheGo@$AVALANCHE_VERSION" docker build -t "$DOCKERHUB_REPO:$BUILD_IMAGE_ID" "$SUBNET_EVM_PATH" -f "$SUBNET_EVM_PATH/Dockerfile" \ - --build-arg AVALANCHE_VERSION="$AVALANCHE_VERSION" \ + --build-arg AVALANCHE_NODE_IMAGE="$AVALANCHE_NODE_IMAGE" \ --build-arg SUBNET_EVM_COMMIT="$SUBNET_EVM_COMMIT" \ --build-arg CURRENT_BRANCH="$CURRENT_BRANCH" diff --git a/scripts/install_avalanchego_release.sh b/scripts/install_avalanchego_release.sh index 53724f2456..56b98a745d 100755 --- a/scripts/install_avalanchego_release.sh +++ b/scripts/install_avalanchego_release.sh @@ -92,7 +92,7 @@ else if [[ $CHECKOUT_STATUS -ne 0 ]]; then echo - echo "'${VERSION}' is not a valid release tag, commit hash, or branch name" + echo "'${AVALANCHE_VERSION}' is not a valid release tag, commit hash, or branch name" exit 1 fi fi diff --git a/scripts/tests.build_antithesis_images.sh b/scripts/tests.build_antithesis_images.sh new file mode 100755 index 0000000000..70b9e9cd89 --- /dev/null +++ b/scripts/tests.build_antithesis_images.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Validates the construction of the antithesis images. +# +# 1. Building the antithesis test images +# 2. Extracting the docker compose configuration from the config image +# 3. Running the workload and its target network without error for a minute +# 4. Stopping the workload and its target network +# + +# e.g., +# ./scripts/tests.build_antithesis_images.sh # Test build of antithesis images +# DEBUG=1 ./scripts/tests.build_antithesis_images.sh # Retain the temporary compose path for troubleshooting + +SUBNET_EVM_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )"; cd .. && pwd ) + +# Discover the default tag that will be used for the image +source "${SUBNET_EVM_PATH}"/scripts/constants.sh +export TAG="${SUBNET_EVM_COMMIT::8}" + +# Build the images for the specified test setup +bash -x "${SUBNET_EVM_PATH}"/scripts/build_antithesis_images.sh + +# Create a container from the config image to extract compose configuration from +IMAGE_NAME="antithesis-subnet-evm-config" +CONTAINER_NAME="tmp-${IMAGE_NAME}" +docker create --name "${CONTAINER_NAME}" "${IMAGE_NAME}:${TAG}" /bin/true + +# Create a temporary directory to write the compose configuration to +TMPDIR="$(mktemp -d)" +echo "using temporary directory ${TMPDIR} as the docker-compose path" + +COMPOSE_FILE="${TMPDIR}/docker-compose.yml" +COMPOSE_CMD="docker-compose -f ${COMPOSE_FILE}" + +# Ensure cleanup +function cleanup { + echo "removing temporary container" + docker rm "${CONTAINER_NAME}" + echo "stopping and removing the docker compose project" + ${COMPOSE_CMD} down --volumes + if [[ -z "${DEBUG:-}" ]]; then + echo "removing temporary dir" + rm -rf "${TMPDIR}" + fi +} +trap cleanup EXIT + +# Copy the docker-compose.yml file out of the container +docker cp "${CONTAINER_NAME}":/docker-compose.yml "${COMPOSE_FILE}" + +# Copy the volume paths out of the container +docker cp "${CONTAINER_NAME}":/volumes "${TMPDIR}/" + +# Run the docker compose project for 2 minutes without error. 2 +# minutes is suggested because the way docker-compose brings all +# containers up simultaneously and the lack of coordination results in +# exponential back-off on the nodes trying to bootstrap. +${COMPOSE_CMD} up -d +sleep 120 +if ${COMPOSE_CMD} ps -q | xargs docker inspect -f '{{ .State.Status }}' | grep -v 'running'; then + echo "An error occurred." + exit 255 +fi + +# Success! diff --git a/scripts/versions.sh b/scripts/versions.sh index e3df74996d..b627ca48e4 100644 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -4,7 +4,7 @@ # shellcheck disable=SC2034 # Don't export them as they're used in the context of other calls -AVALANCHE_VERSION=${AVALANCHE_VERSION:-'v1.11.5'} +AVALANCHE_VERSION=${AVALANCHE_VERSION:-'bcac3aef1'} GINKGO_VERSION=${GINKGO_VERSION:-'v2.2.0'} # This won't be used, but it's here to make code syncs easier diff --git a/tests/antithesis/Dockerfile.config b/tests/antithesis/Dockerfile.config new file mode 100644 index 0000000000..89990cfc46 --- /dev/null +++ b/tests/antithesis/Dockerfile.config @@ -0,0 +1,53 @@ +# The version is supplied as a build argument rather than hard-coded +# to minimize the cost of version changes. +ARG GO_VERSION + +# NODE_IMAGE needs to identify an existing subnet-evm node image and should include the tag +ARG NODE_IMAGE + +# ============= Node Image State ================ +FROM $NODE_IMAGE AS node + +# If this is not an instrumented node image, fake the antithesis dependencies expected by the builder. +RUN [ ! -d /symbols ] && mkdir /symbols || true +RUN [ ! -f /usr/lib/libvoidstar.so ] && touch /usr/lib/libvoidstar.so || true + +# ============= Compilation Stage ================ +FROM golang:$GO_VERSION-bullseye AS builder + +WORKDIR /build +# Copy and download avalanche dependencies using go mod +COPY go.mod . +COPY go.sum . +RUN go mod download + +# Copy the code into the container +COPY . . + +# IMAGE_TAG should be set to the tag for the images in the generated docker compose file. +ARG IMAGE_TAG=latest + +# Copy the avalanchego binary and plugin from the node image +RUN mkdir -p ./build/plugins +COPY --from=node /avalanchego/build/avalanchego ./build +COPY --from=node /avalanchego/build/plugins/* ./build/plugins/ + +# Copy antithesis dependencies required by instrumented binaries +COPY --from=node /symbols /symbols +COPY --from=node /usr/lib/libvoidstar.so /usr/lib/libvoidstar.so + +# Generate docker compose configuration. If the command fails, it will likely be due to a +# node configuration problem. Attempt to start a node with the same configuration so that +# its logging output will be available to aid in troubleshooting. +RUN export AVALANCHEGO_PATH=./build/avalanchego\ + export AVALANCHEGO_PLUGIN_DIR=./build/plugins;\ + TARGET_PATH=./build IMAGE_TAG="$IMAGE_TAG" go run ./tests/antithesis/gencomposeconfig\ + || ${AVALANCHEGO_PATH} --log-display-level=debug\ + --config-file=$(find /root/.tmpnet/networks -name "flags.json" | head -n 1) + +# ============= Cleanup Stage ================ +FROM scratch AS execution + +# Copy the docker compose file and volumes into the container +COPY --from=builder /build/build/docker-compose.yml /docker-compose.yml +COPY --from=builder /build/build/volumes /volumes diff --git a/tests/antithesis/Dockerfile.node b/tests/antithesis/Dockerfile.node new file mode 100644 index 0000000000..eb0f0494ab --- /dev/null +++ b/tests/antithesis/Dockerfile.node @@ -0,0 +1,65 @@ +# The version is supplied as a build argument rather than hard-coded +# to minimize the cost of version changes. +ARG GO_VERSION + +# AVALANCHEGO_NODE_IMAGE needs to identify an existing avalanchego node image and should include the tag +ARG AVALANCHEGO_NODE_IMAGE + +# Antithesis: Getting the Antithesis golang instrumentation library +FROM docker.io/antithesishq/go-instrumentor AS instrumentor + +# ============= Compilation Stage ================ +FROM golang:$GO_VERSION-bullseye AS builder + +WORKDIR /build +# Copy and download avalanche dependencies using go mod +COPY go.mod . +COPY go.sum . +RUN go mod download + +# Copy the code into the container +COPY . . + +# Keep the commit hash to easily verify the exact version that is running +RUN git rev-parse HEAD > ./commit_hash.txt + +# Copy the instrumentor and supporting files to their correct locations +COPY --from=instrumentor /opt/antithesis /opt/antithesis +COPY --from=instrumentor /opt/antithesis/lib /lib + +# Create the destination output directory for the instrumented code +RUN mkdir -p /avalanchego_instrumented + +# Park the .git file in a safe location +RUN mkdir -p /opt/tmp/ +RUN cp -r .git /opt/tmp/ + +# Instrument avalanchego +RUN /opt/antithesis/bin/goinstrumentor \ + -stderrthreshold=INFO \ + -antithesis /opt/antithesis/instrumentation \ + . \ + /avalanchego_instrumented + +WORKDIR /avalanchego_instrumented/customer +RUN go mod download +RUN ln -s /opt/tmp/.git .git + +# Build the VM +RUN ./scripts/build.sh /build/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy + +# ============= Cleanup Stage ================ +FROM $AVALANCHEGO_NODE_IMAGE AS execution + +# Copy identifying information into the container. This will replace +# the avalanchego commit hash in the base image. +COPY --from=builder /build/commit_hash.txt /avalanchego/build/commit_hash.txt + +# Copy the antithesis dependencies into the container +COPY --from=builder /avalanchego_instrumented/symbols /symbols + +# Copy the executable into the container +COPY --from=builder /build/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy\ + /avalanchego/build/plugins/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy + +# The node image's entrypoint will be reused. diff --git a/tests/antithesis/Dockerfile.workload b/tests/antithesis/Dockerfile.workload new file mode 100644 index 0000000000..c4579cbe0b --- /dev/null +++ b/tests/antithesis/Dockerfile.workload @@ -0,0 +1,30 @@ +# The version is supplied as a build argument rather than hard-coded +# to minimize the cost of version changes. +ARG GO_VERSION + +# NODE_IMAGE needs to identify an existing node image and should include the tag +ARG NODE_IMAGE + +# ============= Compilation Stage ================ +FROM golang:$GO_VERSION-bullseye AS builder + +WORKDIR /build +# Copy and download avalanche dependencies using go mod +COPY go.mod . +COPY go.sum . +RUN go mod download + +# Copy the code into the container +COPY . . + +# Build the workload +RUN ./scripts/build_antithesis_workload.sh + +# ============= Cleanup Stage ================ +# Base the workflow on the node image to support bootstrap testing +FROM $NODE_IMAGE AS execution + +# Copy the executable into the container +COPY --from=builder /build/build/workload ./workload + +CMD [ "./workload" ] diff --git a/tests/antithesis/gencomposeconfig/main.go b/tests/antithesis/gencomposeconfig/main.go new file mode 100644 index 0000000000..77b077a7be --- /dev/null +++ b/tests/antithesis/gencomposeconfig/main.go @@ -0,0 +1,65 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package main + +import ( + "fmt" + "log" + "os" + "path/filepath" + + "github.com/ava-labs/avalanchego/tests/antithesis" + "github.com/ava-labs/avalanchego/tests/fixture/tmpnet" + + "github.com/ava-labs/subnet-evm/tests/utils" +) + +const baseImageName = "antithesis-subnet-evm" + +// Creates docker-compose.yml and its associated volumes in the target path. +func main() { + avalancheGoPath := os.Getenv("AVALANCHEGO_PATH") + if len(avalancheGoPath) == 0 { + log.Fatal("AVALANCHEGO_PATH environment variable not set") + } + + pluginDir := os.Getenv("AVALANCHEGO_PLUGIN_DIR") + if len(pluginDir) == 0 { + log.Fatal("AVALANCHEGO_PLUGIN_DIR environment variable not set") + } + + targetPath := os.Getenv("TARGET_PATH") + if len(targetPath) == 0 { + log.Fatal("TARGET_PATH environment variable not set") + } + + imageTag := os.Getenv("IMAGE_TAG") + if len(imageTag) == 0 { + log.Fatal("IMAGE_TAG environment variable not set") + } + + nodeImageName := fmt.Sprintf("%s-node:%s", baseImageName, imageTag) + workloadImageName := fmt.Sprintf("%s-workload:%s", baseImageName, imageTag) + + // Assume the working directory is the root of the repository + cwd, err := os.Getwd() + if err != nil { + log.Fatalf("failed to get current working directory: %s", err) + } + genesisPath := filepath.Join(cwd, "tests/load/genesis/genesis.json") + + // Create a network with an xsvm subnet + network := tmpnet.LocalNetworkOrDie() + network.Subnets = []*tmpnet.Subnet{ + utils.NewTmpnetSubnet("subnet-evm", genesisPath, utils.DefaultChainConfig, network.Nodes...), + } + + if err := antithesis.InitDBVolumes(network, avalancheGoPath, pluginDir, targetPath); err != nil { + log.Fatalf("failed to initialize db volumes: %s", err) + } + + if err := antithesis.GenerateComposeConfig(network, nodeImageName, workloadImageName, targetPath); err != nil { + log.Fatalf("failed to generate config for docker-compose: %s", err) + } +} diff --git a/tests/antithesis/main.go b/tests/antithesis/main.go new file mode 100644 index 0000000000..c7f363aa7a --- /dev/null +++ b/tests/antithesis/main.go @@ -0,0 +1,106 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package main + +import ( + "context" + "crypto/rand" + "log" + "math/big" + "os" + "time" + + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/antithesis" + "github.com/ava-labs/avalanchego/tests/fixture/tmpnet" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" +) + +const NumKeys = 5 + +func main() { + c, err := antithesis.NewConfig(os.Args) + if err != nil { + log.Fatalf("invalid config: %s", err) + } + + ctx := context.Background() + antithesis.AwaitHealthyNodes(ctx, c.URIs) + + if len(c.ChainIDs) != 1 { + log.Fatalf("expected 1 chainID, saw %d", len(c.ChainIDs)) + } + chainID, err := ids.FromString(c.ChainIDs[0]) + if err != nil { + log.Fatalf("failed to parse chainID: %s", err) + } + + genesisWorkload := &workload{ + id: 0, + chainID: chainID, + key: genesis.VMRQKey, + addrs: set.Of(tmpnet.HardhatKey.Address()), + uris: c.URIs, + } + + workloads := make([]*workload, NumKeys) + workloads[0] = genesisWorkload + + for i := 1; i < NumKeys; i++ { + key, err := secp256k1.NewPrivateKey() + if err != nil { + log.Fatalf("failed to generate key: %s", err) + } + + // TODO(marun) Transfer funds to the new key + + workloads[i] = &workload{ + id: i, + chainID: chainID, + key: key, + addrs: set.Of(key.Address()), + uris: c.URIs, + } + } + + for _, w := range workloads[1:] { + go w.run(ctx) + } + genesisWorkload.run(ctx) +} + +type workload struct { + id int + chainID ids.ID + key *secp256k1.PrivateKey + addrs set.Set[ids.ShortID] + uris []string +} + +func (w *workload) run(ctx context.Context) { + timer := time.NewTimer(0) + if !timer.Stop() { + <-timer.C + } + + // TODO(marun) Check initial balance + + for { + // TODO(marun) Exercise evm operations + + val, err := rand.Int(rand.Reader, big.NewInt(int64(time.Second))) + if err != nil { + log.Fatalf("failed to read randomness: %s", err) + } + + timer.Reset(time.Duration(val.Int64())) + select { + case <-ctx.Done(): + return + case <-timer.C: + } + } +}