diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 480981b3..6f5e0a93 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -17,10 +17,6 @@ updates: - dependency-name: "github.com/ethereum/go-ethereum" # Avalanchego is updated to stay compatible with subnet-evm - dependency-name: "github.com/ava-labs/avalanchego" - - package-ecosystem: "gitsubmodule" - directory: "/" - schedule: - interval: "daily" - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/README.md b/README.md index a2fbe8e8..79e0708f 100644 --- a/README.md +++ b/README.md @@ -40,4 +40,33 @@ Running the tests locally doesn't require publishing the `subnet-evm` commit sin > Locally running E2E tests using local checkout of `subnet-evm` will install `avalanchego` version specified by the `AVALANCHEGO_VERSION` in that working tree's `./scripts/versions.sh`. > [!TIP] -> Using the local checkout it's possible to run tests against a `tmpnet` consisting of nodes using a different version of `avalanchego` than the application being tested which might be helpful when troubleshooting. \ No newline at end of file +> Using the local checkout it's possible to run tests against a `tmpnet` consisting of nodes using a different version of `avalanchego` than the application being tested which might be helpful when troubleshooting. + +## Releases +GoReleaser is used to build the binaries of the services and also Docker images with those binaries. The monorepo feature of GoReleaser Pro is used to automate the release flow in response to tags like `signature-aggregator/v0.0.0`. The release actions in .github/workflows automate this, but the release build can also be run locally. Be sure to install the "pro" distribution of the command line utility, so that it can parse the `monorepo` key. For example: + +```bash +$ goreleaser release --single-target --clean --snapshot --config signature-aggregator/.goreleaser.yml +... + • creating archive=dist/linux_amd64/signature-aggregator_0.1.0-rc0-SNAPSHOT-3c2ae78_linux_amd64.tar.gz + • docker images + • building docker image image=avaplatform/signature-aggregator:v0.1.0-rc0-amd64 +``` + +Then: + +```bash +$ docker run -v $(pwd)/signature-aggregator/sample-signature-aggregator-config.json:/config.json avaplatform/signature-aggregator:v0.1.0-rc0-amd64 --config-file /config.json +{"level":"info","timestamp":"2024-09-11T22:25:03.001Z","logger":"signature-aggregator","caller":"main/main.go:76","msg":"Initializing signature-aggregator"} +{"level":"info","timestamp":"2024-09-11T22:25:03.001Z","logger":"signature-aggregator","caller":"main/main.go:79","msg":"Initializing app request network"} +{"level":"debug","timestamp":"2024-09-11T22:25:03.086Z","logger":"p2p-network","caller":"dialer/dialer.go:52","msg":"creating dialer","throttleRPS":50,"dialTimeout":30000000000} +{"level":"info","timestamp":"2024-09-11T22:25:03.086Z","logger":"signature-aggregator","caller":"main/main.go:134","msg":"Initialization complete"} +``` + +Or, for the relayer: + +```bash +$ goreleaser release --single-target --clean --snapshot --config relayer/.goreleaser.yml +... +$ docker run -v $(pwd)/sample-relayer-config.json:/config.json avaplatform/awm-relayer:v1.0.4-test12-amd64 --config-file /config.json +``` diff --git a/go.mod b/go.mod index 60c864d5..8c4ba749 100644 --- a/go.mod +++ b/go.mod @@ -4,27 +4,27 @@ go 1.22.7 require ( github.com/ava-labs/avalanchego v1.11.11 - github.com/ava-labs/coreth v0.13.8-fixed-genesis-upgrade.0.20240815193440-a96bc921e732 - github.com/ava-labs/subnet-evm v0.6.9 + github.com/ava-labs/coreth v0.13.8 + github.com/ava-labs/subnet-evm v0.6.10 github.com/ava-labs/teleporter v1.0.7 - github.com/aws/aws-sdk-go-v2 v1.30.5 + github.com/aws/aws-sdk-go-v2 v1.32.2 github.com/aws/aws-sdk-go-v2/config v1.27.9 - github.com/aws/aws-sdk-go-v2/service/kms v1.35.7 + github.com/aws/aws-sdk-go-v2/service/kms v1.37.2 github.com/ethereum/go-ethereum v1.13.14 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/onsi/ginkgo/v2 v2.20.2 github.com/onsi/gomega v1.34.2 github.com/pingcap/errors v0.11.4 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.20.3 - github.com/redis/go-redis/v9 v9.6.1 + github.com/prometheus/client_golang v1.20.5 + github.com/redis/go-redis/v9 v9.6.2 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.9.0 go.uber.org/mock v0.4.0 go.uber.org/zap v1.27.0 - google.golang.org/grpc v1.66.1 - google.golang.org/protobuf v1.34.2 + google.golang.org/grpc v1.67.1 + google.golang.org/protobuf v1.35.1 ) require ( @@ -33,15 +33,15 @@ require ( github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.17.9 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 // indirect - github.com/aws/smithy-go v1.20.4 // indirect + github.com/aws/smithy-go v1.22.0 // 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 @@ -152,8 +152,8 @@ require ( golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.24.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 80a606f5..c980fcad 100644 --- a/go.sum +++ b/go.sum @@ -60,40 +60,40 @@ 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/ava-labs/avalanchego v1.11.11 h1:MIQq8xRavRj4ZXHA4G+aMiymig7SOScGOG1SApmMvBc= github.com/ava-labs/avalanchego v1.11.11/go.mod h1:yFx3V31Jy9NFa8GZlgGnwiVf8KGjeF2+Uc99l9Scd/8= -github.com/ava-labs/coreth v0.13.8-fixed-genesis-upgrade.0.20240815193440-a96bc921e732 h1:wlhGJbmb7s3bU2QWtxKjscGjfHknQiq+cVhhUjONsB8= -github.com/ava-labs/coreth v0.13.8-fixed-genesis-upgrade.0.20240815193440-a96bc921e732/go.mod h1:RkQLaQ961Xe/sUb3ycn4Qi18vPPuEetTqDf2eDcquAs= -github.com/ava-labs/subnet-evm v0.6.9 h1:0FSPjbysSudOlMD/d0ivkli50d2ixpX3sXCi7XHfPbc= -github.com/ava-labs/subnet-evm v0.6.9/go.mod h1:dw4kg0o58dvYlndj2ZcwB7hioRc1kjg00yXYrcSmnj8= +github.com/ava-labs/coreth v0.13.8 h1:f14X3KgwHl9LwzfxlN6S4bbn5VA2rhEsNnHaRLSTo/8= +github.com/ava-labs/coreth v0.13.8/go.mod h1:t3BSv/eQv0AlDPMfEDCMMoD/jq1RkUsbFzQAFg5qBcE= +github.com/ava-labs/subnet-evm v0.6.10 h1:uIh6bFMA4GCMVMQ3agBPxTMlYHL8FBR5FrhMR+drfKI= +github.com/ava-labs/subnet-evm v0.6.10/go.mod h1:dw4kg0o58dvYlndj2ZcwB7hioRc1kjg00yXYrcSmnj8= github.com/ava-labs/teleporter v1.0.7 h1:9H0wTWhgWeA4u6uxi9KngdBu/LOoYsfAmIZhXNzuvf8= github.com/ava-labs/teleporter v1.0.7/go.mod h1:wgCgU6vU5MtP83otpjEin8jL2jrflVBNQCTxVXMx/kU= -github.com/aws/aws-sdk-go-v2 v1.30.5 h1:mWSRTwQAb0aLE17dSzztCVJWI9+cRMgqebndjwDyK0g= -github.com/aws/aws-sdk-go-v2 v1.30.5/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI= +github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= github.com/aws/aws-sdk-go-v2/config v1.27.9 h1:gRx/NwpNEFSk+yQlgmk1bmxxvQ5TyJ76CWXs9XScTqg= github.com/aws/aws-sdk-go-v2/config v1.27.9/go.mod h1:dK1FQfpwpql83kbD873E9vz4FyAxuJtR22wzoXn3qq0= github.com/aws/aws-sdk-go-v2/credentials v1.17.9 h1:N8s0/7yW+h8qR8WaRlPQeJ6czVMNQVNtNdUqf6cItao= github.com/aws/aws-sdk-go-v2/credentials v1.17.9/go.mod h1:446YhIdmSV0Jf/SLafGZalQo+xr2iw7/fzXGDPTU1yQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 h1:af5YzcLf80tv4Em4jWVD75lpnOHSBkPUZxZfGkrI3HI= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0/go.mod h1:nQ3how7DMnFMWiU1SpECohgC82fpn4cKZ875NDMmwtA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17/go.mod h1:aLJpZlCmjE+V+KtN1q1uyZkfnUWpQGpbsn89XPKyzfU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 h1:UAsR3xA31QGf79WzpG/ixT9FZvQlh5HY1NRqSHBNOCk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21/go.mod h1:JNr43NFf5L9YaG3eKTm7HQzls9J+A9YYcGI5Quh1r2Y= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 h1:6jZVETqmYCadGFvrYEQfC5fAQmlo80CeL5psbno6r0s= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21/go.mod h1:1SR0GbLlnN3QUmYaflZNiH1ql+1qrSiB2vwcJ+4UM60= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 h1:b+E7zIUHMmcB4Dckjpkapoy47W6C9QBv/zoUP+Hn8Kc= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6/go.mod h1:S2fNV0rxrP78NhPbCZeQgY8H9jdDMeGtwcfZIRxzBqU= -github.com/aws/aws-sdk-go-v2/service/kms v1.35.7 h1:v0D1LeMkA/X+JHAZWERrr+sUGOt8KrCZKnJA6KszkcE= -github.com/aws/aws-sdk-go-v2/service/kms v1.35.7/go.mod h1:K9lwD0Rsx9+NSaJKsdAdlDK4b2G4KKOEve9PzHxPoMI= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.2 h1:tfBABi5R6aSZlhgTWHxL+opYUDOnIGoNcJLwVYv0jLM= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.2/go.mod h1:dZYFcQwuoh+cLOlFnZItijZptmyDhRIkOKWFO1CfzV8= github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 h1:mnbuWHOcM70/OFUlZZ5rcdfA8PflGXXiefU/O+1S3+8= github.com/aws/aws-sdk-go-v2/service/sso v1.20.3/go.mod h1:5HFu51Elk+4oRBZVxmHrSds5jFXmFj8C3w7DVF2gnrs= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 h1:uLq0BKatTmDzWa/Nu4WO0M1AaQDaPpwTKAeByEc6WFM= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3/go.mod h1:b+qdhjnxj8GSR6t5YfphOffeoQSQ1KmpoVVuBn+PWxs= github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 h1:J/PpTf/hllOjx8Xu9DMflff3FajfLxqM5+tepvVXmxg= github.com/aws/aws-sdk-go-v2/service/sts v1.28.5/go.mod h1:0ih0Z83YDH/QeQ6Ori2yGE2XvWYv/Xm+cZc01LC6oK0= -github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= -github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= +github.com/aws/smithy-go v1.22.0/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= @@ -270,8 +270,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.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +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/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= @@ -519,8 +519,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= -github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= @@ -528,8 +528,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= -github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= +github.com/redis/go-redis/v9 v9.6.2 h1:w0uvkRbc9KpgD98zcvo5IrVUsn0lXpRMuhNgiHDJzdk= +github.com/redis/go-redis/v9 v9.6.2/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1005,10 +1005,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-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 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= @@ -1027,8 +1027,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.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= -google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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= @@ -1041,8 +1041,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.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/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/peers/app_request_network.go b/peers/app_request_network.go index 7b2d1978..1c0f57aa 100644 --- a/peers/app_request_network.go +++ b/peers/app_request_network.go @@ -213,12 +213,12 @@ type ConnectedCanonicalValidators struct { ConnectedWeight uint64 TotalValidatorWeight uint64 ValidatorSet []*warp.Validator - nodeValidatorIndexMap map[ids.NodeID]int + NodeValidatorIndexMap map[ids.NodeID]int } // Returns the Warp Validator and its index in the canonical Validator ordering for a given nodeID func (c *ConnectedCanonicalValidators) GetValidator(nodeID ids.NodeID) (*warp.Validator, int) { - return c.ValidatorSet[c.nodeValidatorIndexMap[nodeID]], c.nodeValidatorIndexMap[nodeID] + return c.ValidatorSet[c.NodeValidatorIndexMap[nodeID]], c.NodeValidatorIndexMap[nodeID] } // ConnectToCanonicalValidators connects to the canonical validators of the given subnet and returns the connected @@ -256,7 +256,7 @@ func (n *appRequestNetwork) ConnectToCanonicalValidators(subnetID ids.ID) (*Conn ConnectedWeight: connectedWeight, TotalValidatorWeight: totalValidatorWeight, ValidatorSet: validatorSet, - nodeValidatorIndexMap: nodeValidatorIndexMap, + NodeValidatorIndexMap: nodeValidatorIndexMap, }, nil } diff --git a/peers/external_handler.go b/peers/external_handler.go index c412975c..0f82bf9e 100644 --- a/peers/external_handler.go +++ b/peers/external_handler.go @@ -53,7 +53,7 @@ func NewRelayerExternalHandler( TimeoutHalflife: constants.DefaultNetworkTimeoutHalflife, } - timeoutManager, err := timer.NewAdaptiveTimeoutManager(&cfg, prometheus.DefaultRegisterer) + timeoutManager, err := timer.NewAdaptiveTimeoutManager(&cfg, prometheus.NewRegistry()) if err != nil { logger.Error( "Failed to create timeout manager", diff --git a/proto/buf.yaml b/proto/buf.yaml index 6f1b8844..b8901085 100644 --- a/proto/buf.yaml +++ b/proto/buf.yaml @@ -5,6 +5,6 @@ breaking: - FILE lint: use: - - DEFAULT + - STANDARD except: - PACKAGE_VERSION_SUFFIX # versioned naming .v1beta diff --git a/proto/pb/decider/decider.pb.go b/proto/pb/decider/decider.pb.go index 4047fc4a..c9523bb9 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.34.2 +// protoc-gen-go v1.35.1 // protoc (unknown) // source: decider/decider.proto @@ -34,11 +34,9 @@ type ShouldSendMessageRequest struct { func (x *ShouldSendMessageRequest) Reset() { *x = ShouldSendMessageRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_decider_decider_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_decider_decider_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ShouldSendMessageRequest) String() string { @@ -49,7 +47,7 @@ func (*ShouldSendMessageRequest) ProtoMessage() {} func (x *ShouldSendMessageRequest) ProtoReflect() protoreflect.Message { mi := &file_decider_decider_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -109,11 +107,9 @@ type ShouldSendMessageResponse struct { func (x *ShouldSendMessageResponse) Reset() { *x = ShouldSendMessageResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_decider_decider_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_decider_decider_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ShouldSendMessageResponse) String() string { @@ -124,7 +120,7 @@ func (*ShouldSendMessageResponse) ProtoMessage() {} func (x *ShouldSendMessageResponse) ProtoReflect() protoreflect.Message { mi := &file_decider_decider_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -213,32 +209,6 @@ func file_decider_decider_proto_init() { if File_decider_decider_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_decider_decider_proto_msgTypes[0].Exporter = func(v any, i int) any { - switch v := v.(*ShouldSendMessageRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_decider_decider_proto_msgTypes[1].Exporter = func(v any, i int) any { - switch v := v.(*ShouldSendMessageResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/relayer/Dockerfile b/relayer/Dockerfile index 87461e5f..fdaf71b2 100644 --- a/relayer/Dockerfile +++ b/relayer/Dockerfile @@ -1,4 +1,5 @@ -FROM debian:11-slim +FROM debian:12-slim +RUN apt update && apt --yes install ca-certificates COPY awm-relayer /usr/bin/awm-relayer EXPOSE 8080 USER 1001 diff --git a/scripts/versions.sh b/scripts/versions.sh index a85389fc..ceef4a14 100755 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -26,4 +26,4 @@ SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-$(getDepVersion github.com/ava-labs/sub GOLANGCI_LINT_VERSION=${GOLANGCI_LINT_VERSION:-'v1.60'} # Set buf version -BUF_VERSION=${BUF_VERSION:-'v1.37.0'} +BUF_VERSION=${BUF_VERSION:-'v1.44.0'} diff --git a/signature-aggregator/Dockerfile b/signature-aggregator/Dockerfile index 891fdebb..1d39ac66 100644 --- a/signature-aggregator/Dockerfile +++ b/signature-aggregator/Dockerfile @@ -1,5 +1,6 @@ -FROM debian:11-slim +FROM debian:12-slim COPY signature-aggregator /usr/bin/signature-aggregator +RUN apt update && apt --yes install ca-certificates EXPOSE 8080 EXPOSE 8081 CMD ["start"] diff --git a/signature-aggregator/README.md b/signature-aggregator/README.md index ed6e9e97..8970b29b 100644 --- a/signature-aggregator/README.md +++ b/signature-aggregator/README.md @@ -41,7 +41,13 @@ The successful `HTTP 200` response format is } ``` -Unsuccessful responses will include an explanatory `application/json` encoded message in the body of the response. +Unsuccessful responses will include an explanatory `application/json` encoded `error` message in the body of the response along with an appropriate `4xx` or `5xx` status code for user input errors or server side errors respectively e.g.: + +```json +{ + "error": "Could not decode message" +} +``` ## Sample workflow If you want to manually test a locally running service pointed to the Fuji testnet you can do so with the following steps. diff --git a/signature-aggregator/aggregator/aggregator.go b/signature-aggregator/aggregator/aggregator.go index 5bb13b59..7d2b9b01 100644 --- a/signature-aggregator/aggregator/aggregator.go +++ b/signature-aggregator/aggregator/aggregator.go @@ -5,6 +5,7 @@ package aggregator import ( "bytes" + "encoding/hex" "errors" "fmt" "math/big" @@ -556,6 +557,7 @@ func (s *SignatureAggregator) isValidSignatureResponse( if !bls.Verify(pubKey, sig, unsignedMessage.Bytes()) { s.logger.Debug( "Failed verification for signature", + zap.String("pubKey", hex.EncodeToString(bls.PublicKeyToUncompressedBytes(pubKey))), ) return blsSignatureBuf{}, false } diff --git a/signature-aggregator/aggregator/aggregator_test.go b/signature-aggregator/aggregator/aggregator_test.go index 8876a646..03273145 100644 --- a/signature-aggregator/aggregator/aggregator_test.go +++ b/signature-aggregator/aggregator/aggregator_test.go @@ -1,13 +1,22 @@ package aggregator import ( + "bytes" + "context" + "os" "testing" "time" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/message" + "github.com/ava-labs/avalanchego/proto/pb/sdk" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/subnets" + "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/awm-relayer/peers" "github.com/ava-labs/awm-relayer/peers/mocks" @@ -15,10 +24,15 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "google.golang.org/protobuf/proto" ) -var sigAggMetrics *metrics.SignatureAggregatorMetrics -var messageCreator message.Creator +var ( + sigAggMetrics *metrics.SignatureAggregatorMetrics + messageCreator message.Creator +) func instantiateAggregator(t *testing.T) ( *SignatureAggregator, @@ -36,25 +50,89 @@ func instantiateAggregator(t *testing.T) ( constants.DefaultNetworkCompressionType, constants.DefaultNetworkMaximumInboundTimeout, ) - require.Equal(t, err, nil) + require.NoError(t, err) } aggregator, err := NewSignatureAggregator( mockNetwork, - logging.NoLog{}, + logging.NewLogger( + "aggregator_test", + logging.NewWrappedCore( + logging.Debug, + os.Stdout, + zapcore.NewConsoleEncoder( + zap.NewProductionEncoderConfig(), + ), + ), + ), 1024, sigAggMetrics, messageCreator, // Setting the etnaTime to a minute ago so that the post-etna code path is used in the test time.Now().Add(-1*time.Minute), ) - require.Equal(t, err, nil) + require.NoError(t, err) return aggregator, mockNetwork } +// Generate the validator values. +type validatorInfo struct { + nodeID ids.NodeID + blsSecretKey *bls.SecretKey + blsPublicKey *bls.PublicKey + blsPublicKeyBytes []byte +} + +func (v validatorInfo) Compare(o validatorInfo) int { + return bytes.Compare(v.blsPublicKeyBytes, o.blsPublicKeyBytes) +} + +func makeConnectedValidators(validatorCount int) (*peers.ConnectedCanonicalValidators, []*bls.SecretKey) { + validatorValues := make([]validatorInfo, validatorCount) + for i := 0; i < validatorCount; i++ { + secretKey, err := bls.NewSecretKey() + if err != nil { + panic(err) + } + pubKey := bls.PublicFromSecretKey(secretKey) + nodeID := ids.GenerateTestNodeID() + validatorValues[i] = validatorInfo{ + nodeID: nodeID, + blsSecretKey: secretKey, + blsPublicKey: pubKey, + blsPublicKeyBytes: bls.PublicKeyToUncompressedBytes(pubKey), + } + } + + // Sort the validators by public key to construct the NodeValidatorIndexMap + utils.Sort(validatorValues) + + // Placeholder for results + validatorSet := make([]*warp.Validator, validatorCount) + validatorSecretKeys := make([]*bls.SecretKey, validatorCount) + nodeValidatorIndexMap := make(map[ids.NodeID]int) + for i, validator := range validatorValues { + validatorSecretKeys[i] = validator.blsSecretKey + validatorSet[i] = &warp.Validator{ + PublicKey: validator.blsPublicKey, + PublicKeyBytes: validator.blsPublicKeyBytes, + Weight: 1, + NodeIDs: []ids.NodeID{validator.nodeID}, + } + nodeValidatorIndexMap[validator.nodeID] = i + } + + return &peers.ConnectedCanonicalValidators{ + ConnectedWeight: uint64(validatorCount), + TotalValidatorWeight: uint64(validatorCount), + ValidatorSet: validatorSet, + NodeValidatorIndexMap: nodeValidatorIndexMap, + }, validatorSecretKeys +} + func TestCreateSignedMessageFailsWithNoValidators(t *testing.T) { aggregator, mockNetwork := instantiateAggregator(t) msg, err := warp.NewUnsignedMessage(0, ids.Empty, []byte{}) - require.Equal(t, err, nil) + require.NoError(t, err) mockNetwork.EXPECT().GetSubnetID(ids.Empty).Return(ids.Empty, nil) mockNetwork.EXPECT().ConnectToCanonicalValidators(ids.Empty).Return( &peers.ConnectedCanonicalValidators{ @@ -71,7 +149,7 @@ func TestCreateSignedMessageFailsWithNoValidators(t *testing.T) { func TestCreateSignedMessageFailsWithoutSufficientConnectedStake(t *testing.T) { aggregator, mockNetwork := instantiateAggregator(t) msg, err := warp.NewUnsignedMessage(0, ids.Empty, []byte{}) - require.Equal(t, err, nil) + require.NoError(t, err) mockNetwork.EXPECT().GetSubnetID(ids.Empty).Return(ids.Empty, nil) mockNetwork.EXPECT().ConnectToCanonicalValidators(ids.Empty).Return( &peers.ConnectedCanonicalValidators{ @@ -88,3 +166,234 @@ func TestCreateSignedMessageFailsWithoutSufficientConnectedStake(t *testing.T) { "failed to connect to a threshold of stake", ) } + +func makeAppRequests( + chainID ids.ID, + requestID uint32, + connectedValidators *peers.ConnectedCanonicalValidators, +) []ids.RequestID { + var appRequests []ids.RequestID + for _, validator := range connectedValidators.ValidatorSet { + for _, nodeID := range validator.NodeIDs { + appRequests = append( + appRequests, + ids.RequestID{ + NodeID: nodeID, + ChainID: chainID, + RequestID: requestID, + Op: byte( + message.AppResponseOp, + ), + }, + ) + } + } + return appRequests +} + +func TestCreateSignedMessageRetriesAndFailsWithoutP2PResponses(t *testing.T) { + aggregator, mockNetwork := instantiateAggregator(t) + + var ( + connectedValidators, _ = makeConnectedValidators(2) + requestID = aggregator.currentRequestID.Load() + 1 + ) + + chainID := ids.GenerateTestID() + + msg, err := warp.NewUnsignedMessage(0, chainID, []byte{}) + require.NoError(t, err) + + subnetID := ids.GenerateTestID() + mockNetwork.EXPECT().GetSubnetID(chainID).Return( + subnetID, + nil, + ) + + mockNetwork.EXPECT().ConnectToCanonicalValidators(subnetID).Return( + connectedValidators, + nil, + ) + + appRequests := makeAppRequests(chainID, requestID, connectedValidators) + for _, appRequest := range appRequests { + mockNetwork.EXPECT().RegisterAppRequest(appRequest).Times( + maxRelayerQueryAttempts, + ) + } + + mockNetwork.EXPECT().RegisterRequestID( + requestID, + len(appRequests), + ).Return( + make(chan message.InboundMessage, len(appRequests)), + ).Times(maxRelayerQueryAttempts) + + var nodeIDs set.Set[ids.NodeID] + for _, appRequest := range appRequests { + nodeIDs.Add(appRequest.NodeID) + } + mockNetwork.EXPECT().Send( + gomock.Any(), + nodeIDs, + subnetID, + subnets.NoOpAllower, + ).Times(maxRelayerQueryAttempts) + + _, err = aggregator.CreateSignedMessage(msg, nil, subnetID, 80) + require.ErrorContains( + t, + err, + "failed to collect a threshold of signatures", + ) +} + +func TestCreateSignedMessageSucceeds(t *testing.T) { + var msg *warp.UnsignedMessage // to be signed + chainID := ids.GenerateTestID() + networkID := constants.UnitTestID + msg, err := warp.NewUnsignedMessage( + networkID, + chainID, + utils.RandomBytes(1234), + ) + require.NoError(t, err) + + // the signers: + var connectedValidators, validatorSecretKeys = makeConnectedValidators(5) + + // prime the aggregator: + + aggregator, mockNetwork := instantiateAggregator(t) + + subnetID := ids.GenerateTestID() + mockNetwork.EXPECT().GetSubnetID(chainID).Return( + subnetID, + nil, + ) + + mockNetwork.EXPECT().ConnectToCanonicalValidators(subnetID).Return( + connectedValidators, + nil, + ) + + // prime the signers' responses: + + var requestID = aggregator.currentRequestID.Load() + 1 + + appRequests := makeAppRequests(chainID, requestID, connectedValidators) + for _, appRequest := range appRequests { + mockNetwork.EXPECT().RegisterAppRequest(appRequest).Times(1) + } + + var nodeIDs set.Set[ids.NodeID] + responseChan := make(chan message.InboundMessage, len(appRequests)) + for _, appRequest := range appRequests { + nodeIDs.Add(appRequest.NodeID) + validatorSecretKey := validatorSecretKeys[connectedValidators.NodeValidatorIndexMap[appRequest.NodeID]] + responseBytes, err := proto.Marshal( + &sdk.SignatureResponse{ + Signature: bls.SignatureToBytes( + bls.Sign( + validatorSecretKey, + msg.Bytes(), + ), + ), + }, + ) + require.NoError(t, err) + responseChan <- message.InboundAppResponse( + chainID, + requestID, + responseBytes, + appRequest.NodeID, + ) + } + mockNetwork.EXPECT().RegisterRequestID( + requestID, + len(appRequests), + ).Return(responseChan).Times(1) + + mockNetwork.EXPECT().Send( + gomock.Any(), + nodeIDs, + subnetID, + subnets.NoOpAllower, + ).Times(1).Return(nodeIDs) + + // aggregate the signatures: + var quorumPercentage uint64 = 80 + signedMessage, err := aggregator.CreateSignedMessage( + msg, + nil, + subnetID, + quorumPercentage, + ) + require.NoError(t, err) + + // verify the aggregated signature: + pChainState := newPChainStateStub( + chainID, + subnetID, + 1, + connectedValidators, + ) + verifyErr := signedMessage.Signature.Verify( + context.Background(), + msg, + networkID, + pChainState, + pChainState.currentHeight, + quorumPercentage, + 100, + ) + require.NoError(t, verifyErr) +} + +type pChainStateStub struct { + subnetIDByChainID map[ids.ID]ids.ID + connectedCanonicalValidators *peers.ConnectedCanonicalValidators + currentHeight uint64 +} + +func newPChainStateStub( + chainID, subnetID ids.ID, + currentHeight uint64, + connectedValidators *peers.ConnectedCanonicalValidators, +) *pChainStateStub { + subnetIDByChainID := make(map[ids.ID]ids.ID) + subnetIDByChainID[chainID] = subnetID + return &pChainStateStub{ + subnetIDByChainID: subnetIDByChainID, + connectedCanonicalValidators: connectedValidators, + currentHeight: currentHeight, + } +} + +func (p pChainStateStub) GetSubnetID(ctx context.Context, chainID ids.ID) (ids.ID, error) { + return p.subnetIDByChainID[chainID], nil +} + +func (p pChainStateStub) GetMinimumHeight(context.Context) (uint64, error) { return 0, nil } + +func (p pChainStateStub) GetCurrentHeight(context.Context) (uint64, error) { + return p.currentHeight, nil +} + +func (p pChainStateStub) GetValidatorSet( + ctx context.Context, + height uint64, + subnetID ids.ID, +) (map[ids.NodeID]*validators.GetValidatorOutput, error) { + output := make(map[ids.NodeID]*validators.GetValidatorOutput) + for _, validator := range p.connectedCanonicalValidators.ValidatorSet { + for _, nodeID := range validator.NodeIDs { + output[nodeID] = &validators.GetValidatorOutput{ + NodeID: nodeID, + PublicKey: validator.PublicKey, + Weight: validator.Weight, + } + } + } + return output, nil +} diff --git a/signature-aggregator/aggregator/cache/cache.go b/signature-aggregator/aggregator/cache/cache.go index 475a6fdc..7363e07e 100644 --- a/signature-aggregator/aggregator/cache/cache.go +++ b/signature-aggregator/aggregator/cache/cache.go @@ -41,7 +41,11 @@ func (c *Cache) Get(msgID ids.ID) (map[PublicKeyBytes]SignatureBytes, bool) { cachedValue, isCached := c.signatures.Get(msgID) if isCached { - c.logger.Debug("cache hit", zap.Stringer("msgID", msgID)) + c.logger.Debug( + "cache hit", + zap.Stringer("msgID", msgID), + zap.Int("signatureCount", len(cachedValue)), + ) return cachedValue, true } else { c.logger.Debug("cache miss", zap.Stringer("msgID", msgID)) diff --git a/signature-aggregator/api/api.go b/signature-aggregator/api/api.go index f1a324c1..939afc99 100644 --- a/signature-aggregator/api/api.go +++ b/signature-aggregator/api/api.go @@ -43,6 +43,10 @@ type AggregateSignatureResponse struct { SignedMessage string `json:"signed-message"` } +type AggregateSignatureErrorResponse struct { + Error string `json:"error"` +} + func HandleAggregateSignaturesByRawMsgRequest( logger logging.Logger, metrics *metrics.SignatureAggregatorMetrics, @@ -61,9 +65,14 @@ func HandleAggregateSignaturesByRawMsgRequest( func writeJSONError( logger logging.Logger, w http.ResponseWriter, + httpStatusCode int, errorMsg string, ) { - resp, err := json.Marshal(struct{ error string }{error: errorMsg}) + resp, err := json.Marshal( + AggregateSignatureErrorResponse{ + Error: errorMsg, + }, + ) if err != nil { msg := "Error marshalling JSON error response" logger.Error(msg, zap.Error(err)) @@ -71,8 +80,9 @@ func writeJSONError( } w.Header().Set("Content-Type", "application/json") + w.WriteHeader(httpStatusCode) - w.Write(resp) + _, err = w.Write(resp) if err != nil { logger.Error("Error writing error response", zap.Error(err)) } @@ -92,7 +102,7 @@ func signatureAggregationAPIHandler( if err != nil { msg := "Could not decode request body" logger.Warn(msg, zap.Error(err)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } var decodedMessage []byte @@ -106,14 +116,14 @@ func signatureAggregationAPIHandler( zap.String("msg", req.Message), zap.Error(err), ) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } message, err := types.UnpackWarpMessage(decodedMessage) if err != nil { msg := "Error unpacking warp message" logger.Warn(msg, zap.Error(err)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } @@ -127,7 +137,7 @@ func signatureAggregationAPIHandler( zap.String("justification", req.Justification), zap.Error(err), ) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } @@ -135,6 +145,7 @@ func signatureAggregationAPIHandler( writeJSONError( logger, w, + http.StatusBadRequest, "Must provide either message or justification", ) return @@ -146,7 +157,7 @@ func signatureAggregationAPIHandler( } else if req.QuorumPercentage > 100 { msg := "Invalid quorum number" logger.Warn(msg, zap.Uint64("quorum-num", req.QuorumPercentage)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } var signingSubnetID ids.ID @@ -161,7 +172,7 @@ func signatureAggregationAPIHandler( zap.Error(err), zap.String("input", req.SigningSubnetID), ) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } } @@ -175,7 +186,7 @@ func signatureAggregationAPIHandler( if err != nil { msg := "Failed to aggregate signatures" logger.Warn(msg, zap.Error(err)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusInternalServerError, msg) return } resp, err := json.Marshal( @@ -189,7 +200,7 @@ func signatureAggregationAPIHandler( if err != nil { msg := "Failed to marshal response" logger.Error(msg, zap.Error(err)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusInternalServerError, msg) return } w.Header().Set("Content-Type", "application/json")