diff --git a/.github/workflows/release_icm_relayer.yml b/.github/workflows/release_icm_relayer.yml index 60ac34af..5b1fe776 100644 --- a/.github/workflows/release_icm_relayer.yml +++ b/.github/workflows/release_icm_relayer.yml @@ -61,7 +61,7 @@ jobs: uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser-pro - version: '~> v2' + version: v2.5.1 args: release --clean --config relayer/.goreleaser.yml env: # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret diff --git a/.github/workflows/release_signature_aggregator.yml b/.github/workflows/release_signature_aggregator.yml index a6726506..78ab8c94 100644 --- a/.github/workflows/release_signature_aggregator.yml +++ b/.github/workflows/release_signature_aggregator.yml @@ -61,7 +61,7 @@ jobs: uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser-pro - version: '~> v2' + version: v2.5.1 args: release --clean --config signature-aggregator/.goreleaser.yml env: # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret diff --git a/.gitmodules b/.gitmodules index a4ea1404..ee2dcc15 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,5 +1,5 @@ -[submodule "tests/contracts/lib/teleporter"] - path = tests/contracts/lib/teleporter +[submodule "tests/contracts/lib/icm-contracts"] + path = tests/contracts/lib/icm-contracts url = https://github.com/ava-labs/icm-contracts [submodule "tests/contracts/lib/forge-std"] path = tests/contracts/lib/forge-std diff --git a/go.mod b/go.mod index 7f7035d5..c49f27a8 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.23.6 require ( github.com/alexliesenfeld/health v0.8.0 - github.com/ava-labs/avalanchego v1.12.1-0.20241210172525-c7ebd8fbae88 - github.com/ava-labs/icm-contracts v1.0.9-0.20241231155804-0845b3c9fd39 - github.com/ava-labs/subnet-evm v0.6.13-0.20241205165027-6c98da796f35 - github.com/aws/aws-sdk-go-v2 v1.33.0 - github.com/aws/aws-sdk-go-v2/config v1.29.0 - github.com/aws/aws-sdk-go-v2/service/kms v1.37.12 + github.com/ava-labs/avalanchego v1.12.3-0.20250131150857-54ad8e645d65 + github.com/ava-labs/icm-contracts v1.0.9-0.20250204232902-ae24f1f2636f + github.com/ava-labs/subnet-evm v0.7.1 + github.com/aws/aws-sdk-go-v2 v1.36.1 + github.com/aws/aws-sdk-go-v2/config v1.29.6 + github.com/aws/aws-sdk-go-v2/service/kms v1.37.18 github.com/cenkalti/backoff/v4 v4.3.0 github.com/ethereum/go-ethereum v1.13.14 github.com/hashicorp/golang-lru/v2 v2.0.7 @@ -19,33 +19,33 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.5 github.com/redis/go-redis/v9 v9.7.0 - github.com/spf13/pflag v1.0.5 + github.com/spf13/pflag v1.0.6 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.10.0 go.uber.org/atomic v1.11.0 go.uber.org/mock v0.5.0 go.uber.org/zap v1.27.0 - golang.org/x/sync v0.10.0 - google.golang.org/grpc v1.69.4 - google.golang.org/protobuf v1.36.3 + golang.org/x/sync v0.11.0 + google.golang.org/grpc v1.70.0 + google.golang.org/protobuf v1.36.5 ) require ( github.com/DataDog/zstd v1.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect - github.com/ava-labs/coreth v0.13.9-rc.1 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.53 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.10 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.9 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.8 // indirect - github.com/aws/smithy-go v1.22.1 // indirect + github.com/ava-labs/coreth v0.14.1-rc.1 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.59 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.14 // indirect + github.com/aws/smithy-go v1.22.2 // 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 @@ -95,7 +95,6 @@ require ( github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/rpc v1.2.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect @@ -103,9 +102,6 @@ require ( github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.2.4 // indirect - github.com/huin/goupnp v1.3.0 // indirect - github.com/jackpal/gateway v1.0.6 // 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 github.com/klauspost/compress v1.17.9 // indirect @@ -125,7 +121,6 @@ require ( github.com/mr-tron/base58 v1.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pires/go-proxyproto v0.6.2 // indirect @@ -151,27 +146,27 @@ require ( github.com/urfave/cli/v2 v2.25.7 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect - go.opentelemetry.io/otel v1.31.0 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect - go.opentelemetry.io/otel/metric v1.31.0 // indirect - go.opentelemetry.io/otel/sdk v1.31.0 // indirect - go.opentelemetry.io/otel/trace v1.31.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.31.0 // indirect + golang.org/x/crypto v0.32.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/term v0.27.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/oauth2 v0.24.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/time v0.3.0 // indirect - golang.org/x/tools v0.28.0 // indirect + golang.org/x/tools v0.29.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect diff --git a/go.sum b/go.sum index 98157546..8fcc2e96 100644 --- a/go.sum +++ b/go.sum @@ -60,42 +60,42 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax 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.1-0.20241210172525-c7ebd8fbae88 h1:tZdtOPFNblKZx+FmJOhqEfxUUscvPhcLHKGZO3BtQ6A= -github.com/ava-labs/avalanchego v1.12.1-0.20241210172525-c7ebd8fbae88/go.mod h1:yhD5dpZyStIVbxQ550EDi5w5SL7DQ/xGE6TIxosb7U0= -github.com/ava-labs/coreth v0.13.9-rc.1 h1:qIICpC/OZGYUP37QnLgIqqwGmxnLwLpZaUlqJNI85vU= -github.com/ava-labs/coreth v0.13.9-rc.1/go.mod h1:7aMsRIo/3GBE44qWZMjnfqdqfcfZ5yShTTm2LObLaYo= -github.com/ava-labs/icm-contracts v1.0.9-0.20241231155804-0845b3c9fd39 h1:gDvyXiHtyGHL2TfyYz48gybEOfsapI3PBXY148EJ2h8= -github.com/ava-labs/icm-contracts v1.0.9-0.20241231155804-0845b3c9fd39/go.mod h1:hZS72/9tbM+9JKdTs/UuGIWF3z+FEVlcGW4B9C8gECs= -github.com/ava-labs/subnet-evm v0.6.13-0.20241205165027-6c98da796f35 h1:CbXWon0fwGDEDCCiChx2VeIIwO3UML9+8OUTyNwPsxA= -github.com/ava-labs/subnet-evm v0.6.13-0.20241205165027-6c98da796f35/go.mod h1:SfAF4jjYPkezKWShPY/T31WQdD/UHrDyqy0kxA0LE0w= -github.com/aws/aws-sdk-go-v2 v1.33.0 h1:Evgm4DI9imD81V0WwD+TN4DCwjUMdc94TrduMLbgZJs= -github.com/aws/aws-sdk-go-v2 v1.33.0/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= -github.com/aws/aws-sdk-go-v2/config v1.29.0 h1:Vk/u4jof33or1qAQLdofpjKV7mQQT7DcUpnYx8kdmxY= -github.com/aws/aws-sdk-go-v2/config v1.29.0/go.mod h1:iXAZK3Gxvpq3tA+B9WaDYpZis7M8KFgdrDPMmHrgbJM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.53 h1:lwrVhiEDW5yXsuVKlFVUnR2R50zt2DklhOyeLETqDuE= -github.com/aws/aws-sdk-go-v2/credentials v1.17.53/go.mod h1:CkqM1bIw/xjEpBMhBnvqUXYZbpCFuj6dnCAyDk2AtAY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24 h1:5grmdTdMsovn9kPZPI23Hhvp0ZyNm5cRO+IZFIYiAfw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.24/go.mod h1:zqi7TVKTswH3Ozq28PkmBmgzG1tona7mo9G2IJg4Cis= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28 h1:igORFSiH3bfq4lxKFkTSYDhJEUCYo6C8VKiWJjYwQuQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.28/go.mod h1:3So8EA/aAYm36L7XIvCVwLa0s5N0P7o2b1oqnx/2R4g= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28 h1:1mOW9zAUMhTSrMDssEHS/ajx8JcAj/IcftzcmNlmVLI= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.28/go.mod h1:kGlXVIWDfvt2Ox5zEaNglmq0hXPHgQFNMix33Tw22jA= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9 h1:TQmKDyETFGiXVhZfQ/I0cCFziqqX58pi4tKJGYGFSz0= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.9/go.mod h1:HVLPK2iHQBUx7HfZeOQSEu3v2ubZaAY2YPbAm5/WUyY= -github.com/aws/aws-sdk-go-v2/service/kms v1.37.12 h1:jkZNsp+0NwC2isvmcRb2p1EYm188weJTfgcVr+3E9Pc= -github.com/aws/aws-sdk-go-v2/service/kms v1.37.12/go.mod h1:TTGECZ6vGfx8k/pmzQKokSJy7ux2PJID4r96QCh5L0A= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.10 h1:DyZUj3xSw3FR3TXSwDhPhuZkkT14QHBiacdbUVcD0Dg= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.10/go.mod h1:Ro744S4fKiCCuZECXgOi760TiYylUM8ZBf6OGiZzJtY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.9 h1:I1TsPEs34vbpOnR81GIcAq4/3Ud+jRHVGwx6qLQUHLs= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.9/go.mod h1:Fzsj6lZEb8AkTE5S68OhcbBqeWPsR8RnGuKPr8Todl8= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.8 h1:pqEJQtlKWvnv3B6VRt60ZmsHy3SotlEBvfUBPB1KVcM= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.8/go.mod h1:f6vjfZER1M17Fokn0IzssOTMT2N8ZSq+7jnNF0tArvw= -github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= -github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/ava-labs/avalanchego v1.12.3-0.20250131150857-54ad8e645d65 h1:83NePfwbzPqzEi7AQom7/ET9cgWjq3Xs/YTrcEpMFdY= +github.com/ava-labs/avalanchego v1.12.3-0.20250131150857-54ad8e645d65/go.mod h1:uEDLbAUPcGCfDWW680rVfysEofUe/jWte5qQk0j5hMs= +github.com/ava-labs/coreth v0.14.1-rc.1 h1:U72XlRm/fKyASmjThsWzfO/ZRvu1kaONFaX+KdJNxIc= +github.com/ava-labs/coreth v0.14.1-rc.1/go.mod h1:lxDSXLcrszMo0N/PVJzfZ//H+bRwXF/KQWtpEYgXZqM= +github.com/ava-labs/icm-contracts v1.0.9-0.20250204232902-ae24f1f2636f h1:24+o/LWyC4e+zI9ySdm6wu87fwRG7x/OMFfacupjWiQ= +github.com/ava-labs/icm-contracts v1.0.9-0.20250204232902-ae24f1f2636f/go.mod h1:ofBEhsFwoTlPWl433zr7j1PzvmQdvgdS3ixg+QYKxac= +github.com/ava-labs/subnet-evm v0.7.1 h1:wXau+6Aj24hqqlN3wY14OKB4GJobWFhM3MzqFhg3WeU= +github.com/ava-labs/subnet-evm v0.7.1/go.mod h1:jpAX6cNfMuUyoeP2/l9Z0ojDy2K/XbZq5y+E0jPXy38= +github.com/aws/aws-sdk-go-v2 v1.36.1 h1:iTDl5U6oAhkNPba0e1t1hrwAo02ZMqbrGq4k5JBWM5E= +github.com/aws/aws-sdk-go-v2 v1.36.1/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM= +github.com/aws/aws-sdk-go-v2/config v1.29.6 h1:fqgqEKK5HaZVWLQoLiC9Q+xDlSp+1LYidp6ybGE2OGg= +github.com/aws/aws-sdk-go-v2/config v1.29.6/go.mod h1:Ft+WLODzDQmCTHDvqAH1JfC2xxbZ0MxpZAcJqmE1LTQ= +github.com/aws/aws-sdk-go-v2/credentials v1.17.59 h1:9btwmrt//Q6JcSdgJOLI98sdr5p7tssS9yAsGe8aKP4= +github.com/aws/aws-sdk-go-v2/credentials v1.17.59/go.mod h1:NM8fM6ovI3zak23UISdWidyZuI1ghNe2xjzUZAyT+08= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28 h1:KwsodFKVQTlI5EyhRSugALzsV6mG/SGrdjlMXSZSdso= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28/go.mod h1:EY3APf9MzygVhKuPXAc5H+MkGb8k/DOSQjWS0LgkKqI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32 h1:BjUcr3X3K0wZPGFg2bxOWW3VPN8rkE3/61zhP+IHviA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32/go.mod h1:80+OGC/bgzzFFTUmcuwD0lb4YutwQeKLFpmt6hoWapU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32 h1:m1GeXHVMJsRsUAqG6HjZWx9dj7F5TR+cF1bjyfYyBd4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32/go.mod h1:IitoQxGfaKdVLNg0hD8/DXmAqNy0H4K2H2Sf91ti8sI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 h1:Pg9URiobXy85kgFev3og2CuOZ8JZUBENF+dcgWBaYNk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 h1:SYVGSFQHlchIcy6e7x12bsrxClCXSP5et8cqVhL8cuw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13/go.mod h1:kizuDaLX37bG5WZaoxGPQR/LNFXpxp0vsUnqfkWXfNE= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.18 h1:pi9M/9n1PLayBXjia7LfwgXwcpFdFO7Q2cqKOZa1ZmM= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.18/go.mod h1:vZXvmzfhdsPj/axc8+qk/2fSCP4hGyaZ1MAduWEHAxM= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.15 h1:/eE3DogBjYlvlbhd2ssWyeuovWunHLxfgw3s/OJa4GQ= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.15/go.mod h1:2PCJYpi7EKeA5SkStAmZlF6fi0uUABuhtF8ILHjGc3Y= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14 h1:M/zwXiL2iXUrHputuXgmO94TVNmcenPHxgLXLutodKE= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14/go.mod h1:RVwIw3y/IqxC2YEXSIkAzRDdEU1iRabDPaYjpGCbCGQ= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.14 h1:TzeR06UCMUq+KA3bDkujxK1GVGy+G8qQN/QVYzGLkQE= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.14/go.mod h1:dspXf/oYWGWo6DEvj98wpaTeqt5+DMidZD0A9BYTizc= +github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= +github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= 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= @@ -279,8 +279,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= -github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.3 h1:oDTdz9f5VGVVNGu/Q7UXKWYsD0873HXLHdJUNBsSEKM= +github.com/golang/glog v1.2.3/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -372,8 +372,6 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= @@ -394,8 +392,6 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= -github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= 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= @@ -407,10 +403,6 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/ github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= -github.com/jackpal/gateway v1.0.6 h1:/MJORKvJEwNVldtGVJC2p2cwCnsSoLn3hl3zxmZT7tk= -github.com/jackpal/gateway v1.0.6/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -507,8 +499,6 @@ github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5Vgl github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E= -github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -592,8 +582,8 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6 github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= @@ -667,22 +657,22 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -708,8 +698,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-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= 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= @@ -748,6 +738,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -793,8 +785,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/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.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +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/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= @@ -804,8 +796,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -818,8 +810,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= @@ -886,12 +878,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.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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/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.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +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/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= @@ -965,8 +957,8 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= -golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= +golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1038,10 +1030,10 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 h1:fVoAXEKA4+yufmbdVYv+SE73+cPZbbbe8paLsHfkK+U= -google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a h1:OAiGFfOiA0v9MRYsSidp3ubZaBnteRUyn3xB2ZQ5G/E= +google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a/go.mod h1:jehYqy3+AhJU9ve55aNOaSml7wUXjF9x6z2LcCfpAhY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1060,8 +1052,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1074,8 +1066,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/messages/teleporter/config.go b/messages/teleporter/config.go index 24582fd4..177fc126 100644 --- a/messages/teleporter/config.go +++ b/messages/teleporter/config.go @@ -13,9 +13,17 @@ type Config struct { RewardAddress string `json:"reward-address"` } -func (c *Config) Validate() error { - if !common.IsHexAddress(c.RewardAddress) { - return fmt.Errorf("invalid reward address for EVM source subnet: %s", c.RewardAddress) +func ConfigFromMap(m map[string]any) (*Config, error) { + rewardAddress, ok := m["reward-address"].(string) + if !ok { + return nil, fmt.Errorf("reward-address not found") } - return nil + + if !common.IsHexAddress(rewardAddress) { + return nil, fmt.Errorf("invalid reward address for EVM source subnet: %s", rewardAddress) + } + + return &Config{ + RewardAddress: rewardAddress, + }, nil } diff --git a/messages/teleporter/config_test.go b/messages/teleporter/config_test.go index 33241859..3f1ef81d 100644 --- a/messages/teleporter/config_test.go +++ b/messages/teleporter/config_test.go @@ -10,32 +10,47 @@ import ( ) func TestConfigValidate(t *testing.T) { - testCases := []struct { - name string - rewardAddress string - isError bool - }{ + type test struct { + name string + settings map[string]any + isError bool + } + + validAddress := "0x27aE10273D17Cd7e80de8580A51f476960626e5f" + + testCases := []test{ { - name: "valid", - rewardAddress: "0x27aE10273D17Cd7e80de8580A51f476960626e5f", - isError: false, + name: "valid", + settings: map[string]any{ + "reward-address": validAddress, + }, + isError: false, }, { - name: "invalid", - rewardAddress: "0x27aE10273D17Cd7e80de8580A51f476960626e5", - isError: true, + name: "invalid address", + settings: map[string]any{ + "reward-address": validAddress[:len(validAddress)-1], + }, + isError: true, + }, + { + name: "invalid key", + settings: map[string]any{ + "rewardAddress": validAddress, + }, + isError: true, }, } for _, test := range testCases { t.Run(test.name, func(t *testing.T) { - c := &Config{ - RewardAddress: test.rewardAddress, - } - err := c.Validate() + c, err := ConfigFromMap(test.settings) + if test.isError { + require.Nil(t, c) require.Error(t, err) } else { + require.NotNil(t, c) require.NoError(t, err) } }) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index 2918a79d..0f5b2d48 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -5,8 +5,8 @@ package teleporter import ( "context" - "encoding/json" "fmt" + "slices" "time" "github.com/ava-labs/avalanchego/ids" @@ -30,14 +30,11 @@ import ( ) const ( - // The maximum gas limit that can be specified for a Teleporter message - // Based on the C-Chain 15_000_000 gas limit per block, with other Warp message gas overhead conservatively estimated. - maxTeleporterGasLimit = 12_000_000 defaultBlockAcceptanceTimeout = 30 * time.Second ) type factory struct { - messageConfig Config + messageConfig *Config protocolAddress common.Address logger logging.Logger deciderClient pbDecider.DeciderServiceClient @@ -68,19 +65,8 @@ func NewMessageHandlerFactory( messageProtocolConfig config.MessageProtocolConfig, deciderClientConn *grpc.ClientConn, ) (messages.MessageHandlerFactory, error) { - // Marshal the map and unmarshal into the Teleporter config - data, err := json.Marshal(messageProtocolConfig.Settings) + messageConfig, err := ConfigFromMap(messageProtocolConfig.Settings) if err != nil { - logger.Error("Failed to marshal Teleporter config") - return nil, err - } - var messageConfig Config - if err := json.Unmarshal(data, &messageConfig); err != nil { - logger.Error("Failed to unmarshal Teleporter config") - return nil, err - } - - if err := messageConfig.Validate(); err != nil { logger.Error( "Invalid Teleporter config.", zap.Error(err), @@ -127,12 +113,7 @@ func isAllowedRelayer(allowedRelayers []common.Address, eoa common.Address) bool return true } - for _, addr := range allowedRelayers { - if addr == eoa { - return true - } - } - return false + return slices.Contains(allowedRelayers, eoa) } func (m *messageHandler) GetUnsignedMessage() *warp.UnsignedMessage { @@ -165,15 +146,16 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie if err != nil { return false, fmt.Errorf("failed to calculate Teleporter message ID: %w", err) } - + requiredGasLimit := m.teleporterMessage.RequiredGasLimit.Uint64() + destBlockGasLimit := destinationClient.BlockGasLimit() // Check if the specified gas limit is below the maximum threshold - if m.teleporterMessage.RequiredGasLimit.Uint64() > maxTeleporterGasLimit { + if requiredGasLimit > destBlockGasLimit { m.logger.Info( "Gas limit exceeds maximum threshold", zap.String("destinationBlockchainID", destinationBlockchainID.String()), zap.String("teleporterMessageID", teleporterMessageID.String()), zap.Uint64("requiredGasLimit", m.teleporterMessage.RequiredGasLimit.Uint64()), - zap.Uint64("maxGasLimit", maxTeleporterGasLimit), + zap.Uint64("blockGasLimit", destBlockGasLimit), ) return false, nil } diff --git a/messages/teleporter/message_handler_test.go b/messages/teleporter/message_handler_test.go index 370b5b89..ddc3384b 100644 --- a/messages/teleporter/message_handler_test.go +++ b/messages/teleporter/message_handler_test.go @@ -116,8 +116,9 @@ func TestShouldSendMessage(t *testing.T) { ) require.NoError(t, err) + const blockGasLimit = 10_000 gasLimitExceededTeleporterMessage := validTeleporterMessage - gasLimitExceededTeleporterMessage.RequiredGasLimit = big.NewInt(maxTeleporterGasLimit + 1) + gasLimitExceededTeleporterMessage.RequiredGasLimit = big.NewInt(blockGasLimit + 1) gasLimitExceededTeleporterMessageBytes, err := gasLimitExceededTeleporterMessage.Pack() require.NoError(t, err) @@ -233,6 +234,7 @@ func TestShouldSendMessage(t *testing.T) { SenderAddress(). Return(test.senderAddressResult). Times(test.senderAddressTimes) + mockClient.EXPECT().BlockGasLimit().Return(uint64(blockGasLimit)).AnyTimes() mockClient.EXPECT().DestinationBlockchainID().Return(destinationBlockchainID).AnyTimes() if test.messageReceivedCall != nil { messageReceivedInput := interfaces.CallMsg{ diff --git a/peers/app_request_network.go b/peers/app_request_network.go index 128ed3c7..9d9a573c 100644 --- a/peers/app_request_network.go +++ b/peers/app_request_network.go @@ -2,13 +2,16 @@ // See the file LICENSE for licensing terms. //go:generate mockgen -source=$GOFILE -destination=./mocks/mock_app_request_network.go -package=mocks +//go:generate mockgen -destination=./avago_mocks/mock_network.go -package=avago_mocks github.com/ava-labs/avalanchego/network Network package peers import ( "context" "encoding/hex" + "errors" "fmt" + "math/big" "sync" "time" @@ -28,19 +31,25 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/icm-services/peers/utils" "github.com/ava-labs/icm-services/peers/validators" + subnetWarp "github.com/ava-labs/subnet-evm/precompile/contracts/warp" + + sharedUtils "github.com/ava-labs/icm-services/utils" "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" ) const ( InboundMessageChannelSize = 1000 - DefaultAppRequestTimeout = time.Second * 2 ValidatorRefreshPeriod = time.Second * 5 NumBootstrapNodes = 5 ) +var ( + errNotEnoughConnectedStake = errors.New("failed to connect to a threshold of stake") +) + type AppRequestNetwork interface { - ConnectToCanonicalValidators(subnetID ids.ID) ( + GetConnectedCanonicalValidators(subnetID ids.ID) ( *ConnectedCanonicalValidators, error, ) @@ -66,7 +75,7 @@ type appRequestNetwork struct { infoAPI *InfoAPI logger logging.Logger lock *sync.RWMutex - validatorClient *validators.CanonicalValidatorClient + validatorClient validators.CanonicalValidatorState metrics *AppRequestNetworkMetrics trackedSubnets set.Set[ids.ID] @@ -233,6 +242,8 @@ func (n *appRequestNetwork) containsSubnet(subnetID ids.ID) bool { return n.trackedSubnets.Contains(subnetID) } +// TrackSubnet adds the subnet to the list of tracked subnets +// and initiates the connections to the subnet's validators asynchronously func (n *appRequestNetwork) TrackSubnet(subnetID ids.ID) { if n.containsSubnet(subnetID) { return @@ -248,6 +259,10 @@ func (n *appRequestNetwork) startUpdateValidators() { // Fetch validators immediately when called, and refresh every ValidatorRefreshPeriod ticker := time.NewTicker(ValidatorRefreshPeriod) for ; true; <-ticker.C { + n.logger.Debug( + "Fetching validators for subnets", + zap.Any("subnetIDs", append([]ids.ID{constants.PrimaryNetworkID}, n.trackedSubnets.List()...)), + ) n.updateValidatorSet(context.Background(), constants.PrimaryNetworkID) for _, subnet := range n.trackedSubnets.List() { n.updateValidatorSet(context.Background(), subnet) @@ -263,8 +278,6 @@ func (n *appRequestNetwork) updateValidatorSet( n.lock.Lock() defer n.lock.Unlock() - n.logger.Debug("Fetching validators for subnet ID", zap.Stringer("subnetID", subnetID)) - // Fetch the subnet validators from the P-Chain validators, err := n.validatorClient.GetProposedValidators(ctx, subnetID) if err != nil { @@ -325,12 +338,9 @@ func (c *ConnectedCanonicalValidators) GetValidator(nodeID ids.NodeID) (*warp.Va return c.ValidatorSet[c.NodeValidatorIndexMap[nodeID]], c.NodeValidatorIndexMap[nodeID] } -// ConnectToCanonicalValidators connects to the canonical validators of the given subnet and returns the connected -// validator information -func (n *appRequestNetwork) ConnectToCanonicalValidators(subnetID ids.ID) (*ConnectedCanonicalValidators, error) { - // Track the subnet - n.TrackSubnet(subnetID) - +// GetConnectedCanonicalValidators returns the validator information in canonical ordering for the given subnet +// at the time of the call, as well as the total weight of the validators that this network is connected to +func (n *appRequestNetwork) GetConnectedCanonicalValidators(subnetID ids.ID) (*ConnectedCanonicalValidators, error) { // Get the subnet's current canonical validator set startPChainAPICall := time.Now() validatorSet, totalValidatorWeight, err := n.validatorClient.GetCurrentCanonicalValidatorSet(subnetID) @@ -351,8 +361,16 @@ func (n *appRequestNetwork) ConnectToCanonicalValidators(subnetID ids.ID) (*Conn } } + peerInfo := n.network.PeerInfo(nodeIDs.List()) + connectedPeers := set.NewSet[ids.NodeID](len(nodeIDs)) + for _, peer := range peerInfo { + if nodeIDs.Contains(peer.ID) { + connectedPeers.Add(peer.ID) + } + } + // Calculate the total weight of connected validators. - connectedWeight := calculateConnectedWeight(validatorSet, nodeValidatorIndexMap, nodeIDs) + connectedWeight := calculateConnectedWeight(validatorSet, nodeValidatorIndexMap, connectedPeers) return &ConnectedCanonicalValidators{ ConnectedWeight: connectedWeight, @@ -391,6 +409,26 @@ func (n *appRequestNetwork) setPChainAPICallLatencyMS(latency float64) { // Non-receiver util functions +func GetNetworkHealthFunc(network AppRequestNetwork, subnetIDs []ids.ID) func(context.Context) error { + return func(context.Context) error { + for _, subnetID := range subnetIDs { + connectedValidators, err := network.GetConnectedCanonicalValidators(subnetID) + if err != nil { + return fmt.Errorf( + "failed to get connected validators: %s, %w", subnetID, err) + } + if !sharedUtils.CheckStakeWeightExceedsThreshold( + big.NewInt(0).SetUint64(connectedValidators.ConnectedWeight), + connectedValidators.TotalValidatorWeight, + subnetWarp.WarpDefaultQuorumNumerator, + ) { + return errNotEnoughConnectedStake + } + } + return nil + } +} + func calculateConnectedWeight( validatorSet []*warp.Validator, nodeValidatorIndexMap map[ids.NodeID]int, diff --git a/peers/app_request_network_test.go b/peers/app_request_network_test.go index acd690d4..bbfd1084 100644 --- a/peers/app_request_network_test.go +++ b/peers/app_request_network_test.go @@ -7,10 +7,15 @@ import ( "testing" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/network/peer" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/warp" + "github.com/ava-labs/icm-services/peers/avago_mocks" + validator_mocks "github.com/ava-labs/icm-services/peers/validators/mocks" + "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" ) func TestCalculateConnectedWeight(t *testing.T) { @@ -48,10 +53,114 @@ func TestCalculateConnectedWeight(t *testing.T) { require.Equal(t, uint64(60), connectedWeight3) } +func TestConnectToCanonicalValidators(t *testing.T) { + ctrl := gomock.NewController(t) + + subnetID := ids.GenerateTestID() + validator1_1 := makeValidator(t, 1, 1) + validator2_1 := makeValidator(t, 2, 1) + validator3_2 := makeValidator(t, 3, 2) + metrics, _ := newAppRequestNetworkMetrics(prometheus.DefaultRegisterer) + + testCases := []struct { + name string + validators []*warp.Validator + connectedNodes []ids.NodeID + expectedConnectedWeight uint64 + expectedTotalWeight uint64 + }{ + { + name: "no connected nodes, one validator", + validators: []*warp.Validator{&validator1_1}, + connectedNodes: []ids.NodeID{}, + expectedConnectedWeight: 0, + expectedTotalWeight: 1, + }, + { + name: "all validators, missing one nodeID", + validators: []*warp.Validator{&validator1_1, &validator2_1, &validator3_2}, + connectedNodes: []ids.NodeID{ + validator1_1.NodeIDs[0], + validator2_1.NodeIDs[0], + validator3_2.NodeIDs[0], + validator3_2.NodeIDs[1], + }, + expectedConnectedWeight: 6, + expectedTotalWeight: 6, + }, + { + name: "fully connected", + validators: []*warp.Validator{&validator1_1, &validator2_1, &validator3_2}, + connectedNodes: []ids.NodeID{ + validator1_1.NodeIDs[0], + validator2_1.NodeIDs[0], + validator3_2.NodeIDs[0], + validator3_2.NodeIDs[1], + }, + expectedConnectedWeight: 6, + expectedTotalWeight: 6, + }, + { + name: "missing conn to double node validator", + validators: []*warp.Validator{&validator1_1, &validator2_1, &validator3_2}, + connectedNodes: []ids.NodeID{ + validator1_1.NodeIDs[0], + validator2_1.NodeIDs[0], + }, + expectedConnectedWeight: 3, + expectedTotalWeight: 6, + }, + { + name: "irrelevant nodes", + validators: []*warp.Validator{&validator1_1, &validator2_1}, + connectedNodes: []ids.NodeID{ + validator1_1.NodeIDs[0], + validator2_1.NodeIDs[0], + validator3_2.NodeIDs[0], // this nodeID does not map to the validator + }, + expectedConnectedWeight: 3, + expectedTotalWeight: 3, + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + mockNetwork := avago_mocks.NewMockNetwork(ctrl) + mockValidatorClient := validator_mocks.NewMockCanonicalValidatorState(ctrl) + arNetwork := appRequestNetwork{ + network: mockNetwork, + validatorClient: mockValidatorClient, + metrics: metrics, + } + var totalWeight uint64 + for _, vdr := range testCase.validators { + totalWeight += vdr.Weight + } + mockValidatorClient.EXPECT().GetCurrentCanonicalValidatorSet(subnetID).Return( + testCase.validators, + totalWeight, + nil, + ).Times(1) + + peerInfo := make([]peer.Info, len(testCase.validators)) + for _, node := range testCase.connectedNodes { + peerInfo = append(peerInfo, peer.Info{ + ID: node, + }) + } + mockNetwork.EXPECT().PeerInfo(gomock.Any()).Return(peerInfo).Times(1) + + ret, err := arNetwork.GetConnectedCanonicalValidators(subnetID) + require.Equal(t, testCase.expectedConnectedWeight, ret.ConnectedWeight) + require.Equal(t, testCase.expectedTotalWeight, ret.TotalValidatorWeight) + require.NoError(t, err) + }) + } +} + func makeValidator(t *testing.T, weight uint64, numNodeIDs int) warp.Validator { - sk, err := bls.NewSecretKey() + localSigner, err := bls.NewSigner() require.NoError(t, err) - pk := bls.PublicFromSecretKey(sk) + pk := localSigner.PublicKey() nodeIDs := make([]ids.NodeID, numNodeIDs) for i := 0; i < numNodeIDs; i++ { diff --git a/peers/avago_mocks/mock_network.go b/peers/avago_mocks/mock_network.go new file mode 100644 index 00000000..e00eecb1 --- /dev/null +++ b/peers/avago_mocks/mock_network.go @@ -0,0 +1,228 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ava-labs/avalanchego/network (interfaces: Network) +// +// Generated by this command: +// +// mockgen -destination=./avago_mocks/mock_network.go -package=avago_mocks github.com/ava-labs/avalanchego/network Network +// + +// Package avago_mocks is a generated GoMock package. +package avago_mocks + +import ( + context "context" + netip "net/netip" + reflect "reflect" + + ids "github.com/ava-labs/avalanchego/ids" + message "github.com/ava-labs/avalanchego/message" + network "github.com/ava-labs/avalanchego/network" + peer "github.com/ava-labs/avalanchego/network/peer" + common "github.com/ava-labs/avalanchego/snow/engine/common" + subnets "github.com/ava-labs/avalanchego/subnets" + bloom "github.com/ava-labs/avalanchego/utils/bloom" + ips "github.com/ava-labs/avalanchego/utils/ips" + set "github.com/ava-labs/avalanchego/utils/set" + gomock "go.uber.org/mock/gomock" +) + +// MockNetwork is a mock of Network interface. +type MockNetwork struct { + ctrl *gomock.Controller + recorder *MockNetworkMockRecorder + isgomock struct{} +} + +// MockNetworkMockRecorder is the mock recorder for MockNetwork. +type MockNetworkMockRecorder struct { + mock *MockNetwork +} + +// NewMockNetwork creates a new mock instance. +func NewMockNetwork(ctrl *gomock.Controller) *MockNetwork { + mock := &MockNetwork{ctrl: ctrl} + mock.recorder = &MockNetworkMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockNetwork) EXPECT() *MockNetworkMockRecorder { + return m.recorder +} + +// AllowConnection mocks base method. +func (m *MockNetwork) AllowConnection(peerID ids.NodeID) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AllowConnection", peerID) + ret0, _ := ret[0].(bool) + return ret0 +} + +// AllowConnection indicates an expected call of AllowConnection. +func (mr *MockNetworkMockRecorder) AllowConnection(peerID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllowConnection", reflect.TypeOf((*MockNetwork)(nil).AllowConnection), peerID) +} + +// Connected mocks base method. +func (m *MockNetwork) Connected(peerID ids.NodeID) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Connected", peerID) +} + +// Connected indicates an expected call of Connected. +func (mr *MockNetworkMockRecorder) Connected(peerID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connected", reflect.TypeOf((*MockNetwork)(nil).Connected), peerID) +} + +// Disconnected mocks base method. +func (m *MockNetwork) Disconnected(peerID ids.NodeID) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Disconnected", peerID) +} + +// Disconnected indicates an expected call of Disconnected. +func (mr *MockNetworkMockRecorder) Disconnected(peerID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Disconnected", reflect.TypeOf((*MockNetwork)(nil).Disconnected), peerID) +} + +// Dispatch mocks base method. +func (m *MockNetwork) Dispatch() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Dispatch") + ret0, _ := ret[0].(error) + return ret0 +} + +// Dispatch indicates an expected call of Dispatch. +func (mr *MockNetworkMockRecorder) Dispatch() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Dispatch", reflect.TypeOf((*MockNetwork)(nil).Dispatch)) +} + +// HealthCheck mocks base method. +func (m *MockNetwork) HealthCheck(arg0 context.Context) (any, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HealthCheck", arg0) + ret0, _ := ret[0].(any) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HealthCheck indicates an expected call of HealthCheck. +func (mr *MockNetworkMockRecorder) HealthCheck(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HealthCheck", reflect.TypeOf((*MockNetwork)(nil).HealthCheck), arg0) +} + +// KnownPeers mocks base method. +func (m *MockNetwork) KnownPeers() ([]byte, []byte) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "KnownPeers") + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].([]byte) + return ret0, ret1 +} + +// KnownPeers indicates an expected call of KnownPeers. +func (mr *MockNetworkMockRecorder) KnownPeers() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KnownPeers", reflect.TypeOf((*MockNetwork)(nil).KnownPeers)) +} + +// ManuallyTrack mocks base method. +func (m *MockNetwork) ManuallyTrack(nodeID ids.NodeID, ip netip.AddrPort) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ManuallyTrack", nodeID, ip) +} + +// ManuallyTrack indicates an expected call of ManuallyTrack. +func (mr *MockNetworkMockRecorder) ManuallyTrack(nodeID, ip any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ManuallyTrack", reflect.TypeOf((*MockNetwork)(nil).ManuallyTrack), nodeID, ip) +} + +// NodeUptime mocks base method. +func (m *MockNetwork) NodeUptime() (network.UptimeResult, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NodeUptime") + ret0, _ := ret[0].(network.UptimeResult) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// NodeUptime indicates an expected call of NodeUptime. +func (mr *MockNetworkMockRecorder) NodeUptime() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeUptime", reflect.TypeOf((*MockNetwork)(nil).NodeUptime)) +} + +// PeerInfo mocks base method. +func (m *MockNetwork) PeerInfo(nodeIDs []ids.NodeID) []peer.Info { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PeerInfo", nodeIDs) + ret0, _ := ret[0].([]peer.Info) + return ret0 +} + +// PeerInfo indicates an expected call of PeerInfo. +func (mr *MockNetworkMockRecorder) PeerInfo(nodeIDs any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerInfo", reflect.TypeOf((*MockNetwork)(nil).PeerInfo), nodeIDs) +} + +// Peers mocks base method. +func (m *MockNetwork) Peers(peerID ids.NodeID, trackedSubnets set.Set[ids.ID], requestAllPeers bool, knownPeers *bloom.ReadFilter, peerSalt []byte) []*ips.ClaimedIPPort { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Peers", peerID, trackedSubnets, requestAllPeers, knownPeers, peerSalt) + ret0, _ := ret[0].([]*ips.ClaimedIPPort) + return ret0 +} + +// Peers indicates an expected call of Peers. +func (mr *MockNetworkMockRecorder) Peers(peerID, trackedSubnets, requestAllPeers, knownPeers, peerSalt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Peers", reflect.TypeOf((*MockNetwork)(nil).Peers), peerID, trackedSubnets, requestAllPeers, knownPeers, peerSalt) +} + +// Send mocks base method. +func (m *MockNetwork) Send(msg message.OutboundMessage, config common.SendConfig, subnetID ids.ID, allower subnets.Allower) set.Set[ids.NodeID] { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Send", msg, config, subnetID, allower) + ret0, _ := ret[0].(set.Set[ids.NodeID]) + return ret0 +} + +// Send indicates an expected call of Send. +func (mr *MockNetworkMockRecorder) Send(msg, config, subnetID, allower any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockNetwork)(nil).Send), msg, config, subnetID, allower) +} + +// StartClose mocks base method. +func (m *MockNetwork) StartClose() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "StartClose") +} + +// StartClose indicates an expected call of StartClose. +func (mr *MockNetworkMockRecorder) StartClose() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartClose", reflect.TypeOf((*MockNetwork)(nil).StartClose)) +} + +// Track mocks base method. +func (m *MockNetwork) Track(ips []*ips.ClaimedIPPort) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Track", ips) + ret0, _ := ret[0].(error) + return ret0 +} + +// Track indicates an expected call of Track. +func (mr *MockNetworkMockRecorder) Track(ips any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Track", reflect.TypeOf((*MockNetwork)(nil).Track), ips) +} diff --git a/peers/external_handler.go b/peers/external_handler.go index 0f82bf9e..d4b55b9d 100644 --- a/peers/external_handler.go +++ b/peers/external_handler.go @@ -21,6 +21,11 @@ import ( var _ router.ExternalHandler = &RelayerExternalHandler{} +const ( + // Re-exposing DefaultAppRequestTimeout for use by message creators to set deadlines + DefaultAppRequestTimeout = constants.DefaultNetworkMaximumTimeout +) + // Note: all of the external handler's methods are called on peer goroutines. It // is possible for multiple concurrent calls to happen with different NodeIDs. // However, a given NodeID will only be performing one call at a time. @@ -47,7 +52,7 @@ func NewRelayerExternalHandler( // TODO: Leaving this static for now, but we may want to have this as a config option cfg := timer.AdaptiveTimeoutConfig{ InitialTimeout: constants.DefaultNetworkInitialTimeout, - MinimumTimeout: constants.DefaultNetworkInitialTimeout, + MinimumTimeout: constants.DefaultNetworkMinimumTimeout, MaximumTimeout: constants.DefaultNetworkMaximumTimeout, TimeoutCoefficient: constants.DefaultNetworkTimeoutCoefficient, TimeoutHalflife: constants.DefaultNetworkTimeoutHalflife, @@ -139,7 +144,7 @@ func (h *RelayerExternalHandler) RegisterRequestID( return responseChan } -// RegisterRequest registers an AppRequest with the timeout manager. +// RegisterAppRequest registers an AppRequest with the timeout manager. // If RegisterResponse is not called before the timeout, HandleInbound is called with // an internally created AppRequestFailed message. func (h *RelayerExternalHandler) RegisterAppRequest(reqID ids.RequestID) { @@ -155,7 +160,7 @@ func (h *RelayerExternalHandler) RegisterAppRequest(reqID ids.RequestID) { }) } -// RegisterResponse registers an AppResponse with the timeout manager +// registerAppResponse registers an AppResponse with the timeout manager func (h *RelayerExternalHandler) registerAppResponse(inboundMessage message.InboundMessage) { h.lock.Lock() defer h.lock.Unlock() diff --git a/peers/info_client.go b/peers/info_client.go index c5be6fd9..ff648e41 100644 --- a/peers/info_client.go +++ b/peers/info_client.go @@ -56,10 +56,6 @@ func (i *InfoAPI) GetNodeVersion(ctx context.Context) (*info.GetNodeVersionReply return i.client.GetNodeVersion(ctx, i.options...) } -func (i *InfoAPI) GetTxFee(ctx context.Context) (*info.GetTxFeeResponse, error) { - return i.client.GetTxFee(ctx, i.options...) -} - func (i *InfoAPI) GetVMs(ctx context.Context) (map[ids.ID][]string, error) { return i.client.GetVMs(ctx, i.options...) } diff --git a/peers/mocks/mock_app_request_network.go b/peers/mocks/mock_app_request_network.go index 1773661b..1634992c 100644 --- a/peers/mocks/mock_app_request_network.go +++ b/peers/mocks/mock_app_request_network.go @@ -44,19 +44,19 @@ func (m *MockAppRequestNetwork) EXPECT() *MockAppRequestNetworkMockRecorder { return m.recorder } -// ConnectToCanonicalValidators mocks base method. -func (m *MockAppRequestNetwork) ConnectToCanonicalValidators(subnetID ids.ID) (*peers.ConnectedCanonicalValidators, error) { +// GetConnectedCanonicalValidators mocks base method. +func (m *MockAppRequestNetwork) GetConnectedCanonicalValidators(subnetID ids.ID) (*peers.ConnectedCanonicalValidators, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ConnectToCanonicalValidators", subnetID) + ret := m.ctrl.Call(m, "GetConnectedCanonicalValidators", subnetID) ret0, _ := ret[0].(*peers.ConnectedCanonicalValidators) ret1, _ := ret[1].(error) return ret0, ret1 } -// ConnectToCanonicalValidators indicates an expected call of ConnectToCanonicalValidators. -func (mr *MockAppRequestNetworkMockRecorder) ConnectToCanonicalValidators(subnetID any) *gomock.Call { +// GetConnectedCanonicalValidators indicates an expected call of GetConnectedCanonicalValidators. +func (mr *MockAppRequestNetworkMockRecorder) GetConnectedCanonicalValidators(subnetID any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConnectToCanonicalValidators", reflect.TypeOf((*MockAppRequestNetwork)(nil).ConnectToCanonicalValidators), subnetID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConnectedCanonicalValidators", reflect.TypeOf((*MockAppRequestNetwork)(nil).GetConnectedCanonicalValidators), subnetID) } // GetSubnetID mocks base method. diff --git a/peers/validators/canonical_validator_client.go b/peers/validators/canonical_validator_client.go index bc75bb37..317f21b9 100644 --- a/peers/validators/canonical_validator_client.go +++ b/peers/validators/canonical_validator_client.go @@ -3,6 +3,8 @@ package validators +//go:generate mockgen -source=$GOFILE -destination=./mocks/mock_canonical_validator_client.go -package=mocks + import ( "context" @@ -19,9 +21,18 @@ import ( pchainapi "github.com/ava-labs/avalanchego/vms/platformvm/api" ) -var _ validators.State = &CanonicalValidatorClient{} +var _ CanonicalValidatorState = &CanonicalValidatorClient{} + +// CanonicalValidatorState is an interface that wraps [validators.State] and adds additional +// convenience methods for fetching current and proposed validator sets. +type CanonicalValidatorState interface { + validators.State + + GetCurrentCanonicalValidatorSet(subnetID ids.ID) ([]*avalancheWarp.Validator, uint64, error) + GetProposedValidators(ctx context.Context, subnetID ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) +} -// CanonicalValidatorClient wraps platformvm.Client and implements validators.State +// CanonicalValidatorClient wraps [platformvm.Client] and implements [CanonicalValidatorState] type CanonicalValidatorClient struct { logger logging.Logger client platformvm.Client diff --git a/peers/validators/mocks/mock_canonical_validator_client.go b/peers/validators/mocks/mock_canonical_validator_client.go new file mode 100644 index 00000000..59aac370 --- /dev/null +++ b/peers/validators/mocks/mock_canonical_validator_client.go @@ -0,0 +1,151 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: canonical_validator_client.go +// +// Generated by this command: +// +// mockgen -source=canonical_validator_client.go -destination=./mocks/mock_canonical_validator_client.go -package=mocks +// + +// Package mocks is a generated GoMock package. +package mocks + +import ( + context "context" + reflect "reflect" + + ids "github.com/ava-labs/avalanchego/ids" + validators "github.com/ava-labs/avalanchego/snow/validators" + warp "github.com/ava-labs/avalanchego/vms/platformvm/warp" + gomock "go.uber.org/mock/gomock" +) + +// MockCanonicalValidatorState is a mock of CanonicalValidatorState interface. +type MockCanonicalValidatorState struct { + ctrl *gomock.Controller + recorder *MockCanonicalValidatorStateMockRecorder + isgomock struct{} +} + +// MockCanonicalValidatorStateMockRecorder is the mock recorder for MockCanonicalValidatorState. +type MockCanonicalValidatorStateMockRecorder struct { + mock *MockCanonicalValidatorState +} + +// NewMockCanonicalValidatorState creates a new mock instance. +func NewMockCanonicalValidatorState(ctrl *gomock.Controller) *MockCanonicalValidatorState { + mock := &MockCanonicalValidatorState{ctrl: ctrl} + mock.recorder = &MockCanonicalValidatorStateMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockCanonicalValidatorState) EXPECT() *MockCanonicalValidatorStateMockRecorder { + return m.recorder +} + +// GetCurrentCanonicalValidatorSet mocks base method. +func (m *MockCanonicalValidatorState) GetCurrentCanonicalValidatorSet(subnetID ids.ID) ([]*warp.Validator, uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentCanonicalValidatorSet", subnetID) + ret0, _ := ret[0].([]*warp.Validator) + ret1, _ := ret[1].(uint64) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetCurrentCanonicalValidatorSet indicates an expected call of GetCurrentCanonicalValidatorSet. +func (mr *MockCanonicalValidatorStateMockRecorder) GetCurrentCanonicalValidatorSet(subnetID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentCanonicalValidatorSet", reflect.TypeOf((*MockCanonicalValidatorState)(nil).GetCurrentCanonicalValidatorSet), subnetID) +} + +// GetCurrentHeight mocks base method. +func (m *MockCanonicalValidatorState) GetCurrentHeight(arg0 context.Context) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentHeight", arg0) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentHeight indicates an expected call of GetCurrentHeight. +func (mr *MockCanonicalValidatorStateMockRecorder) GetCurrentHeight(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentHeight", reflect.TypeOf((*MockCanonicalValidatorState)(nil).GetCurrentHeight), arg0) +} + +// GetCurrentValidatorSet mocks base method. +func (m *MockCanonicalValidatorState) GetCurrentValidatorSet(ctx context.Context, subnetID ids.ID) (map[ids.ID]*validators.GetCurrentValidatorOutput, uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentValidatorSet", ctx, subnetID) + ret0, _ := ret[0].(map[ids.ID]*validators.GetCurrentValidatorOutput) + ret1, _ := ret[1].(uint64) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetCurrentValidatorSet indicates an expected call of GetCurrentValidatorSet. +func (mr *MockCanonicalValidatorStateMockRecorder) GetCurrentValidatorSet(ctx, subnetID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorSet", reflect.TypeOf((*MockCanonicalValidatorState)(nil).GetCurrentValidatorSet), ctx, subnetID) +} + +// GetMinimumHeight mocks base method. +func (m *MockCanonicalValidatorState) GetMinimumHeight(arg0 context.Context) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMinimumHeight", arg0) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetMinimumHeight indicates an expected call of GetMinimumHeight. +func (mr *MockCanonicalValidatorStateMockRecorder) GetMinimumHeight(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMinimumHeight", reflect.TypeOf((*MockCanonicalValidatorState)(nil).GetMinimumHeight), arg0) +} + +// GetProposedValidators mocks base method. +func (m *MockCanonicalValidatorState) GetProposedValidators(ctx context.Context, subnetID ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetProposedValidators", ctx, subnetID) + ret0, _ := ret[0].(map[ids.NodeID]*validators.GetValidatorOutput) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetProposedValidators indicates an expected call of GetProposedValidators. +func (mr *MockCanonicalValidatorStateMockRecorder) GetProposedValidators(ctx, subnetID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProposedValidators", reflect.TypeOf((*MockCanonicalValidatorState)(nil).GetProposedValidators), ctx, subnetID) +} + +// GetSubnetID mocks base method. +func (m *MockCanonicalValidatorState) GetSubnetID(ctx context.Context, chainID ids.ID) (ids.ID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubnetID", ctx, chainID) + ret0, _ := ret[0].(ids.ID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSubnetID indicates an expected call of GetSubnetID. +func (mr *MockCanonicalValidatorStateMockRecorder) GetSubnetID(ctx, chainID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnetID", reflect.TypeOf((*MockCanonicalValidatorState)(nil).GetSubnetID), ctx, chainID) +} + +// GetValidatorSet mocks base method. +func (m *MockCanonicalValidatorState) GetValidatorSet(ctx context.Context, height uint64, subnetID ids.ID) (map[ids.NodeID]*validators.GetValidatorOutput, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetValidatorSet", ctx, height, subnetID) + ret0, _ := ret[0].(map[ids.NodeID]*validators.GetValidatorOutput) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetValidatorSet indicates an expected call of GetValidatorSet. +func (mr *MockCanonicalValidatorStateMockRecorder) GetValidatorSet(ctx, height, subnetID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorSet", reflect.TypeOf((*MockCanonicalValidatorState)(nil).GetValidatorSet), ctx, height, subnetID) +} diff --git a/proto/pb/decider/decider.pb.go b/proto/pb/decider/decider.pb.go index 47230272..467f6322 100644 --- a/proto/pb/decider/decider.pb.go +++ b/proto/pb/decider/decider.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.3 +// protoc-gen-go v1.36.5 // protoc (unknown) // source: decider/decider.proto @@ -11,6 +11,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -142,7 +143,7 @@ func (x *ShouldSendMessageResponse) GetShouldSendMessage() bool { var File_decider_decider_proto protoreflect.FileDescriptor -var file_decider_decider_proto_rawDesc = []byte{ +var file_decider_decider_proto_rawDesc = string([]byte{ 0x0a, 0x15, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x22, 0xbe, 0x01, 0x0a, 0x18, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, @@ -173,16 +174,16 @@ var file_decider_decider_proto_rawDesc = []byte{ 0x61, 0x62, 0x73, 0x2f, 0x69, 0x63, 0x6d, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x2f, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +}) var ( file_decider_decider_proto_rawDescOnce sync.Once - file_decider_decider_proto_rawDescData = file_decider_decider_proto_rawDesc + file_decider_decider_proto_rawDescData []byte ) func file_decider_decider_proto_rawDescGZIP() []byte { file_decider_decider_proto_rawDescOnce.Do(func() { - file_decider_decider_proto_rawDescData = protoimpl.X.CompressGZIP(file_decider_decider_proto_rawDescData) + file_decider_decider_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_decider_decider_proto_rawDesc), len(file_decider_decider_proto_rawDesc))) }) return file_decider_decider_proto_rawDescData } @@ -211,7 +212,7 @@ func file_decider_decider_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_decider_decider_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_decider_decider_proto_rawDesc), len(file_decider_decider_proto_rawDesc)), NumEnums: 0, NumMessages: 2, NumExtensions: 0, @@ -222,7 +223,6 @@ func file_decider_decider_proto_init() { MessageInfos: file_decider_decider_proto_msgTypes, }.Build() File_decider_decider_proto = out.File - file_decider_decider_proto_rawDesc = nil file_decider_decider_proto_goTypes = nil file_decider_decider_proto_depIdxs = nil } diff --git a/relayer/.goreleaser.yml b/relayer/.goreleaser.yml index 3b666c97..4ba73d91 100644 --- a/relayer/.goreleaser.yml +++ b/relayer/.goreleaser.yml @@ -31,9 +31,11 @@ builds: goarm64: v8.0 env: - CC=oa64-clang - ignore: - goos: darwin goarch: amd64 + goamd64: v1 + env: + - CC=o64-clang dockers: - image_templates: - 'avaplatform/icm-relayer:{{ .Tag }}-amd64' diff --git a/relayer/api/health_check.go b/relayer/api/health_check.go index 1fafe3d8..c0254bf1 100644 --- a/relayer/api/health_check.go +++ b/relayer/api/health_check.go @@ -9,16 +9,23 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/logging" "go.uber.org/atomic" - "go.uber.org/zap" ) const HealthAPIPath = "/health" -func HandleHealthCheck(logger logging.Logger, relayerHealth map[ids.ID]*atomic.Bool) { - http.Handle(HealthAPIPath, healthCheckHandler(logger, relayerHealth)) +func HandleHealthCheck( + logger logging.Logger, + relayerHealth map[ids.ID]*atomic.Bool, + networkHealth func(context.Context) error, +) { + http.Handle(HealthAPIPath, healthCheckHandler(logger, relayerHealth, networkHealth)) } -func healthCheckHandler(logger logging.Logger, relayerHealth map[ids.ID]*atomic.Bool) http.Handler { +func healthCheckHandler( + logger logging.Logger, + relayerHealth map[ids.ID]*atomic.Bool, + networkHealth func(context.Context) error, +) http.Handler { return health.NewHandler(health.NewChecker( health.WithCheck(health.Check{ Name: "relayers-all", @@ -32,11 +39,14 @@ func healthCheckHandler(logger logging.Logger, relayerHealth map[ids.ID]*atomic. } if len(unhealthyRelayers) > 0 { - logger.Fatal("Relayers are unhealthy for blockchains", zap.Strings("blockchains", unhealthyRelayers)) return fmt.Errorf("relayers are unhealthy for blockchains %v", unhealthyRelayers) } return nil }, }), + health.WithCheck(health.Check{ + Name: "network-all", + Check: networkHealth, + }), )) } diff --git a/relayer/api/relay_message.go b/relayer/api/relay_message.go index ffecaa75..1cdf3f51 100644 --- a/relayer/api/relay_message.go +++ b/relayer/api/relay_message.go @@ -39,11 +39,11 @@ type ManualWarpMessageRequest struct { } func HandleRelayMessage(logger logging.Logger, messageCoordinator *relayer.MessageCoordinator) { - http.Handle(RelayAPIPath, relayAPIHandler(logger, messageCoordinator)) + http.Handle(RelayMessageAPIPath, relayMessageAPIHandler(logger, messageCoordinator)) } func HandleRelay(logger logging.Logger, messageCoordinator *relayer.MessageCoordinator) { - http.Handle(RelayMessageAPIPath, relayMessageAPIHandler(logger, messageCoordinator)) + http.Handle(RelayAPIPath, relayAPIHandler(logger, messageCoordinator)) } func relayMessageAPIHandler(logger logging.Logger, messageCoordinator *relayer.MessageCoordinator) http.Handler { diff --git a/relayer/application_relayer.go b/relayer/application_relayer.go index 499d7fbc..ad114b31 100644 --- a/relayer/application_relayer.go +++ b/relayer/application_relayer.go @@ -142,7 +142,7 @@ func (r *ApplicationRelayer) ProcessHeight( handlers []messages.MessageHandler, errChan chan error, ) { - r.logger.Debug( + r.logger.Verbo( "Processing block", zap.Uint64("height", height), zap.Stringer("relayerID", r.relayerID.ID), @@ -167,7 +167,7 @@ func (r *ApplicationRelayer) ProcessHeight( return } r.checkpointManager.StageCommittedHeight(height) - r.logger.Debug( + r.logger.Verbo( "Processed block", zap.Uint64("height", height), zap.String("sourceBlockchainID", r.relayerID.SourceBlockchainID.String()), diff --git a/relayer/checkpoint/checkpoint.go b/relayer/checkpoint/checkpoint.go index c864b09b..f3b3bc5c 100644 --- a/relayer/checkpoint/checkpoint.go +++ b/relayer/checkpoint/checkpoint.go @@ -76,7 +76,7 @@ func (cm *CheckpointManager) writeToDatabase() { if storedHeight >= cm.committedHeight { return } - cm.logger.Debug( + cm.logger.Verbo( "Writing height", zap.Uint64("height", cm.committedHeight), zap.String("relayerID", cm.relayerID.ID.String()), @@ -123,16 +123,16 @@ func (cm *CheckpointManager) StageCommittedHeight(height uint64) { // First push the height onto the pending commits min heap // This will ensure that the heights are committed in order heap.Push(cm.pendingCommits, height) - cm.logger.Debug( + cm.logger.Verbo( "Pending committed heights", - zap.Any("pendingCommits", cm.pendingCommits), + zap.Any("maxPendingHeight", height), zap.Uint64("maxCommittedHeight", cm.committedHeight), zap.String("relayerID", cm.relayerID.ID.String()), ) for cm.pendingCommits.Peek() == cm.committedHeight+1 { h := heap.Pop(cm.pendingCommits).(uint64) - cm.logger.Debug( + cm.logger.Verbo( "Committing height", zap.Uint64("height", height), zap.String("relayerID", cm.relayerID.ID.String()), diff --git a/relayer/config/destination_blockchain.go b/relayer/config/destination_blockchain.go index 2828468f..2e0ef31e 100644 --- a/relayer/config/destination_blockchain.go +++ b/relayer/config/destination_blockchain.go @@ -13,6 +13,12 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) +const ( + // The block gas limit that can be specified for a Teleporter message + // Based on the C-Chain 15_000_000 gas limit per block, with other Warp message gas overhead conservatively estimated. + defaultBlockGasLimit = 12_000_000 +) + // Destination blockchain configuration. Specifies how to connect to and issue // transactions on the destination blockchain. type DestinationBlockchain struct { @@ -23,6 +29,7 @@ type DestinationBlockchain struct { KMSKeyID string `mapstructure:"kms-key-id" json:"kms-key-id"` KMSAWSRegion string `mapstructure:"kms-aws-region" json:"kms-aws-region"` AccountPrivateKey string `mapstructure:"account-private-key" json:"account-private-key"` + BlockGasLimit uint64 `mapstructure:"block-gas-limit" json:"block-gas-limit"` // Fetched from the chain after startup warpConfig WarpConfig @@ -34,6 +41,9 @@ type DestinationBlockchain struct { // Validates the destination subnet configuration func (s *DestinationBlockchain) Validate() error { + if s.BlockGasLimit == 0 { + s.BlockGasLimit = defaultBlockGasLimit + } if err := s.RPCEndpoint.Validate(); err != nil { return fmt.Errorf("invalid rpc-endpoint in destination subnet configuration: %w", err) } @@ -68,6 +78,11 @@ func (s *DestinationBlockchain) Validate() error { } s.subnetID = subnetID + if s.subnetID == constants.PrimaryNetworkID && + s.BlockGasLimit > defaultBlockGasLimit { + return fmt.Errorf("C-Chain block-gas-limit '%d' exceeded", s.BlockGasLimit) + } + return nil } diff --git a/relayer/listener.go b/relayer/listener.go index bb17bd66..c6d90a1a 100644 --- a/relayer/listener.go +++ b/relayer/listener.go @@ -40,7 +40,7 @@ type Listener struct { messageCoordinator *MessageCoordinator } -// runListener creates a Listener instance and the ApplicationRelayers for a subnet. +// RunListener creates a Listener instance and the ApplicationRelayers for a subnet. // The Listener listens for warp messages on that subnet, and the ApplicationRelayers handle delivery to the destination func RunListener( ctx context.Context, diff --git a/relayer/main/main.go b/relayer/main/main.go index 784c2427..4a6b012a 100644 --- a/relayer/main/main.go +++ b/relayer/main/main.go @@ -266,8 +266,10 @@ func main() { sourceClients, ) + networkHealthFunc := peers.GetNetworkHealthFunc(network, cfg.GetTrackedSubnets().List()) + // Each Listener goroutine will have an atomic bool that it can set to false to indicate an unrecoverable error - api.HandleHealthCheck(logger, relayerHealth) + api.HandleHealthCheck(logger, relayerHealth, networkHealthFunc) api.HandleRelay(logger, messageCoordinator) api.HandleRelayMessage(logger, messageCoordinator) @@ -428,7 +430,7 @@ func createApplicationRelayers( return applicationRelayers, minHeights, nil } -// createApplicationRelayers creates Application Relayers for a given source blockchain. +// createApplicationRelayersForSourceChain creates Application Relayers for a given source blockchain. func createApplicationRelayersForSourceChain( ctx context.Context, logger logging.Logger, diff --git a/relayer/message_coordinator.go b/relayer/message_coordinator.go index 69653620..439bc834 100644 --- a/relayer/message_coordinator.go +++ b/relayer/message_coordinator.go @@ -24,7 +24,7 @@ import ( // MessageCoordinator contains all the logic required to process messages in the relayer. // Other components such as the listeners or the API should pass messages to the MessageCoordinator -// so that it can parse the message(s) and pass them the the proper ApplicationRelayer. +// so that it can parse the message(s) and pass them the proper ApplicationRelayer. type MessageCoordinator struct { logger logging.Logger // Maps Source blockchain ID and protocol address to a Message Handler Factory @@ -268,7 +268,7 @@ func (mc *MessageCoordinator) ProcessBlock( // Dispatch all messages in the block to the appropriate application relayer. // An empty slice is still a valid argument to ProcessHeight; in this case the height is immediately committed. handlers := messageHandlers[appRelayer.relayerID.ID] - mc.logger.Debug( + mc.logger.Verbo( "Dispatching to app relayer", zap.Stringer("relayerID", appRelayer.relayerID.ID), zap.Int("numMessages", len(handlers)), diff --git a/relayer/network_utils.go b/relayer/network_utils.go index 179c9711..443444c8 100644 --- a/relayer/network_utils.go +++ b/relayer/network_utils.go @@ -58,7 +58,8 @@ func connectToNonPrimaryNetworkPeers( sourceBlockchain *config.SourceBlockchain, ) error { subnetID := sourceBlockchain.GetSubnetID() - connectedValidators, err := network.ConnectToCanonicalValidators(subnetID) + network.TrackSubnet(subnetID) + connectedValidators, err := network.GetConnectedCanonicalValidators(subnetID) if err != nil { logger.Error( "Failed to connect to canonical validators", @@ -94,7 +95,8 @@ func connectToPrimaryNetworkPeers( for _, destination := range sourceBlockchain.SupportedDestinations { blockchainID := destination.GetBlockchainID() subnetID := cfg.GetSubnetID(blockchainID) - connectedValidators, err := network.ConnectToCanonicalValidators(subnetID) + network.TrackSubnet(subnetID) + connectedValidators, err := network.GetConnectedCanonicalValidators(subnetID) if err != nil { logger.Error( "Failed to connect to canonical validators", diff --git a/scripts/abi_bindings.sh b/scripts/abi_bindings.sh index 75fde5d6..137617cb 100755 --- a/scripts/abi_bindings.sh +++ b/scripts/abi_bindings.sh @@ -11,7 +11,7 @@ ICM_RELAYER_PATH=$( source $ICM_RELAYER_PATH/scripts/constants.sh source $ICM_RELAYER_PATH/scripts/versions.sh -source $TELEPORTER_PATH/scripts/utils.sh +source $ICM_CONTRACTS_PATH/scripts/utils.sh setARCH diff --git a/scripts/build_relayer.sh b/scripts/build_relayer.sh index 447ba1fb..141cff32 100755 --- a/scripts/build_relayer.sh +++ b/scripts/build_relayer.sh @@ -11,7 +11,7 @@ go_version() { } version_lt() { - # Return true if $1 is a lower version than than $2, + # Return true if $1 is a lower version than $2, local ver1=$1 local ver2=$2 # Reverse sort the versions, if the 1st item != ver1 then ver1 < ver2 diff --git a/scripts/build_signature_aggregator.sh b/scripts/build_signature_aggregator.sh index 57d3daa8..c118a720 100755 --- a/scripts/build_signature_aggregator.sh +++ b/scripts/build_signature_aggregator.sh @@ -11,7 +11,7 @@ go_version() { } version_lt() { - # Return true if $1 is a lower version than than $2, + # Return true if $1 is a lower version than $2, local ver1=$1 local ver2=$2 # Reverse sort the versions, if the 1st item != ver1 then ver1 < ver2 diff --git a/scripts/constants.sh b/scripts/constants.sh index e0be0bc3..418ef9a6 100755 --- a/scripts/constants.sh +++ b/scripts/constants.sh @@ -27,8 +27,8 @@ signature_aggregator_path="$BASE_PATH/build/signature-aggregator" # Set the PATHS GOPATH="$(go env GOPATH)" -TELEPORTER_PATH="$BASE_PATH"/tests/contracts/lib/teleporter -source $TELEPORTER_PATH/scripts/constants.sh +ICM_CONTRACTS_PATH="$BASE_PATH"/tests/contracts/lib/icm-contracts +source $ICM_CONTRACTS_PATH/scripts/constants.sh # Avalabs docker hub repo is avaplatform/icm-relayer. # Here we default to the local image (icm-relayer) as to avoid unintentional pushes diff --git a/scripts/e2e_test.sh b/scripts/e2e_test.sh index 6fad06ff..bdb0091a 100755 --- a/scripts/e2e_test.sh +++ b/scripts/e2e_test.sh @@ -38,7 +38,9 @@ cwd=$(pwd) # Install the avalanchego and subnet-evm binaries rm -rf $BASEDIR/avalanchego BASEDIR=$BASEDIR AVALANCHEGO_BUILD_PATH=$BASEDIR/avalanchego ./scripts/install_avalanchego_release.sh -BASEDIR=$BASEDIR "${TELEPORTER_PATH}/scripts/install_subnetevm_release.sh" +BASEDIR=$BASEDIR "${ICM_CONTRACTS_PATH}/scripts/install_subnetevm_release.sh" +# Install the signature aggregator binary version that the icm-contracts repo expects for the tests +BASEDIR=$BASEDIR "${ICM_CONTRACTS_PATH}/scripts/install_sig_agg_release.sh" cp ${BASEDIR}/subnet-evm/subnet-evm ${BASEDIR}/avalanchego/plugins/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy echo "Copied ${BASEDIR}/subnet-evm/subnet-evm binary to ${BASEDIR}/avalanchego/plugins/" @@ -54,7 +56,7 @@ go build -v -o tests/cmd/decider/decider ./tests/cmd/decider/ # Run the tests echo "Running e2e tests $RUN_E2E" -RUN_E2E=true LOG_LEVEL=${LOG_LEVEL} ./tests/tests.test \ +RUN_E2E=true LOG_LEVEL=${LOG_LEVEL} SIG_AGG_PATH=${SIG_AGG_PATH:-"$BASEDIR/icm-services/signature-aggregator"} ./tests/tests.test \ --ginkgo.vv \ --ginkgo.label-filter=${GINKGO_LABEL_FILTER:-""} \ --ginkgo.focus=${GINKGO_FOCUS:-""} diff --git a/scripts/install_avalanchego_release.sh b/scripts/install_avalanchego_release.sh index 420a885e..5946e79e 100755 --- a/scripts/install_avalanchego_release.sh +++ b/scripts/install_avalanchego_release.sh @@ -72,7 +72,7 @@ else git clone --no-checkout ${GIT_CLONE_URL} ${GIT_CLONE_PATH} fi - # check to see if the commitish exists in the repo + # check to see if the commit hash exists in the repo WORKDIR=$(pwd) cd ${GIT_CLONE_PATH} diff --git a/scripts/versions.sh b/scripts/versions.sh index 675b0a28..6dcf4e46 100755 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -13,18 +13,26 @@ function getDepVersion() { grep -m1 "^\s*$1" $BASE_PATH/go.mod | cut -d ' ' -f2 } +function extract_commit() { + local version=$1 + + # Regex for a commit hash (assumed to be a 12+ character hex string) + commit_hash_regex="-([0-9a-f]{12,})$" + + if [[ "$version" =~ $commit_hash_regex ]]; then + # Extract the substring after the last '-' + version=${BASH_REMATCH[1]} + fi + echo "$version" +} + # This needs to be exported to be picked up by the dockerfile. export GO_VERSION=${GO_VERSION:-$(getDepVersion go)} # Don't export them as they're used in the context of other calls -AVALANCHEGO_VERSION=${AVALANCHEGO_VERSION:-$(getDepVersion github.com/ava-labs/avalanchego)} -# Temporarily hardcode the Avalanchego version until outbound networking relaxation is available -AVALANCHEGO_VERSION=v1.12.0 -GINKGO_VERSION=${GINKGO_VERSION:-$(getDepVersion github.com/onsi/ginkgo/v2)} - -SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-$(getDepVersion github.com/ava-labs/subnet-evm)} -# Temporarily harcode the Subnet EVM version until there is a tagged release -SUBNET_EVM_VERSION=6c98da796f359335f2dcfd1151af191584be8d74 +AVALANCHEGO_VERSION=${AVALANCHEGO_VERSION:-$(extract_commit "$(getDepVersion github.com/ava-labs/avalanchego)")} +GINKGO_VERSION=${GINKGO_VERSION:-$(extract_commit "$(getDepVersion github.com/onsi/ginkgo/v2)")} +SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-$(extract_commit "$(getDepVersion github.com/ava-labs/subnet-evm)")} # Set golangci-lint version GOLANGCI_LINT_VERSION=${GOLANGCI_LINT_VERSION:-'v1.60'} diff --git a/signature-aggregator/.goreleaser.yml b/signature-aggregator/.goreleaser.yml index 83a665b7..4df5dbcd 100644 --- a/signature-aggregator/.goreleaser.yml +++ b/signature-aggregator/.goreleaser.yml @@ -31,9 +31,11 @@ builds: goarm64: v8.0 env: - CC=oa64-clang - ignore: - goos: darwin goarch: amd64 + goamd64: v1 + env: + - CC=o64-clang dockers: - image_templates: - 'avaplatform/signature-aggregator:{{ .Tag }}-amd64' diff --git a/signature-aggregator/aggregator/aggregator.go b/signature-aggregator/aggregator/aggregator.go index 5249160e..e3943c41 100644 --- a/signature-aggregator/aggregator/aggregator.go +++ b/signature-aggregator/aggregator/aggregator.go @@ -38,7 +38,10 @@ type blsSignatureBuf [bls.SignatureLen]byte const ( // Maximum amount of time to spend waiting (in addition to network round trip time per attempt) // during relayer signature query routine - signatureRequestTimeout = 20 * time.Second + signatureRequestTimeout = 5 * time.Second + // Maximum amount of time to spend waiting for a connection to a quorum of validators for + // a given subnetID + connectToValidatorsTimeout = 5 * time.Second ) var ( @@ -90,6 +93,54 @@ func (s *SignatureAggregator) Shutdown() { s.network.Shutdown() } +func (s *SignatureAggregator) connectToQuorumValidators( + signingSubnet ids.ID, + quorumPercentage uint64, +) (*peers.ConnectedCanonicalValidators, error) { + s.network.TrackSubnet(signingSubnet) + + var connectedValidators *peers.ConnectedCanonicalValidators + var err error + connectOp := func() error { + connectedValidators, err = s.network.GetConnectedCanonicalValidators(signingSubnet) + if err != nil { + msg := "Failed to fetch connected canonical validators" + s.logger.Error( + msg, + zap.Error(err), + ) + s.metrics.FailuresToGetValidatorSet.Inc() + return fmt.Errorf("%s: %w", msg, err) + } + s.metrics.ConnectedStakeWeightPercentage.WithLabelValues( + signingSubnet.String(), + ).Set( + float64(connectedValidators.ConnectedWeight) / + float64(connectedValidators.TotalValidatorWeight) * 100, + ) + if !utils.CheckStakeWeightExceedsThreshold( + big.NewInt(0).SetUint64(connectedValidators.ConnectedWeight), + connectedValidators.TotalValidatorWeight, + quorumPercentage, + ) { + s.logger.Warn( + "Failed to connect to a threshold of stake", + zap.Uint64("connectedWeight", connectedValidators.ConnectedWeight), + zap.Uint64("totalValidatorWeight", connectedValidators.TotalValidatorWeight), + zap.Uint64("quorumPercentage", quorumPercentage), + ) + s.metrics.FailuresToConnectToSufficientStake.Inc() + return errNotEnoughConnectedStake + } + return nil + } + err = utils.WithRetriesTimeout(s.logger, connectOp, connectToValidatorsTimeout) + if err != nil { + return nil, err + } + return connectedValidators, nil +} + func (s *SignatureAggregator) CreateSignedMessage( unsignedMessage *avalancheWarp.UnsignedMessage, justification []byte, @@ -118,42 +169,17 @@ func (s *SignatureAggregator) CreateSignedMessage( zap.Stringer("signingSubnet", signingSubnet), ) - connectedValidators, err := s.network.ConnectToCanonicalValidators(signingSubnet) + connectedValidators, err := s.connectToQuorumValidators(signingSubnet, quorumPercentage) if err != nil { - msg := "Failed to connect to canonical validators" s.logger.Error( - msg, - zap.String("warpMessageID", unsignedMessage.ID().String()), + "Failed to fetch quorum of connected canonical validators", + zap.Stringer("signingSubnet", signingSubnet), zap.Error(err), ) - s.metrics.FailuresToGetValidatorSet.Inc() - return nil, fmt.Errorf("%s: %w", msg, err) - } - s.logger.Debug("Connected to canonical validators", zap.String("warpMessageID", unsignedMessage.ID().String())) - s.metrics.ConnectedStakeWeightPercentage.WithLabelValues( - signingSubnet.String(), - ).Set( - float64(connectedValidators.ConnectedWeight) / - float64(connectedValidators.TotalValidatorWeight) * 100, - ) - - if !utils.CheckStakeWeightExceedsThreshold( - big.NewInt(0).SetUint64(connectedValidators.ConnectedWeight), - connectedValidators.TotalValidatorWeight, - quorumPercentage, - ) { - s.logger.Error( - "Failed to connect to a threshold of stake", - zap.Uint64("connectedWeight", connectedValidators.ConnectedWeight), - zap.Uint64("totalValidatorWeight", connectedValidators.TotalValidatorWeight), - zap.Uint64("quorumPercentage", quorumPercentage), - ) - s.metrics.FailuresToConnectToSufficientStake.Inc() - return nil, errNotEnoughConnectedStake + return nil, err } accumulatedSignatureWeight := big.NewInt(0) - signatureMap := make(map[int][bls.SignatureLen]byte) if cachedSignatures, ok := s.cache.Get(unsignedMessage.ID()); ok { for i, validator := range connectedValidators.ValidatorSet { @@ -521,7 +547,7 @@ func (s *SignatureAggregator) isValidSignatureResponse( return blsSignatureBuf{}, false } - signature, err := s.unmarshalResponse(appResponse.AppBytes) + signature, err := s.unmarshalResponse(appResponse.GetAppBytes()) if err != nil { s.logger.Error( "Error unmarshaling signature response", @@ -618,6 +644,10 @@ func (s *SignatureAggregator) marshalRequest( } func (s *SignatureAggregator) unmarshalResponse(responseBytes []byte) (blsSignatureBuf, error) { + // empty responses are valid and indicate the node has not seen the message + if len(responseBytes) == 0 { + return blsSignatureBuf{}, nil + } var sigResponse sdk.SignatureResponse err := proto.Unmarshal(responseBytes, &sigResponse) if err != nil { diff --git a/signature-aggregator/aggregator/aggregator_test.go b/signature-aggregator/aggregator/aggregator_test.go index fba03efc..cb0d7d3c 100644 --- a/signature-aggregator/aggregator/aggregator_test.go +++ b/signature-aggregator/aggregator/aggregator_test.go @@ -6,6 +6,8 @@ import ( "os" "testing" + "crypto/rand" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/message" "github.com/ava-labs/avalanchego/proto/pb/sdk" @@ -74,7 +76,7 @@ func instantiateAggregator(t *testing.T) ( // Generate the validator values. type validatorInfo struct { nodeID ids.NodeID - blsSecretKey *bls.SecretKey + blsSigner *bls.LocalSigner blsPublicKey *bls.PublicKey blsPublicKeyBytes []byte } @@ -83,18 +85,18 @@ func (v validatorInfo) Compare(o validatorInfo) int { return bytes.Compare(v.blsPublicKeyBytes, o.blsPublicKeyBytes) } -func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValidators, []*bls.SecretKey) { +func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValidators, []*bls.LocalSigner) { validatorValues := make([]validatorInfo, validatorCount) for i := 0; i < validatorCount; i++ { - secretKey, err := bls.NewSecretKey() + localSigner, err := bls.NewSigner() if err != nil { panic(err) } - pubKey := bls.PublicFromSecretKey(secretKey) + pubKey := localSigner.PublicKey() nodeID := ids.GenerateTestNodeID() validatorValues[i] = validatorInfo{ nodeID: nodeID, - blsSecretKey: secretKey, + blsSigner: localSigner, blsPublicKey: pubKey, blsPublicKeyBytes: bls.PublicKeyToUncompressedBytes(pubKey), } @@ -105,10 +107,10 @@ func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValid // Placeholder for results validatorSet := make([]*warp.Validator, validatorCount) - validatorSecretKeys := make([]*bls.SecretKey, validatorCount) + validatorSigners := make([]*bls.LocalSigner, validatorCount) nodeValidatorIndexMap := make(map[ids.NodeID]int) for i, validator := range validatorValues { - validatorSecretKeys[i] = validator.blsSecretKey + validatorSigners[i] = validator.blsSigner validatorSet[i] = &warp.Validator{ PublicKey: validator.blsPublicKey, PublicKeyBytes: validator.blsPublicKeyBytes, @@ -123,7 +125,7 @@ func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValid TotalValidatorWeight: uint64(validatorCount), ValidatorSet: validatorSet, NodeValidatorIndexMap: nodeValidatorIndexMap, - }, validatorSecretKeys + }, validatorSigners } func TestCreateSignedMessageFailsWithNoValidators(t *testing.T) { @@ -131,7 +133,8 @@ func TestCreateSignedMessageFailsWithNoValidators(t *testing.T) { msg, err := warp.NewUnsignedMessage(0, ids.Empty, []byte{}) require.NoError(t, err) mockNetwork.EXPECT().GetSubnetID(ids.Empty).Return(ids.Empty, nil) - mockNetwork.EXPECT().ConnectToCanonicalValidators(ids.Empty).Return( + mockNetwork.EXPECT().TrackSubnet(ids.Empty) + mockNetwork.EXPECT().GetConnectedCanonicalValidators(ids.Empty).Return( &peers.ConnectedCanonicalValidators{ ConnectedWeight: 0, TotalValidatorWeight: 0, @@ -148,14 +151,15 @@ func TestCreateSignedMessageFailsWithoutSufficientConnectedStake(t *testing.T) { msg, err := warp.NewUnsignedMessage(0, ids.Empty, []byte{}) require.NoError(t, err) mockNetwork.EXPECT().GetSubnetID(ids.Empty).Return(ids.Empty, nil) - mockNetwork.EXPECT().ConnectToCanonicalValidators(ids.Empty).Return( + mockNetwork.EXPECT().TrackSubnet(ids.Empty) + mockNetwork.EXPECT().GetConnectedCanonicalValidators(ids.Empty).Return( &peers.ConnectedCanonicalValidators{ ConnectedWeight: 0, TotalValidatorWeight: 1, ValidatorSet: []*warp.Validator{}, }, nil, - ) + ).AnyTimes() _, err = aggregator.CreateSignedMessage(msg, nil, ids.Empty, 80) require.ErrorContains( t, @@ -207,7 +211,8 @@ func TestCreateSignedMessageRetriesAndFailsWithoutP2PResponses(t *testing.T) { nil, ) - mockNetwork.EXPECT().ConnectToCanonicalValidators(subnetID).Return( + mockNetwork.EXPECT().TrackSubnet(subnetID) + mockNetwork.EXPECT().GetConnectedCanonicalValidators(subnetID).Return( connectedValidators, nil, ) @@ -255,7 +260,7 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { require.NoError(t, err) // the signers: - connectedValidators, validatorSecretKeys := makeConnectedValidators(5) + connectedValidators, validatorSigners := makeConnectedValidators(5) // prime the aggregator: @@ -267,7 +272,8 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { nil, ) - mockNetwork.EXPECT().ConnectToCanonicalValidators(subnetID).Return( + mockNetwork.EXPECT().TrackSubnet(subnetID) + mockNetwork.EXPECT().GetConnectedCanonicalValidators(subnetID).Return( connectedValidators, nil, ) @@ -285,14 +291,11 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { responseChan := make(chan message.InboundMessage, len(appRequests)) for _, appRequest := range appRequests { nodeIDs.Add(appRequest.NodeID) - validatorSecretKey := validatorSecretKeys[connectedValidators.NodeValidatorIndexMap[appRequest.NodeID]] + validatorSigner := validatorSigners[connectedValidators.NodeValidatorIndexMap[appRequest.NodeID]] responseBytes, err := proto.Marshal( &sdk.SignatureResponse{ Signature: bls.SignatureToBytes( - bls.Sign( - validatorSecretKey, - msg.Bytes(), - ), + validatorSigner.Sign(msg.Bytes()), ), }, ) @@ -345,6 +348,54 @@ func TestCreateSignedMessageSucceeds(t *testing.T) { require.NoError(t, verifyErr) } +func TestUnmarshalResponse(t *testing.T) { + aggregator, _ := instantiateAggregator(t) + + emptySignatureResponse, err := proto.Marshal(&sdk.SignatureResponse{Signature: []byte{}}) + require.NoError(t, err) + + randSignature := make([]byte, 96) + _, err = rand.Read(randSignature) + require.NoError(t, err) + + randSignatureResponse, err := proto.Marshal(&sdk.SignatureResponse{Signature: randSignature}) + require.NoError(t, err) + + testCases := []struct { + name string + appResponseBytes []byte + expectedSignature blsSignatureBuf + }{ + { + name: "empty slice", + appResponseBytes: []byte{}, + expectedSignature: blsSignatureBuf{}, + }, + { + name: "nil slice", + appResponseBytes: nil, + expectedSignature: blsSignatureBuf{}, + }, + { + name: "empty signature", + appResponseBytes: emptySignatureResponse, + expectedSignature: blsSignatureBuf{}, + }, + { + name: "random signature", + appResponseBytes: randSignatureResponse, + expectedSignature: blsSignatureBuf(randSignature), + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + signature, err := aggregator.unmarshalResponse(tc.appResponseBytes) + require.NoError(t, err) + require.Equal(t, tc.expectedSignature, signature) + }) + } +} + type pChainStateStub struct { subnetIDByChainID map[ids.ID]ids.ID connectedCanonicalValidators *peers.ConnectedCanonicalValidators diff --git a/signature-aggregator/healthcheck/healthcheck.go b/signature-aggregator/healthcheck/healthcheck.go index 9c378cee..14349c81 100644 --- a/signature-aggregator/healthcheck/healthcheck.go +++ b/signature-aggregator/healthcheck/healthcheck.go @@ -7,11 +7,11 @@ import ( "github.com/alexliesenfeld/health" ) -func HandleHealthCheckRequest() { +func HandleHealthCheckRequest(checkFunc func(context.Context) error) { healthChecker := health.NewChecker( health.WithCheck(health.Check{ - Name: "signature-aggregator", - Check: func(context.Context) error { return nil }, + Name: "signature-aggregator-health", + Check: checkFunc, }), ) diff --git a/signature-aggregator/main/main.go b/signature-aggregator/main/main.go index 3340a380..dc7a4095 100644 --- a/signature-aggregator/main/main.go +++ b/signature-aggregator/main/main.go @@ -139,7 +139,11 @@ func main() { metricsInstance, signatureAggregator, ) - healthcheck.HandleHealthCheckRequest() + + healthCheckSubnets := cfg.GetTrackedSubnets().List() + healthCheckSubnets = append(healthCheckSubnets, constants.PrimaryNetworkID) + networkHealthcheckFunc := peers.GetNetworkHealthFunc(network, healthCheckSubnets) + healthcheck.HandleHealthCheckRequest(networkHealthcheckFunc) logger.Info("Initialization complete") err = http.ListenAndServe(fmt.Sprintf(":%d", cfg.APIPort), nil) diff --git a/tests/contracts/lib/icm-contracts b/tests/contracts/lib/icm-contracts new file mode 160000 index 00000000..ae24f1f2 --- /dev/null +++ b/tests/contracts/lib/icm-contracts @@ -0,0 +1 @@ +Subproject commit ae24f1f2636ff0d895f40a5cb0e657ecddf6b7be diff --git a/tests/contracts/lib/teleporter b/tests/contracts/lib/teleporter deleted file mode 160000 index fc146e9f..00000000 --- a/tests/contracts/lib/teleporter +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fc146e9f23423397fdbfff854646e2c4d1db0fa5 diff --git a/tests/contracts/src/BatchCrossChainMessenger.sol b/tests/contracts/src/BatchCrossChainMessenger.sol index 33b0f471..3d936b8f 100644 --- a/tests/contracts/src/BatchCrossChainMessenger.sol +++ b/tests/contracts/src/BatchCrossChainMessenger.sol @@ -31,7 +31,7 @@ contract BatchCrossChainMessenger is ReentrancyGuard, TeleporterOwnerUpgradeable mapping(bytes32 sourceBlockchainID => string[] messages) private _messages; /** - * @dev Emitted when a message is submited to be sent. + * @dev Emitted when a message is submitted to be sent. */ event SendMessages( bytes32 indexed destinationBlockchainID, diff --git a/tests/utils/utils.go b/tests/utils/utils.go index 9f438695..1241019e 100644 --- a/tests/utils/utils.go +++ b/tests/utils/utils.go @@ -133,7 +133,7 @@ func CreateDefaultRelayerConfig( Expect(err).Should(BeNil()) sources[i] = &relayercfg.SourceBlockchain{ - SubnetID: l1Info.L1ID.String(), + SubnetID: l1Info.SubnetID.String(), BlockchainID: l1Info.BlockchainID.String(), VM: relayercfg.EVM.String(), RPCEndpoint: config.APIConfig{ @@ -161,7 +161,7 @@ func CreateDefaultRelayerConfig( log.Info( "Creating relayer config for source subnet", - "subnetID", l1Info.L1ID.String(), + "subnetID", l1Info.SubnetID.String(), "blockchainID", l1Info.BlockchainID.String(), "host", host, "port", port, @@ -173,7 +173,7 @@ func CreateDefaultRelayerConfig( Expect(err).Should(BeNil()) destinations[i] = &relayercfg.DestinationBlockchain{ - SubnetID: l1Info.L1ID.String(), + SubnetID: l1Info.SubnetID.String(), BlockchainID: l1Info.BlockchainID.String(), VM: relayercfg.EVM.String(), RPCEndpoint: config.APIConfig{ @@ -184,7 +184,7 @@ func CreateDefaultRelayerConfig( log.Info( "Creating relayer config for destination subnet", - "subnetID", l1Info.L1ID.String(), + "subnetID", l1Info.SubnetID.String(), "blockchainID", l1Info.BlockchainID.String(), "host", host, "port", port, diff --git a/utils/client_utils.go b/utils/client_utils.go index 410fa0b9..aa8a04be 100644 --- a/utils/client_utils.go +++ b/utils/client_utils.go @@ -60,7 +60,7 @@ func addQueryParams(endpoint string, queryParams map[string]string) (string, err return uri.String(), nil } -// newClientOptions creates a ClientOption slice from httpHeaders +// newClientHeaderOptions creates a ClientOption slice from httpHeaders func newClientHeaderOptions(httpHeaders map[string]string) []rpc.ClientOption { opts := make([]rpc.ClientOption, 0, len(httpHeaders)) for key, value := range httpHeaders { diff --git a/utils/utils.go b/utils/utils.go index afa49f26..a4d61fa1 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -86,7 +86,7 @@ func CallWithRetry[T any](ctx context.Context, f func() (T, error)) (T, error) { // // BigToHashSafe ensures that a bignum value is able to fit into a 32 byte buffer before converting it to a common.Hash -// Returns an error if overflow/truncation would occur by trying to perfom this operation. +// Returns an error if overflow/truncation would occur by trying to perform this operation. func BigToHashSafe(in *big.Int) (common.Hash, error) { if in == nil { return common.Hash{}, ErrNilInput diff --git a/vms/destination_client.go b/vms/destination_client.go index 81103b01..d2300996 100644 --- a/vms/destination_client.go +++ b/vms/destination_client.go @@ -34,9 +34,14 @@ type DestinationClient interface { // DestinationBlockchainID returns the ID of the destination chain DestinationBlockchainID() ids.ID + + // BlockGasLimit returns destination blockchain block gas limit + BlockGasLimit() uint64 } -func NewDestinationClient(logger logging.Logger, subnetInfo *config.DestinationBlockchain) (DestinationClient, error) { +func NewDestinationClient( + logger logging.Logger, subnetInfo *config.DestinationBlockchain, +) (DestinationClient, error) { switch config.ParseVM(subnetInfo.VM) { case config.EVM: return evm.NewDestinationClient(logger, subnetInfo) diff --git a/vms/evm/destination_client.go b/vms/evm/destination_client.go index 9c1579b8..6c57e93d 100644 --- a/vms/evm/destination_client.go +++ b/vms/evm/destination_client.go @@ -44,6 +44,7 @@ type destinationClient struct { signer signer.Signer evmChainID *big.Int currentNonce uint64 + blockGasLimit uint64 logger logging.Logger } @@ -51,34 +52,34 @@ func NewDestinationClient( logger logging.Logger, destinationBlockchain *config.DestinationBlockchain, ) (*destinationClient, error) { - // Dial the destination RPC endpoint - client, err := utils.NewEthClientWithConfig( - context.Background(), - destinationBlockchain.RPCEndpoint.BaseURL, - destinationBlockchain.RPCEndpoint.HTTPHeaders, - destinationBlockchain.RPCEndpoint.QueryParams, - ) + destinationID, err := ids.FromString(destinationBlockchain.BlockchainID) if err != nil { logger.Error( - "Failed to dial rpc endpoint", + "Could not decode destination chain ID from string", zap.Error(err), ) return nil, err } - destinationID, err := ids.FromString(destinationBlockchain.BlockchainID) + sgnr, err := signer.NewSigner(destinationBlockchain) if err != nil { logger.Error( - "Could not decode destination chain ID from string", + "Failed to create signer", zap.Error(err), ) return nil, err } - sgnr, err := signer.NewSigner(destinationBlockchain) + // Dial the destination RPC endpoint + client, err := utils.NewEthClientWithConfig( + context.Background(), + destinationBlockchain.RPCEndpoint.BaseURL, + destinationBlockchain.RPCEndpoint.HTTPHeaders, + destinationBlockchain.RPCEndpoint.QueryParams, + ) if err != nil { logger.Error( - "Failed to create signer", + "Failed to dial rpc endpoint", zap.Error(err), ) return nil, err @@ -117,6 +118,7 @@ func NewDestinationClient( evmChainID: evmChainID, currentNonce: nonce, logger: logger, + blockGasLimit: destinationBlockchain.BlockGasLimit, }, nil } @@ -210,3 +212,7 @@ func (c *destinationClient) SenderAddress() common.Address { func (c *destinationClient) DestinationBlockchainID() ids.ID { return c.destinationBlockchainID } + +func (c *destinationClient) BlockGasLimit() uint64 { + return c.blockGasLimit +} diff --git a/vms/mocks/mock_destination_client.go b/vms/mocks/mock_destination_client.go index 3fdf0305..43b9852d 100644 --- a/vms/mocks/mock_destination_client.go +++ b/vms/mocks/mock_destination_client.go @@ -42,6 +42,20 @@ func (m *MockDestinationClient) EXPECT() *MockDestinationClientMockRecorder { return m.recorder } +// BlockGasLimit mocks base method. +func (m *MockDestinationClient) BlockGasLimit() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BlockGasLimit") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// BlockGasLimit indicates an expected call of BlockGasLimit. +func (mr *MockDestinationClientMockRecorder) BlockGasLimit() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockGasLimit", reflect.TypeOf((*MockDestinationClient)(nil).BlockGasLimit)) +} + // Client mocks base method. func (m *MockDestinationClient) Client() any { m.ctrl.T.Helper()