From 1b161e6cbe497f2b6ea3e702ede4e852dfdb6649 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 21 Jun 2024 21:52:08 +0000 Subject: [PATCH 01/29] `ShouldSendMessage` decider service support --- .github/workflows/e2e.yml | 5 + .github/workflows/linter.yml | 12 + .gitignore | 1 + README.md | 2 +- config/config.go | 2 + go.mod | 13 +- go.sum | 26 +- main/main.go | 39 ++- messages/teleporter/message_handler.go | 58 ++++- messages/teleporter/message_handler_test.go | 1 + proto/README.md | 11 + proto/buf.gen.yaml | 8 + proto/buf.lock | 8 + proto/buf.yaml | 8 + proto/decider/v1/decider.proto | 21 ++ proto/pb/decider/v1/decider.pb.go | 261 ++++++++++++++++++++ proto/pb/decider/v1/decider_grpc.pb.go | 109 ++++++++ scripts/build.sh | 2 + scripts/e2e_test.sh | 1 + scripts/lint.sh | 2 + scripts/protobuf_codegen.sh | 56 +++++ scripts/test.sh | 5 +- tests/cmd/decider/main.go | 49 ++++ tests/e2e_test.go | 34 ++- tests/utils/utils.go | 7 +- 25 files changed, 713 insertions(+), 28 deletions(-) create mode 100644 proto/README.md create mode 100644 proto/buf.gen.yaml create mode 100644 proto/buf.lock create mode 100644 proto/buf.yaml create mode 100644 proto/decider/v1/decider.proto create mode 100644 proto/pb/decider/v1/decider.pb.go create mode 100644 proto/pb/decider/v1/decider_grpc.pb.go create mode 100755 scripts/protobuf_codegen.sh create mode 100644 tests/cmd/decider/main.go diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 5b77e647..1a17199a 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -49,5 +49,10 @@ jobs: with: submodules: recursive + - name: Install buf + uses: bufbuild/buf-setup-action@v1.31.0 + with: + github_token: ${{ github.token }} + - name: Run E2E Tests run: AVALANCHEGO_BUILD_PATH=/tmp/e2e-test/avalanchego DATA_DIR=/tmp/e2e-test/data ./scripts/e2e_test.sh diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 67cc879f..089aa183 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -27,5 +27,17 @@ jobs: with: go-version-file: 'go.mod' + - name: Install buf + uses: bufbuild/buf-setup-action@v1.31.0 + with: + github_token: ${{ github.token }} + - name: Run Lint run: ./scripts/lint.sh --go-lint + + - name: Ensure protobuf changes are checked in + run: | + scripts/protobuf_codegen.sh + git update-index --really-refresh >> /dev/null + git diff-index HEAD # to show the differences + git diff-index --quiet HEAD || (echo 'protobuf generated code changes have not all been checked in' && exit 1) diff --git a/.gitignore b/.gitignore index 14dd770f..ab9641b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ build/ __debug_bin +tests/cmd/decider/decider .vscode* diff --git a/README.md b/README.md index 6ca8b531..e3f9e33b 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ awm-relayer --help Display awm-relayer usag ### Building -Before building, be sure to install Go, which is required even if you're just building the Docker image. +Before building, be sure to install Go, which is required even if you're just building the Docker image. You'll also need to install [buf](github.com/bufbuild/buf/). Build the relayer by running the script: diff --git a/config/config.go b/config/config.go index b22a01ca..6aceaca8 100644 --- a/config/config.go +++ b/config/config.go @@ -58,6 +58,8 @@ type Config struct { SourceBlockchains []*SourceBlockchain `mapstructure:"source-blockchains" json:"source-blockchains"` DestinationBlockchains []*DestinationBlockchain `mapstructure:"destination-blockchains" json:"destination-blockchains"` ProcessMissedBlocks bool `mapstructure:"process-missed-blocks" json:"process-missed-blocks"` + DeciderHost string `mapstructure:"decider-host" json:"decider-host"` + DeciderPort *uint16 `mapstructure:"decider-port" json:"decider-port"` // convenience field to fetch a blockchain's subnet ID blockchainIDToSubnetID map[ids.ID]ids.ID diff --git a/go.mod b/go.mod index baf45247..b073ab52 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.27.9 github.com/aws/aws-sdk-go-v2/service/kms v1.32.1 github.com/ethereum/go-ethereum v1.12.0 + github.com/golang/protobuf v1.5.4 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.33.1 github.com/pkg/errors v0.9.1 @@ -22,6 +23,7 @@ require ( 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.64.0 ) require ( @@ -85,9 +87,8 @@ require ( golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/tools v0.21.0 // indirect - google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) @@ -108,10 +109,9 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-stack/stack v1.8.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/rpc v1.2.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect @@ -154,8 +154,7 @@ require ( golang.org/x/text v0.15.0 // indirect golang.org/x/time v0.3.0 // indirect gonum.org/v1/gonum v0.11.0 // indirect - google.golang.org/grpc v1.58.3 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/protobuf v1.33.0 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 8daf95ad..7e23c770 100644 --- a/go.sum +++ b/go.sum @@ -273,8 +273,8 @@ github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoB github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/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= @@ -301,8 +301,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -347,8 +347,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -1011,12 +1011,10 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D 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 v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= -google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= -google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 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= @@ -1039,8 +1037,8 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= 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= diff --git a/main/main.go b/main/main.go index a2abe28f..3dc6bb24 100644 --- a/main/main.go +++ b/main/main.go @@ -9,6 +9,8 @@ import ( "log" "net/http" "os" + "runtime" + "strconv" "strings" "github.com/ava-labs/avalanchego/api/metrics" @@ -33,9 +35,16 @@ import ( "go.uber.org/atomic" "go.uber.org/zap" "golang.org/x/sync/errgroup" + "google.golang.org/grpc" + "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/credentials/insecure" ) -var version = "v0.0.0-dev" +var ( + version = "v0.0.0-dev" + + grpcClient *grpc.ClientConn // for connecting to the decider service +) func main() { fs := config.BuildFlagSet() @@ -216,6 +225,33 @@ func main() { // Create listeners for each of the subnets configured as a source errGroup, ctx := errgroup.WithContext(context.Background()) + + if cfg.DeciderPort != nil { + port := strconv.FormatUint(uint64(*cfg.DeciderPort), 10) + + host := cfg.DeciderHost + if len(host) == 0 { + host = "localhost" + } + + grpcClient, err = grpc.NewClient( + strings.Join([]string{host, port}, ":"), + grpc.WithTransportCredentials( + insecure.NewCredentials(), + ), + ) + if err != nil { + logger.Fatal( + "Failed to instantiate decider client", + zap.Error(err), + ) + panic(err) + } + runtime.SetFinalizer(grpcClient, func(c *grpc.ClientConn) { c.Close() }) + grpcClient.WaitForStateChange(ctx, connectivity.Ready) + } + + // Create listeners for each of the subnets configured as a source for _, s := range cfg.SourceBlockchains { sourceBlockchain := s @@ -259,6 +295,7 @@ func createMessageHandlerFactories( logger, address, cfg, + grpcClient, ) case config.OFF_CHAIN_REGISTRY: m, err = offchainregistry.NewMessageHandlerFactory( diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index c0d06573..d124eeee 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -5,8 +5,10 @@ package teleporter import ( "context" + "encoding/hex" "encoding/json" "fmt" + "reflect" "time" "github.com/ava-labs/avalanchego/ids" @@ -15,6 +17,7 @@ import ( warpPayload "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" "github.com/ava-labs/awm-relayer/config" "github.com/ava-labs/awm-relayer/messages" + pbDecider "github.com/ava-labs/awm-relayer/proto/pb/decider/v1" "github.com/ava-labs/awm-relayer/utils" "github.com/ava-labs/awm-relayer/vms" "github.com/ava-labs/subnet-evm/accounts/abi/bind" @@ -25,12 +28,14 @@ import ( teleporterUtils "github.com/ava-labs/teleporter/utils/teleporter-utils" "github.com/ethereum/go-ethereum/common" "go.uber.org/zap" + "google.golang.org/grpc" ) type factory struct { messageConfig Config protocolAddress common.Address logger logging.Logger + deciderClient pbDecider.DeciderServiceClient } type messageHandler struct { @@ -38,12 +43,14 @@ type messageHandler struct { teleporterMessage *teleportermessenger.TeleporterMessage unsignedMessage *warp.UnsignedMessage factory *factory + deciderClient pbDecider.DeciderServiceClient } func NewMessageHandlerFactory( logger logging.Logger, messageProtocolAddress common.Address, messageProtocolConfig config.MessageProtocolConfig, + grpcClient *grpc.ClientConn, ) (messages.MessageHandlerFactory, error) { // Marshal the map and unmarshal into the Teleporter config data, err := json.Marshal(messageProtocolConfig.Settings) @@ -65,10 +72,18 @@ func NewMessageHandlerFactory( return nil, err } + var deciderClient pbDecider.DeciderServiceClient + if grpcClient == nil { + deciderClient = nil + } else { + deciderClient = pbDecider.NewDeciderServiceClient(grpcClient) + } + return &factory{ messageConfig: messageConfig, protocolAddress: messageProtocolAddress, logger: logger, + deciderClient: deciderClient, }, nil } @@ -86,6 +101,7 @@ func (f *factory) NewMessageHandler(unsignedMessage *warp.UnsignedMessage) (mess teleporterMessage: teleporterMessage, unsignedMessage: unsignedMessage, factory: f, + deciderClient: f.deciderClient, }, nil } @@ -167,7 +183,47 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie return false, nil } - return true, nil + var decision bool = true + deciderClientValue := reflect.ValueOf(m.deciderClient) + if deciderClientValue.IsValid() && !deciderClientValue.IsNil() { + warpMsgIDStr := m.unsignedMessage.ID().Hex() + + warpMsgID, err := hex.DecodeString(warpMsgIDStr) + if err != nil { + m.logger.Error( + "Error decoding message ID", + zap.String("warpMsgIDStr", warpMsgIDStr), + zap.Error(err), + ) + return decision, err + } + + // TODO: add a timeout to the context + response, err := m.deciderClient.ShouldSendMessage( + context.Background(), + &pbDecider.ShouldSendMessageRequest{ + NetworkId: m.unsignedMessage.NetworkID, + SourceChainId: m.unsignedMessage.SourceChainID[:], + Payload: m.unsignedMessage.Payload, + BytesRepresentation: m.unsignedMessage.Bytes(), + Id: warpMsgID, + }, + ) + if err != nil { + m.logger.Error( + "Error response from decider.", + zap.String("destinationBlockchainID", destinationBlockchainID.String()), + zap.String("teleporterMessageID", teleporterMessageID.String()), + zap.Any("warpMessageID", warpMsgIDStr), + zap.Error(err), + ) + return decision, err + } + + decision = response.ShouldSendMessage + } + + return decision, nil } // SendMessage extracts the gasLimit and packs the call data to call the receiveCrossChainMessage diff --git a/messages/teleporter/message_handler_test.go b/messages/teleporter/message_handler_test.go index 55d95d44..e74bff62 100644 --- a/messages/teleporter/message_handler_test.go +++ b/messages/teleporter/message_handler_test.go @@ -189,6 +189,7 @@ func TestShouldSendMessage(t *testing.T) { logger, messageProtocolAddress, messageProtocolConfig, + nil, ) require.NoError(t, err) messageHandler, err := factory.NewMessageHandler(test.warpUnsignedMessage) diff --git a/proto/README.md b/proto/README.md new file mode 100644 index 00000000..acfc4c10 --- /dev/null +++ b/proto/README.md @@ -0,0 +1,11 @@ +Protobuf linting and generation for this project is managed by +[buf](https://github.com/bufbuild/buf). + +Please find installation instructions on +[https://docs.buf.build/installation/](https://docs.buf.build/installation/). + +Any changes made to proto definition can be updated by running +`protobuf_codegen.sh` located in the `scripts/` directory of this repo. + +Introduction to `buf` +[https://docs.buf.build/tour/introduction](https://docs.buf.build/tour/introduction) diff --git a/proto/buf.gen.yaml b/proto/buf.gen.yaml new file mode 100644 index 00000000..046f039c --- /dev/null +++ b/proto/buf.gen.yaml @@ -0,0 +1,8 @@ +version: v1 +plugins: + - name: go + out: pb + opt: paths=source_relative + - name: go-grpc + out: pb + opt: paths=source_relative diff --git a/proto/buf.lock b/proto/buf.lock new file mode 100644 index 00000000..bb25989f --- /dev/null +++ b/proto/buf.lock @@ -0,0 +1,8 @@ +# Generated by buf. DO NOT EDIT. +version: v1 +deps: + - remote: buf.build + owner: prometheus + repository: client-model + commit: e171c0b235c546d5a9a597c2961bd357 + digest: shake256:7db3f73ac0f1dce71e70f304f318e9741e857fd78b7b42f0df7a3da353fbb2f387899da7b0a77ac9ee9565194510e39a913cdb9a8ab3c2ff4b8713428c795213 diff --git a/proto/buf.yaml b/proto/buf.yaml new file mode 100644 index 00000000..fdbbe0fc --- /dev/null +++ b/proto/buf.yaml @@ -0,0 +1,8 @@ +version: v1 +name: buf.build/ava-labs/awm-relayer +breaking: + use: + - FILE +lint: + use: + - DEFAULT diff --git a/proto/decider/v1/decider.proto b/proto/decider/v1/decider.proto new file mode 100644 index 00000000..b63dcedc --- /dev/null +++ b/proto/decider/v1/decider.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +package decider.v1; + +option go_package = "github.com/ava-labs/awm-relayer/proto/pb/decider"; + +service DeciderService { + rpc ShouldSendMessage(ShouldSendMessageRequest) returns (ShouldSendMessageResponse); +} + +message ShouldSendMessageRequest { + uint32 network_id = 1; + bytes source_chain_id = 2; + bytes payload = 3; + bytes bytes_representation = 4; + bytes id = 5; +} + +message ShouldSendMessageResponse { + bool should_send_message = 1; +} diff --git a/proto/pb/decider/v1/decider.pb.go b/proto/pb/decider/v1/decider.pb.go new file mode 100644 index 00000000..2fdd34e5 --- /dev/null +++ b/proto/pb/decider/v1/decider.pb.go @@ -0,0 +1,261 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc (unknown) +// source: decider/v1/decider.proto + +package decider + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ShouldSendMessageRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NetworkId uint32 `protobuf:"varint,1,opt,name=network_id,json=networkId,proto3" json:"network_id,omitempty"` + SourceChainId []byte `protobuf:"bytes,2,opt,name=source_chain_id,json=sourceChainId,proto3" json:"source_chain_id,omitempty"` + Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"` + BytesRepresentation []byte `protobuf:"bytes,4,opt,name=bytes_representation,json=bytesRepresentation,proto3" json:"bytes_representation,omitempty"` + Id []byte `protobuf:"bytes,5,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *ShouldSendMessageRequest) Reset() { + *x = ShouldSendMessageRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_decider_v1_decider_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ShouldSendMessageRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ShouldSendMessageRequest) ProtoMessage() {} + +func (x *ShouldSendMessageRequest) ProtoReflect() protoreflect.Message { + mi := &file_decider_v1_decider_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ShouldSendMessageRequest.ProtoReflect.Descriptor instead. +func (*ShouldSendMessageRequest) Descriptor() ([]byte, []int) { + return file_decider_v1_decider_proto_rawDescGZIP(), []int{0} +} + +func (x *ShouldSendMessageRequest) GetNetworkId() uint32 { + if x != nil { + return x.NetworkId + } + return 0 +} + +func (x *ShouldSendMessageRequest) GetSourceChainId() []byte { + if x != nil { + return x.SourceChainId + } + return nil +} + +func (x *ShouldSendMessageRequest) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +func (x *ShouldSendMessageRequest) GetBytesRepresentation() []byte { + if x != nil { + return x.BytesRepresentation + } + return nil +} + +func (x *ShouldSendMessageRequest) GetId() []byte { + if x != nil { + return x.Id + } + return nil +} + +type ShouldSendMessageResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ShouldSendMessage bool `protobuf:"varint,1,opt,name=should_send_message,json=shouldSendMessage,proto3" json:"should_send_message,omitempty"` +} + +func (x *ShouldSendMessageResponse) Reset() { + *x = ShouldSendMessageResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_decider_v1_decider_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ShouldSendMessageResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ShouldSendMessageResponse) ProtoMessage() {} + +func (x *ShouldSendMessageResponse) ProtoReflect() protoreflect.Message { + mi := &file_decider_v1_decider_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ShouldSendMessageResponse.ProtoReflect.Descriptor instead. +func (*ShouldSendMessageResponse) Descriptor() ([]byte, []int) { + return file_decider_v1_decider_proto_rawDescGZIP(), []int{1} +} + +func (x *ShouldSendMessageResponse) GetShouldSendMessage() bool { + if x != nil { + return x.ShouldSendMessage + } + return false +} + +var File_decider_v1_decider_proto protoreflect.FileDescriptor + +var file_decider_v1_decider_proto_rawDesc = []byte{ + 0x0a, 0x18, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x63, + 0x69, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x64, 0x65, 0x63, 0x69, + 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x22, 0xbe, 0x01, 0x0a, 0x18, 0x53, 0x68, 0x6f, 0x75, 0x6c, + 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x72, 0x65, + 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x13, 0x62, 0x79, 0x74, 0x65, 0x73, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, + 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4b, 0x0a, 0x19, 0x53, 0x68, 0x6f, 0x75, 0x6c, + 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x73, + 0x65, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x32, 0x72, 0x0a, 0x0e, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x60, 0x0a, 0x11, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, + 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x2e, 0x64, 0x65, + 0x63, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, + 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x25, 0x2e, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x76, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x61, 0x77, 0x6d, 0x2d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 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_v1_decider_proto_rawDescOnce sync.Once + file_decider_v1_decider_proto_rawDescData = file_decider_v1_decider_proto_rawDesc +) + +func file_decider_v1_decider_proto_rawDescGZIP() []byte { + file_decider_v1_decider_proto_rawDescOnce.Do(func() { + file_decider_v1_decider_proto_rawDescData = protoimpl.X.CompressGZIP(file_decider_v1_decider_proto_rawDescData) + }) + return file_decider_v1_decider_proto_rawDescData +} + +var file_decider_v1_decider_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_decider_v1_decider_proto_goTypes = []interface{}{ + (*ShouldSendMessageRequest)(nil), // 0: decider.v1.ShouldSendMessageRequest + (*ShouldSendMessageResponse)(nil), // 1: decider.v1.ShouldSendMessageResponse +} +var file_decider_v1_decider_proto_depIdxs = []int32{ + 0, // 0: decider.v1.DeciderService.ShouldSendMessage:input_type -> decider.v1.ShouldSendMessageRequest + 1, // 1: decider.v1.DeciderService.ShouldSendMessage:output_type -> decider.v1.ShouldSendMessageResponse + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_decider_v1_decider_proto_init() } +func file_decider_v1_decider_proto_init() { + if File_decider_v1_decider_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_decider_v1_decider_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + 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_v1_decider_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + 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{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_decider_v1_decider_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_decider_v1_decider_proto_goTypes, + DependencyIndexes: file_decider_v1_decider_proto_depIdxs, + MessageInfos: file_decider_v1_decider_proto_msgTypes, + }.Build() + File_decider_v1_decider_proto = out.File + file_decider_v1_decider_proto_rawDesc = nil + file_decider_v1_decider_proto_goTypes = nil + file_decider_v1_decider_proto_depIdxs = nil +} diff --git a/proto/pb/decider/v1/decider_grpc.pb.go b/proto/pb/decider/v1/decider_grpc.pb.go new file mode 100644 index 00000000..00232b5f --- /dev/null +++ b/proto/pb/decider/v1/decider_grpc.pb.go @@ -0,0 +1,109 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: decider/v1/decider.proto + +package decider + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + DeciderService_ShouldSendMessage_FullMethodName = "/decider.v1.DeciderService/ShouldSendMessage" +) + +// DeciderServiceClient is the client API for DeciderService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type DeciderServiceClient interface { + ShouldSendMessage(ctx context.Context, in *ShouldSendMessageRequest, opts ...grpc.CallOption) (*ShouldSendMessageResponse, error) +} + +type deciderServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewDeciderServiceClient(cc grpc.ClientConnInterface) DeciderServiceClient { + return &deciderServiceClient{cc} +} + +func (c *deciderServiceClient) ShouldSendMessage(ctx context.Context, in *ShouldSendMessageRequest, opts ...grpc.CallOption) (*ShouldSendMessageResponse, error) { + out := new(ShouldSendMessageResponse) + err := c.cc.Invoke(ctx, DeciderService_ShouldSendMessage_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// DeciderServiceServer is the server API for DeciderService service. +// All implementations must embed UnimplementedDeciderServiceServer +// for forward compatibility +type DeciderServiceServer interface { + ShouldSendMessage(context.Context, *ShouldSendMessageRequest) (*ShouldSendMessageResponse, error) + mustEmbedUnimplementedDeciderServiceServer() +} + +// UnimplementedDeciderServiceServer must be embedded to have forward compatible implementations. +type UnimplementedDeciderServiceServer struct { +} + +func (UnimplementedDeciderServiceServer) ShouldSendMessage(context.Context, *ShouldSendMessageRequest) (*ShouldSendMessageResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ShouldSendMessage not implemented") +} +func (UnimplementedDeciderServiceServer) mustEmbedUnimplementedDeciderServiceServer() {} + +// UnsafeDeciderServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to DeciderServiceServer will +// result in compilation errors. +type UnsafeDeciderServiceServer interface { + mustEmbedUnimplementedDeciderServiceServer() +} + +func RegisterDeciderServiceServer(s grpc.ServiceRegistrar, srv DeciderServiceServer) { + s.RegisterService(&DeciderService_ServiceDesc, srv) +} + +func _DeciderService_ShouldSendMessage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ShouldSendMessageRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DeciderServiceServer).ShouldSendMessage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: DeciderService_ShouldSendMessage_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DeciderServiceServer).ShouldSendMessage(ctx, req.(*ShouldSendMessageRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// DeciderService_ServiceDesc is the grpc.ServiceDesc for DeciderService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var DeciderService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "decider.v1.DeciderService", + HandlerType: (*DeciderServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ShouldSendMessage", + Handler: _DeciderService_ShouldSendMessage_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "decider/v1/decider.proto", +} diff --git a/scripts/build.sh b/scripts/build.sh index c09c205b..d4661991 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -39,6 +39,8 @@ if version_lt "$(go_version)" "$go_version_minimum"; then exit 1 fi +scripts/protobuf_codegen.sh + if [[ $# -eq 1 ]]; then binary_path=$1 elif [[ $# -eq 0 ]]; then diff --git a/scripts/e2e_test.sh b/scripts/e2e_test.sh index f6016ac8..84f6718d 100755 --- a/scripts/e2e_test.sh +++ b/scripts/e2e_test.sh @@ -66,6 +66,7 @@ source "$RELAYER_PATH"/scripts/versions.sh go install -v github.com/onsi/ginkgo/v2/ginkgo@${GINKGO_VERSION} ginkgo build ./tests/ +go build -v -o tests/cmd/decider/decider ./tests/cmd/decider/ # Run the tests echo "Running e2e tests $RUN_E2E" diff --git a/scripts/lint.sh b/scripts/lint.sh index 49a2282a..7321e833 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -15,3 +15,5 @@ source $RELAYER_PATH/scripts/versions.sh go install -v github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION} golangci-lint run --config=$RELAYER_PATH/.golangci.yml --build-tags=testing ./... --timeout 5m + +(cd proto && buf lint) diff --git a/scripts/protobuf_codegen.sh b/scripts/protobuf_codegen.sh new file mode 100755 index 00000000..d5786892 --- /dev/null +++ b/scripts/protobuf_codegen.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if ! [[ "$0" =~ scripts/protobuf_codegen.sh ]]; then + echo "must be run from repository root" + exit 255 +fi + +## ensure the correct version of "buf" is installed +BUF_VERSION='1.31.0' +if [[ $(buf --version | cut -f2 -d' ') != "${BUF_VERSION}" ]]; then + echo "could not find buf ${BUF_VERSION}, is it installed + in PATH?" + exit 255 +fi + +## install "protoc-gen-go" +PROTOC_GEN_GO_VERSION='v1.33.0' +go install -v google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOC_GEN_GO_VERSION} +if [[ $(protoc-gen-go --version | cut -f2 -d' ') != "${PROTOC_GEN_GO_VERSION}" ]]; then + # e.g., protoc-gen-go v1.28.1 + echo "could not find protoc-gen-go ${PROTOC_GEN_GO_VERSION}, is it installed + in PATH?" + exit 255 +fi + +### install "protoc-gen-go-grpc" +PROTOC_GEN_GO_GRPC_VERSION='1.3.0' +go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@v${PROTOC_GEN_GO_GRPC_VERSION} +if [[ $(protoc-gen-go-grpc --version | cut -f2 -d' ') != "${PROTOC_GEN_GO_GRPC_VERSION}" ]]; then + # e.g., protoc-gen-go-grpc 1.3.0 + echo "could not find protoc-gen-go-grpc ${PROTOC_GEN_GO_GRPC_VERSION}, is it installed + in PATH?" + exit 255 +fi + +TARGET=$PWD/proto +if [ -n "${1:-}" ]; then + TARGET="$1" +fi + +# move to api directory +cd "$TARGET" + +echo "Running protobuf fmt..." +buf format -w + +echo "Running protobuf lint check..." +if ! buf lint; then + echo "ERROR: protobuf linter failed" + exit 1 +fi + +echo "Re-generating protobuf..." +if ! buf generate; then + echo "ERROR: protobuf generation failed" + exit 1 +fi diff --git a/scripts/test.sh b/scripts/test.sh index d453f813..a25ba856 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -32,4 +32,7 @@ RELAYER_PATH=$( cd .. && pwd ) source "$RELAYER_PATH"/scripts/constants.sh -go test -tags testing $VERBOSE ./... \ No newline at end of file + +go build -o tests/cmd/decider/decider ./tests/cmd/decider/ + +go test -tags testing $VERBOSE ./... diff --git a/tests/cmd/decider/main.go b/tests/cmd/decider/main.go new file mode 100644 index 00000000..2589ca91 --- /dev/null +++ b/tests/cmd/decider/main.go @@ -0,0 +1,49 @@ +// a CLI command to serve as a gRPC provider of awm-relayer/proto/decider + +package main + +import ( + "context" + "flag" + "fmt" + "log" + "net" + + pb "github.com/ava-labs/awm-relayer/proto/pb/decider/v1" + "google.golang.org/grpc" +) + +var port = flag.Int("port", 50051, "The server port") + +type deciderServer struct { + pb.UnimplementedDeciderServiceServer +} + +func (s *deciderServer) ShouldSendMessage( + ctx context.Context, + msg *pb.ShouldSendMessageRequest, +) (*pb.ShouldSendMessageResponse, error) { + return &pb.ShouldSendMessageResponse{ + ShouldSendMessage: true, + }, nil +} + +func main() { + flag.Parse() + + server := grpc.NewServer() + + pb.RegisterDeciderServiceServer(server, &deciderServer{}) + + listener, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) + if err != nil { + log.Fatalf("decider failed to listen: %v", err) + } + + log.Printf("decider listening at %v", listener.Addr()) + + err = server.Serve(listener) + if err != nil { + log.Fatalf("decider failed to serve: %v", err) + } +} diff --git a/tests/e2e_test.go b/tests/e2e_test.go index 4ca8cfed..c26e78fa 100644 --- a/tests/e2e_test.go +++ b/tests/e2e_test.go @@ -4,8 +4,12 @@ package tests import ( + "context" "encoding/hex" "os" + "os/exec" + "os/signal" + "syscall" "testing" testUtils "github.com/ava-labs/awm-relayer/tests/utils" @@ -21,7 +25,12 @@ const ( warpGenesisFile = "./tests/utils/warp-genesis.json" ) -var localNetworkInstance *local.LocalNetwork +var ( + localNetworkInstance *local.LocalNetwork + + decider *exec.Cmd + cancelDecider context.CancelFunc +) func TestE2E(t *testing.T) { if os.Getenv("RUN_E2E") == "" { @@ -34,6 +43,7 @@ func TestE2E(t *testing.T) { // Define the Relayer before and after suite functions. var _ = ginkgo.BeforeSuite(func() { + localNetworkInstance = local.NewLocalNetwork(warpGenesisFile) // Generate the Teleporter deployment values teleporterContractAddress := common.HexToAddress( @@ -63,11 +73,31 @@ var _ = ginkgo.BeforeSuite(func() { teleporterContractAddress, fundedKey, ) + + var ctx context.Context + ctx, cancelDecider = context.WithCancel(context.Background()) + // we'll call cancelDecider in AfterSuite, but also call it if this + // process is killed, because AfterSuite won't always run then: + signalChan := make(chan os.Signal, 2) + signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) + go func() { + <-signalChan + cancelDecider() + }() + decider = exec.CommandContext(ctx, "./tests/cmd/decider/decider") + decider.Start() + log.Info("Started decider service") + log.Info("Set up ginkgo before suite") }) var _ = ginkgo.AfterSuite(func() { - localNetworkInstance.TearDownNetwork() + if localNetworkInstance != nil { + localNetworkInstance.TearDownNetwork() + } + if decider != nil { + cancelDecider() + } }) var _ = ginkgo.Describe("[AWM Relayer Integration Tests", func() { diff --git a/tests/utils/utils.go b/tests/utils/utils.go index f8bf27c6..685051c4 100644 --- a/tests/utils/utils.go +++ b/tests/utils/utils.go @@ -1,7 +1,7 @@ // Copyright (C) 2023, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package tests +package utils import ( "bufio" @@ -95,6 +95,7 @@ func BuildAndRunRelayerExecutable(ctx context.Context, relayerConfigPath string) panic(fmt.Errorf("relayer exited abnormally: %w", err)) } }() + return func() { relayerCancel() <-relayerContext.Done() @@ -190,6 +191,8 @@ func CreateDefaultRelayerConfig( ) } + var deciderPort uint16 = 50051 + return config.Config{ LogLevel: logging.Info.LowerString(), PChainAPI: &config.APIConfig{ @@ -205,6 +208,8 @@ func CreateDefaultRelayerConfig( SourceBlockchains: sources, DestinationBlockchains: destinations, APIPort: 8080, + DeciderHost: "localhost", + DeciderPort: &deciderPort, } } From 5c6422e8977a26bfbae4c62abc2678225547e3ae Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 19 Jul 2024 18:19:55 +0000 Subject: [PATCH 02/29] rm superfluous/duplicate comment addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1678079424 --- main/main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main/main.go b/main/main.go index 3dc6bb24..fb73558a 100644 --- a/main/main.go +++ b/main/main.go @@ -223,7 +223,6 @@ func main() { log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", cfg.APIPort), nil)) }() - // Create listeners for each of the subnets configured as a source errGroup, ctx := errgroup.WithContext(context.Background()) if cfg.DeciderPort != nil { From 584556eccf9ea1c2fa23db5adffdb15b5d210fd4 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 19 Jul 2024 19:01:07 +0000 Subject: [PATCH 03/29] msg handler: extract `deciderRejectedMsg()` helper addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1680065952 --- go.mod | 1 - main/main.go | 2 - messages/teleporter/message_handler.go | 85 +++++++++++++++----------- 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index b073ab52..de241dfc 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.27.9 github.com/aws/aws-sdk-go-v2/service/kms v1.32.1 github.com/ethereum/go-ethereum v1.12.0 - github.com/golang/protobuf v1.5.4 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.33.1 github.com/pkg/errors v0.9.1 diff --git a/main/main.go b/main/main.go index fb73558a..8fadf6b0 100644 --- a/main/main.go +++ b/main/main.go @@ -36,7 +36,6 @@ import ( "go.uber.org/zap" "golang.org/x/sync/errgroup" "google.golang.org/grpc" - "google.golang.org/grpc/connectivity" "google.golang.org/grpc/credentials/insecure" ) @@ -247,7 +246,6 @@ func main() { panic(err) } runtime.SetFinalizer(grpcClient, func(c *grpc.ClientConn) { c.Close() }) - grpcClient.WaitForStateChange(ctx, connectivity.Ready) } // Create listeners for each of the subnets configured as a source diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index d124eeee..b769864c 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -183,47 +183,62 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie return false, nil } - var decision bool = true + deciderRejectedMsg, err := m.deciderRejectedMessage() + if err != nil { + m.logger.Warn( + "Error delegating to decider", + zap.String("warpMessageID", m.unsignedMessage.ID().String()), + zap.String("teleporterMessageID", teleporterMessageID.String()), + ) + } + if deciderRejectedMsg { + m.logger.Info( + "Decider rejected message", + zap.String("warpMessageID", m.unsignedMessage.ID().String()), + zap.String("teleporterMessageID", teleporterMessageID.String()), + zap.String("destinationBlockchainID", destinationBlockchainID.String()), + ) + } + + return true, nil +} + +func (m *messageHandler) deciderRejectedMessage() (bool, error) { deciderClientValue := reflect.ValueOf(m.deciderClient) - if deciderClientValue.IsValid() && !deciderClientValue.IsNil() { - warpMsgIDStr := m.unsignedMessage.ID().Hex() - - warpMsgID, err := hex.DecodeString(warpMsgIDStr) - if err != nil { - m.logger.Error( - "Error decoding message ID", - zap.String("warpMsgIDStr", warpMsgIDStr), - zap.Error(err), - ) - return decision, err - } - // TODO: add a timeout to the context - response, err := m.deciderClient.ShouldSendMessage( - context.Background(), - &pbDecider.ShouldSendMessageRequest{ - NetworkId: m.unsignedMessage.NetworkID, - SourceChainId: m.unsignedMessage.SourceChainID[:], - Payload: m.unsignedMessage.Payload, - BytesRepresentation: m.unsignedMessage.Bytes(), - Id: warpMsgID, - }, + if !deciderClientValue.IsValid() || deciderClientValue.IsNil() { + return false, nil + } + + warpMsgIDStr := m.unsignedMessage.ID().Hex() + + warpMsgID, err := hex.DecodeString(warpMsgIDStr) + if err != nil { + m.logger.Error( + "Error decoding message ID", + zap.String("warpMsgIDStr", warpMsgIDStr), + zap.Error(err), ) - if err != nil { - m.logger.Error( - "Error response from decider.", - zap.String("destinationBlockchainID", destinationBlockchainID.String()), - zap.String("teleporterMessageID", teleporterMessageID.String()), - zap.Any("warpMessageID", warpMsgIDStr), - zap.Error(err), - ) - return decision, err - } + return false, err + } - decision = response.ShouldSendMessage + // TODO: add a timeout to the context + response, err := m.deciderClient.ShouldSendMessage( + context.Background(), + &pbDecider.ShouldSendMessageRequest{ + NetworkId: m.unsignedMessage.NetworkID, + SourceChainId: m.unsignedMessage.SourceChainID[:], + Payload: m.unsignedMessage.Payload, + BytesRepresentation: m.unsignedMessage.Bytes(), + Id: warpMsgID, + }, + ) + if err != nil { + m.logger.Error("Error response from decider.", zap.Error(err)) + return false, err } - return decision, nil + return !response.ShouldSendMessage, nil } // SendMessage extracts the gasLimit and packs the call data to call the receiveCrossChainMessage From 562cf7c383f81324f67ede3d812116c74ca93af3 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 19 Jul 2024 19:41:58 +0000 Subject: [PATCH 04/29] extract helper `initializeDeciderClient()` addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1678214333 --- main/main.go | 66 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/main/main.go b/main/main.go index 8fadf6b0..8968b646 100644 --- a/main/main.go +++ b/main/main.go @@ -222,33 +222,20 @@ func main() { log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", cfg.APIPort), nil)) }() - errGroup, ctx := errgroup.WithContext(context.Background()) - - if cfg.DeciderPort != nil { - port := strconv.FormatUint(uint64(*cfg.DeciderPort), 10) - - host := cfg.DeciderHost - if len(host) == 0 { - host = "localhost" - } - - grpcClient, err = grpc.NewClient( - strings.Join([]string{host, port}, ":"), - grpc.WithTransportCredentials( - insecure.NewCredentials(), - ), + grpcClient, err = initializeDeciderClient( + cfg.DeciderHost, + cfg.DeciderPort, + ) + if err != nil { + logger.Fatal( + "Failed to instantiate decider client", + zap.Error(err), ) - if err != nil { - logger.Fatal( - "Failed to instantiate decider client", - zap.Error(err), - ) - panic(err) - } - runtime.SetFinalizer(grpcClient, func(c *grpc.ClientConn) { c.Close() }) + panic(err) } // Create listeners for each of the subnets configured as a source + errGroup, ctx := errgroup.WithContext(context.Background()) for _, s := range cfg.SourceBlockchains { sourceBlockchain := s @@ -485,6 +472,39 @@ func startMetricsServer(logger logging.Logger, gatherer prometheus.Gatherer, por }() } +func initializeDeciderClient(host string, port *uint16) (*grpc.ClientConn, error) { + if port == nil { + return nil, nil + } + + if len(host) == 0 { + host = "localhost" + } + + client, err := grpc.NewClient( + strings.Join( + []string{host, strconv.FormatUint(uint64(*port), 10)}, + ":", + ), + grpc.WithTransportCredentials( + insecure.NewCredentials(), + ), + ) + if err != nil { + return nil, fmt.Errorf( + "Failed to instantiate grpc client: %w", + err, + ) + } + + runtime.SetFinalizer( + client, + func(c *grpc.ClientConn) { c.Close() }, + ) + + return client, nil +} + func initializeMetrics() (prometheus.Gatherer, prometheus.Registerer, error) { gatherer := metrics.NewMultiGatherer() registry := prometheus.NewRegistry() From b01b14bba2fb7977fb2a9498467bc7ad0653416b Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 19 Jul 2024 20:05:18 +0000 Subject: [PATCH 05/29] main: deciderClient as main() local, not global addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1678217423 --- main/main.go | 77 ++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/main/main.go b/main/main.go index 8968b646..b89bdcd2 100644 --- a/main/main.go +++ b/main/main.go @@ -39,11 +39,7 @@ import ( "google.golang.org/grpc/credentials/insecure" ) -var ( - version = "v0.0.0-dev" - - grpcClient *grpc.ClientConn // for connecting to the decider service -) +var version = "v0.0.0-dev" func main() { fs := config.BuildFlagSet() @@ -183,7 +179,23 @@ func main() { relayerHealth := createHealthTrackers(&cfg) - messageHandlerFactories, err := createMessageHandlerFactories(logger, &cfg) + deciderClient, err := createDeciderClient( + cfg.DeciderHost, + cfg.DeciderPort, + ) + if err != nil { + logger.Fatal( + "Failed to instantiate decider client", + zap.Error(err), + ) + panic(err) + } + + messageHandlerFactories, err := createMessageHandlerFactories( + logger, + &cfg, + deciderClient, + ) if err != nil { logger.Fatal("Failed to create message handler factories", zap.Error(err)) panic(err) @@ -222,18 +234,6 @@ func main() { log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", cfg.APIPort), nil)) }() - grpcClient, err = initializeDeciderClient( - cfg.DeciderHost, - cfg.DeciderPort, - ) - if err != nil { - logger.Fatal( - "Failed to instantiate decider client", - zap.Error(err), - ) - panic(err) - } - // Create listeners for each of the subnets configured as a source errGroup, ctx := errgroup.WithContext(context.Background()) for _, s := range cfg.SourceBlockchains { @@ -261,6 +261,7 @@ func main() { func createMessageHandlerFactories( logger logging.Logger, globalConfig *config.Config, + deciderClient *grpc.ClientConn, ) (map[ids.ID]map[common.Address]messages.MessageHandlerFactory, error) { messageHandlerFactories := make(map[ids.ID]map[common.Address]messages.MessageHandlerFactory) for _, sourceBlockchain := range globalConfig.SourceBlockchains { @@ -279,7 +280,7 @@ func createMessageHandlerFactories( logger, address, cfg, - grpcClient, + deciderClient, ) case config.OFF_CHAIN_REGISTRY: m, err = offchainregistry.NewMessageHandlerFactory( @@ -454,25 +455,7 @@ func createApplicationRelayersForSourceChain( return applicationRelayers, minHeight, nil } -func createHealthTrackers(cfg *config.Config) map[ids.ID]*atomic.Bool { - healthTrackers := make(map[ids.ID]*atomic.Bool, len(cfg.SourceBlockchains)) - for _, sourceBlockchain := range cfg.SourceBlockchains { - healthTrackers[sourceBlockchain.GetBlockchainID()] = atomic.NewBool(true) - } - return healthTrackers -} - -func startMetricsServer(logger logging.Logger, gatherer prometheus.Gatherer, port uint16) { - http.Handle("/metrics", promhttp.HandlerFor(gatherer, promhttp.HandlerOpts{})) - - go func() { - logger.Info("starting metrics server...", - zap.Uint16("port", port)) - log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", port), nil)) - }() -} - -func initializeDeciderClient(host string, port *uint16) (*grpc.ClientConn, error) { +func createDeciderClient(host string, port *uint16) (*grpc.ClientConn, error) { if port == nil { return nil, nil } @@ -505,6 +488,24 @@ func initializeDeciderClient(host string, port *uint16) (*grpc.ClientConn, error return client, nil } +func createHealthTrackers(cfg *config.Config) map[ids.ID]*atomic.Bool { + healthTrackers := make(map[ids.ID]*atomic.Bool, len(cfg.SourceBlockchains)) + for _, sourceBlockchain := range cfg.SourceBlockchains { + healthTrackers[sourceBlockchain.GetBlockchainID()] = atomic.NewBool(true) + } + return healthTrackers +} + +func startMetricsServer(logger logging.Logger, gatherer prometheus.Gatherer, port uint16) { + http.Handle("/metrics", promhttp.HandlerFor(gatherer, promhttp.HandlerOpts{})) + + go func() { + logger.Info("starting metrics server...", + zap.Uint16("port", port)) + log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", port), nil)) + }() +} + func initializeMetrics() (prometheus.Gatherer, prometheus.Registerer, error) { gatherer := metrics.NewMultiGatherer() registry := prometheus.NewRegistry() From 249de65ec847d03934e16a78b9ec42b3098a0a99 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 19 Jul 2024 18:56:31 -0400 Subject: [PATCH 06/29] Apply suggestions from code review Co-authored-by: bernard-avalabs <53795885+bernard-avalabs@users.noreply.github.com> Co-authored-by: cam-schultz <78878559+cam-schultz@users.noreply.github.com> Signed-off-by: F. Eugene Aumson --- proto/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proto/README.md b/proto/README.md index acfc4c10..d477d822 100644 --- a/proto/README.md +++ b/proto/README.md @@ -1,10 +1,10 @@ Protobuf linting and generation for this project is managed by [buf](https://github.com/bufbuild/buf). -Please find installation instructions on +Please find installation instructions at [https://docs.buf.build/installation/](https://docs.buf.build/installation/). -Any changes made to proto definition can be updated by running +When changes are made to the proto definition, the generated source code can be updated by running `protobuf_codegen.sh` located in the `scripts/` directory of this repo. Introduction to `buf` From 81b30bc212c5708d9dba60a78343f630d3b0fd57 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 22 Jul 2024 15:13:12 +0000 Subject: [PATCH 07/29] proto .sh: pull protoc-gen-go version from go.mod addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1678238020 --- proto/pb/decider/v1/decider.pb.go | 8 ++++---- scripts/protobuf_codegen.sh | 9 ++++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/proto/pb/decider/v1/decider.pb.go b/proto/pb/decider/v1/decider.pb.go index 2fdd34e5..90afe12d 100644 --- a/proto/pb/decider/v1/decider.pb.go +++ b/proto/pb/decider/v1/decider.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.33.0 +// protoc-gen-go v1.34.2 // protoc (unknown) // source: decider/v1/decider.proto @@ -195,7 +195,7 @@ func file_decider_v1_decider_proto_rawDescGZIP() []byte { } var file_decider_v1_decider_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_decider_v1_decider_proto_goTypes = []interface{}{ +var file_decider_v1_decider_proto_goTypes = []any{ (*ShouldSendMessageRequest)(nil), // 0: decider.v1.ShouldSendMessageRequest (*ShouldSendMessageResponse)(nil), // 1: decider.v1.ShouldSendMessageResponse } @@ -215,7 +215,7 @@ func file_decider_v1_decider_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_decider_v1_decider_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_decider_v1_decider_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*ShouldSendMessageRequest); i { case 0: return &v.state @@ -227,7 +227,7 @@ func file_decider_v1_decider_proto_init() { return nil } } - file_decider_v1_decider_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_decider_v1_decider_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*ShouldSendMessageResponse); i { case 0: return &v.state diff --git a/scripts/protobuf_codegen.sh b/scripts/protobuf_codegen.sh index d5786892..7f3f0ac7 100755 --- a/scripts/protobuf_codegen.sh +++ b/scripts/protobuf_codegen.sh @@ -7,6 +7,13 @@ if ! [[ "$0" =~ scripts/protobuf_codegen.sh ]]; then exit 255 fi +RELAYER_PATH=$( + cd "$(dirname "${BASH_SOURCE[0]}")" + cd .. && pwd +) + +source $RELAYER_PATH/scripts/versions.sh + ## ensure the correct version of "buf" is installed BUF_VERSION='1.31.0' if [[ $(buf --version | cut -f2 -d' ') != "${BUF_VERSION}" ]]; then @@ -15,7 +22,7 @@ if [[ $(buf --version | cut -f2 -d' ') != "${BUF_VERSION}" ]]; then fi ## install "protoc-gen-go" -PROTOC_GEN_GO_VERSION='v1.33.0' +PROTOC_GEN_GO_VERSION=$(getDepVersion google.golang.org/protobuf) go install -v google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOC_GEN_GO_VERSION} if [[ $(protoc-gen-go --version | cut -f2 -d' ') != "${PROTOC_GEN_GO_VERSION}" ]]; then # e.g., protoc-gen-go v1.28.1 From ed3f4e76a7b280d7e33510aa3f96af183050112c Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 22 Jul 2024 15:21:08 +0000 Subject: [PATCH 08/29] rm unused github_token from .github workflow addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1679918857 --- .github/workflows/linter.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 089aa183..469413d7 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -29,8 +29,6 @@ jobs: - name: Install buf uses: bufbuild/buf-setup-action@v1.31.0 - with: - github_token: ${{ github.token }} - name: Run Lint run: ./scripts/lint.sh --go-lint From f89bd35a55efdf0a470a13d42f44de78921490b1 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 22 Jul 2024 15:34:02 +0000 Subject: [PATCH 09/29] add timeout to decider delegation addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1680066442 --- messages/teleporter/message_handler.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index 91d3c0e8..2299f040 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -222,9 +222,10 @@ func (m *messageHandler) deciderRejectedMessage() (bool, error) { return false, err } - // TODO: add a timeout to the context + ctx, cancelCtx := context.WithTimeout(context.Background(), 30*time.Second) + defer cancelCtx() response, err := m.deciderClient.ShouldSendMessage( - context.Background(), + ctx, &pbDecider.ShouldSendMessageRequest{ NetworkId: m.unsignedMessage.NetworkID, SourceChainId: m.unsignedMessage.SourceChainID[:], From 3631b7bcf178e1b8e342434541fb84bd0b192ff5 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 22 Jul 2024 15:50:20 +0000 Subject: [PATCH 10/29] follow ava-go: exclude ver from proto svc name follow the avalanchego convention of excluding the version number from the name of the service. addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1680070678 --- messages/teleporter/message_handler.go | 2 +- proto/buf.yaml | 2 + proto/decider/{v1 => }/decider.proto | 2 +- proto/pb/decider/decider.pb.go | 260 ++++++++++++++++++ proto/pb/decider/{v1 => }/decider_grpc.pb.go | 8 +- proto/pb/decider/v1/decider.pb.go | 261 ------------------- tests/cmd/decider/main.go | 2 +- 7 files changed, 269 insertions(+), 268 deletions(-) rename proto/decider/{v1 => }/decider.proto (95%) create mode 100644 proto/pb/decider/decider.pb.go rename proto/pb/decider/{v1 => }/decider_grpc.pb.go (94%) delete mode 100644 proto/pb/decider/v1/decider.pb.go diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index 2299f040..dd5688b3 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -17,7 +17,7 @@ import ( warpPayload "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" "github.com/ava-labs/awm-relayer/config" "github.com/ava-labs/awm-relayer/messages" - pbDecider "github.com/ava-labs/awm-relayer/proto/pb/decider/v1" + pbDecider "github.com/ava-labs/awm-relayer/proto/pb/decider" "github.com/ava-labs/awm-relayer/utils" "github.com/ava-labs/awm-relayer/vms" "github.com/ava-labs/subnet-evm/accounts/abi/bind" diff --git a/proto/buf.yaml b/proto/buf.yaml index fdbbe0fc..6f1b8844 100644 --- a/proto/buf.yaml +++ b/proto/buf.yaml @@ -6,3 +6,5 @@ breaking: lint: use: - DEFAULT + except: + - PACKAGE_VERSION_SUFFIX # versioned naming .v1beta diff --git a/proto/decider/v1/decider.proto b/proto/decider/decider.proto similarity index 95% rename from proto/decider/v1/decider.proto rename to proto/decider/decider.proto index b63dcedc..3ba61efa 100644 --- a/proto/decider/v1/decider.proto +++ b/proto/decider/decider.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package decider.v1; +package decider; option go_package = "github.com/ava-labs/awm-relayer/proto/pb/decider"; diff --git a/proto/pb/decider/decider.pb.go b/proto/pb/decider/decider.pb.go new file mode 100644 index 00000000..4047fc4a --- /dev/null +++ b/proto/pb/decider/decider.pb.go @@ -0,0 +1,260 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc (unknown) +// source: decider/decider.proto + +package decider + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ShouldSendMessageRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NetworkId uint32 `protobuf:"varint,1,opt,name=network_id,json=networkId,proto3" json:"network_id,omitempty"` + SourceChainId []byte `protobuf:"bytes,2,opt,name=source_chain_id,json=sourceChainId,proto3" json:"source_chain_id,omitempty"` + Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"` + BytesRepresentation []byte `protobuf:"bytes,4,opt,name=bytes_representation,json=bytesRepresentation,proto3" json:"bytes_representation,omitempty"` + Id []byte `protobuf:"bytes,5,opt,name=id,proto3" json:"id,omitempty"` +} + +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) + } +} + +func (x *ShouldSendMessageRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ShouldSendMessageRequest) ProtoMessage() {} + +func (x *ShouldSendMessageRequest) ProtoReflect() protoreflect.Message { + mi := &file_decider_decider_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ShouldSendMessageRequest.ProtoReflect.Descriptor instead. +func (*ShouldSendMessageRequest) Descriptor() ([]byte, []int) { + return file_decider_decider_proto_rawDescGZIP(), []int{0} +} + +func (x *ShouldSendMessageRequest) GetNetworkId() uint32 { + if x != nil { + return x.NetworkId + } + return 0 +} + +func (x *ShouldSendMessageRequest) GetSourceChainId() []byte { + if x != nil { + return x.SourceChainId + } + return nil +} + +func (x *ShouldSendMessageRequest) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +func (x *ShouldSendMessageRequest) GetBytesRepresentation() []byte { + if x != nil { + return x.BytesRepresentation + } + return nil +} + +func (x *ShouldSendMessageRequest) GetId() []byte { + if x != nil { + return x.Id + } + return nil +} + +type ShouldSendMessageResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ShouldSendMessage bool `protobuf:"varint,1,opt,name=should_send_message,json=shouldSendMessage,proto3" json:"should_send_message,omitempty"` +} + +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) + } +} + +func (x *ShouldSendMessageResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ShouldSendMessageResponse) ProtoMessage() {} + +func (x *ShouldSendMessageResponse) ProtoReflect() protoreflect.Message { + mi := &file_decider_decider_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ShouldSendMessageResponse.ProtoReflect.Descriptor instead. +func (*ShouldSendMessageResponse) Descriptor() ([]byte, []int) { + return file_decider_decider_proto_rawDescGZIP(), []int{1} +} + +func (x *ShouldSendMessageResponse) GetShouldSendMessage() bool { + if x != nil { + return x.ShouldSendMessage + } + return false +} + +var File_decider_decider_proto protoreflect.FileDescriptor + +var file_decider_decider_proto_rawDesc = []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, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x31, + 0x0a, 0x14, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x62, 0x79, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, + 0x64, 0x22, 0x4b, 0x0a, 0x19, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, + 0x0a, 0x13, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, + 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x6c, + 0x0a, 0x0e, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x5a, 0x0a, 0x11, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x2e, + 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x64, 0x65, 0x63, 0x69, 0x64, + 0x65, 0x72, 0x2e, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x32, 0x5a, 0x30, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x76, 0x61, 0x2d, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x61, 0x77, 0x6d, 0x2d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 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 +) + +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) + }) + return file_decider_decider_proto_rawDescData +} + +var file_decider_decider_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_decider_decider_proto_goTypes = []any{ + (*ShouldSendMessageRequest)(nil), // 0: decider.ShouldSendMessageRequest + (*ShouldSendMessageResponse)(nil), // 1: decider.ShouldSendMessageResponse +} +var file_decider_decider_proto_depIdxs = []int32{ + 0, // 0: decider.DeciderService.ShouldSendMessage:input_type -> decider.ShouldSendMessageRequest + 1, // 1: decider.DeciderService.ShouldSendMessage:output_type -> decider.ShouldSendMessageResponse + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_decider_decider_proto_init() } +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{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_decider_decider_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_decider_decider_proto_goTypes, + DependencyIndexes: file_decider_decider_proto_depIdxs, + 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/proto/pb/decider/v1/decider_grpc.pb.go b/proto/pb/decider/decider_grpc.pb.go similarity index 94% rename from proto/pb/decider/v1/decider_grpc.pb.go rename to proto/pb/decider/decider_grpc.pb.go index 00232b5f..5784e0e4 100644 --- a/proto/pb/decider/v1/decider_grpc.pb.go +++ b/proto/pb/decider/decider_grpc.pb.go @@ -2,7 +2,7 @@ // versions: // - protoc-gen-go-grpc v1.3.0 // - protoc (unknown) -// source: decider/v1/decider.proto +// source: decider/decider.proto package decider @@ -19,7 +19,7 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - DeciderService_ShouldSendMessage_FullMethodName = "/decider.v1.DeciderService/ShouldSendMessage" + DeciderService_ShouldSendMessage_FullMethodName = "/decider.DeciderService/ShouldSendMessage" ) // DeciderServiceClient is the client API for DeciderService service. @@ -96,7 +96,7 @@ func _DeciderService_ShouldSendMessage_Handler(srv interface{}, ctx context.Cont // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var DeciderService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "decider.v1.DeciderService", + ServiceName: "decider.DeciderService", HandlerType: (*DeciderServiceServer)(nil), Methods: []grpc.MethodDesc{ { @@ -105,5 +105,5 @@ var DeciderService_ServiceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: "decider/v1/decider.proto", + Metadata: "decider/decider.proto", } diff --git a/proto/pb/decider/v1/decider.pb.go b/proto/pb/decider/v1/decider.pb.go deleted file mode 100644 index 90afe12d..00000000 --- a/proto/pb/decider/v1/decider.pb.go +++ /dev/null @@ -1,261 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.34.2 -// protoc (unknown) -// source: decider/v1/decider.proto - -package decider - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ShouldSendMessageRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - NetworkId uint32 `protobuf:"varint,1,opt,name=network_id,json=networkId,proto3" json:"network_id,omitempty"` - SourceChainId []byte `protobuf:"bytes,2,opt,name=source_chain_id,json=sourceChainId,proto3" json:"source_chain_id,omitempty"` - Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"` - BytesRepresentation []byte `protobuf:"bytes,4,opt,name=bytes_representation,json=bytesRepresentation,proto3" json:"bytes_representation,omitempty"` - Id []byte `protobuf:"bytes,5,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *ShouldSendMessageRequest) Reset() { - *x = ShouldSendMessageRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_decider_v1_decider_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ShouldSendMessageRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ShouldSendMessageRequest) ProtoMessage() {} - -func (x *ShouldSendMessageRequest) ProtoReflect() protoreflect.Message { - mi := &file_decider_v1_decider_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ShouldSendMessageRequest.ProtoReflect.Descriptor instead. -func (*ShouldSendMessageRequest) Descriptor() ([]byte, []int) { - return file_decider_v1_decider_proto_rawDescGZIP(), []int{0} -} - -func (x *ShouldSendMessageRequest) GetNetworkId() uint32 { - if x != nil { - return x.NetworkId - } - return 0 -} - -func (x *ShouldSendMessageRequest) GetSourceChainId() []byte { - if x != nil { - return x.SourceChainId - } - return nil -} - -func (x *ShouldSendMessageRequest) GetPayload() []byte { - if x != nil { - return x.Payload - } - return nil -} - -func (x *ShouldSendMessageRequest) GetBytesRepresentation() []byte { - if x != nil { - return x.BytesRepresentation - } - return nil -} - -func (x *ShouldSendMessageRequest) GetId() []byte { - if x != nil { - return x.Id - } - return nil -} - -type ShouldSendMessageResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ShouldSendMessage bool `protobuf:"varint,1,opt,name=should_send_message,json=shouldSendMessage,proto3" json:"should_send_message,omitempty"` -} - -func (x *ShouldSendMessageResponse) Reset() { - *x = ShouldSendMessageResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_decider_v1_decider_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ShouldSendMessageResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ShouldSendMessageResponse) ProtoMessage() {} - -func (x *ShouldSendMessageResponse) ProtoReflect() protoreflect.Message { - mi := &file_decider_v1_decider_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ShouldSendMessageResponse.ProtoReflect.Descriptor instead. -func (*ShouldSendMessageResponse) Descriptor() ([]byte, []int) { - return file_decider_v1_decider_proto_rawDescGZIP(), []int{1} -} - -func (x *ShouldSendMessageResponse) GetShouldSendMessage() bool { - if x != nil { - return x.ShouldSendMessage - } - return false -} - -var File_decider_v1_decider_proto protoreflect.FileDescriptor - -var file_decider_v1_decider_proto_rawDesc = []byte{ - 0x0a, 0x18, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x63, - 0x69, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x64, 0x65, 0x63, 0x69, - 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x22, 0xbe, 0x01, 0x0a, 0x18, 0x53, 0x68, 0x6f, 0x75, 0x6c, - 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x72, 0x65, - 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x13, 0x62, 0x79, 0x74, 0x65, 0x73, 0x52, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, - 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4b, 0x0a, 0x19, 0x53, 0x68, 0x6f, 0x75, 0x6c, - 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x73, - 0x65, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x32, 0x72, 0x0a, 0x0e, 0x44, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x60, 0x0a, 0x11, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, - 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x2e, 0x64, 0x65, - 0x63, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, - 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x25, 0x2e, 0x64, 0x65, 0x63, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x76, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x61, 0x77, 0x6d, 0x2d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 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_v1_decider_proto_rawDescOnce sync.Once - file_decider_v1_decider_proto_rawDescData = file_decider_v1_decider_proto_rawDesc -) - -func file_decider_v1_decider_proto_rawDescGZIP() []byte { - file_decider_v1_decider_proto_rawDescOnce.Do(func() { - file_decider_v1_decider_proto_rawDescData = protoimpl.X.CompressGZIP(file_decider_v1_decider_proto_rawDescData) - }) - return file_decider_v1_decider_proto_rawDescData -} - -var file_decider_v1_decider_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_decider_v1_decider_proto_goTypes = []any{ - (*ShouldSendMessageRequest)(nil), // 0: decider.v1.ShouldSendMessageRequest - (*ShouldSendMessageResponse)(nil), // 1: decider.v1.ShouldSendMessageResponse -} -var file_decider_v1_decider_proto_depIdxs = []int32{ - 0, // 0: decider.v1.DeciderService.ShouldSendMessage:input_type -> decider.v1.ShouldSendMessageRequest - 1, // 1: decider.v1.DeciderService.ShouldSendMessage:output_type -> decider.v1.ShouldSendMessageResponse - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_decider_v1_decider_proto_init() } -func file_decider_v1_decider_proto_init() { - if File_decider_v1_decider_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_decider_v1_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_v1_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{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_decider_v1_decider_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_decider_v1_decider_proto_goTypes, - DependencyIndexes: file_decider_v1_decider_proto_depIdxs, - MessageInfos: file_decider_v1_decider_proto_msgTypes, - }.Build() - File_decider_v1_decider_proto = out.File - file_decider_v1_decider_proto_rawDesc = nil - file_decider_v1_decider_proto_goTypes = nil - file_decider_v1_decider_proto_depIdxs = nil -} diff --git a/tests/cmd/decider/main.go b/tests/cmd/decider/main.go index 2589ca91..d1486571 100644 --- a/tests/cmd/decider/main.go +++ b/tests/cmd/decider/main.go @@ -9,7 +9,7 @@ import ( "log" "net" - pb "github.com/ava-labs/awm-relayer/proto/pb/decider/v1" + pb "github.com/ava-labs/awm-relayer/proto/pb/decider" "google.golang.org/grpc" ) From be38f171f18bfd4bfbfb266ba26b1425c3fa6ec9 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 22 Jul 2024 12:18:06 -0400 Subject: [PATCH 11/29] add descriptions of new config options addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1679927508 Signed-off-by: F. Eugene Aumson --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e3f9e33b..9c20bd7b 100644 --- a/README.md +++ b/README.md @@ -291,6 +291,12 @@ The relayer is configured via a JSON file, the path to which is passed in via th - The AWS region in which the KMS key is located. Required if `kms-key-id` is provided. +`"decider-host": string` + +`"decider-port": unsigned integer` + +- The network location of a service implementing the gRPC service defined by `proto/decider`, which will be queried for each message to determine whether that message should be relayed. If a port is specified but a host is not, the host is assumed to be `localhost`. + ## Architecture ### Components From aab66d5326c1707d0d2705ca4224be6e62d16860 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Mon, 22 Jul 2024 16:29:00 +0000 Subject: [PATCH 12/29] validate uri addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1679930631 --- main/main.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/main/main.go b/main/main.go index b44b81bd..2b37bf29 100644 --- a/main/main.go +++ b/main/main.go @@ -8,6 +8,7 @@ import ( "fmt" "log" "net/http" + "net/url" "os" "runtime" "strconv" @@ -463,14 +464,19 @@ func createDeciderClient(host string, port *uint16) (*grpc.ClientConn, error) { host = "localhost" } + uri := strings.Join( + []string{host, strconv.FormatUint(uint64(*port), 10)}, + ":", + ) + + _, err := url.ParseRequestURI(uri) + if err != nil { + return nil, fmt.Errorf("Invalid URI: %w", err) + } + client, err := grpc.NewClient( - strings.Join( - []string{host, strconv.FormatUint(uint64(*port), 10)}, - ":", - ), - grpc.WithTransportCredentials( - insecure.NewCredentials(), - ), + uri, + grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { return nil, fmt.Errorf( From df26aa2b428fc59ec6f8af7e30a2b3d184148c41 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 24 Jul 2024 15:00:47 +0000 Subject: [PATCH 13/29] improve readbility of decider invocation addresses review comments https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1688712251 and https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1688718437 and https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1688721826 --- messages/teleporter/message_handler.go | 31 +++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index dd5688b3..937ad293 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -183,31 +183,32 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie return false, nil } - deciderRejectedMsg, err := m.deciderRejectedMessage() - if err != nil { + if decision, err := m.getDeciderDecision(); err != nil { m.logger.Warn( "Error delegating to decider", zap.String("warpMessageID", m.unsignedMessage.ID().String()), zap.String("teleporterMessageID", teleporterMessageID.String()), ) - } - if deciderRejectedMsg { - m.logger.Info( - "Decider rejected message", - zap.String("warpMessageID", m.unsignedMessage.ID().String()), - zap.String("teleporterMessageID", teleporterMessageID.String()), - zap.String("destinationBlockchainID", destinationBlockchainID.String()), - ) + } else if decision != nil { + if !*decision { + m.logger.Info( + "Decider rejected message", + zap.String("warpMessageID", m.unsignedMessage.ID().String()), + zap.String("teleporterMessageID", teleporterMessageID.String()), + zap.String("destinationBlockchainID", destinationBlockchainID.String()), + ) + } + return *decision, nil } return true, nil } -func (m *messageHandler) deciderRejectedMessage() (bool, error) { +func (m *messageHandler) getDeciderDecision() (*bool, error) { deciderClientValue := reflect.ValueOf(m.deciderClient) if !deciderClientValue.IsValid() || deciderClientValue.IsNil() { - return false, nil + return nil, nil } warpMsgIDStr := m.unsignedMessage.ID().Hex() @@ -219,7 +220,7 @@ func (m *messageHandler) deciderRejectedMessage() (bool, error) { zap.String("warpMsgIDStr", warpMsgIDStr), zap.Error(err), ) - return false, err + return nil, err } ctx, cancelCtx := context.WithTimeout(context.Background(), 30*time.Second) @@ -236,10 +237,10 @@ func (m *messageHandler) deciderRejectedMessage() (bool, error) { ) if err != nil { m.logger.Error("Error response from decider.", zap.Error(err)) - return false, err + return nil, err } - return !response.ShouldSendMessage, nil + return &response.ShouldSendMessage, nil } // SendMessage extracts the gasLimit and packs the call data to call the receiveCrossChainMessage From a9c374c2377ed4b33ad86dafab7610c6881ffa40 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 24 Jul 2024 15:14:57 +0000 Subject: [PATCH 14/29] validate decider host/port in config, not main addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1688726464 --- config/config.go | 19 +++++++++++++++++++ main/main.go | 16 ++++------------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/config/config.go b/config/config.go index 6aceaca8..c2b6c5a2 100644 --- a/config/config.go +++ b/config/config.go @@ -7,6 +7,9 @@ import ( "context" "errors" "fmt" + "net/url" + "strconv" + "strings" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/constants" @@ -121,6 +124,22 @@ func (c *Config) Validate() error { } c.blockchainIDToSubnetID = blockchainIDToSubnetID + if c.DeciderPort != nil { + portStr := strconv.FormatUint(uint64(*c.DeciderPort), 10) + + host := c.DeciderHost + if len(host) == 0 { + host = "localhost" + } + + uri := strings.Join([]string{host, portStr}, ":") + + _, err := url.ParseRequestURI(uri) + if err != nil { + return fmt.Errorf("Invalid decider URI: %w", err) + } + } + return nil } diff --git a/main/main.go b/main/main.go index 2b37bf29..d76fc6e4 100644 --- a/main/main.go +++ b/main/main.go @@ -8,7 +8,6 @@ import ( "fmt" "log" "net/http" - "net/url" "os" "runtime" "strconv" @@ -464,18 +463,11 @@ func createDeciderClient(host string, port *uint16) (*grpc.ClientConn, error) { host = "localhost" } - uri := strings.Join( - []string{host, strconv.FormatUint(uint64(*port), 10)}, - ":", - ) - - _, err := url.ParseRequestURI(uri) - if err != nil { - return nil, fmt.Errorf("Invalid URI: %w", err) - } - client, err := grpc.NewClient( - uri, + strings.Join( + []string{host, strconv.FormatUint(uint64(*port), 10)}, + ":", + ), grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { From 6a9c27686d03fe38b1e03933335186ab23cc91f6 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 24 Jul 2024 15:26:03 +0000 Subject: [PATCH 15/29] explain `createDeciderClient()` addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1688732284 --- main/main.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/main.go b/main/main.go index d76fc6e4..b07e1f25 100644 --- a/main/main.go +++ b/main/main.go @@ -454,6 +454,9 @@ func createApplicationRelayersForSourceChain( return applicationRelayers, minHeight, nil } +/* if port is nil, neither a client nor an error will be returned. + * if is non-nil, a client will be constructed + * if host is an empty string, a default value of "localhost" is assumed. */ func createDeciderClient(host string, port *uint16) (*grpc.ClientConn, error) { if port == nil { return nil, nil From c37fd4176cec9ebac7b103ee654f8c49d6bd42bd Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 24 Jul 2024 15:28:49 +0000 Subject: [PATCH 16/29] add to README addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1688733902 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c20bd7b..6e98557e 100644 --- a/README.md +++ b/README.md @@ -295,7 +295,7 @@ The relayer is configured via a JSON file, the path to which is passed in via th `"decider-port": unsigned integer` -- The network location of a service implementing the gRPC service defined by `proto/decider`, which will be queried for each message to determine whether that message should be relayed. If a port is specified but a host is not, the host is assumed to be `localhost`. +- The network location of a service implementing the gRPC service defined by `proto/decider`, which will be queried for each message to determine whether that message should be relayed. If a port is specified but a host is not, the host is assumed to be `localhost`. If a host is specified then a port is required. ## Architecture From 7eb5112b149ca2ed3bf321f1a3a5d7d081c787d7 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Wed, 24 Jul 2024 22:09:41 +0000 Subject: [PATCH 17/29] config: just DeciderURL, not Host/Port addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1690259955 and https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1679953463 --- README.md | 6 ++---- config/config.go | 19 +++---------------- main/main.go | 24 ++++++------------------ tests/utils/utils.go | 5 +---- 4 files changed, 12 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 6e98557e..c10e44a2 100644 --- a/README.md +++ b/README.md @@ -291,11 +291,9 @@ The relayer is configured via a JSON file, the path to which is passed in via th - The AWS region in which the KMS key is located. Required if `kms-key-id` is provided. -`"decider-host": string` +`"decider-url": string` -`"decider-port": unsigned integer` - -- The network location of a service implementing the gRPC service defined by `proto/decider`, which will be queried for each message to determine whether that message should be relayed. If a port is specified but a host is not, the host is assumed to be `localhost`. If a host is specified then a port is required. +- The URL of a service implementing the gRPC service defined by `proto/decider`, which will be queried for each message to determine whether that message should be relayed. ## Architecture diff --git a/config/config.go b/config/config.go index c2b6c5a2..c8ea74dc 100644 --- a/config/config.go +++ b/config/config.go @@ -8,8 +8,6 @@ import ( "errors" "fmt" "net/url" - "strconv" - "strings" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/constants" @@ -61,8 +59,7 @@ type Config struct { SourceBlockchains []*SourceBlockchain `mapstructure:"source-blockchains" json:"source-blockchains"` DestinationBlockchains []*DestinationBlockchain `mapstructure:"destination-blockchains" json:"destination-blockchains"` ProcessMissedBlocks bool `mapstructure:"process-missed-blocks" json:"process-missed-blocks"` - DeciderHost string `mapstructure:"decider-host" json:"decider-host"` - DeciderPort *uint16 `mapstructure:"decider-port" json:"decider-port"` + DeciderURL string `mapstructure:"decider-url" json:"decider-url"` // convenience field to fetch a blockchain's subnet ID blockchainIDToSubnetID map[ids.ID]ids.ID @@ -124,18 +121,8 @@ func (c *Config) Validate() error { } c.blockchainIDToSubnetID = blockchainIDToSubnetID - if c.DeciderPort != nil { - portStr := strconv.FormatUint(uint64(*c.DeciderPort), 10) - - host := c.DeciderHost - if len(host) == 0 { - host = "localhost" - } - - uri := strings.Join([]string{host, portStr}, ":") - - _, err := url.ParseRequestURI(uri) - if err != nil { + if len(c.DeciderURL) != 0 { + if _, err := url.ParseRequestURI(c.DeciderURL); err != nil { return fmt.Errorf("Invalid decider URI: %w", err) } } diff --git a/main/main.go b/main/main.go index b07e1f25..d3c5b58a 100644 --- a/main/main.go +++ b/main/main.go @@ -10,7 +10,6 @@ import ( "net/http" "os" "runtime" - "strconv" "strings" "github.com/ava-labs/avalanchego/api/metrics" @@ -178,10 +177,7 @@ func main() { relayerHealth := createHealthTrackers(&cfg) - deciderClient, err := createDeciderClient( - cfg.DeciderHost, - cfg.DeciderPort, - ) + deciderClient, err := createDeciderClient(cfg.DeciderURL) if err != nil { logger.Fatal( "Failed to instantiate decider client", @@ -454,23 +450,15 @@ func createApplicationRelayersForSourceChain( return applicationRelayers, minHeight, nil } -/* if port is nil, neither a client nor an error will be returned. - * if is non-nil, a client will be constructed - * if host is an empty string, a default value of "localhost" is assumed. */ -func createDeciderClient(host string, port *uint16) (*grpc.ClientConn, error) { - if port == nil { +// create a client for the "should send message" decider service. +// if url is unspecified, returns a nil client pointer +func createDeciderClient(url string) (*grpc.ClientConn, error) { + if len(url) == 0 { return nil, nil } - if len(host) == 0 { - host = "localhost" - } - client, err := grpc.NewClient( - strings.Join( - []string{host, strconv.FormatUint(uint64(*port), 10)}, - ":", - ), + url, grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { diff --git a/tests/utils/utils.go b/tests/utils/utils.go index d312b8a3..99bbd41d 100644 --- a/tests/utils/utils.go +++ b/tests/utils/utils.go @@ -191,8 +191,6 @@ func CreateDefaultRelayerConfig( ) } - var deciderPort uint16 = 50051 - return config.Config{ LogLevel: logging.Info.LowerString(), PChainAPI: &config.APIConfig{ @@ -208,8 +206,7 @@ func CreateDefaultRelayerConfig( SourceBlockchains: sources, DestinationBlockchains: destinations, APIPort: 8080, - DeciderHost: "localhost", - DeciderPort: &deciderPort, + DeciderURL: "localhost:50051", } } From 7e02e1ac549f556c3d3d9c4327f245232551e7a4 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 25 Jul 2024 15:38:06 +0000 Subject: [PATCH 18/29] stop returning bool pointer addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1690248736 --- messages/teleporter/message_handler.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index 937ad293..6008d26a 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -189,8 +189,8 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie zap.String("warpMessageID", m.unsignedMessage.ID().String()), zap.String("teleporterMessageID", teleporterMessageID.String()), ) - } else if decision != nil { - if !*decision { + } else { + if !decision { m.logger.Info( "Decider rejected message", zap.String("warpMessageID", m.unsignedMessage.ID().String()), @@ -198,17 +198,17 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie zap.String("destinationBlockchainID", destinationBlockchainID.String()), ) } - return *decision, nil + return decision, nil } return true, nil } -func (m *messageHandler) getDeciderDecision() (*bool, error) { +func (m *messageHandler) getDeciderDecision() (bool, error) { deciderClientValue := reflect.ValueOf(m.deciderClient) if !deciderClientValue.IsValid() || deciderClientValue.IsNil() { - return nil, nil + return true, nil } warpMsgIDStr := m.unsignedMessage.ID().Hex() @@ -220,7 +220,7 @@ func (m *messageHandler) getDeciderDecision() (*bool, error) { zap.String("warpMsgIDStr", warpMsgIDStr), zap.Error(err), ) - return nil, err + return false, err } ctx, cancelCtx := context.WithTimeout(context.Background(), 30*time.Second) @@ -237,10 +237,10 @@ func (m *messageHandler) getDeciderDecision() (*bool, error) { ) if err != nil { m.logger.Error("Error response from decider.", zap.Error(err)) - return nil, err + return false, err } - return &response.ShouldSendMessage, nil + return response.ShouldSendMessage, nil } // SendMessage extracts the gasLimit and packs the call data to call the receiveCrossChainMessage From 0a2249734c98e4edde5be1657f8b38b832e62cd9 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 25 Jul 2024 15:40:59 +0000 Subject: [PATCH 19/29] rename and document helper method --- messages/teleporter/message_handler.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index 6008d26a..8c4ada7a 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -183,7 +183,7 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie return false, nil } - if decision, err := m.getDeciderDecision(); err != nil { + if decision, err := m.getShouldSendMessageFromDecider(); err != nil { m.logger.Warn( "Error delegating to decider", zap.String("warpMessageID", m.unsignedMessage.ID().String()), @@ -204,7 +204,9 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie return true, nil } -func (m *messageHandler) getDeciderDecision() (bool, error) { +// queries the decider service to determine whether this message should be +// sent. if the decider client is nil, returns true. +func (m *messageHandler) getShouldSendMessageFromDecider() (bool, error) { deciderClientValue := reflect.ValueOf(m.deciderClient) if !deciderClientValue.IsValid() || deciderClientValue.IsNil() { From 742a6ee57c1592907b41d82909d63196e4a8e66a Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 25 Jul 2024 16:06:59 +0000 Subject: [PATCH 20/29] e2e test: panic if decider exits abnormally addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1678271724 --- tests/e2e_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/e2e_test.go b/tests/e2e_test.go index ff6df272..a49a6c05 100644 --- a/tests/e2e_test.go +++ b/tests/e2e_test.go @@ -6,6 +6,8 @@ package tests import ( "context" "encoding/hex" + "errors" + "fmt" "os" "os/exec" "os/signal" @@ -101,6 +103,14 @@ var _ = ginkgo.BeforeSuite(func() { }() decider = exec.CommandContext(ctx, "./tests/cmd/decider/decider") decider.Start() + go func() { // panic if the decider exits abnormally + err := decider.Wait() + // Context cancellation is the only expected way for the + // process to exit, otherwise panic + if !errors.Is(ctx.Err(), context.Canceled) { + panic(fmt.Errorf("decider exited abnormally: %w", err)) + } + }() log.Info("Started decider service") log.Info("Set up ginkgo before suite") From 1837d4beff0008a2add173cd474a4309bb574275 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 25 Jul 2024 18:12:15 -0400 Subject: [PATCH 21/29] Update messages/teleporter/message_handler.go Co-authored-by: cam-schultz <78878559+cam-schultz@users.noreply.github.com> Signed-off-by: F. Eugene Aumson --- messages/teleporter/message_handler.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index 8c4ada7a..c2e5a5bc 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -204,8 +204,8 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie return true, nil } -// queries the decider service to determine whether this message should be -// sent. if the decider client is nil, returns true. +// Queries the decider service to determine whether this message should be +// sent. If the decider client is nil, returns true. func (m *messageHandler) getShouldSendMessageFromDecider() (bool, error) { deciderClientValue := reflect.ValueOf(m.deciderClient) From 8ed81129aaeb1329a0eb2ef86e84542806ab392a Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 25 Jul 2024 22:15:08 +0000 Subject: [PATCH 22/29] streamline getShouldSendMessageFromDecider flow addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1692030709 --- messages/teleporter/message_handler.go | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index c2e5a5bc..9a3ecbf0 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -183,25 +183,24 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie return false, nil } - if decision, err := m.getShouldSendMessageFromDecider(); err != nil { + decision, err := m.getShouldSendMessageFromDecider() + if err != nil { m.logger.Warn( "Error delegating to decider", zap.String("warpMessageID", m.unsignedMessage.ID().String()), zap.String("teleporterMessageID", teleporterMessageID.String()), ) - } else { - if !decision { - m.logger.Info( - "Decider rejected message", - zap.String("warpMessageID", m.unsignedMessage.ID().String()), - zap.String("teleporterMessageID", teleporterMessageID.String()), - zap.String("destinationBlockchainID", destinationBlockchainID.String()), - ) - } - return decision, nil + return true, nil } - - return true, nil + if !decision { + m.logger.Info( + "Decider rejected message", + zap.String("warpMessageID", m.unsignedMessage.ID().String()), + zap.String("teleporterMessageID", teleporterMessageID.String()), + zap.String("destinationBlockchainID", destinationBlockchainID.String()), + ) + } + return decision, nil } // Queries the decider service to determine whether this message should be From 6488c81759369362e779ea64fdae7234ed4743b2 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 25 Jul 2024 18:26:09 -0400 Subject: [PATCH 23/29] Update config/config.go Co-authored-by: Geoff Stuart Signed-off-by: F. Eugene Aumson --- config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.go b/config/config.go index c8ea74dc..c7fc7374 100644 --- a/config/config.go +++ b/config/config.go @@ -123,7 +123,7 @@ func (c *Config) Validate() error { if len(c.DeciderURL) != 0 { if _, err := url.ParseRequestURI(c.DeciderURL); err != nil { - return fmt.Errorf("Invalid decider URI: %w", err) + return fmt.Errorf("Invalid decider URL: %w", err) } } From 9a7944dc31ba6a39f775c84fcc3162b3ba55bfa2 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 25 Jul 2024 18:38:14 -0400 Subject: [PATCH 24/29] stop decoding warpMsgID Co-authored-by: Geoff Stuart Signed-off-by: F. Eugene Aumson --- messages/teleporter/message_handler.go | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index 9a3ecbf0..ec4d4a6b 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -5,7 +5,6 @@ package teleporter import ( "context" - "encoding/hex" "encoding/json" "fmt" "reflect" @@ -212,17 +211,7 @@ func (m *messageHandler) getShouldSendMessageFromDecider() (bool, error) { return true, nil } - warpMsgIDStr := m.unsignedMessage.ID().Hex() - - warpMsgID, err := hex.DecodeString(warpMsgIDStr) - if err != nil { - m.logger.Error( - "Error decoding message ID", - zap.String("warpMsgIDStr", warpMsgIDStr), - zap.Error(err), - ) - return false, err - } + warpMsgID := m.unsignedMessage.ID() ctx, cancelCtx := context.WithTimeout(context.Background(), 30*time.Second) defer cancelCtx() @@ -233,7 +222,7 @@ func (m *messageHandler) getShouldSendMessageFromDecider() (bool, error) { SourceChainId: m.unsignedMessage.SourceChainID[:], Payload: m.unsignedMessage.Payload, BytesRepresentation: m.unsignedMessage.Bytes(), - Id: warpMsgID, + Id: warpMsgID[:], }, ) if err != nil { From 19e86895e30760acbf56eaf5e0579c67c5cac2ab Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 25 Jul 2024 22:49:04 +0000 Subject: [PATCH 25/29] rename parameter --- messages/teleporter/message_handler.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index ec4d4a6b..789fe87b 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -49,7 +49,7 @@ func NewMessageHandlerFactory( logger logging.Logger, messageProtocolAddress common.Address, messageProtocolConfig config.MessageProtocolConfig, - grpcClient *grpc.ClientConn, + deciderClientConn *grpc.ClientConn, ) (messages.MessageHandlerFactory, error) { // Marshal the map and unmarshal into the Teleporter config data, err := json.Marshal(messageProtocolConfig.Settings) @@ -72,10 +72,10 @@ func NewMessageHandlerFactory( } var deciderClient pbDecider.DeciderServiceClient - if grpcClient == nil { + if deciderClientConn == nil { deciderClient = nil } else { - deciderClient = pbDecider.NewDeciderServiceClient(grpcClient) + deciderClient = pbDecider.NewDeciderServiceClient(deciderClientConn) } return &factory{ From 682fead651913a9142ff49c59c52844b3a8b66b3 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Thu, 25 Jul 2024 22:53:54 +0000 Subject: [PATCH 26/29] remove redundant assignment of nil to interface addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1692063683 --- messages/teleporter/message_handler.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index 789fe87b..eddf95ef 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -72,9 +72,7 @@ func NewMessageHandlerFactory( } var deciderClient pbDecider.DeciderServiceClient - if deciderClientConn == nil { - deciderClient = nil - } else { + if deciderClientConn != nil { deciderClient = pbDecider.NewDeciderServiceClient(deciderClientConn) } From 79c82b2a1d904428409ba0d228b2b0b58b83f3da Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 26 Jul 2024 14:46:14 +0000 Subject: [PATCH 27/29] `deciderConnection`, not just `deciderClient` addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1693044488 --- main/main.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/main/main.go b/main/main.go index d3c5b58a..3ac8e683 100644 --- a/main/main.go +++ b/main/main.go @@ -177,10 +177,10 @@ func main() { relayerHealth := createHealthTrackers(&cfg) - deciderClient, err := createDeciderClient(cfg.DeciderURL) + deciderConnection, err := createDeciderConnection(cfg.DeciderURL) if err != nil { logger.Fatal( - "Failed to instantiate decider client", + "Failed to instantiate decider connection", zap.Error(err), ) panic(err) @@ -189,7 +189,7 @@ func main() { messageHandlerFactories, err := createMessageHandlerFactories( logger, &cfg, - deciderClient, + deciderConnection, ) if err != nil { logger.Fatal("Failed to create message handler factories", zap.Error(err)) @@ -256,7 +256,7 @@ func main() { func createMessageHandlerFactories( logger logging.Logger, globalConfig *config.Config, - deciderClient *grpc.ClientConn, + deciderConnection *grpc.ClientConn, ) (map[ids.ID]map[common.Address]messages.MessageHandlerFactory, error) { messageHandlerFactories := make(map[ids.ID]map[common.Address]messages.MessageHandlerFactory) for _, sourceBlockchain := range globalConfig.SourceBlockchains { @@ -275,7 +275,7 @@ func createMessageHandlerFactories( logger, address, cfg, - deciderClient, + deciderConnection, ) case config.OFF_CHAIN_REGISTRY: m, err = offchainregistry.NewMessageHandlerFactory( @@ -450,14 +450,14 @@ func createApplicationRelayersForSourceChain( return applicationRelayers, minHeight, nil } -// create a client for the "should send message" decider service. +// create a connection to the "should send message" decider service. // if url is unspecified, returns a nil client pointer -func createDeciderClient(url string) (*grpc.ClientConn, error) { +func createDeciderConnection(url string) (*grpc.ClientConn, error) { if len(url) == 0 { return nil, nil } - client, err := grpc.NewClient( + connection, err := grpc.NewClient( url, grpc.WithTransportCredentials(insecure.NewCredentials()), ) @@ -469,11 +469,11 @@ func createDeciderClient(url string) (*grpc.ClientConn, error) { } runtime.SetFinalizer( - client, + connection, func(c *grpc.ClientConn) { c.Close() }, ) - return client, nil + return connection, nil } func createHealthTrackers(cfg *config.Config) map[ids.ID]*atomic.Bool { From c4b226224ab1ee1020826367909cc3950bfd8fe1 Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 26 Jul 2024 10:54:44 -0400 Subject: [PATCH 28/29] add comment to separate two "halves" of function Co-authored-by: cam-schultz <78878559+cam-schultz@users.noreply.github.com> Signed-off-by: F. Eugene Aumson --- messages/teleporter/message_handler.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index eddf95ef..212950ce 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -179,7 +179,8 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie ) return false, nil } - + // Dispatch to the external decider service. If the service is unavailable or returns + // an error, then use the decision that has already been made, i.e. return true decision, err := m.getShouldSendMessageFromDecider() if err != nil { m.logger.Warn( From f8662fdaf33fa9d196655df3ef485144d089e69d Mon Sep 17 00:00:00 2001 From: "F. Eugene Aumson" Date: Fri, 26 Jul 2024 15:09:23 +0000 Subject: [PATCH 29/29] when conn==nil, init client to "empty" impl addresses review comment https://github.com/ava-labs/awm-relayer/pull/344#discussion_r1692063683 --- messages/teleporter/message_handler.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/messages/teleporter/message_handler.go b/messages/teleporter/message_handler.go index 212950ce..dd7d8b58 100644 --- a/messages/teleporter/message_handler.go +++ b/messages/teleporter/message_handler.go @@ -7,7 +7,6 @@ import ( "context" "encoding/json" "fmt" - "reflect" "time" "github.com/ava-labs/avalanchego/ids" @@ -45,6 +44,17 @@ type messageHandler struct { deciderClient pbDecider.DeciderServiceClient } +// define an "empty" decider client to use when a connection isn't provided: +type emptyDeciderClient struct{} + +func (s *emptyDeciderClient) ShouldSendMessage( + _ context.Context, + _ *pbDecider.ShouldSendMessageRequest, + _ ...grpc.CallOption, +) (*pbDecider.ShouldSendMessageResponse, error) { + return &pbDecider.ShouldSendMessageResponse{ShouldSendMessage: true}, nil +} + func NewMessageHandlerFactory( logger logging.Logger, messageProtocolAddress common.Address, @@ -72,7 +82,9 @@ func NewMessageHandlerFactory( } var deciderClient pbDecider.DeciderServiceClient - if deciderClientConn != nil { + if deciderClientConn == nil { + deciderClient = &emptyDeciderClient{} + } else { deciderClient = pbDecider.NewDeciderServiceClient(deciderClientConn) } @@ -204,12 +216,6 @@ func (m *messageHandler) ShouldSendMessage(destinationClient vms.DestinationClie // Queries the decider service to determine whether this message should be // sent. If the decider client is nil, returns true. func (m *messageHandler) getShouldSendMessageFromDecider() (bool, error) { - deciderClientValue := reflect.ValueOf(m.deciderClient) - - if !deciderClientValue.IsValid() || deciderClientValue.IsNil() { - return true, nil - } - warpMsgID := m.unsignedMessage.ID() ctx, cancelCtx := context.WithTimeout(context.Background(), 30*time.Second)