diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..17244a16d1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,75 @@ + # Security Policy + +## Introduction + +Security researchers are essential in identifying vulnerabilities that may impact the Axelar Network. If you have discovered a security vulnerability in the Axelar chain or any repository managed by Axelar, we encourage you to notify us using one of the methods outlined below. + +### Guidelines for Responsible Vulnerability Testing and Reporting + +1. **Refrain from testing vulnerabilities on our publicly accessible environments**, including but not limited to: + - Axelar mainnet + - Axelar Frontend Apps e.g satellite.money + - Axelar Testnet + - Axelar Testnet Frontend Apps e.g testnet.satellite.money + +2. **Avoid reporting security vulnerabilities through public channels, including GitHub issues** + +## Reporting Security Issues + +To privately report a security vulnerability, please choose one of the following options: + +### 1. Email + +Send your detailed vulnerability report to `security@axelar.network`. + +### 2. Bug Bounty Program + +Axelar is partnered with Immunefi to offer a bug bounty program. Please visit [Immunefi's website](https://immunefi.com/bug-bounty/axelarnetwork/information/) for more information. + +## Submit Vulnerability Report + +When reporting a vulnerability through either method, please include the following details to aid in our assessment: + +- Type of vulnerability +- Description of the vulnerability +- Steps to reproduce the issue +- Impact of the issue +- Explanation of how an attacker could exploit it + +> [!NOTE] +> Review our criteria in the [Official Docs](https://docs.axelar.dev/resources/bug-bounty/#vulnerability-criteria) + +## Vulnerability Disclosure Process + +1. **Initial Report**: Submit the vulnerability via one of the above channels. +2. **Confirmation**: We will confirm receipt of your report within 48 hours. +3. **Assessment**: Our security team will evaluate the vulnerability and inform you of its severity and the estimated time frame for resolution. +4. **Resolution**: Once fixed, you will be contacted to verify the solution. +5. **Public Disclosure**: Details of the vulnerability may be publicly disclosed after ensuring it poses no further risk. + +During the vulnerability disclosure process, we ask security researchers to keep vulnerabilities and communications around vulnerability submissions private and confidential until a patch is developed. Should a security issue require a network upgrade, additional time may be needed to raise a governance proposal and complete the upgrade. + +During this time: + +- Avoid exploiting any vulnerabilities you discover. +- Demonstrate good faith by not disrupting or degrading Axelar's services. + +## Severity Characterization + +| Severity | Description | +|--------------|-------------------------------------------------------------------------| +| **CRITICAL** | Immediate threat to critical systems (e.g., chain halts, funds at risk) | +| **HIGH** | Significant impact on major functionality | +| **MEDIUM** | Impacts minor features or exposes non-sensitive data | +| **LOW** | Minimal impact | + +## Bug Bounty + +Our bug bounty program is managed by Immunefi. Please visit [Immunefi's website](https://immunefi.com/bug-bounty/axelarnetwork/information/) for more information. + +> [!WARNING] +> Targeting our production environments will disqualify you from receiving any bounty. + +## Feedback on this Policy + +For recommendations on how to improve this policy, either submit a pull request or send an email to `security@axelar.network`. diff --git a/app/keepers.go b/app/keepers.go index c6afd19fcc..9254f0190f 100644 --- a/app/keepers.go +++ b/app/keepers.go @@ -7,6 +7,7 @@ import ( "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server/types" @@ -163,20 +164,28 @@ func initStakingKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, ke func initWasmKeeper(encodingConfig axelarParams.EncodingConfig, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache, bApp *bam.BaseApp, appOpts types.AppOptions, wasmOpts []wasm.Option, wasmDir string) *wasm.Keeper { wasmConfig := mustReadWasmConfig(appOpts) + nexusK := GetKeeper[nexusKeeper.Keeper](keepers) // The last arguments can contain custom message handlers, and custom query handlers, // if we want to allow any custom callbacks - wasmOpts = append(wasmOpts, wasmkeeper.WithMessageHandlerDecorator( - func(old wasmkeeper.Messenger) wasmkeeper.Messenger { - encoders := wasm.DefaultEncoders(encodingConfig.Codec, GetKeeper[ibctransferkeeper.Keeper](keepers)) - encoders.Custom = nexusKeeper.EncodeRoutingMessage - - return WithAnteHandlers( - encoders, - initMessageAnteDecorators(encodingConfig, keepers), - // for security reasons we disallow some msg types that can be used for arbitrary calls - wasmkeeper.NewMessageHandlerChain(NewMsgTypeBlacklistMessenger(), old, nexusKeeper.NewMessenger(GetKeeper[nexusKeeper.Keeper](keepers)))) - })) + wasmOpts = append( + wasmOpts, + wasmkeeper.WithMessageHandlerDecorator( + func(old wasmkeeper.Messenger) wasmkeeper.Messenger { + encoders := wasm.DefaultEncoders(encodingConfig.Codec, GetKeeper[ibctransferkeeper.Keeper](keepers)) + encoders.Custom = nexusKeeper.EncodeRoutingMessage + + return WithAnteHandlers( + encoders, + initMessageAnteDecorators(encodingConfig, keepers), + // for security reasons we disallow some msg types that can be used for arbitrary calls + wasmkeeper.NewMessageHandlerChain(NewMsgTypeBlacklistMessenger(), old, nexusKeeper.NewMessenger(nexusK))) + }), + wasmkeeper.WithWasmEngineDecorator(func(old wasmtypes.WasmerEngine) wasmtypes.WasmerEngine { + return nexusKeeper.NewWasmerEngine(old, nexusK) + }), + wasmkeeper.WithQueryPlugins(NewQueryPlugins(nexusK)), + ) scopedWasmK := GetKeeper[capabilitykeeper.Keeper](keepers).ScopeToModule(wasm.ModuleName) ibcKeeper := GetKeeper[ibckeeper.Keeper](keepers) diff --git a/app/wasm.go b/app/wasm.go index 4a5c142cf0..dd72239bb3 100644 --- a/app/wasm.go +++ b/app/wasm.go @@ -15,6 +15,9 @@ import ( "golang.org/x/exp/maps" "github.com/axelarnetwork/axelar-core/x/ante" + nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexusKeeper "github.com/axelarnetwork/axelar-core/x/nexus/keeper" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" "github.com/axelarnetwork/utils/funcs" ) @@ -146,3 +149,28 @@ func (m WasmAppModuleBasicOverride) DefaultGenesis(cdc codec.JSONCodec) json.Raw }, }) } + +// QueryRequest is the custom queries wasm contracts can make for the core modules +type QueryRequest struct { + Nexus *nexus.WasmQueryRequest +} + +// NewQueryPlugins returns a new instance of the custom query plugins +func NewQueryPlugins(msgIDGenerator nexustypes.MsgIDGenerator) *wasmkeeper.QueryPlugins { + nexusWasmQuerier := nexusKeeper.NewWasmQuerier(msgIDGenerator) + + return &wasmkeeper.QueryPlugins{ + Custom: func(ctx sdk.Context, request json.RawMessage) ([]byte, error) { + req := QueryRequest{} + if err := json.Unmarshal(request, &req); err != nil { + return nil, wasmvmtypes.InvalidRequest{Err: "invalid Custom query request", Request: request} + } + + if req.Nexus != nil { + return nexusWasmQuerier.Query(ctx, *req.Nexus) + } + + return nil, wasmvmtypes.UnsupportedRequest{Kind: "unknown Custom query request"} + }, + } +} diff --git a/app/wasm_test.go b/app/wasm_test.go index b941ac3229..4477f3142c 100644 --- a/app/wasm_test.go +++ b/app/wasm_test.go @@ -2,6 +2,7 @@ package app_test import ( "encoding/json" + "fmt" "testing" "github.com/CosmWasm/wasmd/x/wasm" @@ -20,6 +21,8 @@ import ( "github.com/axelarnetwork/axelar-core/cmd/axelard/cmd" "github.com/axelarnetwork/axelar-core/testutils/fake" "github.com/axelarnetwork/axelar-core/testutils/rand" + nexusmock "github.com/axelarnetwork/axelar-core/x/nexus/types/mock" + "github.com/axelarnetwork/utils/funcs" . "github.com/axelarnetwork/utils/test" ) @@ -328,3 +331,62 @@ func TestMaxSizeOverrideForClient(t *testing.T) { assert.NoError(t, msg.ValidateBasic()) } + +func TestQueryPlugins(t *testing.T) { + var ( + msgIDGenerator *nexusmock.MsgIDGeneratorMock + req json.RawMessage + ctx sdk.Context + ) + + Given("the tx id generator", func() { + ctx = sdk.NewContext(nil, tmproto.Header{}, false, log.TestingLogger()) + msgIDGenerator = &nexusmock.MsgIDGeneratorMock{} + }). + Branch( + When("request is invalid", func() { + req = []byte("{\"invalid\"}") + }). + Then("it should return an error", func(t *testing.T) { + _, err := app.NewQueryPlugins(msgIDGenerator).Custom(ctx, req) + + assert.ErrorContains(t, err, "invalid Custom query request") + }), + + When("request is unknown", func() { + req = []byte("{\"unknown\":{}}") + }). + Then("it should return an error", func(t *testing.T) { + _, err := app.NewQueryPlugins(msgIDGenerator).Custom(ctx, req) + + assert.ErrorContains(t, err, "unknown Custom query request") + }), + + When("request is a nexus wasm query but unknown", func() { + req = []byte("{\"nexus\":{}}") + }). + Then("it should return an error", func(t *testing.T) { + _, err := app.NewQueryPlugins(msgIDGenerator).Custom(ctx, req) + + assert.ErrorContains(t, err, "unknown Nexus query request") + }), + + When("request is a nexus wasm TxID query", func() { + req = []byte("{\"nexus\":{\"tx_hash_and_nonce\":{}}}") + }). + Then("it should return an error", func(t *testing.T) { + txHash := [32]byte(rand.Bytes(32)) + index := uint64(rand.PosI64()) + msgIDGenerator.CurrIDFunc = func(ctx sdk.Context) ([32]byte, uint64) { + return txHash, index + } + + actual, err := app.NewQueryPlugins(msgIDGenerator).Custom(ctx, req) + + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("{\"tx_hash\":%s,\"nonce\":%d}", funcs.Must(json.Marshal(txHash)), index), string(actual)) + }), + ). + Run(t) + +} diff --git a/docs/proto/proto-docs.md b/docs/proto/proto-docs.md index c16a558aa8..10280d792a 100644 --- a/docs/proto/proto-docs.md +++ b/docs/proto/proto-docs.md @@ -1548,6 +1548,7 @@ TransferFee represents accumulated fees generated by the network | `source_tx_index` | [uint64](#uint64) | | | | `sender` | [bytes](#bytes) | | | | `id` | [string](#string) | | | +| `token` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | diff --git a/proto/axelar/nexus/exported/v1beta1/types.proto b/proto/axelar/nexus/exported/v1beta1/types.proto index f108c119f9..d4a57b8dc6 100644 --- a/proto/axelar/nexus/exported/v1beta1/types.proto +++ b/proto/axelar/nexus/exported/v1beta1/types.proto @@ -123,7 +123,7 @@ message WasmMessage { uint64 source_tx_index = 7 [ (gogoproto.jsontag) = "source_tx_index" ]; bytes sender = 8 [ (gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress" ]; - string id = 9 [ - (gogoproto.customname) = "ID" - ]; + string id = 9 [ (gogoproto.customname) = "ID" ]; + cosmos.base.v1beta1.Coin token = 10 + [ (gogoproto.nullable) = true, (gogoproto.customname) = "Asset" ]; } diff --git a/testutils/fake/blockchain.go b/testutils/fake/blockchain.go index c6d137ca89..fffeed4edd 100644 --- a/testutils/fake/blockchain.go +++ b/testutils/fake/blockchain.go @@ -320,7 +320,7 @@ func (n *Node) start() { if err != nil { n.Ctx.Logger().Error(fmt.Sprintf("error from handler for route %s: %s", msgRoute, err.Error())) // to allow failed messages we need to implement a cache for the multistore to revert in case of failure - // outputing the error message here so that we can have a sense for why it panics in case verbose mode is not active. + // outputting the error message here so that we can have a sense for why it panics in case verbose mode is not active. panic(fmt.Sprintf("no failing messages allowed for now: error from handler for route %s: %s\nmessage: %v", msgRoute, err.Error(), msg)) } msgEvents := sdk.Events{ diff --git a/testutils/fake/store.go b/testutils/fake/store.go index 716f70a42d..06b9b80af7 100644 --- a/testutils/fake/store.go +++ b/testutils/fake/store.go @@ -19,7 +19,7 @@ type MultiStore struct { *mock.MultiStoreMock } -// CachedMultiStore is a simple chached multistore for testing +// CachedMultiStore is a simple cached multistore for testing type CachedMultiStore struct { kvstore map[string]interfaces.KVStore *mock.CacheMultiStoreMock diff --git a/x/nexus/exported/types.go b/x/nexus/exported/types.go index b170426f5b..6a3fa9dc25 100644 --- a/x/nexus/exported/types.go +++ b/x/nexus/exported/types.go @@ -414,3 +414,14 @@ func (bz *WasmBytes) UnmarshalJSON(data []byte) error { return nil } + +// WasmQueryRequest is the request for wasm contracts to query +type WasmQueryRequest struct { + TxHashAndNonce *struct{} `json:"tx_hash_and_nonce,omitempty"` +} + +// WasmQueryTxHashAndNonceResponse is the response for the TxHashAndNonce query +type WasmQueryTxHashAndNonceResponse struct { + TxHash [32]byte `json:"tx_hash,omitempty"` // the hash of the current transaction + Nonce uint64 `json:"nonce,omitempty"` // the nonce of the current execution, which increments with each entry of any wasm execution +} diff --git a/x/nexus/exported/types.pb.go b/x/nexus/exported/types.pb.go index 510658aceb..e53d9c1546 100644 --- a/x/nexus/exported/types.pb.go +++ b/x/nexus/exported/types.pb.go @@ -412,6 +412,7 @@ type WasmMessage struct { SourceTxIndex uint64 `protobuf:"varint,7,opt,name=source_tx_index,json=sourceTxIndex,proto3" json:"source_tx_index"` Sender github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,8,opt,name=sender,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"sender,omitempty"` ID string `protobuf:"bytes,9,opt,name=id,proto3" json:"id,omitempty"` + Asset *types.Coin `protobuf:"bytes,10,opt,name=token,proto3" json:"token,omitempty"` } func (m *WasmMessage) Reset() { *m = WasmMessage{} } @@ -466,89 +467,90 @@ func init() { } var fileDescriptor_82a7a8692925fe67 = []byte{ - // 1302 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4b, 0x73, 0xdb, 0x54, - 0x14, 0xb6, 0xfc, 0xce, 0x75, 0x92, 0x3a, 0xb7, 0x2f, 0x57, 0x4c, 0x6d, 0xd7, 0xf4, 0x91, 0x76, - 0xa8, 0x9d, 0xa6, 0x94, 0x05, 0x0c, 0x0f, 0x3f, 0xe4, 0x56, 0xb4, 0x75, 0x3c, 0xb2, 0x02, 0x0c, - 0x1b, 0x8f, 0x22, 0x1d, 0x27, 0x9a, 0xc4, 0xba, 0x1e, 0x5d, 0xb9, 0xd8, 0xff, 0x80, 0x31, 0x1b, - 0x16, 0x6c, 0xbd, 0x60, 0x60, 0xc1, 0xf0, 0x13, 0xd8, 0xb1, 0xa2, 0x1b, 0x66, 0xba, 0x64, 0x58, - 0x18, 0x48, 0x59, 0xf1, 0x13, 0xba, 0x62, 0xee, 0xbd, 0x52, 0xfc, 0x48, 0xa6, 0x29, 0x1d, 0x56, - 0xb6, 0xee, 0x39, 0xdf, 0x77, 0x5e, 0xdf, 0xb9, 0x12, 0xba, 0x69, 0x0c, 0xe0, 0xc0, 0x70, 0x4b, - 0x0e, 0x0c, 0xfa, 0xb4, 0x04, 0x83, 0x1e, 0x71, 0x3d, 0xb0, 0x4a, 0x4f, 0xee, 0xec, 0x80, 0x67, - 0xdc, 0x29, 0x79, 0xc3, 0x1e, 0xd0, 0x62, 0xcf, 0x25, 0x1e, 0xc1, 0x97, 0x85, 0x6b, 0x91, 0xbb, - 0x16, 0x03, 0xd7, 0xa2, 0xef, 0x2a, 0x9f, 0xdb, 0x25, 0xbb, 0x84, 0x7b, 0x96, 0xd8, 0x3f, 0x01, - 0x92, 0xb3, 0x26, 0xa1, 0x5d, 0x42, 0x4b, 0x3b, 0x06, 0x85, 0x23, 0x56, 0x93, 0xd8, 0x8e, 0x6f, - 0xbf, 0xe1, 0xc7, 0xf7, 0xe8, 0xcb, 0xa3, 0x17, 0x7e, 0x96, 0x50, 0xac, 0xba, 0x67, 0xd8, 0x0e, - 0xbe, 0x82, 0xa2, 0x8e, 0xd1, 0x85, 0x8c, 0x94, 0x97, 0xd6, 0x97, 0x2a, 0x2b, 0x2f, 0x26, 0xb9, - 0x25, 0x6e, 0x68, 0x18, 0x5d, 0xd0, 0xb8, 0x09, 0xbf, 0x83, 0x2e, 0xd2, 0x7e, 0x8f, 0xb1, 0xd1, - 0x76, 0x87, 0xb8, 0x60, 0xef, 0x3a, 0x6d, 0x83, 0x52, 0xf0, 0x68, 0x26, 0x92, 0x97, 0xd6, 0x93, - 0xda, 0xf9, 0xc0, 0x5c, 0x17, 0xd6, 0x32, 0x37, 0xe2, 0x0f, 0x51, 0x72, 0x1f, 0x86, 0x6d, 0x16, - 0x37, 0x13, 0xcd, 0x4b, 0xeb, 0xab, 0x9b, 0x57, 0x8b, 0x7e, 0xd5, 0x1e, 0x3d, 0x5e, 0x73, 0xf1, - 0x21, 0x0c, 0xf5, 0x61, 0x0f, 0xb4, 0xc4, 0xbe, 0xf8, 0x83, 0x2f, 0xa0, 0x78, 0x97, 0x58, 0xfd, - 0x03, 0xc8, 0xc4, 0x58, 0x76, 0x9a, 0xff, 0xf4, 0x71, 0x34, 0x19, 0x4e, 0x47, 0x0a, 0x04, 0xad, - 0x55, 0x5d, 0x42, 0x29, 0x4f, 0xb7, 0x6c, 0x59, 0x2e, 0x50, 0x8a, 0x3f, 0x42, 0x31, 0x93, 0x3d, - 0xf3, 0x7a, 0x52, 0xd3, 0x80, 0x27, 0xb7, 0xb9, 0xc8, 0xb1, 0x95, 0xe8, 0xd3, 0x49, 0x2e, 0xa4, - 0x09, 0x20, 0xce, 0xa0, 0x84, 0x21, 0xc8, 0x32, 0x61, 0x1e, 0x35, 0x78, 0x2c, 0x7c, 0x15, 0x46, - 0x78, 0x1a, 0x51, 0x77, 0x0d, 0x87, 0x76, 0xc0, 0xc5, 0x3a, 0x5a, 0x72, 0xc1, 0xb4, 0x7b, 0x36, - 0x38, 0x9e, 0x1f, 0x76, 0xe3, 0xb4, 0xb0, 0x8b, 0x79, 0xfb, 0x29, 0x4c, 0x89, 0xf0, 0x3d, 0x14, - 0xe3, 0x3d, 0xe6, 0x49, 0xa4, 0x36, 0x2f, 0x15, 0xc5, 0xe8, 0x8b, 0x6c, 0xf4, 0x53, 0x1e, 0x32, - 0xcd, 0x9e, 0x7b, 0xe3, 0xab, 0x28, 0x6c, 0x5b, 0x7c, 0x2c, 0xd1, 0xca, 0xb9, 0xc3, 0x49, 0x2e, - 0xac, 0xd6, 0x5e, 0x4c, 0x72, 0x28, 0x48, 0x56, 0xad, 0x69, 0x61, 0xdb, 0xc2, 0x15, 0x14, 0xa3, - 0x9e, 0xe1, 0x05, 0x63, 0x79, 0xeb, 0x94, 0x74, 0x03, 0x74, 0x8b, 0x61, 0x34, 0x01, 0x2d, 0xf4, - 0x50, 0x2a, 0x38, 0xaf, 0x03, 0x60, 0x03, 0xc5, 0x98, 0x10, 0x69, 0x46, 0xca, 0x47, 0x5e, 0x9e, - 0xef, 0x06, 0xcb, 0xf7, 0xc7, 0x3f, 0x72, 0xeb, 0xbb, 0xb6, 0xb7, 0xd7, 0xdf, 0x29, 0x9a, 0xa4, - 0x5b, 0xf2, 0x75, 0x2d, 0x7e, 0x6e, 0x53, 0x6b, 0xdf, 0x57, 0x2b, 0x03, 0x50, 0x4d, 0x30, 0x17, - 0xbe, 0x0d, 0xa3, 0x44, 0x1d, 0x40, 0x75, 0x3a, 0x04, 0xbf, 0x39, 0x3b, 0xe7, 0x63, 0xba, 0xf5, - 0x47, 0x79, 0x6e, 0xb6, 0x87, 0x4b, 0x41, 0x8b, 0x54, 0x94, 0xec, 0x00, 0xb4, 0x5d, 0x56, 0x3f, - 0x6b, 0xd4, 0x72, 0xa5, 0xc8, 0x32, 0xfa, 0x7d, 0x92, 0xbb, 0xfe, 0x0a, 0x19, 0xd5, 0xc0, 0xd4, - 0x12, 0x1d, 0x00, 0xcd, 0xf0, 0x00, 0xdf, 0x47, 0x89, 0xae, 0xed, 0xb4, 0x3b, 0x20, 0x3a, 0xf9, - 0xdf, 0x98, 0x54, 0xc7, 0xd3, 0xe2, 0x5d, 0xdb, 0x61, 0xdd, 0x63, 0x44, 0xc6, 0x80, 0x13, 0xc5, - 0x5e, 0x93, 0xc8, 0x18, 0xd4, 0x01, 0x0a, 0x0f, 0x51, 0x8c, 0x6f, 0x1f, 0xab, 0xdd, 0x02, 0x87, - 0x74, 0x45, 0x83, 0x34, 0xf1, 0x80, 0xaf, 0xa3, 0x33, 0x36, 0x6d, 0x3b, 0x86, 0x67, 0x3f, 0x01, - 0xb1, 0xc3, 0xfe, 0x0a, 0xaf, 0xd8, 0xb4, 0xc1, 0x4f, 0x39, 0xda, 0xdf, 0xb0, 0x6f, 0x62, 0x68, - 0xf5, 0x3e, 0x38, 0xe0, 0x1a, 0x07, 0x8f, 0x81, 0x52, 0x63, 0x97, 0xad, 0x24, 0xd3, 0x97, 0x68, - 0x7a, 0x5c, 0xe8, 0x8b, 0x2b, 0xaa, 0x81, 0xe2, 0x14, 0x1c, 0x0b, 0x5c, 0x5f, 0xaf, 0xaf, 0xbb, - 0x01, 0x3e, 0xcb, 0xfc, 0x52, 0x45, 0xfe, 0xaf, 0xa5, 0xba, 0x82, 0x96, 0x7b, 0xc6, 0xf0, 0x80, - 0x18, 0x56, 0x7b, 0xcf, 0xa0, 0x7b, 0x62, 0x68, 0x5a, 0xca, 0x3f, 0x7b, 0x60, 0xd0, 0x3d, 0xfc, - 0x08, 0xc5, 0x99, 0xbe, 0xfb, 0x94, 0x0f, 0x62, 0x75, 0xf3, 0xed, 0x53, 0xa2, 0xce, 0xf7, 0xa7, - 0xd8, 0xe2, 0x58, 0xcd, 0xe7, 0xc0, 0xa5, 0x40, 0x81, 0xf1, 0x53, 0xb6, 0x38, 0x10, 0xe7, 0x06, - 0x5a, 0xa6, 0xa4, 0xef, 0x9a, 0xd0, 0xf6, 0x06, 0x6d, 0xdb, 0xca, 0x24, 0xb8, 0x1a, 0x56, 0x0f, - 0x27, 0x39, 0xd4, 0xe2, 0xe7, 0xfa, 0x40, 0xad, 0x69, 0x88, 0x06, 0xff, 0x2d, 0x36, 0xd2, 0x19, - 0x84, 0x63, 0xc1, 0x20, 0x93, 0x64, 0xeb, 0xaf, 0xad, 0x1c, 0x39, 0xb1, 0xc3, 0xc2, 0x2f, 0x12, - 0x8a, 0x8b, 0xec, 0xf0, 0x0d, 0x84, 0x5b, 0x7a, 0x59, 0xdf, 0x6e, 0xb5, 0xb7, 0x1b, 0xad, 0xa6, - 0x52, 0x55, 0xeb, 0xaa, 0x52, 0x4b, 0x87, 0xe4, 0x33, 0xa3, 0x71, 0x3e, 0xd5, 0x20, 0x8e, 0x32, - 0xb0, 0xa9, 0x27, 0xfa, 0x75, 0xc6, 0x77, 0x2c, 0x37, 0x9b, 0xda, 0xd6, 0x27, 0x4a, 0x2d, 0x2d, - 0xc9, 0xcb, 0xa3, 0x71, 0x3e, 0x59, 0xee, 0xf5, 0x5c, 0xf2, 0x04, 0x2c, 0x7c, 0x0d, 0xad, 0xf9, - 0x2e, 0x4d, 0x6d, 0xab, 0xaa, 0xb4, 0x5a, 0x6a, 0xe3, 0x7e, 0x3a, 0x2c, 0xaf, 0x8e, 0xc6, 0x79, - 0xd4, 0x74, 0x89, 0x09, 0x94, 0xda, 0xce, 0xee, 0x0c, 0x93, 0xf2, 0x99, 0x52, 0xdd, 0xd6, 0x95, - 0x5a, 0x3a, 0x22, 0x98, 0x94, 0x01, 0x98, 0x7d, 0x0f, 0x2c, 0x7c, 0x19, 0xad, 0xf8, 0x2e, 0xf5, - 0xb2, 0xfa, 0x48, 0xa9, 0xa5, 0xa3, 0x32, 0x1a, 0x8d, 0xf3, 0xf1, 0xba, 0x61, 0x1f, 0x80, 0x25, - 0x27, 0xbf, 0xfc, 0x2e, 0x1b, 0xfa, 0xe1, 0xfb, 0xac, 0x54, 0xf8, 0x3b, 0x82, 0x52, 0x9f, 0x1a, - 0xb4, 0x1b, 0x68, 0x72, 0xda, 0xb3, 0x97, 0x5c, 0x09, 0x29, 0xe1, 0x22, 0x5e, 0x7a, 0xd7, 0xd0, - 0xaa, 0x8f, 0x98, 0xbf, 0xea, 0xfd, 0x96, 0x05, 0x2f, 0x93, 0x77, 0xd1, 0x9a, 0x05, 0xd4, 0xb3, - 0xd9, 0xbe, 0x10, 0xc7, 0x67, 0x8f, 0x9c, 0xc4, 0x9e, 0x9e, 0xf1, 0x13, 0x21, 0x4a, 0xe8, 0xec, - 0x2c, 0x36, 0x88, 0x13, 0xe5, 0x71, 0xf0, 0x8c, 0x29, 0x08, 0xb6, 0xb1, 0xa0, 0x4d, 0x71, 0x0f, - 0xf0, 0x38, 0xac, 0xd8, 0xca, 0xd0, 0x03, 0x3a, 0x2f, 0xd5, 0xf7, 0x17, 0xb4, 0x12, 0xe7, 0x88, - 0x37, 0xe6, 0xb5, 0x32, 0x8f, 0x9f, 0x15, 0xce, 0x7b, 0xc7, 0x85, 0x93, 0xe0, 0xef, 0x8d, 0xb3, - 0xff, 0x4c, 0x72, 0x8b, 0xa6, 0x05, 0x35, 0x61, 0xf5, 0x68, 0xdf, 0x93, 0x3c, 0xea, 0x9d, 0x17, - 0x93, 0xdc, 0xed, 0x57, 0xb8, 0xab, 0xca, 0xa6, 0xe9, 0x17, 0x7c, 0xb4, 0xea, 0xe2, 0x4a, 0x59, - 0x5a, 0xbc, 0x52, 0x6e, 0xfd, 0x2a, 0xa1, 0x95, 0xb9, 0x37, 0x0f, 0xce, 0x22, 0x59, 0xd7, 0xca, - 0x8d, 0x56, 0x5d, 0xd1, 0xda, 0x4c, 0x2a, 0xca, 0xbc, 0x7e, 0xf1, 0x0d, 0x74, 0x61, 0xc1, 0xde, - 0x54, 0x1a, 0x35, 0x26, 0x48, 0x49, 0x4e, 0x8d, 0xc6, 0xf9, 0x44, 0x13, 0x1c, 0x8b, 0xa9, 0xf1, - 0x26, 0xba, 0xb8, 0xe0, 0x58, 0xd6, 0xaa, 0x0f, 0x54, 0xa6, 0xef, 0xb0, 0xaf, 0x6f, 0xd7, 0xdc, - 0xb3, 0x99, 0xbe, 0x3f, 0x40, 0x85, 0x05, 0x57, 0xb5, 0xd1, 0xda, 0xae, 0xd7, 0xd5, 0xaa, 0xaa, - 0x34, 0xf4, 0x76, 0xf9, 0xf1, 0xd6, 0x76, 0x43, 0x4f, 0x47, 0xe4, 0x0b, 0xa3, 0x71, 0x1e, 0xab, - 0x0e, 0xed, 0x77, 0x3a, 0xb6, 0xc9, 0x2e, 0x9b, 0x72, 0x97, 0xf4, 0x1d, 0x6f, 0x2a, 0xdb, 0x5b, - 0x3f, 0x49, 0x68, 0x2d, 0xa8, 0xa7, 0x66, 0xbb, 0x60, 0xb2, 0xe9, 0xe3, 0xbb, 0x28, 0x7b, 0xc4, - 0x5f, 0x53, 0x35, 0xa5, 0xaa, 0xab, 0x5b, 0x8d, 0x93, 0xf6, 0x72, 0xdb, 0xa1, 0x3d, 0x30, 0xed, - 0x8e, 0x0d, 0x16, 0xfb, 0x22, 0x3b, 0x01, 0x54, 0xd7, 0xb6, 0x1e, 0xa7, 0x25, 0xf9, 0xd2, 0x68, - 0x9c, 0x3f, 0x7f, 0x2c, 0x50, 0xdd, 0x25, 0x5d, 0xbc, 0x89, 0xce, 0x9f, 0x80, 0xd3, 0xb7, 0xd2, - 0x61, 0xf9, 0xe2, 0x68, 0x9c, 0x3f, 0x7b, 0x0c, 0xa5, 0x13, 0x39, 0xca, 0x0a, 0xa8, 0xb4, 0x9e, - 0xfe, 0x95, 0x0d, 0x3d, 0x3d, 0xcc, 0x4a, 0xcf, 0x0e, 0xb3, 0xd2, 0x9f, 0x87, 0x59, 0xe9, 0xeb, - 0xe7, 0xd9, 0xd0, 0xb3, 0xe7, 0xd9, 0xd0, 0x6f, 0xcf, 0xb3, 0xa1, 0xcf, 0xef, 0xcd, 0x4c, 0x5e, - 0x5c, 0x97, 0x0e, 0x78, 0x5f, 0x10, 0x77, 0xdf, 0x7f, 0xba, 0x6d, 0x12, 0x17, 0x4a, 0x83, 0x85, - 0xef, 0xe2, 0x9d, 0x38, 0xff, 0x18, 0xbd, 0xfb, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xeb, 0xb7, - 0xed, 0x31, 0x37, 0x0b, 0x00, 0x00, + // 1325 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4b, 0x6f, 0x1b, 0xd5, + 0x17, 0xf7, 0xf8, 0x9d, 0xeb, 0x24, 0x75, 0x6e, 0x5f, 0xee, 0xfc, 0x55, 0xdb, 0xf5, 0xbf, 0x8f, + 0xb4, 0xa2, 0x76, 0x9a, 0x52, 0x16, 0x20, 0x0a, 0x7e, 0x8c, 0xdb, 0xa1, 0xad, 0x63, 0x8d, 0x27, + 0x80, 0xd8, 0x58, 0x93, 0x99, 0xe3, 0x64, 0x94, 0x78, 0xae, 0x35, 0x77, 0x5c, 0x9c, 0x6f, 0x80, + 0xcc, 0x86, 0x05, 0x5b, 0x2f, 0x10, 0x5d, 0x20, 0x3e, 0x02, 0x3b, 0x56, 0x64, 0x83, 0xd4, 0x25, + 0x62, 0x61, 0x20, 0xdd, 0xf1, 0x11, 0xba, 0x42, 0xf7, 0xde, 0x99, 0xf8, 0x91, 0x28, 0x29, 0x15, + 0x2b, 0xfb, 0xde, 0x73, 0x7e, 0xe7, 0xf9, 0x3b, 0xe7, 0x0e, 0xba, 0x6d, 0x0c, 0x60, 0xcf, 0x70, + 0x4b, 0x0e, 0x0c, 0xfa, 0xb4, 0x04, 0x83, 0x1e, 0x71, 0x3d, 0xb0, 0x4a, 0xcf, 0xef, 0x6d, 0x81, + 0x67, 0xdc, 0x2b, 0x79, 0xfb, 0x3d, 0xa0, 0xc5, 0x9e, 0x4b, 0x3c, 0x82, 0xaf, 0x0a, 0xd5, 0x22, + 0x57, 0x2d, 0x06, 0xaa, 0x45, 0x5f, 0x55, 0xbe, 0xb0, 0x4d, 0xb6, 0x09, 0xd7, 0x2c, 0xb1, 0x7f, + 0x02, 0x24, 0x67, 0x4d, 0x42, 0xbb, 0x84, 0x96, 0xb6, 0x0c, 0x0a, 0x47, 0x56, 0x4d, 0x62, 0x3b, + 0xbe, 0xfc, 0x96, 0xef, 0xdf, 0xa3, 0xa7, 0x7b, 0x2f, 0xfc, 0x2c, 0xa1, 0x58, 0x75, 0xc7, 0xb0, + 0x1d, 0x7c, 0x0d, 0x45, 0x1d, 0xa3, 0x0b, 0x19, 0x29, 0x2f, 0xad, 0x2e, 0x54, 0x96, 0x5e, 0x8f, + 0x73, 0x0b, 0x5c, 0xd0, 0x30, 0xba, 0xa0, 0x71, 0x11, 0x7e, 0x0f, 0x5d, 0xa6, 0xfd, 0x1e, 0xb3, + 0x46, 0xdb, 0x1d, 0xe2, 0x82, 0xbd, 0xed, 0xb4, 0x0d, 0x4a, 0xc1, 0xa3, 0x99, 0x48, 0x5e, 0x5a, + 0x4d, 0x6a, 0x17, 0x03, 0x71, 0x5d, 0x48, 0xcb, 0x5c, 0x88, 0x3f, 0x42, 0xc9, 0x5d, 0xd8, 0x6f, + 0x33, 0xbf, 0x99, 0x68, 0x5e, 0x5a, 0x5d, 0x5e, 0xbf, 0x5e, 0xf4, 0xb3, 0xf6, 0xe8, 0xf1, 0x9c, + 0x8b, 0x4f, 0x60, 0x5f, 0xdf, 0xef, 0x81, 0x96, 0xd8, 0x15, 0x7f, 0xf0, 0x25, 0x14, 0xef, 0x12, + 0xab, 0xbf, 0x07, 0x99, 0x18, 0x8b, 0x4e, 0xf3, 0x4f, 0x9f, 0x44, 0x93, 0xe1, 0x74, 0xa4, 0x40, + 0xd0, 0x4a, 0xd5, 0x25, 0x94, 0xf2, 0x70, 0xcb, 0x96, 0xe5, 0x02, 0xa5, 0xf8, 0x63, 0x14, 0x33, + 0xd9, 0x99, 0xe7, 0x93, 0x9a, 0x38, 0x3c, 0xb9, 0xcc, 0x45, 0x8e, 0xad, 0x44, 0x0f, 0xc6, 0xb9, + 0x90, 0x26, 0x80, 0x38, 0x83, 0x12, 0x86, 0x30, 0x96, 0x09, 0x73, 0xaf, 0xc1, 0xb1, 0xf0, 0x75, + 0x18, 0xe1, 0x89, 0x47, 0xdd, 0x35, 0x1c, 0xda, 0x01, 0x17, 0xeb, 0x68, 0xc1, 0x05, 0xd3, 0xee, + 0xd9, 0xe0, 0x78, 0xbe, 0xdb, 0xb5, 0xb3, 0xdc, 0xce, 0xc7, 0xed, 0x87, 0x30, 0x31, 0x84, 0x1f, + 0xa0, 0x18, 0xaf, 0x31, 0x0f, 0x22, 0xb5, 0x7e, 0xa5, 0x28, 0x5a, 0x5f, 0x64, 0xad, 0x9f, 0xd8, + 0x21, 0x93, 0xe8, 0xb9, 0x36, 0xbe, 0x8e, 0xc2, 0xb6, 0xc5, 0xdb, 0x12, 0xad, 0x5c, 0x38, 0x1c, + 0xe7, 0xc2, 0x6a, 0xed, 0xf5, 0x38, 0x87, 0x82, 0x60, 0xd5, 0x9a, 0x16, 0xb6, 0x2d, 0x5c, 0x41, + 0x31, 0xea, 0x19, 0x5e, 0xd0, 0x96, 0x77, 0xce, 0x08, 0x37, 0x40, 0xb7, 0x18, 0x46, 0x13, 0xd0, + 0x42, 0x0f, 0xa5, 0x82, 0xfb, 0x3a, 0x00, 0x36, 0x50, 0x8c, 0x11, 0x91, 0x66, 0xa4, 0x7c, 0xe4, + 0xf4, 0x78, 0xd7, 0x58, 0xbc, 0x3f, 0xfe, 0x91, 0x5b, 0xdd, 0xb6, 0xbd, 0x9d, 0xfe, 0x56, 0xd1, + 0x24, 0xdd, 0x92, 0xcf, 0x6b, 0xf1, 0x73, 0x97, 0x5a, 0xbb, 0x3e, 0x5b, 0x19, 0x80, 0x6a, 0xc2, + 0x72, 0xe1, 0xbb, 0x30, 0x4a, 0xd4, 0x01, 0x54, 0xa7, 0x43, 0xf0, 0xff, 0xa7, 0xfb, 0x7c, 0x8c, + 0xb7, 0x7e, 0x2b, 0x2f, 0x4c, 0xd7, 0x70, 0x21, 0x28, 0x91, 0x8a, 0x92, 0x1d, 0x80, 0xb6, 0xcb, + 0xf2, 0x67, 0x85, 0x5a, 0xac, 0x14, 0x59, 0x44, 0xbf, 0x8f, 0x73, 0x37, 0xdf, 0x20, 0xa2, 0x1a, + 0x98, 0x5a, 0xa2, 0x03, 0xa0, 0x19, 0x1e, 0xe0, 0x47, 0x28, 0xd1, 0xb5, 0x9d, 0x76, 0x07, 0x44, + 0x25, 0xff, 0x9d, 0x25, 0xd5, 0xf1, 0xb4, 0x78, 0xd7, 0x76, 0x58, 0xf5, 0x98, 0x21, 0x63, 0xc0, + 0x0d, 0xc5, 0xde, 0xd2, 0x90, 0x31, 0xa8, 0x03, 0x14, 0x9e, 0xa0, 0x18, 0x9f, 0x3e, 0x96, 0xbb, + 0x05, 0x0e, 0xe9, 0x8a, 0x02, 0x69, 0xe2, 0x80, 0x6f, 0xa2, 0x73, 0x36, 0x6d, 0x3b, 0x86, 0x67, + 0x3f, 0x07, 0x31, 0xc3, 0xfe, 0x08, 0x2f, 0xd9, 0xb4, 0xc1, 0x6f, 0x39, 0xda, 0x9f, 0xb0, 0x6f, + 0x63, 0x68, 0xf9, 0x11, 0x38, 0xe0, 0x1a, 0x7b, 0xcf, 0x80, 0x52, 0x63, 0x9b, 0x8d, 0x24, 0xe3, + 0x97, 0x28, 0x7a, 0x5c, 0xf0, 0x8b, 0x33, 0xaa, 0x81, 0xe2, 0x14, 0x1c, 0x0b, 0x5c, 0x9f, 0xaf, + 0x6f, 0x3b, 0x01, 0xbe, 0x95, 0xd9, 0xa1, 0x8a, 0xfc, 0x57, 0x43, 0x75, 0x0d, 0x2d, 0xf6, 0x8c, + 0xfd, 0x3d, 0x62, 0x58, 0xed, 0x1d, 0x83, 0xee, 0x88, 0xa6, 0x69, 0x29, 0xff, 0xee, 0xb1, 0x41, + 0x77, 0xf0, 0x53, 0x14, 0x67, 0xfc, 0xee, 0x53, 0xde, 0x88, 0xe5, 0xf5, 0x77, 0xcf, 0xf0, 0x3a, + 0x5b, 0x9f, 0x62, 0x8b, 0x63, 0x35, 0xdf, 0x06, 0x2e, 0x05, 0x0c, 0x8c, 0x9f, 0x31, 0xc5, 0x01, + 0x39, 0xd7, 0xd0, 0x22, 0x25, 0x7d, 0xd7, 0x84, 0xb6, 0x37, 0x68, 0xdb, 0x56, 0x26, 0xc1, 0xd9, + 0xb0, 0x7c, 0x38, 0xce, 0xa1, 0x16, 0xbf, 0xd7, 0x07, 0x6a, 0x4d, 0x43, 0x34, 0xf8, 0x6f, 0xb1, + 0x96, 0x4e, 0x21, 0x1c, 0x0b, 0x06, 0x99, 0x24, 0x1b, 0x7f, 0x6d, 0xe9, 0x48, 0x89, 0x5d, 0x16, + 0x7e, 0x91, 0x50, 0x5c, 0x44, 0x87, 0x6f, 0x21, 0xdc, 0xd2, 0xcb, 0xfa, 0x66, 0xab, 0xbd, 0xd9, + 0x68, 0x35, 0x95, 0xaa, 0x5a, 0x57, 0x95, 0x5a, 0x3a, 0x24, 0x9f, 0x1b, 0x8e, 0xf2, 0xa9, 0x06, + 0x71, 0x94, 0x81, 0x4d, 0x3d, 0x51, 0xaf, 0x73, 0xbe, 0x62, 0xb9, 0xd9, 0xd4, 0x36, 0x3e, 0x55, + 0x6a, 0x69, 0x49, 0x5e, 0x1c, 0x8e, 0xf2, 0xc9, 0x72, 0xaf, 0xe7, 0x92, 0xe7, 0x60, 0xe1, 0x1b, + 0x68, 0xc5, 0x57, 0x69, 0x6a, 0x1b, 0x55, 0xa5, 0xd5, 0x52, 0x1b, 0x8f, 0xd2, 0x61, 0x79, 0x79, + 0x38, 0xca, 0xa3, 0xa6, 0x4b, 0x4c, 0xa0, 0xd4, 0x76, 0xb6, 0xa7, 0x2c, 0x29, 0x9f, 0x2b, 0xd5, + 0x4d, 0x5d, 0xa9, 0xa5, 0x23, 0xc2, 0x92, 0x32, 0x00, 0xb3, 0xef, 0x81, 0x85, 0xaf, 0xa2, 0x25, + 0x5f, 0xa5, 0x5e, 0x56, 0x9f, 0x2a, 0xb5, 0x74, 0x54, 0x46, 0xc3, 0x51, 0x3e, 0x5e, 0x37, 0xec, + 0x3d, 0xb0, 0xe4, 0xe4, 0x57, 0xdf, 0x67, 0x43, 0x3f, 0xbc, 0xc8, 0x4a, 0x85, 0x17, 0x51, 0x94, + 0xfa, 0xcc, 0xa0, 0xdd, 0x80, 0x93, 0x93, 0x9a, 0x9d, 0xb2, 0x12, 0x52, 0x42, 0x45, 0x3c, 0x7a, + 0x37, 0xd0, 0xb2, 0x8f, 0x98, 0x5d, 0xf5, 0x7e, 0xc9, 0x82, 0xc7, 0xe4, 0x7d, 0xb4, 0x62, 0x01, + 0xf5, 0x6c, 0x36, 0x2f, 0xc4, 0xf1, 0xad, 0x47, 0x4e, 0xb2, 0x9e, 0x9e, 0xd2, 0x13, 0x2e, 0x4a, + 0xe8, 0xfc, 0x34, 0x36, 0xf0, 0x13, 0xe5, 0x7e, 0xf0, 0x94, 0x28, 0x70, 0xb6, 0x36, 0xc7, 0x4d, + 0xb1, 0x07, 0xb8, 0x1f, 0x96, 0x6c, 0x65, 0xdf, 0x03, 0x3a, 0x4b, 0xd5, 0x0f, 0xe7, 0xb8, 0x12, + 0xe7, 0x88, 0xff, 0xcd, 0x72, 0x65, 0x16, 0x3f, 0x4d, 0x9c, 0x0f, 0x8e, 0x13, 0x27, 0xc1, 0xdf, + 0x8d, 0xf3, 0x7f, 0x8f, 0x73, 0xf3, 0xa2, 0x39, 0x36, 0x61, 0xf5, 0x68, 0xde, 0x93, 0xdc, 0xeb, + 0xbd, 0xd7, 0xe3, 0xdc, 0xdd, 0x37, 0xd8, 0x55, 0x65, 0xd3, 0xf4, 0x13, 0x3e, 0x1a, 0x75, 0xb1, + 0x52, 0x16, 0x8e, 0xad, 0x94, 0x87, 0x28, 0xe6, 0x91, 0x5d, 0x70, 0x32, 0xe8, 0xac, 0x17, 0x70, + 0xe9, 0x60, 0x9c, 0x93, 0x0e, 0xc7, 0x39, 0xb1, 0xfa, 0x34, 0x01, 0xbb, 0xf3, 0xab, 0x84, 0x96, + 0x66, 0x5e, 0x2e, 0x9c, 0x45, 0xb2, 0xae, 0x95, 0x1b, 0xad, 0xba, 0xa2, 0xb5, 0x19, 0xd5, 0x94, + 0x59, 0xfe, 0xe3, 0x5b, 0xe8, 0xd2, 0x9c, 0xbc, 0xa9, 0x34, 0x6a, 0x8c, 0xd0, 0x92, 0x9c, 0x1a, + 0x8e, 0xf2, 0x89, 0x26, 0x38, 0x16, 0x63, 0xf3, 0x6d, 0x74, 0x79, 0x4e, 0xb1, 0xac, 0x55, 0x1f, + 0xab, 0x6c, 0x3e, 0xc2, 0xfe, 0x7c, 0xb8, 0xe6, 0x8e, 0xcd, 0xe6, 0xe3, 0x21, 0x2a, 0xcc, 0xa9, + 0xaa, 0x8d, 0xd6, 0x66, 0xbd, 0xae, 0x56, 0x55, 0xa5, 0xa1, 0xb7, 0xcb, 0xcf, 0x36, 0x36, 0x1b, + 0x7a, 0x3a, 0x22, 0x5f, 0x1a, 0x8e, 0xf2, 0x58, 0x75, 0x68, 0xbf, 0xd3, 0xb1, 0x4d, 0xb6, 0xac, + 0xca, 0x5d, 0xd2, 0x77, 0xbc, 0x09, 0xed, 0xef, 0xfc, 0x24, 0xa1, 0x95, 0x20, 0x9f, 0x9a, 0xed, + 0x82, 0xc9, 0xd8, 0x83, 0xef, 0xa3, 0xec, 0x91, 0xfd, 0x9a, 0xaa, 0x29, 0x55, 0x5d, 0xdd, 0x68, + 0x9c, 0x34, 0xd7, 0x9b, 0x0e, 0xed, 0x81, 0x69, 0x77, 0x6c, 0xb0, 0xd8, 0x17, 0xdd, 0x09, 0xa0, + 0xba, 0xb6, 0xf1, 0x2c, 0x2d, 0xc9, 0x57, 0x86, 0xa3, 0xfc, 0xc5, 0x63, 0x8e, 0xea, 0x2e, 0xe9, + 0xe2, 0x75, 0x74, 0xf1, 0x04, 0x9c, 0xbe, 0x91, 0x0e, 0xcb, 0x97, 0x87, 0xa3, 0xfc, 0xf9, 0x63, + 0x28, 0x9d, 0xc8, 0x51, 0x96, 0x40, 0xa5, 0x75, 0xf0, 0x57, 0x36, 0x74, 0x70, 0x98, 0x95, 0x5e, + 0x1e, 0x66, 0xa5, 0x3f, 0x0f, 0xb3, 0xd2, 0x37, 0xaf, 0xb2, 0xa1, 0x97, 0xaf, 0xb2, 0xa1, 0xdf, + 0x5e, 0x65, 0x43, 0x5f, 0x3c, 0x98, 0x62, 0x8e, 0x58, 0xb7, 0x0e, 0x78, 0x5f, 0x12, 0x77, 0xd7, + 0x3f, 0xdd, 0x35, 0x89, 0x0b, 0xa5, 0xc1, 0xdc, 0x77, 0xf5, 0x56, 0x9c, 0x7f, 0xcc, 0xde, 0xff, + 0x27, 0x00, 0x00, 0xff, 0xff, 0x7c, 0x4e, 0x32, 0x71, 0x77, 0x0b, 0x00, 0x00, } func (m *Chain) Marshal() (dAtA []byte, err error) { @@ -946,6 +948,18 @@ func (m *WasmMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Asset != nil { + { + size, err := m.Asset.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } if len(m.ID) > 0 { i -= len(m.ID) copy(dAtA[i:], m.ID) @@ -1208,6 +1222,10 @@ func (m *WasmMessage) Size() (n int) { if l > 0 { n += 1 + l + sovTypes(uint64(l)) } + if m.Asset != nil { + l = m.Asset.Size() + n += 1 + l + sovTypes(uint64(l)) + } return n } @@ -2638,6 +2656,42 @@ func (m *WasmMessage) Unmarshal(dAtA []byte) error { } m.ID = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Asset", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Asset == nil { + m.Asset = &types.Coin{} + } + if err := m.Asset.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) diff --git a/x/nexus/keeper/general_message.go b/x/nexus/keeper/general_message.go index 2ee7c80f9e..494e1a236a 100644 --- a/x/nexus/keeper/general_message.go +++ b/x/nexus/keeper/general_message.go @@ -1,7 +1,6 @@ package keeper import ( - "crypto/sha256" "encoding/hex" "fmt" @@ -32,9 +31,7 @@ func getProcessingMessageKey(destinationChain exported.ChainName, id string) key // GenerateMessageID generates a unique general message ID, and returns the message ID, current transacation ID and a unique integer nonce // The message ID is just a concatenation of the transaction ID and the nonce func (k Keeper) GenerateMessageID(ctx sdk.Context) (string, []byte, uint64) { - counter := utils.NewCounter[uint64](messageNonceKey, k.getStore(ctx)) - nonce := counter.Incr(ctx) - hash := sha256.Sum256(ctx.TxBytes()) + hash, nonce := k.nextID(ctx) return fmt.Sprintf("0x%s-%d", hex.EncodeToString(hash[:]), nonce), hash[:], nonce } diff --git a/x/nexus/keeper/msg_dispatcher.go b/x/nexus/keeper/msg_dispatcher.go index 7273cf1d1a..37421970b8 100644 --- a/x/nexus/keeper/msg_dispatcher.go +++ b/x/nexus/keeper/msg_dispatcher.go @@ -69,16 +69,20 @@ func (m Messenger) routeMsg(ctx sdk.Context, msg exported.WasmMessage) error { } // If message already exists, then this is a no-op to avoid causing an error from reverting the whole message batch being routed in Amplifier - if _, ok := m.Nexus.GetMessage(ctx, msg.ID); ok { + if _, ok := m.GetMessage(ctx, msg.ID); ok { return nil } + if msg.Asset != nil && !m.IsAssetRegistered(ctx, destinationChain, msg.Asset.Denom) { + return fmt.Errorf("asset %s is not registered on chain %s", msg.Asset.Denom, destinationChain.Name) + } + sourceChain := exported.Chain{Name: msg.SourceChain, SupportsForeignAssets: false, KeyType: tss.None, Module: wasmtypes.ModuleName} sender := exported.CrossChainAddress{Chain: sourceChain, Address: msg.SourceAddress} recipient := exported.CrossChainAddress{Chain: destinationChain, Address: msg.DestinationAddress} - nexusMsg := exported.NewGeneralMessage(fmt.Sprintf("%s-%s", msg.SourceChain, msg.ID), sender, recipient, msg.PayloadHash, msg.SourceTxID, msg.SourceTxIndex, nil) - if err := m.Nexus.SetNewMessage(ctx, nexusMsg); err != nil { + nexusMsg := exported.NewGeneralMessage(fmt.Sprintf("%s-%s", msg.SourceChain, msg.ID), sender, recipient, msg.PayloadHash, msg.SourceTxID, msg.SourceTxIndex, msg.Asset) + if err := m.SetNewMessage(ctx, nexusMsg); err != nil { return err } diff --git a/x/nexus/keeper/msg_dispatcher_test.go b/x/nexus/keeper/msg_dispatcher_test.go index 89c53c72c8..6cb18e1fbd 100644 --- a/x/nexus/keeper/msg_dispatcher_test.go +++ b/x/nexus/keeper/msg_dispatcher_test.go @@ -94,9 +94,65 @@ func TestMessenger_DispatchMsg(t *testing.T) { Run(t) givenMessenger. - When("the msg is encoded correctly and the gateway is set correctly", func() { + When("the msg is encoded correctly with token and the gateway is set correctly", func() { msg = wasmvmtypes.CosmosMsg{ - Custom: []byte("{\"source_chain\":\"sourcechain\",\"source_address\":\"0xb860\",\"destination_chain\":\"Axelarnet\",\"destination_address\":\"axelarvaloper1zh9wrak6ke4n6fclj5e8yk397czv430ygs5jz7\",\"payload_hash\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_id\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_index\":100, \"id\": \"0x73657e3da2e404f474218fe2789462585d7f6060741bd312c862378cf67ca981-1\"}"), + Custom: []byte("{\"source_chain\":\"sourcechain\",\"source_address\":\"0xb860\",\"destination_chain\":\"Axelarnet\",\"destination_address\":\"axelarvaloper1zh9wrak6ke4n6fclj5e8yk397czv430ygs5jz7\",\"payload_hash\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_id\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_index\":100, \"id\": \"0x73657e3da2e404f474218fe2789462585d7f6060741bd312c862378cf67ca981-1\",\"token\":{\"denom\":\"test\",\"amount\":\"100\"}}"), + } + + nexus.GetParamsFunc = func(_ sdk.Context) types.Params { + params := types.DefaultParams() + params.Gateway = contractAddr + + return params + } + nexus.GetChainFunc = func(_ sdk.Context, chain exported.ChainName) (exported.Chain, bool) { + switch chain { + case evm.Ethereum.Name: + return evm.Ethereum, true + case axelarnet.Axelarnet.Name: + return axelarnet.Axelarnet, true + default: + return exported.Chain{}, false + } + } + nexus.GetMessageFunc = func(_ sdk.Context, _ string) (exported.GeneralMessage, bool) { + return exported.GeneralMessage{}, false + } + }). + Branch( + When("the asset is not registered for the destination chain", func() { + nexus.IsAssetRegisteredFunc = func(_ sdk.Context, _ exported.Chain, _ string) bool { return false } + }). + Then("should return error", func(t *testing.T) { + _, _, err := messenger.DispatchMsg(ctx, contractAddr, "", msg) + + assert.ErrorContains(t, err, "is not registered on chain") + assert.False(t, errors.Is(err, wasmtypes.ErrUnknownMsg)) + }), + + When("the asset is registered for the destination chain", func() { + nexus.IsAssetRegisteredFunc = func(_ sdk.Context, _ exported.Chain, _ string) bool { return true } + }). + Then("should set new message", func(t *testing.T) { + nexus.SetNewMessageFunc = func(_ sdk.Context, msg exported.GeneralMessage) error { + return msg.ValidateBasic() + } + nexus.RouteMessageFunc = func(ctx sdk.Context, id string, _ ...exported.RoutingContext) error { return nil } + + _, _, err := messenger.DispatchMsg(ctx, contractAddr, "", msg) + + assert.NoError(t, err) + assert.Len(t, nexus.SetNewMessageCalls(), 1) + assert.Len(t, nexus.RouteMessageCalls(), 1) + assert.NotNil(t, nexus.SetNewMessageCalls()[0].Msg.Asset) + }), + ). + Run(t) + + givenMessenger. + When("the msg is encoded correctly without token and the gateway is set correctly", func() { + msg = wasmvmtypes.CosmosMsg{ + Custom: []byte("{\"source_chain\":\"sourcechain\",\"source_address\":\"0xb860\",\"destination_chain\":\"Axelarnet\",\"destination_address\":\"axelarvaloper1zh9wrak6ke4n6fclj5e8yk397czv430ygs5jz7\",\"payload_hash\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_id\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_index\":100, \"id\": \"0x73657e3da2e404f474218fe2789462585d7f6060741bd312c862378cf67ca981-1\",\"token\":null}"), } nexus.GetParamsFunc = func(_ sdk.Context) types.Params { @@ -124,9 +180,6 @@ func TestMessenger_DispatchMsg(t *testing.T) { }). When("the msg fails to be set", func() { - nexus.GenerateMessageIDFunc = func(_ sdk.Context) (string, []byte, uint64) { - return "1", []byte("1"), 1 - } nexus.GetMessageFunc = func(_ sdk.Context, _ string) (exported.GeneralMessage, bool) { return exported.GeneralMessage{}, false } @@ -165,9 +218,6 @@ func TestMessenger_DispatchMsg(t *testing.T) { } }). When("the msg succeeds to be set", func() { - nexus.GenerateMessageIDFunc = func(_ sdk.Context) (string, []byte, uint64) { - return "1", []byte("1"), 1 - } nexus.GetMessageFunc = func(_ sdk.Context, _ string) (exported.GeneralMessage, bool) { return exported.GeneralMessage{}, false } @@ -231,6 +281,7 @@ func TestMessenger_DispatchMsg(t *testing.T) { ), ). Run(t) + } func TestMessenger_DispatchMsg_WasmConnectionNotActivated(t *testing.T) { diff --git a/x/nexus/keeper/msg_id_generator.go b/x/nexus/keeper/msg_id_generator.go new file mode 100644 index 0000000000..935f79a442 --- /dev/null +++ b/x/nexus/keeper/msg_id_generator.go @@ -0,0 +1,31 @@ +package keeper + +import ( + "crypto/sha256" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/axelarnetwork/axelar-core/utils" + "github.com/axelarnetwork/axelar-core/x/nexus/types" +) + +var _ types.MsgIDGenerator = &Keeper{} + +func getTxHash(ctx sdk.Context) [32]byte { + return sha256.Sum256(ctx.TxBytes()) +} + +// IncrID increments the nonce +func (k Keeper) IncrID(ctx sdk.Context) { + utils.NewCounter[uint64](messageNonceKey, k.getStore(ctx)).Incr(ctx) +} + +// nextID returns the transaction hash of the current transaction and the incremented nonce +func (k Keeper) nextID(ctx sdk.Context) ([32]byte, uint64) { + return getTxHash(ctx), utils.NewCounter[uint64](messageNonceKey, k.getStore(ctx)).Incr(ctx) +} + +// CurrID returns the current transaction hash and index +func (k Keeper) CurrID(ctx sdk.Context) ([32]byte, uint64) { + return getTxHash(ctx), utils.NewCounter[uint64](messageNonceKey, k.getStore(ctx)).Curr(ctx) +} diff --git a/x/nexus/keeper/wasm_querier.go b/x/nexus/keeper/wasm_querier.go new file mode 100644 index 0000000000..9fb785f332 --- /dev/null +++ b/x/nexus/keeper/wasm_querier.go @@ -0,0 +1,36 @@ +package keeper + +import ( + "encoding/json" + + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/axelarnetwork/axelar-core/x/nexus/exported" + "github.com/axelarnetwork/axelar-core/x/nexus/types" + "github.com/axelarnetwork/utils/funcs" +) + +// WasmQuerier is a querier for the wasm contracts +type WasmQuerier struct { + msgIDGenerator types.MsgIDGenerator +} + +// NewWasmQuerier creates a new WasmQuerier +func NewWasmQuerier(msgIDGenerator types.MsgIDGenerator) *WasmQuerier { + return &WasmQuerier{msgIDGenerator} +} + +// Query handles the wasm queries for the nexus module +func (q WasmQuerier) Query(ctx sdk.Context, req exported.WasmQueryRequest) ([]byte, error) { + if req.TxHashAndNonce != nil { + txHash, nonce := q.msgIDGenerator.CurrID(ctx) + + return funcs.Must(json.Marshal(exported.WasmQueryTxHashAndNonceResponse{ + TxHash: txHash, + Nonce: nonce, + })), nil + } + + return nil, wasmvmtypes.UnsupportedRequest{Kind: "unknown Nexus query request"} +} diff --git a/x/nexus/keeper/wasmer_engine.go b/x/nexus/keeper/wasmer_engine.go new file mode 100644 index 0000000000..981aa0ced4 --- /dev/null +++ b/x/nexus/keeper/wasmer_engine.go @@ -0,0 +1,113 @@ +package keeper + +import ( + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + wasmvm "github.com/CosmWasm/wasmvm" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/axelarnetwork/axelar-core/x/nexus/types" +) + +// WasmerEngine is a wrapper around the WasmerEngine to add a transaction ID generator +type WasmerEngine struct { + wasmtypes.WasmerEngine + msgIDGenerator types.MsgIDGenerator +} + +// NewWasmerEngine wraps the given engine with a transaction ID generator +func NewWasmerEngine(inner wasmtypes.WasmerEngine, msgIDGenerator types.MsgIDGenerator) wasmtypes.WasmerEngine { + return &WasmerEngine{WasmerEngine: inner, msgIDGenerator: msgIDGenerator} +} + +func getCtx(querier wasmvm.Querier) sdk.Context { + return querier.(wasmkeeper.QueryHandler).Ctx +} + +// Instantiate calls the inner engine and increments the transaction ID +func (w *WasmerEngine) Instantiate( + checksum wasmvm.Checksum, + env wasmvmtypes.Env, + info wasmvmtypes.MessageInfo, + initMsg []byte, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + deserCost wasmvmtypes.UFraction, +) (*wasmvmtypes.Response, uint64, error) { + defer w.msgIDGenerator.IncrID(getCtx(querier)) + + return w.WasmerEngine.Instantiate(checksum, env, info, initMsg, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + +// Execute calls the inner engine and increments the transaction ID +func (w *WasmerEngine) Execute( + code wasmvm.Checksum, + env wasmvmtypes.Env, + info wasmvmtypes.MessageInfo, + executeMsg []byte, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + deserCost wasmvmtypes.UFraction, +) (*wasmvmtypes.Response, uint64, error) { + defer w.msgIDGenerator.IncrID(getCtx(querier)) + + return w.WasmerEngine.Execute(code, env, info, executeMsg, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + +// Migrate calls the inner engine and increments the transaction ID +func (w *WasmerEngine) Migrate( + checksum wasmvm.Checksum, + env wasmvmtypes.Env, + migrateMsg []byte, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + deserCost wasmvmtypes.UFraction, +) (*wasmvmtypes.Response, uint64, error) { + defer w.msgIDGenerator.IncrID(getCtx(querier)) + + return w.WasmerEngine.Migrate(checksum, env, migrateMsg, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + +// Sudo calls the inner engine and increments the transaction ID +func (w *WasmerEngine) Sudo( + checksum wasmvm.Checksum, + env wasmvmtypes.Env, + sudoMsg []byte, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + deserCost wasmvmtypes.UFraction, +) (*wasmvmtypes.Response, uint64, error) { + defer w.msgIDGenerator.IncrID(getCtx(querier)) + + return w.WasmerEngine.Sudo(checksum, env, sudoMsg, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + +// Reply calls the inner engine and increments the transaction ID +func (w *WasmerEngine) Reply( + checksum wasmvm.Checksum, + env wasmvmtypes.Env, + reply wasmvmtypes.Reply, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + deserCost wasmvmtypes.UFraction, +) (*wasmvmtypes.Response, uint64, error) { + defer w.msgIDGenerator.IncrID(getCtx(querier)) + + return w.WasmerEngine.Reply(checksum, env, reply, store, goapi, querier, gasMeter, gasLimit, deserCost) +} diff --git a/x/nexus/types/expected_keepers.go b/x/nexus/types/expected_keepers.go index d726cc987e..b29e3432f2 100644 --- a/x/nexus/types/expected_keepers.go +++ b/x/nexus/types/expected_keepers.go @@ -14,7 +14,7 @@ import ( snapshot "github.com/axelarnetwork/axelar-core/x/snapshot/exported" ) -//go:generate moq -out ./mock/expected_keepers.go -pkg mock . Nexus Snapshotter AxelarnetKeeper RewardKeeper SlashingKeeper WasmKeeper AccountKeeper StakingKeeper +//go:generate moq -out ./mock/expected_keepers.go -pkg mock . Nexus Snapshotter AxelarnetKeeper RewardKeeper SlashingKeeper WasmKeeper AccountKeeper StakingKeeper MsgIDGenerator // Nexus provides functionality to manage cross-chain transfers type Nexus interface { @@ -44,12 +44,18 @@ type Nexus interface { GetFeeInfo(ctx sdk.Context, chain exported.Chain, asset string) exported.FeeInfo SetRateLimit(ctx sdk.Context, chainName exported.ChainName, limit sdk.Coin, window time.Duration) error RateLimitTransfer(ctx sdk.Context, chain exported.ChainName, asset sdk.Coin, direction exported.TransferDirection) error - GenerateMessageID(ctx sdk.Context) (string, []byte, uint64) SetNewMessage(ctx sdk.Context, msg exported.GeneralMessage) error GetMessage(ctx sdk.Context, id string) (exported.GeneralMessage, bool) SetMessageExecuted(ctx sdk.Context, id string) error RouteMessage(ctx sdk.Context, id string, routingCtx ...exported.RoutingContext) error DequeueRouteMessage(ctx sdk.Context) (exported.GeneralMessage, bool) + IsAssetRegistered(ctx sdk.Context, chain exported.Chain, denom string) bool +} + +// MsgIDGenerator provides functionality to generate msg IDs +type MsgIDGenerator interface { + IncrID(ctx sdk.Context) + CurrID(ctx sdk.Context) ([32]byte, uint64) } // Snapshotter provides functionality to the snapshot module diff --git a/x/nexus/types/mock/expected_keepers.go b/x/nexus/types/mock/expected_keepers.go index dfe3aa6e39..16fed77aa3 100644 --- a/x/nexus/types/mock/expected_keepers.go +++ b/x/nexus/types/mock/expected_keepers.go @@ -48,9 +48,6 @@ var _ nexustypes.Nexus = &NexusMock{} // ExportGenesisFunc: func(ctx cosmossdktypes.Context) *nexustypes.GenesisState { // panic("mock out the ExportGenesis method") // }, -// GenerateMessageIDFunc: func(ctx cosmossdktypes.Context) (string, []byte, uint64) { -// panic("mock out the GenerateMessageID method") -// }, // GetChainFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) { // panic("mock out the GetChain method") // }, @@ -75,6 +72,9 @@ var _ nexustypes.Nexus = &NexusMock{} // InitGenesisFunc: func(ctx cosmossdktypes.Context, genState *nexustypes.GenesisState) { // panic("mock out the InitGenesis method") // }, +// IsAssetRegisteredFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, denom string) bool { +// panic("mock out the IsAssetRegistered method") +// }, // IsChainActivatedFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) bool { // panic("mock out the IsChainActivated method") // }, @@ -142,9 +142,6 @@ type NexusMock struct { // ExportGenesisFunc mocks the ExportGenesis method. ExportGenesisFunc func(ctx cosmossdktypes.Context) *nexustypes.GenesisState - // GenerateMessageIDFunc mocks the GenerateMessageID method. - GenerateMessageIDFunc func(ctx cosmossdktypes.Context) (string, []byte, uint64) - // GetChainFunc mocks the GetChain method. GetChainFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) @@ -169,6 +166,9 @@ type NexusMock struct { // InitGenesisFunc mocks the InitGenesis method. InitGenesisFunc func(ctx cosmossdktypes.Context, genState *nexustypes.GenesisState) + // IsAssetRegisteredFunc mocks the IsAssetRegistered method. + IsAssetRegisteredFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, denom string) bool + // IsChainActivatedFunc mocks the IsChainActivated method. IsChainActivatedFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) bool @@ -253,11 +253,6 @@ type NexusMock struct { // Ctx is the ctx argument value. Ctx cosmossdktypes.Context } - // GenerateMessageID holds details about calls to the GenerateMessageID method. - GenerateMessageID []struct { - // Ctx is the ctx argument value. - Ctx cosmossdktypes.Context - } // GetChain holds details about calls to the GetChain method. GetChain []struct { // Ctx is the ctx argument value. @@ -312,6 +307,15 @@ type NexusMock struct { // GenState is the genState argument value. GenState *nexustypes.GenesisState } + // IsAssetRegistered holds details about calls to the IsAssetRegistered method. + IsAssetRegistered []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + // Denom is the denom argument value. + Denom string + } // IsChainActivated holds details about calls to the IsChainActivated method. IsChainActivated []struct { // Ctx is the ctx argument value. @@ -425,7 +429,6 @@ type NexusMock struct { lockDeactivateWasmConnection sync.RWMutex lockDequeueRouteMessage sync.RWMutex lockExportGenesis sync.RWMutex - lockGenerateMessageID sync.RWMutex lockGetChain sync.RWMutex lockGetChainMaintainerStates sync.RWMutex lockGetChainMaintainers sync.RWMutex @@ -434,6 +437,7 @@ type NexusMock struct { lockGetMessage sync.RWMutex lockGetParams sync.RWMutex lockInitGenesis sync.RWMutex + lockIsAssetRegistered sync.RWMutex lockIsChainActivated sync.RWMutex lockIsChainMaintainer sync.RWMutex lockIsWasmConnectionActivated sync.RWMutex @@ -689,38 +693,6 @@ func (mock *NexusMock) ExportGenesisCalls() []struct { return calls } -// GenerateMessageID calls GenerateMessageIDFunc. -func (mock *NexusMock) GenerateMessageID(ctx cosmossdktypes.Context) (string, []byte, uint64) { - if mock.GenerateMessageIDFunc == nil { - panic("NexusMock.GenerateMessageIDFunc: method is nil but Nexus.GenerateMessageID was just called") - } - callInfo := struct { - Ctx cosmossdktypes.Context - }{ - Ctx: ctx, - } - mock.lockGenerateMessageID.Lock() - mock.calls.GenerateMessageID = append(mock.calls.GenerateMessageID, callInfo) - mock.lockGenerateMessageID.Unlock() - return mock.GenerateMessageIDFunc(ctx) -} - -// GenerateMessageIDCalls gets all the calls that were made to GenerateMessageID. -// Check the length with: -// -// len(mockedNexus.GenerateMessageIDCalls()) -func (mock *NexusMock) GenerateMessageIDCalls() []struct { - Ctx cosmossdktypes.Context -} { - var calls []struct { - Ctx cosmossdktypes.Context - } - mock.lockGenerateMessageID.RLock() - calls = mock.calls.GenerateMessageID - mock.lockGenerateMessageID.RUnlock() - return calls -} - // GetChain calls GetChainFunc. func (mock *NexusMock) GetChain(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) { if mock.GetChainFunc == nil { @@ -1005,6 +977,46 @@ func (mock *NexusMock) InitGenesisCalls() []struct { return calls } +// IsAssetRegistered calls IsAssetRegisteredFunc. +func (mock *NexusMock) IsAssetRegistered(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, denom string) bool { + if mock.IsAssetRegisteredFunc == nil { + panic("NexusMock.IsAssetRegisteredFunc: method is nil but Nexus.IsAssetRegistered was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Denom string + }{ + Ctx: ctx, + Chain: chain, + Denom: denom, + } + mock.lockIsAssetRegistered.Lock() + mock.calls.IsAssetRegistered = append(mock.calls.IsAssetRegistered, callInfo) + mock.lockIsAssetRegistered.Unlock() + return mock.IsAssetRegisteredFunc(ctx, chain, denom) +} + +// IsAssetRegisteredCalls gets all the calls that were made to IsAssetRegistered. +// Check the length with: +// +// len(mockedNexus.IsAssetRegisteredCalls()) +func (mock *NexusMock) IsAssetRegisteredCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Denom string +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Denom string + } + mock.lockIsAssetRegistered.RLock() + calls = mock.calls.IsAssetRegistered + mock.lockIsAssetRegistered.RUnlock() + return calls +} + // IsChainActivated calls IsChainActivatedFunc. func (mock *NexusMock) IsChainActivated(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) bool { if mock.IsChainActivatedFunc == nil { @@ -2916,3 +2928,113 @@ func (mock *StakingKeeperMock) ValidatorCalls() []struct { mock.lockValidator.RUnlock() return calls } + +// Ensure, that MsgIDGeneratorMock does implement nexustypes.MsgIDGenerator. +// If this is not the case, regenerate this file with moq. +var _ nexustypes.MsgIDGenerator = &MsgIDGeneratorMock{} + +// MsgIDGeneratorMock is a mock implementation of nexustypes.MsgIDGenerator. +// +// func TestSomethingThatUsesMsgIDGenerator(t *testing.T) { +// +// // make and configure a mocked nexustypes.MsgIDGenerator +// mockedMsgIDGenerator := &MsgIDGeneratorMock{ +// CurrIDFunc: func(ctx cosmossdktypes.Context) ([32]byte, uint64) { +// panic("mock out the CurrID method") +// }, +// IncrIDFunc: func(ctx cosmossdktypes.Context) { +// panic("mock out the IncrID method") +// }, +// } +// +// // use mockedMsgIDGenerator in code that requires nexustypes.MsgIDGenerator +// // and then make assertions. +// +// } +type MsgIDGeneratorMock struct { + // CurrIDFunc mocks the CurrID method. + CurrIDFunc func(ctx cosmossdktypes.Context) ([32]byte, uint64) + + // IncrIDFunc mocks the IncrID method. + IncrIDFunc func(ctx cosmossdktypes.Context) + + // calls tracks calls to the methods. + calls struct { + // CurrID holds details about calls to the CurrID method. + CurrID []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } + // IncrID holds details about calls to the IncrID method. + IncrID []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } + } + lockCurrID sync.RWMutex + lockIncrID sync.RWMutex +} + +// CurrID calls CurrIDFunc. +func (mock *MsgIDGeneratorMock) CurrID(ctx cosmossdktypes.Context) ([32]byte, uint64) { + if mock.CurrIDFunc == nil { + panic("MsgIDGeneratorMock.CurrIDFunc: method is nil but MsgIDGenerator.CurrID was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockCurrID.Lock() + mock.calls.CurrID = append(mock.calls.CurrID, callInfo) + mock.lockCurrID.Unlock() + return mock.CurrIDFunc(ctx) +} + +// CurrIDCalls gets all the calls that were made to CurrID. +// Check the length with: +// +// len(mockedMsgIDGenerator.CurrIDCalls()) +func (mock *MsgIDGeneratorMock) CurrIDCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockCurrID.RLock() + calls = mock.calls.CurrID + mock.lockCurrID.RUnlock() + return calls +} + +// IncrID calls IncrIDFunc. +func (mock *MsgIDGeneratorMock) IncrID(ctx cosmossdktypes.Context) { + if mock.IncrIDFunc == nil { + panic("MsgIDGeneratorMock.IncrIDFunc: method is nil but MsgIDGenerator.IncrID was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockIncrID.Lock() + mock.calls.IncrID = append(mock.calls.IncrID, callInfo) + mock.lockIncrID.Unlock() + mock.IncrIDFunc(ctx) +} + +// IncrIDCalls gets all the calls that were made to IncrID. +// Check the length with: +// +// len(mockedMsgIDGenerator.IncrIDCalls()) +func (mock *MsgIDGeneratorMock) IncrIDCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockIncrID.RLock() + calls = mock.calls.IncrID + mock.lockIncrID.RUnlock() + return calls +}