diff --git a/cmd/chains.go b/cmd/chains.go index 53404cabe..7e471ae00 100644 --- a/cmd/chains.go +++ b/cmd/chains.go @@ -39,6 +39,7 @@ func chainsCmd(a *appState) *cobra.Command { chainsShowCmd(a), chainsAddrCmd(a), chainsAddDirCmd(a), + cmdChainsConfigure(a), ) return cmd @@ -144,6 +145,19 @@ $ %s ch d ibc-0`, appName, appName)), return cmd } +func cmdChainsConfigure(a *appState) *cobra.Command { + cmd := &cobra.Command{ + Use: "configure", + Short: "manage local chain configurations", + } + + cmd.AddCommand( + feegrantConfigureBaseCmd(a), + ) + + return cmd +} + func chainsRegistryList(a *appState) *cobra.Command { cmd := &cobra.Command{ Use: "registry-list", @@ -277,9 +291,10 @@ func chainsAddCmd(a *appState) *cobra.Command { " the chain-registry or passing a file (-f) or url (-u)", Args: withUsage(cobra.MinimumNArgs(0)), Example: fmt.Sprintf(` $ %s chains add cosmoshub + $ %s chains add testnets/cosmoshubtestnet $ %s chains add cosmoshub osmosis $ %s chains add --file chains/ibc0.json ibc0 - $ %s chains add --url https://relayer.com/ibc0.json ibc0`, appName, appName, appName, appName), + $ %s chains add --url https://relayer.com/ibc0.json ibc0`, appName, appName, appName, appName, appName), RunE: func(cmd *cobra.Command, args []string) error { file, url, err := getAddInputs(cmd) if err != nil { @@ -447,7 +462,7 @@ func addChainsFromRegistry(ctx context.Context, a *appState, chains []string) er continue } - chainConfig, err := chainInfo.GetChainConfig(ctx) + chainConfig, err := chainInfo.GetChainConfig(ctx, chain) if err != nil { a.log.Warn( "Error generating chain config", diff --git a/cmd/feegrant.go b/cmd/feegrant.go new file mode 100644 index 000000000..3d0c86421 --- /dev/null +++ b/cmd/feegrant.go @@ -0,0 +1,197 @@ +package cmd + +import ( + "errors" + "fmt" + + "github.com/cosmos/relayer/v2/relayer/chains/cosmos" + "github.com/spf13/cobra" +) + +// feegrantConfigureCmd returns the fee grant configuration commands for this module +func feegrantConfigureBaseCmd(a *appState) *cobra.Command { + cmd := &cobra.Command{ + Use: "feegrant", + Short: "Configure the client to use round-robin feegranted accounts when sending TXs", + Long: "Use round-robin feegranted accounts when sending TXs. Useful for relayers and applications where sequencing is important", + } + + cmd.AddCommand( + feegrantConfigureBasicCmd(a), + ) + + return cmd +} + +func feegrantConfigureBasicCmd(a *appState) *cobra.Command { + var numGrantees int + var update bool + var updateGrantees bool + var grantees []string + + cmd := &cobra.Command{ + Use: "basicallowance [chain-name] [granter] --num-grantees [int] --overwrite-granter --overwrite-grantees", + Short: "feegrants for the given chain and granter (if granter is unspecified, use the default key)", + Long: "feegrants for the given chain. 10 grantees by default, all with an unrestricted BasicAllowance.", + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + chain := args[0] + cosmosChain, ok := a.config.Chains[chain] + if !ok { + return errChainNotFound(args[0]) + } + + prov, ok := cosmosChain.ChainProvider.(*cosmos.CosmosProvider) + if !ok { + return errors.New("only CosmosProvider can be feegranted") + } + + granterKeyOrAddr := "" + + if len(args) > 1 { + granterKeyOrAddr = args[1] + } else if prov.PCfg.FeeGrants != nil { + granterKeyOrAddr = prov.PCfg.FeeGrants.GranterKey + } else { + granterKeyOrAddr = prov.PCfg.Key + } + + granterKey, err := prov.KeyFromKeyOrAddress(granterKeyOrAddr) + if err != nil { + return fmt.Errorf("could not get granter key from '%s'", granterKeyOrAddr) + } + + if prov.PCfg.FeeGrants != nil && granterKey != prov.PCfg.FeeGrants.GranterKey && !update { + return fmt.Errorf("you specified granter '%s' which is different than configured feegranter '%s', but you did not specify the --overwrite-granter flag", granterKeyOrAddr, prov.PCfg.FeeGrants.GranterKey) + } else if prov.PCfg.FeeGrants != nil && granterKey != prov.PCfg.FeeGrants.GranterKey && update { + cfgErr := a.performConfigLockingOperation(cmd.Context(), func() error { + prov.PCfg.FeeGrants.GranterKey = granterKey + return nil + }) + cobra.CheckErr(cfgErr) + } + + if prov.PCfg.FeeGrants == nil || updateGrantees || len(grantees) > 0 { + var feegrantErr error + + //No list of grantees was provided, so we will use the default naming convention "grantee1, ... granteeN" + if grantees == nil { + feegrantErr = prov.ConfigureFeegrants(numGrantees, granterKey) + } else { + feegrantErr = prov.ConfigureWithGrantees(grantees, granterKey) + } + + if feegrantErr != nil { + return feegrantErr + } + + cfgErr := a.performConfigLockingOperation(cmd.Context(), func() error { + chain := a.config.Chains[chain] + oldProv := chain.ChainProvider.(*cosmos.CosmosProvider) + oldProv.PCfg.FeeGrants = prov.PCfg.FeeGrants + return nil + }) + cobra.CheckErr(cfgErr) + } + + memo, err := cmd.Flags().GetString(flagMemo) + if err != nil { + return err + } + + ctx := cmd.Context() + _, err = prov.EnsureBasicGrants(ctx, memo) + if err != nil { + return fmt.Errorf("error writing grants on chain: '%s'", err.Error()) + } + + //Get latest height from the chain, mark feegrant configuration as verified up to that height. + //This means we've verified feegranting is enabled on-chain and TXs can be sent with a feegranter. + if prov.PCfg.FeeGrants != nil { + fmt.Printf("Querying latest chain height to mark FeeGrant height... \n") + h, err := prov.QueryLatestHeight(ctx) + cobra.CheckErr(err) + + cfgErr := a.performConfigLockingOperation(cmd.Context(), func() error { + chain := a.config.Chains[chain] + oldProv := chain.ChainProvider.(*cosmos.CosmosProvider) + oldProv.PCfg.FeeGrants = prov.PCfg.FeeGrants + oldProv.PCfg.FeeGrants.BlockHeightVerified = h + fmt.Printf("Feegrant chain height marked: %d\n", h) + return nil + }) + cobra.CheckErr(cfgErr) + } + + return nil + }, + } + cmd.Flags().BoolVar(&update, "overwrite-granter", false, "allow overwriting the existing granter") + cmd.Flags().BoolVar(&updateGrantees, "overwrite-grantees", false, "allow overwriting existing grantees") + cmd.Flags().IntVar(&numGrantees, "num-grantees", 10, "number of grantees that will be feegranted with basic allowances") + cmd.Flags().StringSliceVar(&grantees, "grantees", []string{}, "comma separated list of grantee key names (keys are created if they do not exist)") + cmd.MarkFlagsMutuallyExclusive("num-grantees", "grantees") + + memoFlag(a.viper, cmd) + return cmd +} + +func feegrantBasicGrantsCmd(a *appState) *cobra.Command { + cmd := &cobra.Command{ + Use: "basic chain-name [granter]", + Short: "query the grants for an account (if none is specified, the default account is returned)", + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + chain := args[0] + cosmosChain, ok := a.config.Chains[chain] + if !ok { + return errChainNotFound(args[0]) + } + + prov, ok := cosmosChain.ChainProvider.(*cosmos.CosmosProvider) + if !ok { + return errors.New("only CosmosProvider can be feegranted") + } + + // TODO fix pagination + // pageReq, err := client.ReadPageRequest(cmd.Flags()) + // if err != nil { + // return err + // } + + //TODO fix height + // height, err := lensCmd.ReadHeight(cmd.Flags()) + // if err != nil { + // return err + // } + + keyNameOrAddress := "" + if len(args) == 0 { + keyNameOrAddress = prov.PCfg.Key + } else { + keyNameOrAddress = args[0] + } + + granterAcc, err := prov.AccountFromKeyOrAddress(keyNameOrAddress) + if err != nil { + fmt.Printf("Error retrieving account from key '%s'\n", keyNameOrAddress) + return err + } + granterAddr := prov.MustEncodeAccAddr(granterAcc) + + res, err := prov.QueryFeegrantsByGranter(granterAddr, nil) + if err != nil { + return err + } + + for _, grant := range res { + allowance, e := prov.Sprint(grant.Allowance) + cobra.CheckErr(e) + fmt.Printf("Granter: %s, Grantee: %s, Allowance: %s\n", grant.Granter, grant.Grantee, allowance) + } + + return nil + }, + } + return paginationFlags(a.viper, cmd, "feegrant") +} diff --git a/cmd/query.go b/cmd/query.go index 5540fb916..cd91bc2d7 100644 --- a/cmd/query.go +++ b/cmd/query.go @@ -47,6 +47,21 @@ func queryCmd(a *appState) *cobra.Command { lineBreakCommand(), queryIBCDenoms(a), queryBaseDenomFromIBCDenom(a), + feegrantQueryCmd(a), + ) + + return cmd +} + +// feegrantQueryCmd returns the fee grant query commands for this module +func feegrantQueryCmd(a *appState) *cobra.Command { + cmd := &cobra.Command{ + Use: "feegrant", + Short: "Querying commands for the feegrant module [currently BasicAllowance only]", + } + + cmd.AddCommand( + feegrantBasicGrantsCmd(a), ) return cmd diff --git a/cregistry/chain_info.go b/cregistry/chain_info.go index 4d49017f0..7309296e2 100644 --- a/cregistry/chain_info.go +++ b/cregistry/chain_info.go @@ -206,8 +206,8 @@ func (c ChainInfo) GetRandomRPCEndpoint(ctx context.Context) (string, error) { } // GetAssetList returns the asset metadata from the cosmos chain registry for this particular chain. -func (c ChainInfo) GetAssetList(ctx context.Context) (AssetList, error) { - chainRegURL := fmt.Sprintf("https://raw.githubusercontent.com/cosmos/chain-registry/master/%s/assetlist.json", c.ChainName) +func (c ChainInfo) GetAssetList(ctx context.Context, name string) (AssetList, error) { + chainRegURL := fmt.Sprintf("https://raw.githubusercontent.com/cosmos/chain-registry/master/%s/assetlist.json", name) res, err := http.Get(chainRegURL) if err != nil { @@ -236,11 +236,11 @@ func (c ChainInfo) GetAssetList(ctx context.Context) (AssetList, error) { // GetChainConfig returns a CosmosProviderConfig composed from the details found in the cosmos chain registry for // this particular chain. -func (c ChainInfo) GetChainConfig(ctx context.Context) (*cosmos.CosmosProviderConfig, error) { +func (c ChainInfo) GetChainConfig(ctx context.Context, name string) (*cosmos.CosmosProviderConfig, error) { debug := viper.GetBool("debug") home := viper.GetString("home") - assetList, err := c.GetAssetList(ctx) + assetList, err := c.GetAssetList(ctx, name) if err != nil { return nil, err } diff --git a/go.work.sum b/go.work.sum index 2767b9f8c..4232792ab 100644 --- a/go.work.sum +++ b/go.work.sum @@ -7,321 +7,761 @@ cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFO cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go/accessapproval v1.5.0 h1:/nTivgnV/n1CaAeo+ekGexTYUsKEU9jUVkoY5359+3Q= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accessapproval v1.6.0 h1:x0cEHro/JFPd7eS4BlEWNTMecIj2HdXjOVB5BtvwER0= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/accesscontextmanager v1.7.0 h1:MG60JgnEoawHJrbWw0jGdv6HLNSf6gQvYRiXpuzqgEA= cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= +cloud.google.com/go/aiplatform v1.37.0 h1:zTw+suCVchgZyO+k847wjzdVjWmrAuehxdvcZvJwfGg= cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= +cloud.google.com/go/analytics v0.19.0 h1:LqAo3tAh2FU9+w/r7vc3hBjU23Kv7GhO/PDIW7kIYgM= cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/apigateway v1.5.0 h1:ZI9mVO7x3E9RK/BURm2p1aw9YTBSCQe3klmyP1WxWEg= cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigeeconnect v1.5.0 h1:sWOmgDyAsi1AZ48XRHcATC0tsi9SkPT7DA/+VCfkaeA= cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeregistry v0.6.0 h1:E43RdhhCxdlV+I161gUY2rI4eOaMzHTA5kNkvRsFXvc= cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apikeys v0.6.0 h1:B9CdHFZTFjVti89tmyXXrO+7vSNo2jvZuHG8zD5trdQ= cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= +cloud.google.com/go/appengine v1.7.1 h1:aBGDKmRIaRRoWJ2tAoN0oVSHoWLhtO9aj/NvUyP4aYs= cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= +cloud.google.com/go/area120 v0.7.1 h1:ugckkFh4XkHJMPhTIx0CyvdoBxmOpMe8rNs4Ok8GAag= cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/artifactregistry v1.13.0 h1:o1Q80vqEB6Qp8WLEH3b8FBLNUCrGQ4k5RFj0sn/sgO8= cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= +cloud.google.com/go/asset v1.13.0 h1:YAsssO08BqZ6mncbb6FPlj9h6ACS7bJQUOlzciSfbNk= cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= +cloud.google.com/go/assuredworkloads v1.10.0 h1:VLGnVFta+N4WM+ASHbhc14ZOItOabDLH1MSoDv+Xuag= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/automl v1.12.0 h1:50VugllC+U4IGl3tDNcZaWvApHBTrn/TvyHDJ0wM+Uw= cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/baremetalsolution v0.5.0 h1:2AipdYXL0VxMboelTTw8c1UJ7gYu35LZYUbuRv9Q28s= cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/batch v0.7.0 h1:YbMt0E6BtqeD5FvSv1d56jbVsWEzlGm55lYte+M6Mzs= cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/beyondcorp v0.5.0 h1:UkY2BTZkEUAVrgqnSdOJ4p3y9ZRBPEe1LkjgC8Bj/Pc= cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= +cloud.google.com/go/bigquery v1.50.0 h1:RscMV6LbnAmhAzD893Lv9nXXy2WCaJmbxYPWDLbGqNQ= cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= +cloud.google.com/go/billing v1.13.0 h1:JYj28UYF5w6VBAh0gQYlgHJ/OD1oA+JgW29YZQU+UHM= cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= +cloud.google.com/go/binaryauthorization v1.5.0 h1:d3pMDBCCNivxt5a4eaV7FwL7cSH0H7RrEnFrTb1QKWs= cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/certificatemanager v1.6.0 h1:5C5UWeSt8Jkgp7OWn2rCkLmYurar/vIWIoSQ2+LaTOc= cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/channel v1.12.0 h1:GpcQY5UJKeOekYgsX3QXbzzAc/kRGtBq43fTmyKe6Uw= cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/cloudbuild v1.9.0 h1:GHQCjV4WlPPVU/j3Rlpc8vNIDwThhd1U9qSY/NPZdko= cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/clouddms v1.5.0 h1:E7v4TpDGUyEm1C/4KIrpVSOCTm0P6vWdHT0I4mostRA= cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/cloudtasks v1.10.0 h1:uK5k6abf4yligFgYFnG0ni8msai/dSv6mDmiBulU0hU= cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/contactcenterinsights v1.6.0 h1:jXIpfcH/VYSE1SYcPzO0n1VVb+sAamiLOgCw45JbOQk= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/container v1.15.0 h1:NKlY/wCDapfVZlbVVaeuu2UZZED5Dy1z4Zx1KhEzm8c= cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= +cloud.google.com/go/containeranalysis v0.9.0 h1:EQ4FFxNaEAg8PqQCO7bVQfWz9NVwZCUKaM1b3ycfx3U= cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= +cloud.google.com/go/datacatalog v1.13.0 h1:4H5IJiyUE0X6ShQBqgFFZvGGcrwGVndTwUSLP4c52gw= cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= +cloud.google.com/go/dataflow v0.8.0 h1:eYyD9o/8Nm6EttsKZaEGD84xC17bNgSKCu0ZxwqUbpg= cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataform v0.7.0 h1:Dyk+fufup1FR6cbHjFpMuP4SfPiF3LI3JtoIIALoq48= cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/datafusion v1.6.0 h1:sZjRnS3TWkGsu1LjYPFD/fHeMLZNXDK6PDHi2s2s/bk= cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datalabeling v0.7.0 h1:ch4qA2yvddGRUrlfwrNJCr79qLqhS9QBwofPHfFlDIk= cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/dataplex v1.6.0 h1:RvoZ5T7gySwm1CHzAw7yY1QwwqaGswunmqEssPxU/AM= cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataproc v1.12.0 h1:W47qHL3W4BPkAIbk4SWmIERwsWBaNnWm0P2sdx3YgGU= cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataqna v0.7.0 h1:yFzi/YU4YAdjyo7pXkBE2FeHbgz5OQQBVDdbErEHmVQ= cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= +cloud.google.com/go/datastore v1.11.0 h1:iF6I/HaLs3Ado8uRKMvZRvF/ZLkWaWE9i8AiHzbC774= cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= +cloud.google.com/go/datastream v1.7.0 h1:BBCBTnWMDwwEzQQmipUXxATa7Cm7CA/gKjKcR2w35T0= cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/deploy v1.8.0 h1:otshdKEbmsi1ELYeCKNYppwV0UH5xD05drSdBm7ouTk= cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= +cloud.google.com/go/dialogflow v1.32.0 h1:uVlKKzp6G/VtSW0E7IH1Y5o0H48/UOCmqksG2riYCwQ= cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dlp v1.9.0 h1:1JoJqezlgu6NWCroBxr4rOZnwNFILXr4cB9dMaSKO4A= cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/documentai v1.18.0 h1:KM3Xh0QQyyEdC8Gs2vhZfU+rt6OCPF0dwVwxKgLmWfI= cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= +cloud.google.com/go/domains v0.8.0 h1:2ti/o9tlWL4N+wIuWUNH+LbfgpwxPr8J1sv9RHA4bYQ= cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/edgecontainer v1.0.0 h1:O0YVE5v+O0Q/ODXYsQHmHb+sYM8KNjGZw2pjX2Ws41c= cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/errorreporting v0.3.0 h1:kj1XEWMu8P0qlLhm3FwcaFsUvXChV/OraZwA70trRR0= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.5.0 h1:gIzEhCoOT7bi+6QZqZIzX1Erj4SswMPIteNvYVlu+pM= cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/eventarc v1.11.0 h1:fsJmNeqvqtk74FsaVDU6cH79lyZNCYP8Rrv7EhaB/PU= cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/filestore v1.6.0 h1:ckTEXN5towyTMu4q0uQ1Mde/JwTHur0gXs8oaIZnKfw= cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/firestore v1.9.0 h1:IBlRyxgGySXu5VuW0RgGFlTtLukSnNkpDiEOMkQkmpA= cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/functions v1.13.0 h1:pPDqtsXG2g9HeOQLoquLbmvmb82Y4Ezdo1GXuotFoWg= cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= +cloud.google.com/go/gaming v1.9.0 h1:7vEhFnZmd931Mo7sZ6pJy7uQPDxF7m7v8xtBheG08tc= cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gkebackup v0.4.0 h1:za3QZvw6ujR0uyqkhomKKKNoXDyqYGPJies3voUK8DA= cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= +cloud.google.com/go/gkeconnect v0.7.0 h1:gXYKciHS/Lgq0GJ5Kc9SzPA35NGc3yqu6SkjonpEr2Q= cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkehub v0.12.0 h1:TqCSPsEBQ6oZSJgEYZ3XT8x2gUadbvfwI32YB0kuHCs= cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkemulticloud v0.5.0 h1:8I84Q4vl02rJRsFiinBxl7WCozfdLlUVBQuSrqr9Wtk= cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/grafeas v0.2.0 h1:CYjC+xzdPvbV65gi6Dr4YowKcmLo045pm18L0DhdELM= +cloud.google.com/go/gsuiteaddons v1.5.0 h1:1mvhXqJzV0Vg5Fa95QwckljODJJfDFXV4pn+iL50zzA= cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iap v1.7.1 h1:PxVHFuMxmSZyfntKXHXhd8bo82WJ+LcATenq7HLdVnU= cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/ids v1.3.0 h1:fodnCDtOXuMmS8LTC2y3h8t24U8F3eKWfhi+3LY6Qf0= cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/iot v1.6.0 h1:39W5BFSarRNZfVG0eXI5LYux+OVQT8GkgpHCnrZL2vM= cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/kms v1.10.1 h1:7hm1bRqGCA1GBRQUrp831TwJ9TWhP+tvLuP497CQS2g= cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/language v1.9.0 h1:7Ulo2mDk9huBoBi8zCE3ONOoBrL6UXfAI71CLQ9GEIM= cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/lifesciences v0.8.0 h1:uWrMjWTsGjLZpCTWEAzYvyXj+7fhiZST45u9AgasasI= cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I= cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/managedidentities v1.5.0 h1:ZRQ4k21/jAhrHBVKl/AY7SjgzeJwG1iZa+mJ82P+VNg= cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/maps v0.7.0 h1:mv9YaczD4oZBZkM5XJl6fXQ984IkJNHPwkc8MUsdkBo= cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= +cloud.google.com/go/mediatranslation v0.7.0 h1:anPxH+/WWt8Yc3EdoEJhPMBRF7EhIdz426A+tuoA0OU= cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/memcache v1.9.0 h1:8/VEmWCpnETCrBwS3z4MhT+tIdKgR1Z4Tr2tvYH32rg= cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/metastore v1.10.0 h1:QCFhZVe2289KDBQ7WxaHV2rAmPrmRAdLC6gbjUd3HPo= cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/monitoring v1.13.0 h1:2qsrgXGVoRXpP7otZ14eE1I568zAa92sJSDPyOJvwjM= cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/networkconnectivity v1.11.0 h1:ZD6b4Pk1jEtp/cx9nx0ZYcL3BKqDa+KixNDZ6Bjs1B8= cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkmanagement v1.6.0 h1:8KWEUNGcpSX9WwZXq7FtciuNGPdPdPN/ruDm769yAEM= cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networksecurity v0.8.0 h1:sOc42Ig1K2LiKlzG71GUVloeSJ0J3mffEBYmvu+P0eo= cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= +cloud.google.com/go/notebooks v1.8.0 h1:Kg2K3K7CbSXYJHZ1aGQpf1xi5x2GUvQWf2sFVuiZh8M= cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/optimization v1.3.1 h1:dj8O4VOJRB4CUwZXdmwNViH1OtI0WtWL867/lnYH248= cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/orchestration v1.6.0 h1:Vw+CEXo8M/FZ1rb4EjcLv0gJqqw89b7+g+C/EmniTb8= cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orgpolicy v1.10.0 h1:XDriMWug7sd0kYT1QKofRpRHzjad0bK8Q8uA9q+XrU4= cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/osconfig v1.11.0 h1:PkSQx4OHit5xz2bNyr11KGcaFccL5oqglFPdTboyqwQ= cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/oslogin v1.9.0 h1:whP7vhpmc+ufZa90eVpkfbgzJRK/Xomjz+XCD4aGwWw= cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/phishingprotection v0.7.0 h1:l6tDkT7qAEV49MNEJkEJTB6vOO/onbSOcNtAT09HPuA= cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/policytroubleshooter v1.6.0 h1:yKAGC4p9O61ttZUswaq9GAn1SZnEzTd0vUYXD7ZBT7Y= cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= +cloud.google.com/go/privatecatalog v0.8.0 h1:EPEJ1DpEGXLDnmc7mnCAqFmkwUJbIsaLAiLHVOkkwtc= cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= +cloud.google.com/go/pubsub v1.30.0 h1:vCge8m7aUKBJYOgrZp7EsNDf6QMd2CAlXZqWTn3yq6s= cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsublite v1.7.0 h1:cb9fsrtpINtETHiJ3ECeaVzrfIVhcGjhhJEjybHXHao= cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= +cloud.google.com/go/recaptchaenterprise v1.3.1 h1:u6EznTGzIdsyOsvm+Xkw0aSuKFXQlyjGE9a4exk6iNQ= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.0 h1:6iOCujSNJ0YS7oNymI64hXsjGq60T4FK1zdLugxbzvU= cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= +cloud.google.com/go/recommendationengine v0.7.0 h1:VibRFCwWXrFebEWKHfZAt2kta6pS7Tlimsnms0fjv7k= cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommender v1.9.0 h1:ZnFRY5R6zOVk2IDS1Jbv5Bw+DExCI5rFumsTnMXiu/A= cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/redis v1.11.0 h1:JoAd3SkeDt3rLFAAxEvw6wV4t+8y4ZzfZcZmddqphQ8= cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/resourcemanager v1.7.0 h1:NRM0p+RJkaQF9Ee9JMnUV9BQ2QBIOq/v8M+Pbv/wmCs= cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcesettings v1.5.0 h1:8Dua37kQt27CCWHm4h/Q1XqCF6ByD7Ouu49xg95qJzI= cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/retail v1.12.0 h1:1Dda2OpFNzIb4qWgFZjYlpP7sxX3aLeypKG6A3H4Yys= cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/run v0.9.0 h1:ydJQo+k+MShYnBfhaRHSZYeD/SQKZzZLAROyfpeD9zw= cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= +cloud.google.com/go/scheduler v1.9.0 h1:NpQAHtx3sulByTLe2dMwWmah8PWgeoieFPpJpArwFV0= cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= +cloud.google.com/go/secretmanager v1.10.0 h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60= cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/security v1.13.0 h1:PYvDxopRQBfYAXKAuDpFCKBvDOWPWzp9k/H5nB3ud3o= cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= +cloud.google.com/go/securitycenter v1.19.0 h1:AF3c2s3awNTMoBtMX3oCUoOMmGlYxGOeuXSYHNBkf14= cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/servicecontrol v1.11.1 h1:d0uV7Qegtfaa7Z2ClDzr9HJmnbJW7jn0WhZ7wOX6hLE= cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= +cloud.google.com/go/servicedirectory v1.9.0 h1:SJwk0XX2e26o25ObYUORXx6torSFiYgsGkWSkZgkoSU= cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicemanagement v1.8.0 h1:fopAQI/IAzlxnVeiKn/8WiV6zKndjFkvi+gzu+NjywY= cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= +cloud.google.com/go/serviceusage v1.6.0 h1:rXyq+0+RSIm3HFypctp7WoXxIA563rn206CfMWdqXX4= cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= +cloud.google.com/go/shell v1.6.0 h1:wT0Uw7ib7+AgZST9eCDygwTJn4+bHMDtZo5fh7kGWDU= cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/spanner v1.45.0 h1:7VdjZ8zj4sHbDw55atp5dfY6kn1j9sam9DRNpPQhqR4= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= +cloud.google.com/go/speech v1.15.0 h1:JEVoWGNnTF128kNty7T4aG4eqv2z86yiMJPT9Zjp+iw= cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storagetransfer v1.8.0 h1:5T+PM+3ECU3EY2y9Brv0Sf3oka8pKmsCfpQ07+91G9o= cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= +cloud.google.com/go/talent v1.5.0 h1:nI9sVZPjMKiO2q3Uu0KhTDVov3Xrlpt63fghP9XjyEM= cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/texttospeech v1.6.0 h1:H4g1ULStsbVtalbZGktyzXzw6jP26RjVGYx9RaYjBzc= cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/tpu v1.5.0 h1:/34T6CbSi+kTv5E19Q9zbU/ix8IviInZpzwz3rsFE+A= cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/trace v1.9.0 h1:olxC0QHC59zgJVALtgqfD9tGk0lfeCP5/AGXL3Px/no= cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/translate v1.7.0 h1:GvLP4oQ4uPdChBmBaUSa/SaZxCdyWELtlAaKzpHsXdA= cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/video v1.15.0 h1:upIbnGI0ZgACm58HPjAeBMleW3sl5cT84AbYQ8PWOgM= cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/videointelligence v1.10.0 h1:Uh5BdoET8XXqXX2uXIahGb+wTKbLkGH7s4GXR58RrG8= cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/vision v1.2.0 h1:/CsSTkbmO9HC8iQpxbK8ATms3OQaX3YQUeTMGCxlaK4= +cloud.google.com/go/vision/v2 v2.7.0 h1:8C8RXUJoflCI4yVdqhTy9tRyygSHmp60aP363z23HKg= cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vmmigration v1.6.0 h1:Azs5WKtfOC8pxvkyrDvt7J0/4DYBch0cVbuFfCCFt5k= cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmwareengine v0.3.0 h1:b0NBu7S294l0gmtrT0nOJneMYgZapr5x9tVWvgDoVEM= cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vpcaccess v1.6.0 h1:FOe6CuiQD3BhHJWt7E8QlbBcaIzVRddupwJlp7eqmn4= cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/webrisk v1.8.0 h1:IY+L2+UwxcVm2zayMAtBhZleecdIFLiC+QJMzgb0kT0= cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/websecurityscanner v1.5.0 h1:AHC1xmaNMOZtNqxI9Rmm87IJEyPaRkOxeI0gpAacXGk= cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/workflows v1.10.0 h1:FfGp9w0cYnaKZJhUOMqCOJCYT/WlvYBfTQhFWV3sRKI= cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= +github.com/Abirdcfly/dupword v0.0.7 h1:z14n0yytA3wNO2gpCD/jVtp/acEXPGmYu0esewpBt6Q= github.com/Abirdcfly/dupword v0.0.7/go.mod h1:K/4M1kj+Zh39d2aotRwypvasonOyAMH1c/IZJzE0dmk= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= +github.com/Antonboom/errname v0.1.7 h1:mBBDKvEYwPl4WFFNwec1CZO096G6vzK9vvDQzAwkako= github.com/Antonboom/errname v0.1.7/go.mod h1:g0ONh16msHIPgJSGsecu1G/dcF2hlYR/0SddnIAGavU= +github.com/Antonboom/nilnil v0.1.1 h1:PHhrh5ANKFWRBh7TdYmyyq2gyT2lotnvFvvFbylF81Q= github.com/Antonboom/nilnil v0.1.1/go.mod h1:L1jBqoWM7AOeTD+tSquifKSesRHs4ZdaxvZR+xdJEaI= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 h1:qoVeMsc9/fh/yhxVaA0obYjVH/oI/ihrOoMwsLS9KSA= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 h1:E+m3SkZCN0Bf5q7YdTs5lSm2CYY3CK4spn5OmUIiQtk= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0 h1:Px2UA+2RvSSvv+RvJNuUB6n7rs5Wsel4dXLe90Um2n4= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= +github.com/CosmWasm/wasmd v0.40.0-rc.1 h1:prIM2vP1jNh0zgs9seua5BgKdayBgp3FiHtwxFcZSGs= +github.com/CosmWasm/wasmvm v1.2.3 h1:OKYlobwmVGbl0eSn0mXoAAjE5hIuXnQCLPjbNd91sVY= +github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7IAzX8QezqtFV9m0MUHFJgts= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= +github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZdunyA= github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= +github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I= github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8= +github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s= +github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= +github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/kingpin/v2 v2.3.1 h1:ANLJcKmQm4nIaog7xdr/id6FM6zm5hHnfZrvtKPxqGg= github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= +github.com/apache/arrow/go/v11 v11.0.0 h1:hqauxvFQxww+0mEU/2XHG6LT7eZternCZq+A5Yly2uM= +github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA= github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a h1:pv34s756C4pEXnjgPfGYgdhg/ZdajGhyOvzx8k+23nw= +github.com/ashanbrown/forbidigo v1.3.0 h1:VkYIwb/xxdireGAdJNZoo24O4lmnEWkactplBlWTShc= github.com/ashanbrown/forbidigo v1.3.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= +github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/aws/aws-lambda-go v1.13.3 h1:SuCy7H3NLyp+1Mrfp+m80jcbi9KYWAs9/BXwppwRDzY= +github.com/aws/aws-sdk-go-v2 v1.9.1 h1:ZbovGV/qo40nrOJ4q8G33AGICzaPI45FHQWJ9650pF4= +github.com/aws/aws-sdk-go-v2/config v1.1.1 h1:ZAoq32boMzcaTW9bcUacBswAmHTbvlvDJICgHFZuECo= +github.com/aws/aws-sdk-go-v2/credentials v1.1.1 h1:NbvWIM1Mx6sNPTxowHgS2ewXCRp+NGTzUYb/96FZJbY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 h1:EtEU7WRaWliitZh2nmuxEXrN0Cb8EgPUFGIoTMeqbzI= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1 h1:w/fPGB0t5rWwA43mux4e9ozFSH5zF1moQemlA131PWc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 h1:4AH9fFjUlVktQMznF+YN33aWNXaR4VgDXyP28qokJC0= +github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 h1:cKr6St+CtC3/dl/rEBJvlk7A/IN5D5F02GNkGzfbtVU= +github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 h1:37QubsarExl5ZuCBlnRP+7l1tNwZPBSTqpTBrPH98RU= +github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 h1:TJoIfnIFubCX0ACVeJ0w46HEH5MwjwYN4iFhuYIhfIY= +github.com/aws/smithy-go v1.8.0 h1:AEwwwXQZtUwP5Mz506FeXXrKBe0jA8gVM+1gEcSRooc= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= +github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/bradleyfalzon/ghinstallation/v2 v2.0.4 h1:tXKVfhE7FcSkhkv0UwkLvPDeZ4kz6OXd0PKPlFqf81M= +github.com/breml/bidichk v0.2.3 h1:qe6ggxpTfA8E75hdjWPZ581sY3a2lnl0IRxLQFelECI= github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= +github.com/breml/errchkjson v0.3.0 h1:YdDqhfqMT+I1vIxPSas44P+9Z9HzJwCeAzjB8PxP1xw= github.com/breml/errchkjson v0.3.0/go.mod h1:9Cogkyv9gcT8HREpzi3TiqBxCqDzo8awa92zSDFcofU= github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= github.com/btcsuite/btcd/btcutil v1.1.2/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= +github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= +github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= +github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= +github.com/bufbuild/buf v1.7.0 h1:uWRjhIXcrWkzIkA5TqXGyJbF51VW54QJsQZ3nwaes5Q= github.com/bufbuild/buf v1.7.0/go.mod h1:Go40fMAF46PnPLC7jJgTQhAI95pmC0+VtxFKVC0qLq0= +github.com/bufbuild/connect-go v1.0.0 h1:htSflKUT8y1jxhoPhPYTZMrsY3ipUXjjrbcZR5O2cVo= github.com/bufbuild/connect-go v1.0.0/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY= github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/casbin/casbin/v2 v2.37.0 h1:/poEwPSovi4bTOcP752/CsTQiRz2xycyVKFG7GUhbDw= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy6EEutYk= github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= +github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 h1:E7LT642ysztPWE0dfz43cWOvMiF42DyTRC+eZIaO4yI= github.com/chavacava/garif v0.0.0-20220630083739-93517212f375/go.mod h1:4m1Rv7xfuwWPNKXlThldNuJvutYM6J95wNuuVmn55To= +github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8= +github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= +github.com/cheggaaa/pb v1.0.27 h1:wIkZHkNfC7R6GI5w7l/PdAdzXzlrbcI3p8OAlnkTsnc= +github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= +github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= +github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec h1:EdRZT3IeKQmfCSrgo8SZ8V3MEnskuJP0wCYNpe+aiXo= +github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= +github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= +github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/pebble v0.0.0-20220817183557-09c6e030a677 h1:qbb/AE938DFhOajUYh9+OXELpSF9KZw2ZivtmW6eX1Q= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= +github.com/cometbft/cometbft v0.37.1/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= +github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= +github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f h1:C43yEtQ6NIf4ftFXD/V55gnGFgPbMQobd//YlnLjUJ8= +github.com/containerd/aufs v1.0.0 h1:2oeJiwX5HstO7shSrPZjrohJZLzK36wvpdmzDRkL/LY= +github.com/containerd/btrfs v1.0.0 h1:osn1exbzdub9L5SouXO5swW4ea/xVdJZ3wokxN5GrnA= +github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= +github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU= +github.com/containerd/go-cni v1.1.6 h1:el5WPymG5nRRLQF1EfB97FWob4Tdc8INg8RZMaXWZlo= +github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= +github.com/containerd/imgcrypt v1.1.4 h1:iKTstFebwy3Ak5UF0RHSeuCTahC5OIrPJa6vjMAM81s= +github.com/containerd/nri v0.1.0 h1:6QioHRlThlKh2RkRTR4kIT3PKAcrLo3gIWnjkM4dQmQ= +github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI= +github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v1.0.0 h1:cXLJbx+4Jj7rNsTiqVfm6i+RNLx6FFA2fMmDlEf+Wm8= +github.com/containernetworking/cni v1.1.1 h1:ky20T7c0MvKvbMOwS/FrlbNwjEoqJEUUYfsL4b0mc4k= +github.com/containernetworking/plugins v1.1.1 h1:+AGfFigZ5TiQH00vhR8qPeSatj53eNGz0C1d3wVYlHE= +github.com/containers/ocicrypt v1.1.3 h1:uMxn2wTb4nDR7GqG3rnZSfpJXqWURfzZ7nKydzIeKpA= +github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= +github.com/coreos/go-etcd v2.0.0+incompatible h1:bXhRBIXoTm9BYHS3gE0TtQuyNZyeEMux2sDi4oo5YOo= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf h1:CAKfRE2YtTUIjjh1bkBtyYFaUT/WmOqsJjgtihT0vMI= +github.com/cosmos/cosmos-db v0.0.0-20221226095112-f3c38ecb5e32 h1:zlCp9n3uwQieELltZWHRmwPmPaZ8+XoL2Sj+A2YJlr8= +github.com/cosmos/cosmos-sdk v0.47.2/go.mod h1:zYzgI8w8hhotXTSoGbbSOAKfpJTx4wOy4XgbaKhtRtc= +github.com/cosmos/cosmos-sdk/db v1.0.0-beta.1.0.20220726092710-f848e4300a8a h1:2humuGPw3O5riJVFq/E2FRjF57UrO97W1qJcGVmK+6k= github.com/cosmos/cosmos-sdk/db v1.0.0-beta.1.0.20220726092710-f848e4300a8a/go.mod h1:c8IO23vgNxueCCJlSI9awQtcxsvc+buzaeThB85qfBU= github.com/cosmos/gogoproto v1.4.1/go.mod h1:Ac9lzL4vFpBMcptJROQ6dQ4M3pOEK5Z/l0Q9p+LoCr4= +github.com/cosmos/gogoproto v1.4.8/go.mod h1:hnb0DIEWTv+wdNzNcqus5xCQXq5+CXauq1FJuurRfVY= +github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= +github.com/cosmos/ibc-go/v7 v7.0.0/go.mod h1:BFh8nKWjr5zeR2OZfhkzdgDzj1+KjRn3aJLpwapStj8= github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk= +github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cristalhq/acmd v0.8.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= +github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= +github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/daixiang0/gci v0.8.1 h1:T4xpSC+hmsi4CSyuYfIJdMZAr9o7xZmHpQVygMghGZ4= github.com/daixiang0/gci v0.8.1/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= +github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= +github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= +github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v20.10.19+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= +github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= +github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= +github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= +github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= +github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c h1:CndMRAH4JIwxbW8KYq6Q+cGWcGHz0FjGR3QqcInWcW0= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db h1:gb2Z18BhTPJPpLQWj4T+rfKHYCHxRHCtRxhKKjRidVw= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 h1:a9ENSRDFBUPkJ5lCgVZh26+ZbGyoVJG7yb5SSzF5H54= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= +github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgxrzK5E1fW7RQGeDwE8F/ZZnUYc= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= +github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= +github.com/getsentry/sentry-go v0.17.0 h1:UustVWnOoDFHBS7IJUB2QK/nB5pap748ZEp0swnQJak= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-critic/go-critic v0.6.5 h1:fDaR/5GWURljXwF8Eh31T2GZNz9X4jeboS912mWF8Uo= github.com/go-critic/go-critic v0.6.5/go.mod h1:ezfP/Lh7MA6dBNn4c6ab5ALv3sKnZVLx37tr00uuaOY= +github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.4.0 h1:Vaw7LaSTRJOUric7pe4vnzBSgyuf2KrLsu2Y4ZpQBDE= github.com/go-git/go-billy/v5 v5.4.0/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= +github.com/go-git/go-git/v5 v5.5.2 h1:v8lgZa5k9ylUw+OR/roJHTxR4QItsNFI5nKtAXFuynw= github.com/go-git/go-git/v5 v5.5.2/go.mod h1:BE5hUJ5yaV2YMxhmaP4l6RBQ08kMxKSPD4BlxtH7OjI= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.2 h1:YnWf5Rnh1hUudj11kei53kI57quN/VH6Hp1n+erozn0= github.com/go-toolsmith/astcopy v1.0.2/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astequal v1.0.3 h1:+LVdyRatFS+XO78SGV4I3TCEA0AC7fKEGma+fH+674o= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo= github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/go-zookeeper/zk v1.0.2 h1:4mx0EYENAdX/B/rbunjlt5+4RTA/a9SMHBRuSKdGxPM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= +github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= +github.com/golangci/golangci-lint v1.50.1 h1:C829clMcZXEORakZlwpk7M4iDw2XiwxxKaG504SZ9zY= github.com/golangci/golangci-lint v1.50.1/go.mod h1:AQjHBopYS//oB8xs0y0M/dtxdKHkdhl0RvmjUct0/4w= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.3.5 h1:pLzmVdl3VxTOncgzHcvLOKirdvcx/TydsClUQXTehjo= github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= +github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= +github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/go-type-adapters v1.0.0 h1:9XdMn+d/G57qq1s8dNc5IesGCXHf6V2HZ2JwRxfA2tA= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 h1:PVRE9d4AQKmbelZ7emNig1+NT27DUmKZn5qXxfio54U= github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= +github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= +github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= +github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= +github.com/hashicorp/consul/api v1.20.0 h1:9IHTjNVSZ7MIwjlW3N3a7iGiykCMDpxZu8jsxFJh0yc= github.com/hashicorp/consul/api v1.20.0/go.mod h1:nR64eD44KQ59Of/ECwt2vUmIK2DKsDzAwTmwmLl8Wpo= +github.com/hashicorp/consul/sdk v0.3.0 h1:UOxjlb4xVNF93jak1mzzoBatyFju9nrkxpVwIp/QqxQ= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.5.3 h1:QlWt0KvWT0lq8MFppF9tsJGF+ynG7ztc2KIPhzRGk7s= github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= +github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= +github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= +github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hudl/fargo v1.4.0 h1:ZDDILMbB37UlAVLlWcJ2Iz1XuahZZTDZfdCKeclfq2s= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb v1.8.3 h1:WEypI1BQFTT4teLM+1qkEcvUi0dAvopAI/ir0vAiBg8= +github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= +github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= +github.com/informalsystems/tm-load-test v1.3.0 h1:FGjKy7vBw6mXNakt+wmNWKggQZRsKkEYpaFk/zR64VA= github.com/informalsystems/tm-load-test v1.3.0/go.mod h1:OQ5AQ9TbT5hKWBNIwsMjn6Bf4O0U4b1kRc+0qZlQJKw= +github.com/intel/goresctrl v0.2.0 h1:JyZjdMQu9Kl/wLXe9xA6s1X+tF6BWsQPFGJMEeCfWzE= +github.com/ipfs/go-datastore v0.5.1 h1:WkRhLuISI+XPD0uk3OskB0fYFSyqK8Ob5ZYew9Qa1nQ= +github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro= +github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo= +github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a h1:d4+I1YEKVmWZrgkt6jpXBnLgV2ZjO0YxEtLDdfIZfH4= github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= +github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f h1:BNuUg9k2EiJmlMwjoef3e8vZLHplbVw6DrjGFjLL+Yo= github.com/jhump/protocompile v0.0.0-20220216033700-d705409f108f/go.mod h1:qr2b5kx4HbFS7/g4uYO5qv9ei8303JMsC7ESbYiqr2Q= github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= github.com/jhump/protoreflect v1.12.1-0.20220721211354-060cc04fc18b/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= +github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/errcheck v1.6.2 h1:uGQ9xI8/pgc9iOoCe7kWQgRE6SBTrCGmTSf0LrEtY7c= github.com/kisielk/errcheck v1.6.2/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= +github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/kkHAIKE/contextcheck v1.1.3 h1:l4pNvrb8JSwRd51ojtcOxOeHJzHek+MtOyXbaR0uvmw= github.com/kkHAIKE/contextcheck v1.1.3/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= +github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= +github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8= +github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= +github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= +github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= +github.com/ldez/tagliatelle v0.3.1 h1:3BqVVlReVUZwafJUwQ+oxbx2BEX2vUG4Yu/NOfMiKiM= github.com/ldez/tagliatelle v0.3.1/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/leonklingele/grouper v1.1.0 h1:tC2y/ygPbMFSBOs3DcyaEMKnnwH7eYKzohOtRrf0SAg= github.com/leonklingele/grouper v1.1.0/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= +github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw= +github.com/libp2p/go-libp2p-testing v0.11.0 h1:+R7FRl/U3Y00neyBSM2qgDzqz3HkWH24U9nMlascHL4= +github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= +github.com/libp2p/go-msgio v0.2.0 h1:W6shmB+FeynDrUVl2dgFQvzfBZcXiyqY4VmpQLu9FqU= +github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= +github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= +github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= +github.com/libp2p/go-yamux/v3 v3.1.2 h1:lNEy28MBk1HavUAlzKgShp+F6mn/ea1nDYWftZhFW9Q= +github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743 h1:143Bb8f8DuGWck/xpNUOckBVYfFbBTnLevfRZ1aVVqo= +github.com/lightstep/lightstep-tracer-go v0.18.1 h1:vi1F1IQ8N7hNWytK9DpJsUfQhGuNSc19z330K6vl4zk= +github.com/lucas-clemente/quic-go v0.28.1 h1:Uo0lvVxWg5la9gflIF9lwa39ONq85Xq2D91YNEIslzU= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= +github.com/lyft/protoc-gen-star/v2 v2.0.1 h1:keaAo8hRuAT0O3DfJ/wM3rufbAjGeJ1lAtWZHDjKGB0= +github.com/lyft/protoc-gen-validate v0.0.13 h1:KNt/RhmQTOLr7Aj8PsJ7mTronaFyx80mRTT9qF261dA= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= +github.com/maratori/testpackage v1.1.0 h1:GJY4wlzQhuBusMF1oahQCBtUV/AQ/k69IZ68vxaac2Q= github.com/maratori/testpackage v1.1.0/go.mod h1:PeAhzU8qkCwdGEMTEupsHJNlQu2gZopMC6RjbhmHeDc= +github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ= +github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ= +github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM= +github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU= +github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= +github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= @@ -335,40 +775,109 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= +github.com/mgechev/revive v1.2.4 h1:+2Hd/S8oO2H0Ikq2+egtNwQsVhAeELHjxjIUFX5ajLI= github.com/mgechev/revive v1.2.4/go.mod h1:iAWlQishqCuj4yhV24FTnKSXGpbAA+0SckXB8GQMX/Q= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= +github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= +github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1:aKW/4cBs+yK6gpqU3K/oIwk9Q/XICqd3zOX/UFuvqmk= +github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= +github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/moby/buildkit v0.10.4 h1:FvC+buO8isGpUFZ1abdSLdGHZVqg9sqI4BbFL8tlzP4= github.com/moby/buildkit v0.10.4/go.mod h1:Yajz9vt1Zw5q9Pp4pdb3TCSUXJBIroIQGQ3TTs/sLug= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= +github.com/moby/sys/signal v0.6.0 h1:aDpY94H8VlhTGa9sNYUFCFsMZIUh5wm0B6XkIoJj/iY= +github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc= github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4= github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mrunalp/fileutils v0.5.0 h1:NKzVxiH7eSk+OQ4M+ZYW1K6h27RUV3MI6NUTsHhU6Z4= +github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multistream v0.3.3 h1:d5PZpjwRgVlbwfdTDjife7XszfZd8KYWfROYFlGcR8o= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76 h1:0xuRacu/Zr+jX+KyLLPPktbwXqyOvnOPUQmMLzX1jxU= +github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= +github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0= +github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI= +github.com/nats-io/jwt/v2 v2.0.3 h1:i/O6cmIsjpcQyWDYNcq2JyZ3/VTF8SJ4JWluI5OhpvI= +github.com/nats-io/nats-server/v2 v2.5.0 h1:wsnVaaXH9VRSg+A2MVg5Q727/CqxnmPLGFQ3YZYKTQg= +github.com/nats-io/nats.go v1.12.1 h1:+0ndxwUPz3CmQ2vjbXdkC1fo3FdiOQDim4gl3Mge8Qo= +github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/nishanths/exhaustive v0.8.3 h1:pw5O09vwg8ZaditDp/nQRqVnrMczSJDxRDJMowvhsrM= github.com/nishanths/exhaustive v0.8.3/go.mod h1:qj+zJJUgJ76tR92+25+03oYUhzF4R7/2Wk7fGTfCHmg= +github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= +github.com/oklog/oklog v0.3.2 h1:wVfs8F+in6nTBMkA7CbRw+zZMIB7nNM825cM1wuzoTk= +github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= +github.com/opencontainers/selinux v1.10.1 h1:09LIPVRP3uuZGQvgR+SgMSNBd1Eb3vlRbGqQpoHsF8w= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU= +github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU= +github.com/openzipkin/zipkin-go v0.2.5 h1:UwtQQx2pyPIgWYHRg+epgdx1/HnBQTgN3/oIYEJTQzU= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pact-foundation/pact-go v1.0.4 h1:OYkFijGHoZAYbOIb1LWXrwKQbMMRUv1oQ89blD2Mh2Q= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/performancecopilot/speed v3.0.0+incompatible h1:2WnRzIquHa5QxaJKShDkLM+sc0JPuwhXzK8OYOyt3Vg= +github.com/performancecopilot/speed/v4 v4.0.0 h1:VxEDCmdkfbQYDlcr/GC9YoN9PQ6p8ulk9xVsepYy9ZY= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= +github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= +github.com/pjbgf/sha1cd v0.2.3 h1:uKQP/7QOzNtKYH7UTohZLcjF5/55EnTw0jO/Ru4jZwI= github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/profile v1.6.0 h1:hUDfIISABYI59DyeB3OTay/HxSRwTQ8rB/H83k6r5dM= github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= +github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= +github.com/pointlander/compress v1.1.1-0.20190518213731-ff44bd196cc3 h1:hUmXhbljNFtrH5hzV9kiRoddZ5nfPTq3K0Sb2hYYiqE= github.com/pointlander/compress v1.1.1-0.20190518213731-ff44bd196cc3/go.mod h1:q5NXNGzqj5uPnVuhGkZfmgHqNUhf15VLi6L9kW0VEc0= +github.com/pointlander/jetset v1.0.1-0.20190518214125-eee7eff80bd4 h1:RHHRCZeaNyBXdYPMjZNH8/XHDBH38TZzw8izrW7dmBE= github.com/pointlander/jetset v1.0.1-0.20190518214125-eee7eff80bd4/go.mod h1:RdR1j20Aj5pB6+fw6Y9Ur7lMHpegTEjY1vc19hEZL40= +github.com/pointlander/peg v1.0.1 h1:mgA/GQE8TeS9MdkU6Xn6iEzBmQUQCNuWD7rHCK6Mjs0= github.com/pointlander/peg v1.0.1/go.mod h1:5hsGDQR2oZI4QoWz0/Kdg3VSVEC31iJw/b7WjqCBGRI= +github.com/polyfloyd/go-errorlint v1.0.5 h1:AHB5JRCjlmelh9RrLxT9sgzpalIwwq4hqE8EkwIwKdY= github.com/polyfloyd/go-errorlint v1.0.5/go.mod h1:APVvOesVSAnne5SClsPxPdfvZTVDojXh1/G3qb5wjGI= +github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= @@ -379,87 +888,185 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= +github.com/quasilyte/go-ruleguard v0.3.18 h1:sd+abO1PEI9fkYennwzHn9kl3nqP6M5vE7FiOzZ+5CE= github.com/quasilyte/go-ruleguard v0.3.18/go.mod h1:lOIzcYlgxrQ2sGJ735EHXmf/e9MJ516j16K/Ifcttvs= github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/dsl v0.3.21/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= +github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f h1:6Gtn2i04RD0gVyYf2/IUMTIs+qYleBt4zxDqkLTcu4U= github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= +github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= +github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8 h1:xe+mmCnDN82KhC010l3NfYlA8ZbOuzbXAzSYBa6wbMc= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= +github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/ryancurrah/gomodguard v1.2.4 h1:CpMSDKan0LtNGGhPrvupAoLeObRFjND8/tU1rEOtBp4= github.com/ryancurrah/gomodguard v1.2.4/go.mod h1:+Kem4VjWwvFpUJRJSwa16s1tBJe+vbv02+naTow2f6M= +github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw= github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f h1:UFr9zpz4xgTnIE5yIMtWAMngCdZ9p/+q6lTbgelo80M= +github.com/sagikazarmark/crypt v0.10.0 h1:96E1qrToLBU6fGzo+PRRz7KGOc9FkYFiPnR3/zf8Smg= github.com/sagikazarmark/crypt v0.10.0/go.mod h1:gwTNHQVoOS3xp9Xvz5LLR+1AauC5M6880z5NWzdhOyQ= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCLY7gIfzeQaUJ+kppEO5WQG3cL8iE8tGHU= +github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= +github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= +github.com/sashamelentyev/usestdlibvars v1.20.0 h1:K6CXjqqtSYSsuyRDDC7Sjn6vTMLiSJa4ZmDkiokoqtw= github.com/sashamelentyev/usestdlibvars v1.20.0/go.mod h1:0GaP+ecfZMXShS0A94CJn6aEuPRILv8h/VuWI9n1ygg= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 h1:RpforrEYXWkmGwJHIGnLZ3tTWStkjVVstwzNGqxX2Ds= +github.com/securego/gosec/v2 v2.13.1 h1:7mU32qn2dyC81MH9L2kefnQyRMUarfDER3iQyMHcjYM= github.com/securego/gosec/v2 v2.13.1/go.mod h1:EO1sImBMBWFjOTFzMWfTRrZW6M15gm60ljzrmy/wtHo= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= +github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= +github.com/sivchari/tenv v1.7.0 h1:d4laZMBK6jpe5PWepxlV9S+LC0yXqvYHiq8E6ceoVVE= github.com/sivchari/tenv v1.7.0/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= +github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0= github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa h1:YJfZp12Z3AFhSBeXOlv4BO55RMwPn2NoQeDsrdWnBtY= github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= +github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= +github.com/sony/gobreaker v0.4.1 h1:oMnRNZXX5j85zso6xCPRNPtmAycat+WcoKbklScLDgQ= +github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ= github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= +github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg= +github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I= +github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo= +github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e h1:mOtuXaRAbVZsxAHVdPR3IjfmN8T1h2iczJLynhLybf8= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344 h1:m+8fKfQwCAy1QjzINvKe/pYtLjo2dl59x2w9YSEJxuY= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/tchap/go-patricia v2.2.6+incompatible h1:JvoDL7JSoIP2HDE8AbDH3zC8QBPxmzYe32HHy5yQ+Ck= +github.com/tdakkota/asciicheck v0.1.1 h1:PKzG7JUTUmVspQTDqtkX9eSiLGossXTybutHwTXuO0A= github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= +github.com/tendermint/tendermint v0.37.0-rc2 h1:2n1em+jfbhSv6QnBj8F6KHCpbIzZCB8KgcjidJUQNlY= +github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= +github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= +github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 h1:kl4KhGNsJIbDHS9/4U9yQo1UcPQM0kOMJHn29EoH/Ro= github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/timonwong/loggercheck v0.9.3 h1:ecACo9fNiHxX4/Bc02rW2+kaJIAMAes7qJ7JKxt0EZI= github.com/timonwong/loggercheck v0.9.3/go.mod h1:wUqnk9yAOIKtGA39l1KLE9Iz0QiTocu/YZoOf+OzFdw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE= +github.com/tomarrell/wrapcheck/v2 v2.7.0 h1:J/F8DbSKJC83bAvC6FoZaRjZiZ/iKoueSdrEkmGeacA= github.com/tomarrell/wrapcheck/v2 v2.7.0/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= +github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= +github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= +github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842Y= github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= +github.com/vektra/mockery/v2 v2.14.0 h1:KZ1p5Hrn8tiY+LErRMr14HHle6khxo+JKOXLBW/yfqs= github.com/vektra/mockery/v2 v2.14.0/go.mod h1:bnD1T8tExSgPD1ripLkDbr60JA9VtQeu12P3wgLZd7M= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xhit/go-str2duration v1.2.0 h1:BcV5u025cITWxEQKGWr1URRzrcXtu7uk8+luz3Yuhwc= github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= +github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zondax/ledger-go v0.14.0/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0= gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= +go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= +go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= +go.etcd.io/etcd/client/v2 v2.305.7 h1:AELPkjNR3/igjbO7CjyF1fPuVPjrblliiKj+Y6xSGOU= go.etcd.io/etcd/client/v2 v2.305.7/go.mod h1:GQGT5Z3TBuAQGvgPfhR7VPySu/SudxmEkRq9BgzFU6s= +go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= +go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg= go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.3 h1:syAz40OyelLZo42+3U68Phisvrx4qh+4wpdZw7eUUdY= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.3/go.mod h1:Dts42MGkzZne2yCru741+bFiTMWkIj/LLRizad7b9tw= +go.opentelemetry.io/otel v1.11.0 h1:kfToEGMDq6TrVrJ9Vht84Y8y9enykSZzDDZglV0kIEk= go.opentelemetry.io/otel v1.11.0/go.mod h1:H2KtuEphyMvlhZ+F7tg9GRhAOe60moNx61Ex+WmiKkk= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 h1:R/OBkMoGgfy2fLhs2QhkCI1w4HLEQX92GCcJB6SSdNk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0 h1:giGm8w67Ja7amYNfYMdme7xSp2pIxThWopw8+QP51Yk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0 h1:VQbUHoJqytHHSJ1OZodPH9tvZZSVzUHjPHpkO85sT6k= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0 h1:Ydage/P0fRrSPpZeCVxzjqGcI6iVmG2xb43+IR8cjqM= +go.opentelemetry.io/otel/sdk v1.3.0 h1:3278edCoH89MEJ0Ky8WQXVmDQv3FX4ZJ3Pp+9fJreAI= +go.opentelemetry.io/otel/trace v1.11.0 h1:20U/Vj42SX+mASlXLmSGBg6jpI1jQtv682lZtTAOVFI= go.opentelemetry.io/otel/trace v1.11.0/go.mod h1:nyYjis9jy0gytE9LXGU+/m1sHTKbRY0fX0hulNNDP1U= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -467,19 +1074,23 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= -golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230131160201-f062dba9d201/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 h1:Ic/qN6TEifvObMGQy72k0n1LlJr7DjWWEi+MOsDOiSk= golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -522,6 +1133,7 @@ golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -557,16 +1169,20 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= @@ -575,20 +1191,48 @@ google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsA google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= google.golang.org/protobuf v1.27.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.2-0.20230222093303-bc1253ad3743/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.27 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo= +gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= +honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA= honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw= +k8s.io/api v0.22.5 h1:xk7C+rMjF/EGELiD560jdmwzrB788mfcHiNbMQLIVI8= +k8s.io/apimachinery v0.22.5 h1:cIPwldOYm1Slq9VLBRPtEYpyhjIm1C6aAMAoENuvN9s= +k8s.io/apiserver v0.22.5 h1:71krQxCUz218ecb+nPhfDsNB6QgP1/4EMvi1a2uYBlg= +k8s.io/client-go v0.22.5 h1:I8Zn/UqIdi2r02aZmhaJ1hqMxcpfJ3t5VqvHtctHYFo= +k8s.io/component-base v0.22.5 h1:U0eHqZm7mAFE42hFwYhY6ze/MmVaW00JpMrzVsQmzYE= +k8s.io/cri-api v0.23.1 h1:0DHL/hpTf4Fp+QkUXFefWcp1fhjXr9OlNdY9X99c+O8= +k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw= +k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b h1:wxEMGetGMur3J1xuGLQY7GEQYg9bZxKn3tKo5k/eYcs= +mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 h1:seuXWbRB1qPrS3NQnHmFKLJLtskWyueeIzmLXghMGgk= mvdan.cc/unparam v0.0.0-20220706161116-678bad134442/go.mod h1:F/Cxw/6mVrNKqrR2YjFf5CaW0Bw4RL8RfbEf4GRggJk= +rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= +rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 h1:ucqkfpjg9WzSUubAO62csmucvxl4/JeW3F4I4909XkM= diff --git a/interchaintest/acc_cache_test.go b/interchaintest/acc_cache_test.go new file mode 100644 index 000000000..a2d0fbbc2 --- /dev/null +++ b/interchaintest/acc_cache_test.go @@ -0,0 +1,44 @@ +package interchaintest + +import ( + "testing" + + "github.com/cometbft/cometbft/crypto/ed25519" + "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// See https://github.com/cosmos/cosmos-sdk/issues/15317 for description of bug. +// Basically, in cosmos SDK, there is an account address cache that will ignore the bech32 prefix setting. +// This will cause the AccAddress.String() to print out unexpected prefixes. +// If this function fails you are on an unsafe SDK version that should NOT be used with the relayer. +func TestAccCacheBugfix(t *testing.T) { + types.SetAddrCacheEnabled(false) + + // Use a random key + priv := ed25519.GenPrivKey() + pub := priv.PubKey() + + //Set to 'osmo' + prefix := "osmo" + sdkConf := sdk.GetConfig() + sdkConf.SetBech32PrefixForAccount(prefix, prefix+"pub") + sdkConf.SetBech32PrefixForValidator(prefix+"valoper", prefix+"valoperpub") + sdkConf.SetBech32PrefixForConsensusNode(prefix+"valcons", prefix+"valconspub") + + addrOsmo := sdk.AccAddress(pub.Address()) + osmoAddrBech32 := addrOsmo.String() + + //Set to 'cosmos' + prefix = "cosmos" + sdkConf.SetBech32PrefixForAccount(prefix, prefix+"pub") + sdkConf.SetBech32PrefixForValidator(prefix+"valoper", prefix+"valoperpub") + sdkConf.SetBech32PrefixForConsensusNode(prefix+"valcons", prefix+"valconspub") + + addrCosmos := sdk.AccAddress(pub.Address()) + cosmosAddrBech32 := addrCosmos.String() + + //If the addresses are equal, the AccAddress caching caused a bug + require.NotEqual(t, osmoAddrBech32, cosmosAddrBech32) +} diff --git a/interchaintest/client_threshold_test.go b/interchaintest/client_threshold_test.go index 8b608ca68..bc6e22a12 100644 --- a/interchaintest/client_threshold_test.go +++ b/interchaintest/client_threshold_test.go @@ -12,6 +12,7 @@ import ( "github.com/strangelove-ventures/interchaintest/v7/testreporter" "github.com/strangelove-ventures/interchaintest/v7/testutil" "github.com/stretchr/testify/require" + "go.uber.org/zap" "go.uber.org/zap/zaptest" "golang.org/x/sync/errgroup" ) @@ -24,8 +25,6 @@ const ( // Tests that the Relayer will update light clients within a // user specified time threshold. func TestScenarioClientThresholdUpdate(t *testing.T) { - t.Parallel() - ctx := context.Background() nv := 1 @@ -85,6 +84,9 @@ func TestScenarioClientThresholdUpdate(t *testing.T) { Client: client, NetworkID: network, })) + + t.Parallel() + t.Cleanup(func() { _ = ic.Close() }) @@ -144,9 +146,8 @@ func TestScenarioClientThresholdUpdate(t *testing.T) { // Tests that without the threshold flag, the clients will be updated // automatically due to passing 2/3 trusting period expiration. func TestScenarioClientTrustingPeriodUpdate(t *testing.T) { - t.Parallel() - ctx := context.Background() + t.Parallel() nv := 1 nf := 0 @@ -164,12 +165,13 @@ func TestScenarioClientTrustingPeriodUpdate(t *testing.T) { client, network := interchaintest.DockerSetup(t) relayerinterchaintest.BuildRelayerImage(t) + logger := zaptest.NewLogger(t) // Relayer is set with "--time-threshold 0" // The Relayer should NOT continuously update clients r := interchaintest.NewBuiltinRelayerFactory( ibc.CosmosRly, - zaptest.NewLogger(t), + logger, interchaintestrelayer.CustomDockerImage(relayerinterchaintest.RelayerImageName, "latest", "100:1000"), interchaintestrelayer.ImagePull(false), ).Build(t, client, network) @@ -203,18 +205,24 @@ func TestScenarioClientTrustingPeriodUpdate(t *testing.T) { SkipPathCreation: false, })) + t.Cleanup(func() { _ = ic.Close() }) // Wait 2 blocks after building interchain require.NoError(t, testutil.WaitForBlocks(ctx, 2, g0, g1)) + g0Ctx := context.Background() + g1Ctx := context.Background() - g0Height, err := g0.Height(ctx) + g0Height, err := g0.Height(g0Ctx) require.NoError(t, err) - g1Height, err := g1.Height(ctx) + g1Height, err := g1.Height(g1Ctx) require.NoError(t, err) + logger.Info("Chain height", zap.String("g0 chainID", g0.Config().ChainID), zap.Uint64("height", g0Height)) + logger.Info("Chain height", zap.String("g1 chainID", g1.Config().ChainID), zap.Uint64("g1 height", g1Height)) + require.NoError(t, r.StartRelayer(ctx, eRep, ibcPath)) t.Cleanup(func() { _ = r.StopRelayer(ctx, eRep) @@ -222,13 +230,13 @@ func TestScenarioClientTrustingPeriodUpdate(t *testing.T) { const heightOffset = 10 - g0Conns, err := r.GetConnections(ctx, eRep, g0ChainId) + g0Conns, err := r.GetConnections(g0Ctx, eRep, g0ChainId) require.NoError(t, err) require.Len(t, g0Conns, 1) g0ClientID := g0Conns[0].ClientID - g1Conns, err := r.GetConnections(ctx, eRep, g1ChainId) + g1Conns, err := r.GetConnections(g1Ctx, eRep, g1ChainId) require.NoError(t, err) require.Len(t, g1Conns, 1) @@ -236,7 +244,11 @@ func TestScenarioClientTrustingPeriodUpdate(t *testing.T) { var eg errgroup.Group eg.Go(func() error { - msg, err := pollForUpdateClient(ctx, g0, g0Height, g0Height+heightOffset) + updatedG0Height, err := g0.Height(g0Ctx) + require.NoError(t, err) + logger.Info("G0 Chain height (2)", zap.String("g0 chainID", g0.Config().ChainID), zap.Uint64("g0 height", updatedG0Height)) + + msg, err := pollForUpdateClient(g0Ctx, g0, updatedG0Height, updatedG0Height+heightOffset) if err != nil { return fmt.Errorf("first chain: %w", err) } @@ -246,7 +258,11 @@ func TestScenarioClientTrustingPeriodUpdate(t *testing.T) { return nil }) eg.Go(func() error { - msg, err := pollForUpdateClient(ctx, g1, g1Height, g1Height+heightOffset) + updatedG1Height, err := g1.Height(g1Ctx) + require.NoError(t, err) + logger.Info("G1 Chain height (2)", zap.String("g1 chainID", g1.Config().ChainID), zap.Uint64("g1 height", updatedG1Height)) + + msg, err := pollForUpdateClient(g1Ctx, g1, updatedG1Height, updatedG1Height+heightOffset) if err != nil { return fmt.Errorf("second chain: %w", err) } diff --git a/interchaintest/fee_middleware_test.go b/interchaintest/fee_middleware_test.go index 93caad39e..850fe27d7 100644 --- a/interchaintest/fee_middleware_test.go +++ b/interchaintest/fee_middleware_test.go @@ -21,8 +21,6 @@ func TestRelayerFeeMiddleware(t *testing.T) { t.Skip() } - t.Parallel() - nv := 1 nf := 0 @@ -73,11 +71,13 @@ func TestRelayerFeeMiddleware(t *testing.T) { SkipPathCreation: false, })) + t.Parallel() + t.Cleanup(func() { _ = ic.Close() }) - err = testutil.WaitForBlocks(ctx, 10, chainA, chainB) + err = testutil.WaitForBlocks(ctx, 5, chainA, chainB) require.NoError(t, err) // ChainID of ChainA diff --git a/interchaintest/feegrant_test.go b/interchaintest/feegrant_test.go new file mode 100644 index 000000000..0d0dcd13a --- /dev/null +++ b/interchaintest/feegrant_test.go @@ -0,0 +1,532 @@ +package interchaintest + +import ( + "context" + "encoding/hex" + "fmt" + "math/rand" + "strings" + "testing" + "time" + + "github.com/avast/retry-go/v4" + rpcclient "github.com/cometbft/cometbft/rpc/client" + ctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cosmos/cosmos-sdk/types" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/go-bip39" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + "github.com/cosmos/relayer/v2/relayer" + "github.com/cosmos/relayer/v2/relayer/chains/cosmos" + "github.com/cosmos/relayer/v2/relayer/processor" + interchaintest "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testreporter" + "github.com/strangelove-ventures/interchaintest/v7/testutil" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" + "golang.org/x/sync/errgroup" +) + +// protoTxProvider is a type which can provide a proto transaction. It is a +// workaround to get access to the wrapper TxBuilder's method GetProtoTx(). +type protoTxProvider interface { + GetProtoTx() *txtypes.Tx +} + +type chainFeegrantInfo struct { + granter string + grantees []string +} + +func genMnemonic(t *testing.T) string { + // read entropy seed straight from tmcrypto.Rand and convert to mnemonic + entropySeed, err := bip39.NewEntropy(256) + if err != nil { + t.Fail() + } + + mn, err := bip39.NewMnemonic(entropySeed) + if err != nil { + t.Fail() + } + + return mn +} + +// TestScenarioFeegrantBasic Feegrant on a single chain +// Run this test with e.g. go test -timeout 300s -run ^TestScenarioFeegrantBasic$ github.com/cosmos/relayer/v2/ibctest. +// +// Helpful to debug: +// docker ps -a --format {{.Names}} then e.g. docker logs gaia-1-val-0-TestScenarioFeegrantBasic 2>&1 -f +func TestScenarioFeegrantBasic(t *testing.T) { + ctx := context.Background() + logger := zaptest.NewLogger(t) + + nv := 1 + nf := 0 + + //In order to have this image locally you'd need to build it with heighliner, e.g., + //from within the local "gaia" directory, run the following command: + //../heighliner/heighliner build -c gaia --local -f ../heighliner/chains.yaml + // gaiaImage := ibc.DockerImage{ + // Repository: "gaia", + // Version: "local", + // UidGid: "1025:1025", //the heighliner user string. this isn't exposed on ibctest + // } + + // gaiaChainSpec := &interchaintest.ChainSpec{ + // ChainName: "gaia", + // NumValidators: &nv, + // NumFullNodes: &nf, + // ChainConfig: ibc.ChainConfig{ + // Type: "cosmos", + // Name: "gaia", + // //ChainID: "gaia-1", //I believe this will be auto-generated? + // Images: []ibc.DockerImage{gaiaImage}, + // Bin: "gaiad", + // Bech32Prefix: "cosmos", + // Denom: "uatom", + // GasPrices: "0.01uatom", + // TrustingPeriod: "504h", + // GasAdjustment: 1.3, + // }} + + // Chain Factory + cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ + {Name: "gaia", ChainName: "gaia", Version: "v7.0.3", NumValidators: &nv, NumFullNodes: &nf}, + {Name: "osmosis", ChainName: "osmosis", Version: "v14.0.1", NumValidators: &nv, NumFullNodes: &nf}, + }) + + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + gaia, osmosis := chains[0], chains[1] + + // Relayer Factory to construct relayer + r := NewRelayerFactory(RelayerConfig{ + Processor: relayer.ProcessorEvents, + InitialBlockHistory: 100, + }).Build(t, nil, "") + + processor.PathProcMessageCollector = make(chan *processor.PathProcessorMessageResp, 10000) + + // Prep Interchain + const ibcPath = "gaia-osmosis" + ic := interchaintest.NewInterchain(). + AddChain(gaia). + AddChain(osmosis). + AddRelayer(r, "relayer"). + AddLink(interchaintest.InterchainLink{ + Chain1: gaia, + Chain2: osmosis, + Relayer: r, + Path: ibcPath, + }) + + // Reporter/logs + rep := testreporter.NewNopReporter() + eRep := rep.RelayerExecReporter(t) + + client, network := interchaintest.DockerSetup(t) + + // Build interchain + require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + + SkipPathCreation: false, + })) + + t.Parallel() + + // Get Channel ID + gaiaChans, err := r.GetChannels(ctx, eRep, gaia.Config().ChainID) + require.NoError(t, err) + gaiaChannel := gaiaChans[0] + osmosisChannel := gaiaChans[0].Counterparty + + // Create and Fund User Wallets + fundAmount := int64(10_000_000) + + // Tiny amount of funding, not enough to pay for a single TX fee (the GRANTER should be paying the fee) + granteeFundAmount := int64(10) + granteeKeyPrefix := "grantee1" + grantee2KeyPrefix := "grantee2" + grantee3KeyPrefix := "grantee3" + granterKeyPrefix := "default" + + mnemonicAny := genMnemonic(t) + gaiaGranterWallet, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, granterKeyPrefix, mnemonicAny, int64(fundAmount), gaia) + require.NoError(t, err) + + mnemonicAny = genMnemonic(t) + gaiaGranteeWallet, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, granteeKeyPrefix, mnemonicAny, int64(granteeFundAmount), gaia) + require.NoError(t, err) + + mnemonicAny = genMnemonic(t) + gaiaGrantee2Wallet, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, grantee2KeyPrefix, mnemonicAny, int64(granteeFundAmount), gaia) + require.NoError(t, err) + + mnemonicAny = genMnemonic(t) + gaiaGrantee3Wallet, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, grantee3KeyPrefix, mnemonicAny, int64(granteeFundAmount), gaia) + require.NoError(t, err) + + mnemonicAny = genMnemonic(t) + osmosisUser, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, "recipient", mnemonicAny, int64(fundAmount), osmosis) + require.NoError(t, err) + + mnemonicAny = genMnemonic(t) + gaiaUser, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, "recipient", mnemonicAny, int64(fundAmount), gaia) + require.NoError(t, err) + + mnemonic := gaiaGranterWallet.Mnemonic() + fmt.Printf("Wallet mnemonic: %s\n", mnemonic) + + rand.Seed(time.Now().UnixNano()) + + //IBC chain config is unrelated to RELAYER config so this step is necessary + if err := r.RestoreKey(ctx, + eRep, + gaia.Config(), + gaiaGranterWallet.KeyName(), + gaiaGranterWallet.Mnemonic(), + ); err != nil { + t.Fatalf("failed to restore granter key to relayer for chain %s: %s", gaia.Config().ChainID, err.Error()) + } + + //IBC chain config is unrelated to RELAYER config so this step is necessary + if err := r.RestoreKey(ctx, + eRep, + gaia.Config(), + gaiaGranteeWallet.KeyName(), + gaiaGranteeWallet.Mnemonic(), + ); err != nil { + t.Fatalf("failed to restore granter key to relayer for chain %s: %s", gaia.Config().ChainID, err.Error()) + } + + //IBC chain config is unrelated to RELAYER config so this step is necessary + if err := r.RestoreKey(ctx, + eRep, + gaia.Config(), + gaiaGrantee2Wallet.KeyName(), + gaiaGrantee2Wallet.Mnemonic(), + ); err != nil { + t.Fatalf("failed to restore granter key to relayer for chain %s: %s", gaia.Config().ChainID, err.Error()) + } + + //IBC chain config is unrelated to RELAYER config so this step is necessary + if err := r.RestoreKey(ctx, + eRep, + gaia.Config(), + gaiaGrantee3Wallet.KeyName(), + gaiaGrantee3Wallet.Mnemonic(), + ); err != nil { + t.Fatalf("failed to restore granter key to relayer for chain %s: %s", gaia.Config().ChainID, err.Error()) + } + + //IBC chain config is unrelated to RELAYER config so this step is necessary + if err := r.RestoreKey(ctx, + eRep, + osmosis.Config(), + osmosisUser.KeyName(), + osmosisUser.Mnemonic(), + ); err != nil { + t.Fatalf("failed to restore granter key to relayer for chain %s: %s", osmosis.Config().ChainID, err.Error()) + } + + //IBC chain config is unrelated to RELAYER config so this step is necessary + if err := r.RestoreKey(ctx, + eRep, + osmosis.Config(), + gaiaUser.KeyName(), + gaiaUser.Mnemonic(), + ); err != nil { + t.Fatalf("failed to restore granter key to relayer for chain %s: %s", gaia.Config().ChainID, err.Error()) + } + + gaiaGranteeAddr := gaiaGranteeWallet.FormattedAddress() + gaiaGrantee2Addr := gaiaGrantee2Wallet.FormattedAddress() + gaiaGrantee3Addr := gaiaGrantee3Wallet.FormattedAddress() + gaiaGranterAddr := gaiaGranterWallet.FormattedAddress() + + granteeCsv := gaiaGranteeWallet.KeyName() + "," + gaiaGrantee2Wallet.KeyName() + "," + gaiaGrantee3Wallet.KeyName() + + //You MUST run the configure feegrant command prior to starting the relayer, otherwise it'd be like you never set it up at all (within this test) + //Note that Gaia supports feegrants, but Osmosis does not (x/feegrant module, or any compatible module, is not included in Osmosis SDK app modules) + localRelayer := r.(*Relayer) + res := localRelayer.sys().Run(logger, "chains", "configure", "feegrant", "basicallowance", gaia.Config().ChainID, gaiaGranterWallet.KeyName(), "--grantees", granteeCsv, "--overwrite-granter") + if res.Err != nil { + fmt.Printf("configure feegrant results: %s\n", res.Stdout.String()) + t.Fatalf("failed to rly config feegrants: %v", res.Err) + } + + //Map of feegranted chains and the feegrant info for the chain + feegrantedChains := map[string]*chainFeegrantInfo{} + feegrantedChains[gaia.Config().ChainID] = &chainFeegrantInfo{granter: gaiaGranterAddr, grantees: []string{gaiaGranteeAddr, gaiaGrantee2Addr, gaiaGrantee3Addr}} + + time.Sleep(14 * time.Second) //commit a couple blocks + r.StartRelayer(ctx, eRep, ibcPath) + + // Send Transaction + amountToSend := int64(1_000) + + gaiaDstAddress := types.MustBech32ifyAddressBytes(osmosis.Config().Bech32Prefix, gaiaUser.Address()) + osmosisDstAddress := types.MustBech32ifyAddressBytes(gaia.Config().Bech32Prefix, osmosisUser.Address()) + + gaiaHeight, err := gaia.Height(ctx) + require.NoError(t, err) + + osmosisHeight, err := osmosis.Height(ctx) + require.NoError(t, err) + + var eg errgroup.Group + var gaiaTx ibc.Tx + + eg.Go(func() error { + gaiaTx, err = gaia.SendIBCTransfer(ctx, gaiaChannel.ChannelID, gaiaUser.KeyName(), ibc.WalletAmount{ + Address: gaiaDstAddress, + Denom: gaia.Config().Denom, + Amount: amountToSend, + }, + ibc.TransferOptions{}, + ) + if err != nil { + return err + } + if err := gaiaTx.Validate(); err != nil { + return err + } + + _, err = testutil.PollForAck(ctx, gaia, gaiaHeight, gaiaHeight+20, gaiaTx.Packet) + return err + }) + + eg.Go(func() error { + tx, err := osmosis.SendIBCTransfer(ctx, osmosisChannel.ChannelID, osmosisUser.KeyName(), ibc.WalletAmount{ + Address: osmosisDstAddress, + Denom: osmosis.Config().Denom, + Amount: amountToSend, + }, + ibc.TransferOptions{}, + ) + if err != nil { + return err + } + if err := tx.Validate(); err != nil { + return err + } + _, err = testutil.PollForAck(ctx, osmosis, osmosisHeight, osmosisHeight+20, tx.Packet) + return err + }) + + eg.Go(func() error { + tx, err := osmosis.SendIBCTransfer(ctx, osmosisChannel.ChannelID, osmosisUser.KeyName(), ibc.WalletAmount{ + Address: osmosisDstAddress, + Denom: osmosis.Config().Denom, + Amount: amountToSend, + }, + ibc.TransferOptions{}, + ) + if err != nil { + return err + } + if err := tx.Validate(); err != nil { + return err + } + _, err = testutil.PollForAck(ctx, osmosis, osmosisHeight, osmosisHeight+20, tx.Packet) + return err + }) + + eg.Go(func() error { + tx, err := osmosis.SendIBCTransfer(ctx, osmosisChannel.ChannelID, osmosisUser.KeyName(), ibc.WalletAmount{ + Address: osmosisDstAddress, + Denom: osmosis.Config().Denom, + Amount: amountToSend, + }, + ibc.TransferOptions{}, + ) + if err != nil { + return err + } + if err := tx.Validate(); err != nil { + return err + } + _, err = testutil.PollForAck(ctx, osmosis, osmosisHeight, osmosisHeight+20, tx.Packet) + return err + }) + + require.NoError(t, err) + require.NoError(t, eg.Wait()) + + feegrantMsgSigners := map[string][]string{} //chain to list of signers + + for len(processor.PathProcMessageCollector) > 0 { + select { + case curr, ok := <-processor.PathProcMessageCollector: + if ok && curr.Error == nil && curr.SuccessfulTx { + cProv, cosmProv := curr.DestinationChain.(*cosmos.CosmosProvider) + if cosmProv { + chain := cProv.PCfg.ChainID + feegrantInfo, isFeegrantedChain := feegrantedChains[chain] + if isFeegrantedChain && !strings.Contains(cProv.PCfg.KeyDirectory, t.Name()) { + //This would indicate that a parallel test is inserting msgs into the queue. + //We can safely skip over any messages inserted by other test cases. + fmt.Println("Skipping PathProcessorMessageResp from unrelated Parallel test case") + continue + } + + done := cProv.SetSDKContext() + + hash, err := hex.DecodeString(curr.Response.TxHash) + require.Nil(t, err) + txResp, err := TxWithRetry(ctx, cProv.RPCClient, hash) + require.Nil(t, err) + + require.Nil(t, err) + dc := cProv.Cdc.TxConfig.TxDecoder() + tx, err := dc(txResp.Tx) + require.Nil(t, err) + builder, err := cProv.Cdc.TxConfig.WrapTxBuilder(tx) + require.Nil(t, err) + txFinder := builder.(protoTxProvider) + fullTx := txFinder.GetProtoTx() + isFeegrantedMsg := false + + msgs := "" + msgType := "" + for _, m := range fullTx.GetMsgs() { + msgType = types.MsgTypeURL(m) + //We want all IBC transfers (on an open channel/connection) to be feegranted in round robin fashion + if msgType == "/ibc.core.channel.v1.MsgRecvPacket" || msgType == "/ibc.core.channel.v1.MsgAcknowledgement" { + isFeegrantedMsg = true + msgs += msgType + ", " + } else { + msgs += msgType + ", " + } + } + + //It's required that TXs be feegranted in a round robin fashion for this chain and message type + if isFeegrantedChain && isFeegrantedMsg { + fmt.Printf("Msg types: %+v\n", msgs) + signers := fullTx.GetSigners() + require.Equal(t, len(signers), 1) + granter := fullTx.FeeGranter() + + //Feegranter for the TX that was signed on chain must be the relayer chain's configured feegranter + require.Equal(t, feegrantInfo.granter, granter.String()) + require.NotEmpty(t, granter) + + for _, msg := range fullTx.GetMsgs() { + msgType = types.MsgTypeURL(msg) + //We want all IBC transfers (on an open channel/connection) to be feegranted in round robin fashion + if msgType == "/ibc.core.channel.v1.MsgRecvPacket" { + c := msg.(*chantypes.MsgRecvPacket) + appData := c.Packet.GetData() + tokenTransfer := &transfertypes.FungibleTokenPacketData{} + err := tokenTransfer.Unmarshal(appData) + if err == nil { + fmt.Printf("%+v\n", tokenTransfer) + } else { + fmt.Println(string(appData)) + } + } + } + + //Grantee for the TX that was signed on chain must be a configured grantee in the relayer's chain feegrants. + //In addition, the grantee must be used in round robin fashion + //expectedGrantee := nextGrantee(feegrantInfo) + actualGrantee := signers[0].String() + signerList, ok := feegrantMsgSigners[chain] + if ok { + signerList = append(signerList, actualGrantee) + feegrantMsgSigners[chain] = signerList + } else { + feegrantMsgSigners[chain] = []string{actualGrantee} + } + fmt.Printf("Chain: %s, msg type: %s, height: %d, signer: %s, granter: %s\n", chain, msgType, curr.Response.Height, actualGrantee, granter.String()) + } + done() + } + } + default: + fmt.Println("Unknown channel message") + } + } + + for chain, signers := range feegrantMsgSigners { + require.Equal(t, chain, gaia.Config().ChainID) + signerCountMap := map[string]int{} + + for _, signer := range signers { + count, ok := signerCountMap[signer] + if ok { + signerCountMap[signer] = count + 1 + } else { + signerCountMap[signer] = 1 + } + } + + highestCount := 0 + for _, count := range signerCountMap { + if count > highestCount { + highestCount = count + } + } + + //At least one feegranter must have signed a TX + require.GreaterOrEqual(t, highestCount, 1) + + //All of the feegrantees must have signed at least one TX + expectedFeegrantInfo := feegrantedChains[chain] + require.Equal(t, len(signerCountMap), len(expectedFeegrantInfo.grantees)) + + // verify that TXs were signed in a round robin fashion. + // no grantee should have signed more TXs than any other grantee (off by one is allowed). + for signer, count := range signerCountMap { + fmt.Printf("signer %s signed %d feegranted TXs \n", signer, count) + require.LessOrEqual(t, highestCount-count, 1) + } + } + + // Trace IBC Denom + gaiaDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom(osmosisChannel.PortID, osmosisChannel.ChannelID, gaia.Config().Denom)) + gaiaIbcDenom := gaiaDenomTrace.IBCDenom() + + osmosisDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom(gaiaChannel.PortID, gaiaChannel.ChannelID, osmosis.Config().Denom)) + osmosisIbcDenom := osmosisDenomTrace.IBCDenom() + + // Test destination wallets have increased funds + gaiaIBCBalance, err := osmosis.GetBalance(ctx, gaiaDstAddress, gaiaIbcDenom) + require.NoError(t, err) + require.Equal(t, amountToSend, gaiaIBCBalance) + + osmosisIBCBalance, err := gaia.GetBalance(ctx, osmosisDstAddress, osmosisIbcDenom) + require.NoError(t, err) + require.Equal(t, 3*amountToSend, osmosisIBCBalance) + + // Test grantee still has exact amount expected + gaiaGranteeIBCBalance, err := gaia.GetBalance(ctx, gaiaGranteeAddr, gaia.Config().Denom) + require.NoError(t, err) + require.Equal(t, granteeFundAmount, gaiaGranteeIBCBalance) + + // Test granter has less than they started with, meaning fees came from their account + gaiaGranterIBCBalance, err := gaia.GetBalance(ctx, gaiaGranterAddr, gaia.Config().Denom) + require.NoError(t, err) + require.Less(t, gaiaGranterIBCBalance, fundAmount) + r.StopRelayer(ctx, eRep) +} + +func TxWithRetry(ctx context.Context, client rpcclient.Client, hash []byte) (*ctypes.ResultTx, error) { + var err error + var res *ctypes.ResultTx + if err = retry.Do(func() error { + res, err = client.Tx(ctx, hash, true) + return err + }, retry.Context(ctx), relayer.RtyAtt, relayer.RtyDel, relayer.RtyErr); err != nil { + return res, err + } + + return res, err +} diff --git a/interchaintest/go.mod b/interchaintest/go.mod index 6d4e1f484..6352c1099 100644 --- a/interchaintest/go.mod +++ b/interchaintest/go.mod @@ -3,12 +3,13 @@ module github.com/cosmos/relayer/v2/interchaintest go 1.20 require ( - cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff + cosmossdk.io/simapp v0.0.0-20230224204036-a6adb0821462 github.com/cometbft/cometbft v0.37.2 github.com/cosmos/cosmos-sdk v0.47.3 + github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/ibc-go/v7 v7.2.0 - github.com/cosmos/relayer/v2 v2.0.0-00010101000000-000000000000 + github.com/cosmos/relayer/v2 v2.0.0 github.com/docker/docker v24.0.1+incompatible github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845 github.com/moby/moby v24.0.2+incompatible @@ -64,7 +65,6 @@ require ( github.com/containerd/containerd v1.6.8 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect - github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v0.20.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect diff --git a/interchaintest/go.sum b/interchaintest/go.sum index 37d2d6154..74c50689d 100644 --- a/interchaintest/go.sum +++ b/interchaintest/go.sum @@ -200,8 +200,8 @@ cosmossdk.io/log v1.1.0 h1:v0ogPHYeTzPcBTcPR1A3j1hkei4pZama8kz8LKlCMv0= cosmossdk.io/log v1.1.0/go.mod h1:6zjroETlcDs+mm62gd8Ig7mZ+N+fVOZS91V17H+M4N4= cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= -cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff h1:P1ialzTepD1oxdNPYc5N8Eggq3RdejZq3cJs8YYMs9Y= -cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff/go.mod h1:AKzx6Mb544LjJ9RHmGFHjY9rEOLiUAi8I0F727TR0dY= +cosmossdk.io/simapp v0.0.0-20230224204036-a6adb0821462 h1:g8muUHnXL8vhld2Sjilyhb1UQObc+x9GVuDK43TYZns= +cosmossdk.io/simapp v0.0.0-20230224204036-a6adb0821462/go.mod h1:4Dd3NLoLYoN90kZ0uyHoTHzVVk9+J0v4HhZRBNTAq2c= cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -484,8 +484,8 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -507,8 +507,8 @@ github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8c github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= @@ -520,7 +520,6 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= diff --git a/interchaintest/ica_channel_close_test.go b/interchaintest/ica_channel_close_test.go index b21a41c32..6eac44b64 100644 --- a/interchaintest/ica_channel_close_test.go +++ b/interchaintest/ica_channel_close_test.go @@ -26,8 +26,6 @@ func TestScenarioICAChannelClose(t *testing.T) { t.Skip("skipping in short mode") } - t.Parallel() - client, network := interchaintest.DockerSetup(t) rep := testreporter.NewNopReporter() @@ -93,6 +91,8 @@ func TestScenarioICAChannelClose(t *testing.T) { // BlockDatabaseFile: interchaintest.DefaultBlockDatabaseFilepath(), })) + t.Parallel() + // Fund a user account on chain1 and chain2 const userFunds = int64(10_000_000_000) users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, chain1, chain2) @@ -244,7 +244,7 @@ func TestScenarioICAChannelClose(t *testing.T) { // Wait for ack _, err = cosmos.PollForMessage(ctx, chain1, ir, - c1h, c1h+10, ackFound) + c1h, c1h+25, ackFound) require.NoError(t, err) // Assert that the funds have been received by the user account on chain2 @@ -311,7 +311,7 @@ func TestScenarioICAChannelClose(t *testing.T) { // Wait for channel open confirm _, err = cosmos.PollForMessage(ctx, chain2, ir, - c2h, c2h+30, channelFound) + c2h, c2h+40, channelFound) require.NoError(t, err) // Assert that a new channel has been opened and the same ICA is in use diff --git a/interchaintest/interchain_accounts_test.go b/interchaintest/interchain_accounts_test.go index 0185b2bc2..0ec0a1df5 100644 --- a/interchaintest/interchain_accounts_test.go +++ b/interchaintest/interchain_accounts_test.go @@ -27,8 +27,6 @@ func TestScenarioInterchainAccounts(t *testing.T) { t.Skip("skipping in short mode") } - t.Parallel() - client, network := interchaintest.DockerSetup(t) rep := testreporter.NewNopReporter() @@ -94,6 +92,8 @@ func TestScenarioInterchainAccounts(t *testing.T) { // BlockDatabaseFile: interchaintest.DefaultBlockDatabaseFilepath(), })) + t.Parallel() + // Fund a user account on chain1 and chain2 const userFunds = int64(10_000_000_000) users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, chain1, chain2) diff --git a/interchaintest/misbehaviour_test.go b/interchaintest/misbehaviour_test.go index 2dc8b4656..9c99c5504 100644 --- a/interchaintest/misbehaviour_test.go +++ b/interchaintest/misbehaviour_test.go @@ -35,6 +35,7 @@ import ( "github.com/strangelove-ventures/interchaintest/v7/testreporter" "github.com/strangelove-ventures/interchaintest/v7/testutil" "github.com/stretchr/testify/require" + "go.uber.org/zap" "go.uber.org/zap/zaptest" ) @@ -43,13 +44,13 @@ func TestRelayerMisbehaviourDetection(t *testing.T) { t.Skip() } - t.Parallel() - numVals := 1 numFullNodes := 0 - cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ - {Name: "gaia", Version: "v9.0.0-rc1", NumValidators: &numVals, NumFullNodes: &numFullNodes, ChainConfig: ibc.ChainConfig{ChainID: "chain-a", GasPrices: "0.0uatom"}}, - {Name: "gaia", Version: "v9.0.0-rc1", NumValidators: &numVals, NumFullNodes: &numFullNodes, ChainConfig: ibc.ChainConfig{ChainID: "chain-b", GasPrices: "0.0uatom"}}}, + logger := zaptest.NewLogger(t) + + cf := interchaintest.NewBuiltinChainFactory(logger, []*interchaintest.ChainSpec{ + {Name: "gaia", Version: "v9.0.0-rc1", NumValidators: &numVals, NumFullNodes: &numFullNodes, ChainConfig: ibc.ChainConfig{ChainID: "chain-a", GasPrices: "0.0uatom", Bech32Prefix: "cosmos"}}, + {Name: "gaia", Version: "v9.0.0-rc1", NumValidators: &numVals, NumFullNodes: &numFullNodes, ChainConfig: ibc.ChainConfig{ChainID: "chain-b", GasPrices: "0.0uatom", Bech32Prefix: "cosmos"}}}, ) chains, err := cf.Chains(t.Name()) @@ -86,6 +87,8 @@ func TestRelayerMisbehaviourDetection(t *testing.T) { SkipPathCreation: false, })) + t.Parallel() + t.Cleanup(func() { _ = ic.Close() }) @@ -186,6 +189,7 @@ func TestRelayerMisbehaviourDetection(t *testing.T) { ClientMessage: protoAny, Signer: user.FormattedAddress(), } + logger.Info("Misbehaviour test, MsgUpdateClient", zap.String("Signer", user.FormattedAddress())) resp, err := cosmos.BroadcastTx(ctx, b, user, msg) require.NoError(t, err) diff --git a/interchaintest/path_filter_test.go b/interchaintest/path_filter_test.go index 1ec706a80..3ef7b9215 100644 --- a/interchaintest/path_filter_test.go +++ b/interchaintest/path_filter_test.go @@ -21,7 +21,6 @@ import ( // TestScenarioPathFilterAllow tests the channel allowlist func TestScenarioPathFilterAllow(t *testing.T) { - t.Parallel() ctx := context.Background() nv := 1 @@ -43,6 +42,8 @@ func TestScenarioPathFilterAllow(t *testing.T) { InitialBlockHistory: 100, }).Build(t, nil, "") + t.Parallel() + // Prep Interchain const ibcPath = "gaia-osmosis" ic := interchaintest.NewInterchain(). @@ -167,7 +168,6 @@ func TestScenarioPathFilterAllow(t *testing.T) { // TestScenarioPathFilterDeny tests the channel denylist func TestScenarioPathFilterDeny(t *testing.T) { - t.Parallel() ctx := context.Background() nv := 1 @@ -216,6 +216,8 @@ func TestScenarioPathFilterDeny(t *testing.T) { SkipPathCreation: false, })) + t.Parallel() + // Get Channel ID gaiaChans, err := r.GetChannels(ctx, eRep, gaia.Config().ChainID) require.NoError(t, err) diff --git a/interchaintest/relayer.go b/interchaintest/relayer.go index d06c0e1b8..8641830bc 100644 --- a/interchaintest/relayer.go +++ b/interchaintest/relayer.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/relayer/v2/cmd" "github.com/cosmos/relayer/v2/internal/relayertest" "github.com/cosmos/relayer/v2/relayer" @@ -37,6 +38,9 @@ func NewRelayer( t *testing.T, config RelayerConfig, ) ibc.Relayer { + //prevent incorrect bech32 address prefixed addresses when calling AccAddress.String() + types.SetAddrCacheEnabled(false) + r := &Relayer{ t: t, home: t.TempDir(), diff --git a/interchaintest/stride/stride_icq_test.go b/interchaintest/stride/stride_icq_test.go index 00a42c609..ac9a067e4 100644 --- a/interchaintest/stride/stride_icq_test.go +++ b/interchaintest/stride/stride_icq_test.go @@ -16,6 +16,7 @@ import ( "github.com/strangelove-ventures/interchaintest/v7/testreporter" "github.com/strangelove-ventures/interchaintest/v7/testutil" "github.com/stretchr/testify/require" + "go.uber.org/zap" "go.uber.org/zap/zaptest" "golang.org/x/sync/errgroup" ) @@ -26,9 +27,6 @@ func TestScenarioStrideICAandICQ(t *testing.T) { if testing.Short() { t.Skip() } - - t.Parallel() - client, network := interchaintest.DockerSetup(t) rep := testreporter.NewNopReporter() @@ -38,9 +36,10 @@ func TestScenarioStrideICAandICQ(t *testing.T) { nf := 0 nv := 1 + logger := zaptest.NewLogger(t) // Define chains involved in test - cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ + cf := interchaintest.NewBuiltinChainFactory(logger, []*interchaintest.ChainSpec{ { Name: "stride", ChainName: "stride", @@ -113,10 +112,15 @@ func TestScenarioStrideICAandICQ(t *testing.T) { SkipPathCreation: false, })) + + t.Parallel() + t.Cleanup(func() { _ = ic.Close() }) + logger.Info("TestScenarioStrideICAandICQ [1]") + // Fund user accounts, so we can query balances and make assertions. const userFunds = int64(10_000_000_000_000) users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, stride, gaia) @@ -128,6 +132,8 @@ func TestScenarioStrideICAandICQ(t *testing.T) { err = r.StartRelayer(ctx, eRep, pathStrideGaia) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [2]") + t.Cleanup( func() { err := r.StopRelayer(ctx, eRep) @@ -147,6 +153,8 @@ func TestScenarioStrideICAandICQ(t *testing.T) { strideAdminAddr, err := types.Bech32ifyAddressBytes(strideCfg.Bech32Prefix, strideAdminAddrBytes) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [3]") + err = stride.SendFunds(ctx, interchaintest.FaucetAccountKeyName, ibc.WalletAmount{ Address: strideAdminAddr, Amount: userFunds, @@ -154,12 +162,16 @@ func TestScenarioStrideICAandICQ(t *testing.T) { }) require.NoError(t, err, "failed to fund stride admin account") + logger.Info("TestScenarioStrideICAandICQ [4]") + // get native chain user addresses strideAddr := strideUser.FormattedAddress() require.NotEmpty(t, strideAddr) + logger.Info("TestScenarioStrideICAandICQ [5]", zap.String("stride addr", strideAddr)) gaiaAddress := gaiaUser.FormattedAddress() require.NotEmpty(t, gaiaAddress) + logger.Info("TestScenarioStrideICAandICQ [6]", zap.String("gaia addr", gaiaAddress)) // get ibc paths gaiaConns, err := r.GetConnections(ctx, eRep, gaiaCfg.ChainID) @@ -168,6 +180,8 @@ func TestScenarioStrideICAandICQ(t *testing.T) { gaiaChans, err := r.GetChannels(ctx, eRep, gaiaCfg.ChainID) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [7]") + atomIBCDenom := transfertypes.ParseDenomTrace( transfertypes.GetPrefixedDenom( gaiaChans[0].Counterparty.PortID, @@ -182,6 +196,8 @@ func TestScenarioStrideICAandICQ(t *testing.T) { gaiaHeight, err := gaia.Height(ctx) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [8]") + // Fund stride user with ibc denom atom tx, err := gaia.SendIBCTransfer(ctx, gaiaChans[0].ChannelID, gaiaUser.KeyName(), ibc.WalletAmount{ Amount: 1_000_000_000_000, @@ -190,13 +206,19 @@ func TestScenarioStrideICAandICQ(t *testing.T) { }, ibc.TransferOptions{}) require.NoError(t, err) - _, err = testutil.PollForAck(ctx, gaia, gaiaHeight, gaiaHeight+10, tx.Packet) + logger.Info("TestScenarioStrideICAandICQ [9]") + + _, err = testutil.PollForAck(ctx, gaia, gaiaHeight, gaiaHeight+40, tx.Packet) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [10]") + require.NoError(t, eg.Wait()) + logger.Info("TestScenarioStrideICAandICQ [11]") + // Register gaia host zone - _, err = strideFullNode.ExecTx(ctx, StrideAdminAccount, + res, err := strideFullNode.ExecTx(ctx, StrideAdminAccount, "stakeibc", "register-host-zone", gaiaConns[0].Counterparty.ConnectionId, gaiaCfg.Denom, gaiaCfg.Bech32Prefix, atomIBCDenom, gaiaChans[0].Counterparty.ChannelID, "1", @@ -204,30 +226,40 @@ func TestScenarioStrideICAandICQ(t *testing.T) { ) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [12]", zap.String("execTx res", res)) + gaiaHeight, err = gaia.Height(ctx) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [13]") + // Wait for the ICA accounts to be setup // Poll for 4 MsgChannelOpenConfirm with timeout after 15 blocks. chanCount := 0 _, err = cosmos.PollForMessage( - ctx, gaia, gaiaCfg.EncodingConfig.InterfaceRegistry, gaiaHeight, gaiaHeight+15, + ctx, gaia, gaiaCfg.EncodingConfig.InterfaceRegistry, gaiaHeight, gaiaHeight+40, func(found *chantypes.MsgChannelOpenConfirm) bool { chanCount++; return chanCount == 4 }, ) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [14]") + // Get validator address gaiaVal1Address, err := gaia.Validators[0].KeyBech32(ctx, "validator", "val") require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [15]") + // Add gaia validator - _, err = strideFullNode.ExecTx(ctx, StrideAdminAccount, + res, err = strideFullNode.ExecTx(ctx, StrideAdminAccount, "stakeibc", "add-validator", gaiaCfg.ChainID, "gval1", gaiaVal1Address, "10", "5", ) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [16]", zap.String("execTx res", res)) + var gaiaHostZone HostZoneWrapper // query gaia host zone @@ -238,20 +270,31 @@ func TestScenarioStrideICAandICQ(t *testing.T) { err = json.Unmarshal(stdout, &gaiaHostZone) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [17]", zap.String("execQuery res", string(stdout))) + // Liquid stake some atom - _, err = strideFullNode.ExecTx(ctx, strideUser.KeyName(), + res, err = strideFullNode.ExecTx(ctx, strideUser.KeyName(), "stakeibc", "liquid-stake", "1000000000000", gaiaCfg.Denom, ) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [18]", zap.String("execTx res", res)) + strideHeight, err := stride.Height(ctx) require.NoError(t, err) + logger.Info("TestScenarioStrideICAandICQ [19]") + // Poll for MsgSubmitQueryResponse with timeout after 20 blocks - _, err = cosmos.PollForMessage( - ctx, stride, strideCfg.EncodingConfig.InterfaceRegistry, strideHeight, strideHeight+20, + resp, err := cosmos.PollForMessage( + ctx, stride, strideCfg.EncodingConfig.InterfaceRegistry, strideHeight, strideHeight+40, func(found *rlystride.MsgSubmitQueryResponse) bool { return true }, ) + + logger.Info("TestScenarioStrideICAandICQ [20]", zap.String("[poll for msg] resp", resp.String())) + if err != nil { + logger.Info("error poll: " + err.Error()) + } require.NoError(t, err) } diff --git a/interchaintest/tendermint_v0.37_boundary_test.go b/interchaintest/tendermint_v0.37_boundary_test.go index c7972c1ac..04a7a8c47 100644 --- a/interchaintest/tendermint_v0.37_boundary_test.go +++ b/interchaintest/tendermint_v0.37_boundary_test.go @@ -18,8 +18,6 @@ func TestScenarioTendermint37Boundary(t *testing.T) { t.Skip("skipping in short mode") } - t.Parallel() - nv := 1 nf := 0 @@ -58,6 +56,8 @@ func TestScenarioTendermint37Boundary(t *testing.T) { }) r := rf.Build(t, client, network) + t.Parallel() + ic := interchaintest.NewInterchain(). AddChain(chain). AddChain(counterpartyChain). diff --git a/relayer/chains/cosmos/feegrant.go b/relayer/chains/cosmos/feegrant.go new file mode 100644 index 000000000..92b14b6d3 --- /dev/null +++ b/relayer/chains/cosmos/feegrant.go @@ -0,0 +1,529 @@ +package cosmos + +import ( + "context" + "errors" + "fmt" + "regexp" + "strconv" + "time" + + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" + "github.com/cosmos/cosmos-sdk/x/feegrant" +) + +// Searches for valid, existing BasicAllowance grants for the ChainClient's configured Feegranter. +// Expired grants are ignored. Other grant types are ignored. +func (cc *CosmosProvider) GetValidBasicGrants() ([]*feegrant.Grant, error) { + validGrants := []*feegrant.Grant{} + + if cc.PCfg.FeeGrants == nil { + return nil, errors.New("no feegrant configuration for chainclient") + } + + keyNameOrAddress := cc.PCfg.FeeGrants.GranterKey + address, err := cc.AccountFromKeyOrAddress(keyNameOrAddress) + if err != nil { + return nil, err + } + + encodedAddr := cc.MustEncodeAccAddr(address) + grants, err := cc.QueryFeegrantsByGranter(encodedAddr, nil) + if err != nil { + return nil, err + } + + for _, grant := range grants { + switch grant.Allowance.TypeUrl { + case "/cosmos.feegrant.v1beta1.BasicAllowance": + //var feegrantAllowance feegrant.BasicAllowance + var feegrantAllowance feegrant.FeeAllowanceI + e := cc.Cdc.InterfaceRegistry.UnpackAny(grant.Allowance, &feegrantAllowance) + if e != nil { + return nil, e + } + //feegrantAllowance := grant.Allowance.GetCachedValue().(*feegrant.BasicAllowance) + if isValidGrant(feegrantAllowance.(*feegrant.BasicAllowance)) { + validGrants = append(validGrants, grant) + } + default: + fmt.Printf("Ignoring grant type %s for granter %s and grantee %s\n", grant.Allowance.TypeUrl, grant.Granter, grant.Grantee) + } + } + + return validGrants, nil +} + +// Searches for valid, existing BasicAllowance grants for the given grantee & ChainClient's configured granter. +// Expired grants are ignored. Other grant types are ignored. +func (cc *CosmosProvider) GetGranteeValidBasicGrants(granteeKey string) ([]*feegrant.Grant, error) { + validGrants := []*feegrant.Grant{} + + if cc.PCfg.FeeGrants == nil { + return nil, errors.New("no feegrant configuration for chainclient") + } + + granterAddr, err := cc.AccountFromKeyOrAddress(cc.PCfg.FeeGrants.GranterKey) + if err != nil { + return nil, err + } + granterEncodedAddr := cc.MustEncodeAccAddr(granterAddr) + + address, err := cc.AccountFromKeyOrAddress(granteeKey) + if err != nil { + return nil, err + } + + encodedAddr := cc.MustEncodeAccAddr(address) + grants, err := cc.QueryFeegrantsByGrantee(encodedAddr, nil) + if err != nil { + return nil, err + } + + for _, grant := range grants { + if grant.Granter == granterEncodedAddr { + switch grant.Allowance.TypeUrl { + case "/cosmos.feegrant.v1beta1.BasicAllowance": + var feegrantAllowance feegrant.FeeAllowanceI + e := cc.Cdc.InterfaceRegistry.UnpackAny(grant.Allowance, &feegrantAllowance) + if e != nil { + return nil, e + } + if isValidGrant(feegrantAllowance.(*feegrant.BasicAllowance)) { + validGrants = append(validGrants, grant) + } + default: + fmt.Printf("Ignoring grant type %s for granter %s and grantee %s\n", grant.Allowance.TypeUrl, grant.Granter, grant.Grantee) + } + } + } + + return validGrants, nil +} + +// True if the grant has not expired and all coins have positive balances, false otherwise +// Note: technically, any single coin with a positive balance makes the grant usable +func isValidGrant(a *feegrant.BasicAllowance) bool { + //grant expired due to time limit + if a.Expiration != nil && time.Now().After(*a.Expiration) { + return false + } + + //feegrant without a spending limit specified allows unlimited fees to be spent + valid := true + + //spending limit is specified, check if there are funds remaining on every coin + if a.SpendLimit != nil { + for _, coin := range a.SpendLimit { + if coin.Amount.LTE(types.ZeroInt()) { + valid = false + } + } + } + + return valid +} + +func (cc *CosmosProvider) ConfigureFeegrants(numGrantees int, granterKey string) error { + cc.PCfg.FeeGrants = &FeeGrantConfiguration{ + GranteesWanted: numGrantees, + GranterKey: granterKey, + ManagedGrantees: []string{}, + } + + return cc.PCfg.FeeGrants.AddGranteeKeys(cc) +} + +func (cc *CosmosProvider) ConfigureWithGrantees(grantees []string, granterKey string) error { + if len(grantees) == 0 { + return errors.New("list of grantee names cannot be empty") + } + + cc.PCfg.FeeGrants = &FeeGrantConfiguration{ + GranteesWanted: len(grantees), + GranterKey: granterKey, + ManagedGrantees: grantees, + } + + for _, newGrantee := range grantees { + if !cc.KeyExists(newGrantee) { + //Add another key to the chain client for the grantee + _, err := cc.AddKey(newGrantee, sdk.CoinType, string(hd.Secp256k1Type)) + if err != nil { + return err + } + } + } + + return nil +} + +func (fg *FeeGrantConfiguration) AddGranteeKeys(cc *CosmosProvider) error { + for i := len(fg.ManagedGrantees); i < fg.GranteesWanted; i++ { + newGranteeIdx := strconv.Itoa(len(fg.ManagedGrantees) + 1) + newGrantee := "grantee" + newGranteeIdx + + //Add another key to the chain client for the grantee + _, err := cc.AddKey(newGrantee, sdk.CoinType, string(hd.Secp256k1Type)) + if err != nil { + return err + } + + fg.ManagedGrantees = append(fg.ManagedGrantees, newGrantee) + } + + return nil +} + +// Get the feegrant params to use for the next TX. If feegrants are not configured for the chain client, the default key will be used for TX signing. +// Otherwise, a configured feegrantee will be chosen for TX signing in round-robin fashion. +func (cc *CosmosProvider) GetTxFeeGrant() (txSignerKey string, feeGranterKey string) { + //By default, we should sign TXs with the ChainClient's default key + txSignerKey = cc.PCfg.Key + + if cc.PCfg.FeeGrants == nil { + fmt.Printf("cc.Config.FeeGrants == nil\n") + return + } + + // Use the ChainClient's configured Feegranter key for the next TX. + feeGranterKey = cc.PCfg.FeeGrants.GranterKey + + // The ChainClient Feegrant configuration has never been verified on chain. + // Don't use Feegrants as it could cause the TX to fail on chain. + if feeGranterKey == "" || cc.PCfg.FeeGrants.BlockHeightVerified <= 0 { + fmt.Printf("cc.Config.FeeGrants.BlockHeightVerified <= 0\n") + feeGranterKey = "" + return + } + + //Pick the next managed grantee in the list as the TX signer + lastGranteeIdx := cc.PCfg.FeeGrants.GranteeLastSignerIndex + + if lastGranteeIdx >= 0 && lastGranteeIdx <= len(cc.PCfg.FeeGrants.ManagedGrantees)-1 { + txSignerKey = cc.PCfg.FeeGrants.ManagedGrantees[lastGranteeIdx] + cc.PCfg.FeeGrants.GranteeLastSignerIndex = cc.PCfg.FeeGrants.GranteeLastSignerIndex + 1 + + //Restart the round robin at 0 if we reached the end of the list of grantees + if cc.PCfg.FeeGrants.GranteeLastSignerIndex == len(cc.PCfg.FeeGrants.ManagedGrantees) { + cc.PCfg.FeeGrants.GranteeLastSignerIndex = 0 + } + } + + return +} + +// Ensure all Basic Allowance grants are in place for the given ChainClient. +// This will query (RPC) for existing grants and create new grants if they don't exist. +func (cc *CosmosProvider) EnsureBasicGrants(ctx context.Context, memo string) (*sdk.TxResponse, error) { + if cc.PCfg.FeeGrants == nil { + return nil, errors.New("ChainClient must be a FeeGranter to establish grants") + } else if len(cc.PCfg.FeeGrants.ManagedGrantees) == 0 { + return nil, errors.New("ChainClient is a FeeGranter, but is not managing any Grantees") + } + + granterKey := cc.PCfg.FeeGrants.GranterKey + if granterKey == "" { + granterKey = cc.PCfg.Key + } + + granterAcc, err := cc.GetKeyAddressForKey(granterKey) + if err != nil { + fmt.Printf("Retrieving key '%s': ChainClient FeeGranter misconfiguration: %s", granterKey, err.Error()) + return nil, err + } + + granterAddr, granterAddrErr := cc.EncodeBech32AccAddr(granterAcc) + if granterAddrErr != nil { + return nil, granterAddrErr + } + + validGrants, err := cc.GetValidBasicGrants() + failedLookupGrantsByGranter := err != nil + + msgs := []sdk.Msg{} + numGrantees := len(cc.PCfg.FeeGrants.ManagedGrantees) + grantsNeeded := 0 + + for _, grantee := range cc.PCfg.FeeGrants.ManagedGrantees { + + //Searching for all grants with the given granter failed, so we will search by the grantee. + //Reason this lookup sometimes fails is because the 'Search by granter' request is in SDK v0.46+ + if failedLookupGrantsByGranter { + validGrants, err = cc.GetGranteeValidBasicGrants(grantee) + if err != nil { + return nil, err + } + } + + granteeAcc, err := cc.GetKeyAddressForKey(grantee) + if err != nil { + fmt.Printf("Misconfiguration for grantee key %s. Error: %s\n", grantee, err.Error()) + return nil, err + } + + granteeAddr, granteeAddrErr := cc.EncodeBech32AccAddr(granteeAcc) + if granteeAddrErr != nil { + return nil, granteeAddrErr + } + + hasGrant := false + for _, basicGrant := range validGrants { + if basicGrant.Grantee == granteeAddr { + fmt.Printf("Valid grant found for granter %s, grantee %s\n", basicGrant.Granter, basicGrant.Grantee) + hasGrant = true + } + } + + if !hasGrant { + grantsNeeded += 1 + fmt.Printf("Grant will be created on chain for granter %s and grantee %s\n", granterAddr, granteeAddr) + grantMsg, err := cc.getMsgGrantBasicAllowance(granterAcc, granteeAcc) + if err != nil { + return nil, err + } + msgs = append(msgs, grantMsg) + } + } + + if len(msgs) > 0 { + //Make sure the granter has funds on chain, if not, we can't even pay TX fees. + //Also, depending how the config was initialized, the key might only exist locally, not on chain. + balance, err := cc.QueryBalanceWithAddress(ctx, granterAddr) + if err != nil { + return nil, err + } + + //Check to ensure the feegranter has funds on chain that can pay TX fees + weBroke := true + gasDenom, err := getGasTokenDenom(cc.PCfg.GasPrices) + if err != nil { + return nil, err + } + + for _, coin := range balance { + if coin.Denom == gasDenom { + if coin.Amount.GT(sdk.ZeroInt()) { + weBroke = false + } + } + } + + //Feegranter can pay TX fees + if !weBroke { + txResp, err := cc.SubmitTxAwaitResponse(ctx, msgs, memo, 0, granterKey) + if err != nil { + fmt.Printf("Error: SubmitTxAwaitResponse: %s", err.Error()) + return nil, err + } else if txResp != nil && txResp.TxResponse != nil && txResp.TxResponse.Code != 0 { + fmt.Printf("Submitting grants for granter %s failed. Code: %d, TX hash: %s\n", granterKey, txResp.TxResponse.Code, txResp.TxResponse.TxHash) + return nil, fmt.Errorf("could not configure feegrant for granter %s", granterKey) + } + + fmt.Printf("TX succeeded, %d new grants configured, %d grants already in place. TX hash: %s\n", grantsNeeded, numGrantees-grantsNeeded, txResp.TxResponse.TxHash) + return txResp.TxResponse, err + } else { + return nil, fmt.Errorf("granter %s does not have funds on chain in fee denom '%s' (no TXs submitted)", granterKey, gasDenom) + } + } else { + fmt.Printf("All grantees (%d total) already had valid feegrants. Feegrant configuration verified.\n", numGrantees) + } + + return nil, nil +} + +func getGasTokenDenom(gasPrices string) (string, error) { + r := regexp.MustCompile(`(?P[0-9.]*)(?P.*)`) + submatches := r.FindStringSubmatch(gasPrices) + if len(submatches) != 3 { + return "", errors.New("could not find fee denom") + } + + return submatches[2], nil +} + +// GrantBasicAllowance Send a feegrant with the basic allowance type. +// This function does not check for existing feegrant authorizations. +// TODO: check for existing authorizations prior to attempting new one. +func (cc *CosmosProvider) GrantAllGranteesBasicAllowance(ctx context.Context, gas uint64) error { + if cc.PCfg.FeeGrants == nil { + return errors.New("ChainClient must be a FeeGranter to establish grants") + } else if len(cc.PCfg.FeeGrants.ManagedGrantees) == 0 { + return errors.New("ChainClient is a FeeGranter, but is not managing any Grantees") + } + + granterKey := cc.PCfg.FeeGrants.GranterKey + if granterKey == "" { + granterKey = cc.PCfg.Key + } + granterAddr, err := cc.GetKeyAddressForKey(granterKey) + if err != nil { + fmt.Printf("ChainClient FeeGranter misconfiguration: %s", err.Error()) + return err + } + + for _, grantee := range cc.PCfg.FeeGrants.ManagedGrantees { + granteeAddr, err := cc.GetKeyAddressForKey(grantee) + + if err != nil { + fmt.Printf("Misconfiguration for grantee %s. Error: %s\n", grantee, err.Error()) + return err + } + + grantResp, err := cc.GrantBasicAllowance(ctx, granterAddr, granterKey, granteeAddr, gas) + if err != nil { + return err + } else if grantResp != nil && grantResp.TxResponse != nil && grantResp.TxResponse.Code != 0 { + fmt.Printf("grantee %s and granter %s. Code: %d\n", granterAddr.String(), granteeAddr.String(), grantResp.TxResponse.Code) + return fmt.Errorf("could not configure feegrant for granter %s and grantee %s", granterAddr.String(), granteeAddr.String()) + } + } + return nil +} + +// GrantBasicAllowance Send a feegrant with the basic allowance type. +// This function does not check for existing feegrant authorizations. +// TODO: check for existing authorizations prior to attempting new one. +func (cc *CosmosProvider) GrantAllGranteesBasicAllowanceWithExpiration(ctx context.Context, gas uint64, expiration time.Time) error { + if cc.PCfg.FeeGrants == nil { + return errors.New("ChainClient must be a FeeGranter to establish grants") + } else if len(cc.PCfg.FeeGrants.ManagedGrantees) == 0 { + return errors.New("ChainClient is a FeeGranter, but is not managing any Grantees") + } + + granterKey := cc.PCfg.FeeGrants.GranterKey + if granterKey == "" { + granterKey = cc.PCfg.Key + } + + granterAddr, err := cc.GetKeyAddressForKey(granterKey) + if err != nil { + fmt.Printf("ChainClient FeeGranter misconfiguration: %s", err.Error()) + return err + } + + for _, grantee := range cc.PCfg.FeeGrants.ManagedGrantees { + granteeAddr, err := cc.GetKeyAddressForKey(grantee) + + if err != nil { + fmt.Printf("Misconfiguration for grantee %s. Error: %s\n", grantee, err.Error()) + return err + } + + grantResp, err := cc.GrantBasicAllowanceWithExpiration(ctx, granterAddr, granterKey, granteeAddr, gas, expiration) + if err != nil { + return err + } else if grantResp != nil && grantResp.TxResponse != nil && grantResp.TxResponse.Code != 0 { + fmt.Printf("grantee %s and granter %s. Code: %d\n", granterAddr.String(), granteeAddr.String(), grantResp.TxResponse.Code) + return fmt.Errorf("could not configure feegrant for granter %s and grantee %s", granterAddr.String(), granteeAddr.String()) + } + } + return nil +} + +func (cc *CosmosProvider) getMsgGrantBasicAllowanceWithExpiration(granter sdk.AccAddress, grantee sdk.AccAddress, expiration time.Time) (sdk.Msg, error) { + //thirtyMin := time.Now().Add(30 * time.Minute) + feeGrantBasic := &feegrant.BasicAllowance{ + Expiration: &expiration, + } + msgGrantAllowance, err := feegrant.NewMsgGrantAllowance(feeGrantBasic, granter, grantee) + if err != nil { + fmt.Printf("Error: GrantBasicAllowance.NewMsgGrantAllowance: %s", err.Error()) + return nil, err + } + + //Due to the way Lens configures the SDK, addresses will have the 'cosmos' prefix which + //doesn't necessarily match the chain prefix of the ChainClient config. So calling the internal + //'NewMsgGrantAllowance' function will return the *incorrect* 'cosmos' prefixed bech32 address. + + //Update the Grant to ensure the correct chain-specific granter is set + granterAddr, granterAddrErr := cc.EncodeBech32AccAddr(granter) + if granterAddrErr != nil { + fmt.Printf("EncodeBech32AccAddr: %s", granterAddrErr.Error()) + return nil, granterAddrErr + } + + //Update the Grant to ensure the correct chain-specific grantee is set + granteeAddr, granteeAddrErr := cc.EncodeBech32AccAddr(grantee) + if granteeAddrErr != nil { + fmt.Printf("EncodeBech32AccAddr: %s", granteeAddrErr.Error()) + return nil, granteeAddrErr + } + + //override the 'cosmos' prefixed bech32 addresses with the correct chain prefix + msgGrantAllowance.Grantee = granteeAddr + msgGrantAllowance.Granter = granterAddr + + return msgGrantAllowance, nil +} + +func (cc *CosmosProvider) getMsgGrantBasicAllowance(granter sdk.AccAddress, grantee sdk.AccAddress) (sdk.Msg, error) { + //thirtyMin := time.Now().Add(30 * time.Minute) + feeGrantBasic := &feegrant.BasicAllowance{ + //Expiration: &thirtyMin, + } + msgGrantAllowance, err := feegrant.NewMsgGrantAllowance(feeGrantBasic, granter, grantee) + if err != nil { + fmt.Printf("Error: GrantBasicAllowance.NewMsgGrantAllowance: %s", err.Error()) + return nil, err + } + + //Due to the way Lens configures the SDK, addresses will have the 'cosmos' prefix which + //doesn't necessarily match the chain prefix of the ChainClient config. So calling the internal + //'NewMsgGrantAllowance' function will return the *incorrect* 'cosmos' prefixed bech32 address. + + //Update the Grant to ensure the correct chain-specific granter is set + granterAddr, granterAddrErr := cc.EncodeBech32AccAddr(granter) + if granterAddrErr != nil { + fmt.Printf("EncodeBech32AccAddr: %s", granterAddrErr.Error()) + return nil, granterAddrErr + } + + //Update the Grant to ensure the correct chain-specific grantee is set + granteeAddr, granteeAddrErr := cc.EncodeBech32AccAddr(grantee) + if granteeAddrErr != nil { + fmt.Printf("EncodeBech32AccAddr: %s", granteeAddrErr.Error()) + return nil, granteeAddrErr + } + + //override the 'cosmos' prefixed bech32 addresses with the correct chain prefix + msgGrantAllowance.Grantee = granteeAddr + msgGrantAllowance.Granter = granterAddr + + return msgGrantAllowance, nil +} + +func (cc *CosmosProvider) GrantBasicAllowance(ctx context.Context, granter sdk.AccAddress, granterKeyName string, grantee sdk.AccAddress, gas uint64) (*txtypes.GetTxResponse, error) { + msgGrantAllowance, err := cc.getMsgGrantBasicAllowance(granter, grantee) + if err != nil { + return nil, err + } + + msgs := []sdk.Msg{msgGrantAllowance} + txResp, err := cc.SubmitTxAwaitResponse(ctx, msgs, "", gas, granterKeyName) + if err != nil { + fmt.Printf("Error: GrantBasicAllowance.SubmitTxAwaitResponse: %s", err.Error()) + return nil, err + } + + return txResp, nil +} + +func (cc *CosmosProvider) GrantBasicAllowanceWithExpiration(ctx context.Context, granter sdk.AccAddress, granterKeyName string, grantee sdk.AccAddress, gas uint64, expiration time.Time) (*txtypes.GetTxResponse, error) { + msgGrantAllowance, err := cc.getMsgGrantBasicAllowanceWithExpiration(granter, grantee, expiration) + if err != nil { + return nil, err + } + + msgs := []sdk.Msg{msgGrantAllowance} + txResp, err := cc.SubmitTxAwaitResponse(ctx, msgs, "", gas, granterKeyName) + if err != nil { + fmt.Printf("Error: GrantBasicAllowance.SubmitTxAwaitResponse: %s", err.Error()) + return nil, err + } + + return txResp, nil +} diff --git a/relayer/chains/cosmos/grpc_query.go b/relayer/chains/cosmos/grpc_query.go index dec0c84a8..33f274e8d 100644 --- a/relayer/chains/cosmos/grpc_query.go +++ b/relayer/chains/cosmos/grpc_query.go @@ -177,7 +177,7 @@ func (cc *CosmosProvider) TxServiceBroadcast(ctx context.Context, req *tx.Broadc wg.Add(1) - if err := cc.broadcastTx(ctx, req.TxBytes, nil, nil, ctx, blockTimeout, callback); err != nil { + if err := cc.broadcastTx(ctx, req.TxBytes, nil, nil, ctx, blockTimeout, []func(*provider.RelayerTxResponse, error){callback}); err != nil { return nil, err } diff --git a/relayer/chains/cosmos/keys.go b/relayer/chains/cosmos/keys.go index 0ccdd0938..858f77505 100644 --- a/relayer/chains/cosmos/keys.go +++ b/relayer/chains/cosmos/keys.go @@ -192,8 +192,8 @@ func (cc *CosmosProvider) ExportPrivKeyArmor(keyName string) (armor string, err } // GetKeyAddress returns the account address representation for the currently configured key. -func (cc *CosmosProvider) GetKeyAddress() (sdk.AccAddress, error) { - info, err := cc.Keybase.Key(cc.PCfg.Key) +func (cc *CosmosProvider) GetKeyAddress(key string) (sdk.AccAddress, error) { + info, err := cc.Keybase.Key(key) if err != nil { return nil, err } @@ -219,3 +219,34 @@ func CreateMnemonic() (string, error) { func (cc *CosmosProvider) EncodeBech32AccAddr(addr sdk.AccAddress) (string, error) { return sdk.Bech32ifyAddressBytes(cc.PCfg.AccountPrefix, addr) } + +func (cc *CosmosProvider) DecodeBech32AccAddr(addr string) (sdk.AccAddress, error) { + return sdk.GetFromBech32(addr, cc.PCfg.AccountPrefix) +} + +func (cc *CosmosProvider) GetKeyAddressForKey(key string) (sdk.AccAddress, error) { + info, err := cc.Keybase.Key(key) + if err != nil { + return nil, err + } + return info.GetAddress() +} + +func (cc *CosmosProvider) KeyFromKeyOrAddress(keyOrAddress string) (string, error) { + switch { + case keyOrAddress == "": + return cc.PCfg.Key, nil + case cc.KeyExists(keyOrAddress): + return keyOrAddress, nil + default: + acc, err := cc.DecodeBech32AccAddr(keyOrAddress) + if err != nil { + return "", err + } + kr, err := cc.Keybase.KeyByAddress(acc) + if err != nil { + return "", err + } + return kr.Name, nil + } +} diff --git a/relayer/chains/cosmos/log.go b/relayer/chains/cosmos/log.go index 9008e58d5..f6e6564a0 100644 --- a/relayer/chains/cosmos/log.go +++ b/relayer/chains/cosmos/log.go @@ -7,7 +7,9 @@ import ( "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" typestx "github.com/cosmos/cosmos-sdk/types/tx" + feetypes "github.com/cosmos/ibc-go/v7/modules/apps/29-fee/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" "github.com/cosmos/relayer/v2/relayer/provider" @@ -162,6 +164,11 @@ func getFeePayer(tx *typestx.Tx) string { case *clienttypes.MsgUpdateClient: // Same failure mode as MsgCreateClient. return firstMsg.Signer + case *clienttypes.MsgSubmitMisbehaviour: + // Same failure mode as MsgCreateClient. + return firstMsg.Signer + case *feetypes.MsgRegisterCounterpartyPayee: + return firstMsg.Relayer default: return firstMsg.GetSigners()[0].String() } diff --git a/relayer/chains/cosmos/msg.go b/relayer/chains/cosmos/msg.go index 6f0dfeb14..ddd5a770d 100644 --- a/relayer/chains/cosmos/msg.go +++ b/relayer/chains/cosmos/msg.go @@ -11,12 +11,15 @@ import ( ) type CosmosMessage struct { - Msg sdk.Msg + Msg sdk.Msg + SetSigner func(string) //callback to update the Msg Signer field + FeegrantDisabled bool //marks whether this message type should ALWAYS disable feegranting (use the default signer) } -func NewCosmosMessage(msg sdk.Msg) provider.RelayerMessage { +func NewCosmosMessage(msg sdk.Msg, optionalSetSigner func(string)) provider.RelayerMessage { return CosmosMessage{ - Msg: msg, + Msg: msg, + SetSigner: optionalSetSigner, } } diff --git a/relayer/chains/cosmos/provider.go b/relayer/chains/cosmos/provider.go index 505b26782..c33743faf 100644 --- a/relayer/chains/cosmos/provider.go +++ b/relayer/chains/cosmos/provider.go @@ -58,6 +58,23 @@ type CosmosProviderConfig struct { Broadcast provider.BroadcastMode `json:"broadcast-mode" yaml:"broadcast-mode"` MinLoopDuration time.Duration `json:"min-loop-duration" yaml:"min-loop-duration"` ExtensionOptions []provider.ExtensionOption `json:"extension-options" yaml:"extension-options"` + + //If FeeGrantConfiguration is set, TXs submitted by the ChainClient will be signed by the FeeGrantees in a round-robin fashion by default. + FeeGrants *FeeGrantConfiguration `json:"feegrants" yaml:"feegrants"` +} + +// By default, TXs will be signed by the feegrantees 'ManagedGrantees' keys in a round robin fashion. +// Clients can use other signing keys by invoking 'tx.SendMsgsWith' and specifying the signing key. +type FeeGrantConfiguration struct { + GranteesWanted int `json:"num_grantees" yaml:"num_grantees"` + //Normally this is the default ChainClient key + GranterKey string `json:"granter" yaml:"granter"` + //List of keys (by name) that this FeeGranter manages + ManagedGrantees []string `json:"grantees" yaml:"grantees"` + //Last checked on chain (0 means grants never checked and may not exist) + BlockHeightVerified int64 `json:"block_last_verified" yaml:"block_last_verified"` + //Index of the last ManagedGrantee used as a TX signer + GranteeLastSignerIndex int } func (pc CosmosProviderConfig) Validate() error { @@ -92,6 +109,7 @@ func (pc CosmosProviderConfig) NewProvider(log *zap.Logger, homepath string, deb KeyringOptions: []keyring.Option{ethermint.EthSecp256k1Option()}, Input: os.Stdin, Output: os.Stdout, + walletStateMap: map[string]*WalletState{}, // TODO: this is a bit of a hack, we should probably have a better way to inject modules Cdc: MakeCodec(pc.Modules, pc.ExtraCodecs), @@ -113,8 +131,13 @@ type CosmosProvider struct { Cdc Codec // TODO: GRPC Client type? - nextAccountSeq uint64 - txMu sync.Mutex + //nextAccountSeq uint64 + feegrantMu sync.Mutex + + // the map key is the TX signer, which can either be 'default' (provider key) or a feegrantee + // the purpose of the map is to lock on the signer from TX creation through submission, + // thus making TX sequencing errors less likely. + walletStateMap map[string]*WalletState // metrics to monitor the provider TotalFees sdk.Coins @@ -126,6 +149,11 @@ type CosmosProvider struct { cometLegacyEncoding bool } +type WalletState struct { + NextAccountSequence uint64 + Mu sync.Mutex +} + func (cc *CosmosProvider) ProviderConfig() provider.ProviderConfig { return cc.PCfg } @@ -175,6 +203,28 @@ func (cc *CosmosProvider) Address() (string, error) { return out, err } +func (cc *CosmosProvider) MustEncodeAccAddr(addr sdk.AccAddress) string { + enc, err := cc.EncodeBech32AccAddr(addr) + if err != nil { + panic(err) + } + return enc +} + +// AccountFromKeyOrAddress returns an account from either a key or an address. +// If 'keyOrAddress' is the empty string, this returns the default key's address. +func (cc *CosmosProvider) AccountFromKeyOrAddress(keyOrAddress string) (out sdk.AccAddress, err error) { + switch { + case keyOrAddress == "": + out, err = cc.GetKeyAddress(cc.PCfg.Key) + case cc.KeyExists(keyOrAddress): + out, err = cc.GetKeyAddress(keyOrAddress) + default: + out, err = sdk.GetFromBech32(keyOrAddress, cc.PCfg.AccountPrefix) + } + return +} + func (cc *CosmosProvider) TrustingPeriod(ctx context.Context) (time.Duration, error) { res, err := cc.QueryStakingParams(ctx) @@ -297,9 +347,9 @@ func (cc *CosmosProvider) SetMetrics(m *processor.PrometheusMetrics) { cc.metrics = m } -func (cc *CosmosProvider) updateNextAccountSequence(seq uint64) { - if seq > cc.nextAccountSeq { - cc.nextAccountSeq = seq +func (cc *CosmosProvider) updateNextAccountSequence(sequenceGuard *WalletState, seq uint64) { + if seq > sequenceGuard.NextAccountSequence { + sequenceGuard.NextAccountSequence = seq } } diff --git a/relayer/chains/cosmos/query.go b/relayer/chains/cosmos/query.go index 6e438727f..766ad06dc 100644 --- a/relayer/chains/cosmos/query.go +++ b/relayer/chains/cosmos/query.go @@ -17,8 +17,11 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" + "github.com/cosmos/cosmos-sdk/types/query" querytypes "github.com/cosmos/cosmos-sdk/types/query" bankTypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/feegrant" "github.com/cosmos/cosmos-sdk/x/params/types/proposal" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" @@ -33,6 +36,7 @@ import ( "github.com/cosmos/relayer/v2/relayer/provider" "go.uber.org/zap" "golang.org/x/sync/errgroup" + "google.golang.org/grpc/metadata" ) const PaginationDelay = 10 * time.Millisecond @@ -183,6 +187,93 @@ func parseEventsFromResponseDeliverTx(resp abci.ResponseDeliverTx) []provider.Re return events } +// QueryFeegrantsByGrantee returns all requested grants for the given grantee. +// Default behavior will return all grants. +func (cc *CosmosProvider) QueryFeegrantsByGrantee(address string, paginator *query.PageRequest) ([]*feegrant.Grant, error) { + grants := []*feegrant.Grant{} + allPages := paginator == nil + + req := &feegrant.QueryAllowancesRequest{Grantee: address, Pagination: paginator} + queryClient := feegrant.NewQueryClient(cc) + ctx, cancel := cc.GetQueryContext(0) + defer cancel() + hasNextPage := true + + for { + res, err := queryClient.Allowances(ctx, req) + if err != nil { + return nil, err + } + + if res.Allowances != nil { + grants = append(grants, res.Allowances...) + } + + if res.Pagination != nil { + req.Pagination.Key = res.Pagination.NextKey + if len(res.Pagination.NextKey) == 0 { + hasNextPage = false + } + } else { + hasNextPage = false + } + + if !allPages || !hasNextPage { + break + } + } + + return grants, nil +} + +// Feegrant_GrantsByGranterRPC returns all requested grants for the given Granter. +// Default behavior will return all grants. +func (cc *CosmosProvider) QueryFeegrantsByGranter(address string, paginator *query.PageRequest) ([]*feegrant.Grant, error) { + grants := []*feegrant.Grant{} + allPages := paginator == nil + + req := &feegrant.QueryAllowancesByGranterRequest{Granter: address, Pagination: paginator} + queryClient := feegrant.NewQueryClient(cc) + ctx, cancel := cc.GetQueryContext(0) + defer cancel() + hasNextPage := true + + for { + res, err := queryClient.AllowancesByGranter(ctx, req) + if err != nil { + return nil, err + } + + if res.Allowances != nil { + grants = append(grants, res.Allowances...) + } + + if res.Pagination != nil && res.Pagination.NextKey != nil { + req.Pagination.Key = res.Pagination.NextKey + if len(res.Pagination.NextKey) == 0 { + hasNextPage = false + } + } else { + hasNextPage = false + } + + if !allPages || !hasNextPage { + break + } + } + + return grants, nil +} + +// GetQueryContext returns a context that includes the height and uses the timeout from the config +func (cc *CosmosProvider) GetQueryContext(height int64) (context.Context, context.CancelFunc) { + timeout, _ := time.ParseDuration(cc.PCfg.Timeout) // Timeout is validated in the config so no error check + ctx, cancel := context.WithTimeout(context.Background(), timeout) + strHeight := strconv.FormatInt(height, 10) + ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, strHeight) + return ctx, cancel +} + // QueryBalance returns the amount of coins in the relayer account func (cc *CosmosProvider) QueryBalance(ctx context.Context, keyName string) (sdk.Coins, error) { addr, err := cc.ShowAddress(keyName) diff --git a/relayer/chains/cosmos/relayer_packets.go b/relayer/chains/cosmos/relayer_packets.go index 168b6be9a..ad7779c6a 100644 --- a/relayer/chains/cosmos/relayer_packets.go +++ b/relayer/chains/cosmos/relayer_packets.go @@ -66,7 +66,9 @@ func (rp relayMsgTimeout) Msg(src provider.ChainProvider, srcPortId, srcChanId, Signer: addr, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } type relayMsgRecvPacket struct { @@ -129,7 +131,9 @@ func (rp relayMsgRecvPacket) Msg(src provider.ChainProvider, srcPortId, srcChanI Signer: addr, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } type relayMsgPacketAck struct { @@ -184,5 +188,7 @@ func (rp relayMsgPacketAck) Msg(src provider.ChainProvider, srcPortId, srcChanId Signer: addr, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } diff --git a/relayer/chains/cosmos/tx.go b/relayer/chains/cosmos/tx.go index 8d9ae37d1..48eeb6a9d 100644 --- a/relayer/chains/cosmos/tx.go +++ b/relayer/chains/cosmos/tx.go @@ -6,6 +6,7 @@ import ( "fmt" "math" "math/big" + "math/rand" "regexp" "strconv" "strings" @@ -14,6 +15,7 @@ import ( "github.com/avast/retry-go/v4" abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/libs/bytes" "github.com/cometbft/cometbft/light" rpcclient "github.com/cometbft/cometbft/rpc/client" coretypes "github.com/cometbft/cometbft/rpc/core/types" @@ -78,6 +80,26 @@ func (cc *CosmosProvider) SendMessage(ctx context.Context, msg provider.RelayerM return cc.SendMessages(ctx, []provider.RelayerMessage{msg}, memo) } +var seqGuardSingleton sync.Mutex + +// Gets the sequence guard. If it doesn't exist, initialized and returns it. +func ensureSequenceGuard(cc *CosmosProvider, key string) *WalletState { + seqGuardSingleton.Lock() + defer seqGuardSingleton.Unlock() + + if cc.walletStateMap == nil { + cc.walletStateMap = map[string]*WalletState{} + } + + sequenceGuard, ok := cc.walletStateMap[key] + if !ok { + cc.walletStateMap[key] = &WalletState{} + return cc.walletStateMap[key] + } + + return sequenceGuard +} + // SendMessages attempts to sign, encode, & send a slice of RelayerMessages // This is used extensively in the relayer as an extension of the Provider interface // @@ -101,7 +123,7 @@ func (cc *CosmosProvider) SendMessages(ctx context.Context, msgs []provider.Rela wg.Add(1) if err := retry.Do(func() error { - return cc.SendMessagesToMempool(ctx, msgs, memo, ctx, callback) + return cc.SendMessagesToMempool(ctx, msgs, memo, ctx, []func(*provider.RelayerTxResponse, error){callback}) }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { cc.log.Info( "Error building or broadcasting transaction", @@ -137,37 +159,183 @@ func (cc *CosmosProvider) SendMessagesToMempool( memo string, asyncCtx context.Context, - asyncCallback func(*provider.RelayerTxResponse, error), + asyncCallbacks []func(*provider.RelayerTxResponse, error), ) error { - // Guard against account sequence number mismatch errors by locking for the specific wallet for - // the account sequence query all the way through the transaction broadcast success/fail. - cc.txMu.Lock() - defer cc.txMu.Unlock() + txSignerKey, feegranterKey, err := cc.buildSignerConfig(msgs) + if err != nil { + return err + } + + sequenceGuard := ensureSequenceGuard(cc, txSignerKey) + sequenceGuard.Mu.Lock() + defer sequenceGuard.Mu.Unlock() - txBytes, sequence, fees, err := cc.buildMessages(ctx, msgs, memo) + txBytes, sequence, fees, err := cc.buildMessages(ctx, msgs, memo, 0, txSignerKey, feegranterKey, sequenceGuard) if err != nil { // Account sequence mismatch errors can happen on the simulated transaction also. if strings.Contains(err.Error(), sdkerrors.ErrWrongSequence.Error()) { - cc.handleAccountSequenceMismatchError(err) + cc.handleAccountSequenceMismatchError(sequenceGuard, err) } return err } - if err := cc.broadcastTx(ctx, txBytes, msgs, fees, asyncCtx, defaultBroadcastWaitTimeout, asyncCallback); err != nil { + if err := cc.broadcastTx(ctx, txBytes, msgs, fees, asyncCtx, defaultBroadcastWaitTimeout, asyncCallbacks); err != nil { if strings.Contains(err.Error(), sdkerrors.ErrWrongSequence.Error()) { - cc.handleAccountSequenceMismatchError(err) + cc.handleAccountSequenceMismatchError(sequenceGuard, err) } return err } // we had a successful tx broadcast with this sequence, so update it to the next - cc.updateNextAccountSequence(sequence + 1) - + cc.updateNextAccountSequence(sequenceGuard, sequence+1) return nil } +func (cc *CosmosProvider) SubmitTxAwaitResponse(ctx context.Context, msgs []sdk.Msg, memo string, gas uint64, signingKeyName string) (*txtypes.GetTxResponse, error) { + resp, err := cc.SendMsgsWith(ctx, msgs, memo, gas, signingKeyName, "") + if err != nil { + return nil, err + } + fmt.Printf("TX result code: %d. Waiting for TX with hash %s\n", resp.Code, resp.Hash) + tx1resp, err := cc.AwaitTx(resp.Hash, 15*time.Second) + if err != nil { + return nil, err + } + + return tx1resp, err +} + +// Get the TX by hash, waiting for it to be included in a block +func (cc *CosmosProvider) AwaitTx(txHash bytes.HexBytes, timeout time.Duration) (*txtypes.GetTxResponse, error) { + var txByHash *txtypes.GetTxResponse + var txLookupErr error + startTime := time.Now() + timeBetweenQueries := 100 + + txClient := txtypes.NewServiceClient(cc) + + for txByHash == nil { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + if time.Since(startTime) > timeout { + cancel() + return nil, txLookupErr + } + + txByHash, txLookupErr = txClient.GetTx(ctx, &txtypes.GetTxRequest{Hash: txHash.String()}) + if txLookupErr != nil { + time.Sleep(time.Duration(timeBetweenQueries) * time.Millisecond) + } + cancel() + } + + return txByHash, nil +} + +// SendMsgs wraps the msgs in a StdTx, signs and sends it. An error is returned if there +// was an issue sending the transaction. A successfully sent, but failed transaction will +// not return an error. If a transaction is successfully sent, the result of the execution +// of that transaction will be logged. A boolean indicating if a transaction was successfully +// sent and executed successfully is returned. +// +// feegranterKey - key name of the address set as the feegranter, empty string will not feegrant +func (cc *CosmosProvider) SendMsgsWith(ctx context.Context, msgs []sdk.Msg, memo string, gas uint64, signingKey string, feegranterKey string) (*coretypes.ResultBroadcastTx, error) { + sdkConfigMutex.Lock() + sdkConf := sdk.GetConfig() + sdkConf.SetBech32PrefixForAccount(cc.PCfg.AccountPrefix, cc.PCfg.AccountPrefix+"pub") + sdkConf.SetBech32PrefixForValidator(cc.PCfg.AccountPrefix+"valoper", cc.PCfg.AccountPrefix+"valoperpub") + sdkConf.SetBech32PrefixForConsensusNode(cc.PCfg.AccountPrefix+"valcons", cc.PCfg.AccountPrefix+"valconspub") + defer sdkConfigMutex.Unlock() + + rand.Seed(time.Now().UnixNano()) + feegrantKeyAcc, _ := cc.GetKeyAddressForKey(feegranterKey) + + txf, err := cc.PrepareFactory(cc.TxFactory(), signingKey) + if err != nil { + return nil, err + } + + adjusted := gas + + if gas == 0 { + // TODO: Make this work with new CalculateGas method + // TODO: This is related to GRPC client stuff? + // https://github.com/cosmos/cosmos-sdk/blob/5725659684fc93790a63981c653feee33ecf3225/client/tx/tx.go#L297 + _, adjusted, err = cc.CalculateGas(ctx, txf, signingKey, msgs...) + + if err != nil { + return nil, err + } + + adjusted = uint64(float64(adjusted) * cc.PCfg.GasAdjustment) + } + + //Cannot feegrant your own TX + if signingKey != feegranterKey && feegranterKey != "" { + //Must be set in Factory to affect gas calculation (sim tx) as well as real tx + txf = txf.WithFeeGranter(feegrantKeyAcc) + } + + if memo != "" { + txf = txf.WithMemo(memo) + } + + // Set the gas amount on the transaction factory + txf = txf.WithGas(adjusted) + + // Build the transaction builder + txb, err := txf.BuildUnsignedTx(msgs...) + if err != nil { + return nil, err + } + + // Attach the signature to the transaction + // c.LogFailedTx(nil, err, msgs) + // Force encoding in the chain specific address + for _, msg := range msgs { + cc.Cdc.Marshaler.MustMarshalJSON(msg) + } + + err = func() error { + //done := cc.SetSDKContext() + // ensure that we allways call done, even in case of an error or panic + //defer done() + + if err = tx.Sign(txf, signingKey, txb, false); err != nil { + return err + } + return nil + }() + + if err != nil { + return nil, err + } + + // Generate the transaction bytes + txBytes, err := cc.Cdc.TxConfig.TxEncoder()(txb.GetTx()) + if err != nil { + return nil, err + } + + res, err := cc.RPCClient.BroadcastTxAsync(ctx, txBytes) + if res != nil { + fmt.Printf("TX hash: %s\n", res.Hash) + } + if err != nil { + return nil, err + } + + // transaction was executed, log the success or failure using the tx response code + // NOTE: error is nil, logic should use the returned error to determine if the + // transaction was successfully executed. + if res.Code != 0 { + return res, fmt.Errorf("transaction failed with code: %d", res.Code) + } + + return res, nil +} + // sdkError will return the Cosmos SDK registered error for a given codespace/code combo if registered, otherwise nil. func (cc *CosmosProvider) sdkError(codespace string, code uint32) error { // ABCIError will return an error other than "unknown" if syncRes.Code is a registered error in syncRes.Codespace @@ -190,7 +358,7 @@ func (cc *CosmosProvider) broadcastTx( asyncCtx context.Context, // context for async wait for block inclusion after successful tx broadcast asyncTimeout time.Duration, // timeout for waiting for block inclusion - asyncCallback func(*provider.RelayerTxResponse, error), // callback for success/fail of the wait for block inclusion + asyncCallbacks []func(*provider.RelayerTxResponse, error), // callback for success/fail of the wait for block inclusion ) error { res, err := cc.RPCClient.BroadcastTxSync(ctx, tx) isErr := err != nil @@ -228,7 +396,7 @@ func (cc *CosmosProvider) broadcastTx( // TODO: maybe we need to check if the node has tx indexing enabled? // if not, we need to find a new way to block until inclusion in a block - go cc.waitForTx(asyncCtx, res.Hash, msgs, asyncTimeout, asyncCallback) + go cc.waitForTx(asyncCtx, res.Hash, msgs, asyncTimeout, asyncCallbacks) return nil } @@ -240,13 +408,16 @@ func (cc *CosmosProvider) waitForTx( txHash []byte, msgs []provider.RelayerMessage, // used for logging only waitTimeout time.Duration, - callback func(*provider.RelayerTxResponse, error), + callbacks []func(*provider.RelayerTxResponse, error), ) { res, err := cc.waitForBlockInclusion(ctx, txHash, waitTimeout) if err != nil { cc.log.Error("Failed to wait for block inclusion", zap.Error(err)) - if callback != nil { - callback(nil, err) + if len(callbacks) > 0 { + for _, cb := range callbacks { + //Call each callback in order since waitForTx is already invoked asyncronously + cb(nil, err) + } } return } @@ -270,15 +441,21 @@ func (cc *CosmosProvider) waitForTx( if err == nil { err = fmt.Errorf("transaction failed to execute") } - if callback != nil { - callback(nil, err) + if len(callbacks) > 0 { + for _, cb := range callbacks { + //Call each callback in order since waitForTx is already invoked asyncronously + cb(nil, err) + } } cc.LogFailedTx(rlyResp, nil, msgs) return } - if callback != nil { - callback(rlyResp, nil) + if len(callbacks) > 0 { + for _, cb := range callbacks { + //Call each callback in order since waitForTx is already invoked asyncronously + cb(rlyResp, nil) + } } cc.LogSuccessTx(res, msgs) } @@ -345,9 +522,76 @@ func parseEventsFromTxResponse(resp *sdk.TxResponse) []provider.RelayerEvent { return events } -func (cc *CosmosProvider) buildMessages(ctx context.Context, msgs []provider.RelayerMessage, memo string) ([]byte, uint64, sdk.Coins, error) { - // Query account details - txf, err := cc.PrepareFactory(cc.TxFactory()) +func (cc *CosmosProvider) buildSignerConfig(msgs []provider.RelayerMessage) ( + txSignerKey string, + feegranterKey string, + err error, +) { + //Guard against race conditions when choosing a signer/feegranter + cc.feegrantMu.Lock() + defer cc.feegrantMu.Unlock() + + //Some messages have feegranting disabled. If any message in the TX disables feegrants, then the TX will not be feegranted. + isFeegrantEligible := cc.PCfg.FeeGrants != nil + + for _, curr := range msgs { + if cMsg, ok := curr.(CosmosMessage); ok { + if cMsg.FeegrantDisabled { + isFeegrantEligible = false + } + } + } + + //By default, we should sign TXs with the provider's default key + txSignerKey = cc.PCfg.Key + + if isFeegrantEligible { + txSignerKey, feegranterKey = cc.GetTxFeeGrant() + signerAcc, addrErr := cc.GetKeyAddressForKey(txSignerKey) + if addrErr != nil { + err = addrErr + return + } + + signerAccAddr, encodeErr := cc.EncodeBech32AccAddr(signerAcc) + if encodeErr != nil { + err = encodeErr + return + } + + //Overwrite the 'Signer' field in any Msgs that provide an 'optionalSetSigner' callback + for _, curr := range msgs { + if cMsg, ok := curr.(CosmosMessage); ok { + if cMsg.SetSigner != nil { + cMsg.SetSigner(signerAccAddr) + } + } + } + } + + return +} + +func (cc *CosmosProvider) buildMessages( + ctx context.Context, + msgs []provider.RelayerMessage, + memo string, + gas uint64, + txSignerKey string, + feegranterKey string, + sequenceGuard *WalletState, +) ( + txBytes []byte, + sequence uint64, + fees sdk.Coins, + err error, +) { + done := cc.SetSDKContext() + defer done() + + cMsgs := CosmosMsgs(msgs...) + + txf, err := cc.PrepareFactory(cc.TxFactory(), txSignerKey) if err != nil { return nil, 0, sdk.Coins{}, err } @@ -356,73 +600,66 @@ func (cc *CosmosProvider) buildMessages(ctx context.Context, msgs []provider.Rel txf = txf.WithMemo(memo) } - sequence := txf.Sequence() - cc.updateNextAccountSequence(sequence) - if sequence < cc.nextAccountSeq { - sequence = cc.nextAccountSeq + sequence = txf.Sequence() + cc.updateNextAccountSequence(sequenceGuard, sequence) + if sequence < sequenceGuard.NextAccountSequence { + sequence = sequenceGuard.NextAccountSequence txf = txf.WithSequence(sequence) } - // TODO: Make this work with new CalculateGas method - // TODO: This is related to GRPC client stuff? - // https://github.com/cosmos/cosmos-sdk/blob/5725659684fc93790a63981c653feee33ecf3225/client/tx/tx.go#L297 - // If users pass gas adjustment, then calculate gas - _, adjusted, err := cc.CalculateGas(ctx, txf, CosmosMsgs(msgs...)...) - if err != nil { - return nil, 0, sdk.Coins{}, err - } + adjusted := gas - // Set the gas amount on the transaction factory - txf = txf.WithGas(adjusted) + if gas == 0 { + _, adjusted, err = cc.CalculateGas(ctx, txf, txSignerKey, cMsgs...) - var txb client.TxBuilder - // Build the transaction builder & retry on failures - if err := retry.Do(func() error { - txb, err = txf.BuildUnsignedTx(CosmosMsgs(msgs...)...) if err != nil { - return err + return nil, 0, sdk.Coins{}, err } - return nil - }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr); err != nil { - return nil, 0, sdk.Coins{}, err } - done := cc.SetSDKContext() - - if err := retry.Do(func() error { - if err := tx.Sign(txf, cc.PCfg.Key, txb, false); err != nil { - return err + //Cannot feegrant your own TX + if txSignerKey != feegranterKey && feegranterKey != "" { + granterAddr, err := cc.GetKeyAddressForKey(feegranterKey) + if err != nil { + return nil, 0, sdk.Coins{}, err } - return nil - }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr); err != nil { + + txf = txf.WithFeeGranter(granterAddr) + } + + // Set the gas amount on the transaction factory + txf = txf.WithGas(adjusted) + + // Build the transaction builder + txb, err := txf.BuildUnsignedTx(cMsgs...) + if err != nil { return nil, 0, sdk.Coins{}, err } - done() + if err = tx.Sign(txf, txSignerKey, txb, false); err != nil { + return nil, 0, sdk.Coins{}, err + } tx := txb.GetTx() - fees := tx.GetFee() + fees = tx.GetFee() - var txBytes []byte // Generate the transaction bytes - if err := retry.Do(func() error { - var err error - txBytes, err = cc.Cdc.TxConfig.TxEncoder()(tx) - if err != nil { - return err - } - return nil - }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr); err != nil { + txBytes, err = cc.Cdc.TxConfig.TxEncoder()(tx) + if err != nil { return nil, 0, sdk.Coins{}, err } - return txBytes, sequence, fees, nil + return txBytes, txf.Sequence(), fees, nil } // handleAccountSequenceMismatchError will parse the error string, e.g.: // "account sequence mismatch, expected 10, got 9: incorrect account sequence" // and update the next account sequence with the expected value. -func (cc *CosmosProvider) handleAccountSequenceMismatchError(err error) { +func (cc *CosmosProvider) handleAccountSequenceMismatchError(sequenceGuard *WalletState, err error) { + if sequenceGuard == nil { + panic("sequence guard not configured") + } + sequences := numRegex.FindAllString(err.Error(), -1) if len(sequences) != 2 { return @@ -431,9 +668,24 @@ func (cc *CosmosProvider) handleAccountSequenceMismatchError(err error) { if err != nil { return } - cc.nextAccountSeq = nextSeq + sequenceGuard.NextAccountSequence = nextSeq } +// handleAccountSequenceMismatchError will parse the error string, e.g.: +// "account sequence mismatch, expected 10, got 9: incorrect account sequence" +// and update the next account sequence with the expected value. +// func (cc *CosmosProvider) handleAccountSequenceMismatchError(err error) { +// sequences := numRegex.FindAllString(err.Error(), -1) +// if len(sequences) != 2 { +// return +// } +// nextSeq, err := strconv.ParseUint(sequences[0], 10, 64) +// if err != nil { +// return +// } +// cc.nextAccountSeq = nextSeq +// } + // MsgCreateClient creates an sdk.Msg to update the client on src with consensus state from dst func (cc *CosmosProvider) MsgCreateClient( clientState ibcexported.ClientState, @@ -460,7 +712,9 @@ func (cc *CosmosProvider) MsgCreateClient( Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) MsgUpdateClient(srcClientID string, dstHeader ibcexported.ClientMessage) (provider.RelayerMessage, error) { @@ -478,7 +732,9 @@ func (cc *CosmosProvider) MsgUpdateClient(srcClientID string, dstHeader ibcexpor ClientMessage: clientMsg, Signer: acc, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) MsgUpgradeClient(srcClientId string, consRes *clienttypes.QueryConsensusStateResponse, clientRes *clienttypes.QueryClientStateResponse) (provider.RelayerMessage, error) { @@ -489,9 +745,14 @@ func (cc *CosmosProvider) MsgUpgradeClient(srcClientId string, consRes *clientty if acc, err = cc.Address(); err != nil { return nil, err } - return NewCosmosMessage(&clienttypes.MsgUpgradeClient{ClientId: srcClientId, ClientState: clientRes.ClientState, + + msgUpgradeClient := &clienttypes.MsgUpgradeClient{ClientId: srcClientId, ClientState: clientRes.ClientState, ConsensusState: consRes.ConsensusState, ProofUpgradeClient: consRes.GetProof(), - ProofUpgradeConsensusState: consRes.ConsensusState.Value, Signer: acc}), nil + ProofUpgradeConsensusState: consRes.ConsensusState.Value, Signer: acc} + + return NewCosmosMessage(msgUpgradeClient, func(signer string) { + msgUpgradeClient.Signer = signer + }), nil } // MsgTransfer creates a new transfer message @@ -518,7 +779,9 @@ func (cc *CosmosProvider) MsgTransfer( msg.TimeoutHeight = info.TimeoutHeight } - return NewCosmosMessage(msg), nil + msgTransfer := NewCosmosMessage(msg, nil).(CosmosMessage) + msgTransfer.FeegrantDisabled = true + return msgTransfer, nil } func (cc *CosmosProvider) ValidatePacket(msgTransfer provider.PacketInfo, latest provider.LatestBlock) error { @@ -584,7 +847,9 @@ func (cc *CosmosProvider) MsgRecvPacket( Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) PacketAcknowledgement( @@ -622,7 +887,9 @@ func (cc *CosmosProvider) MsgAcknowledgement( Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) PacketReceipt( @@ -675,7 +942,9 @@ func (cc *CosmosProvider) MsgTimeout(msgTransfer provider.PacketInfo, proof prov Signer: signer, } - return NewCosmosMessage(assembled), nil + return NewCosmosMessage(assembled, func(signer string) { + assembled.Signer = signer + }), nil } func (cc *CosmosProvider) MsgTimeoutOnClose(msgTransfer provider.PacketInfo, proof provider.PacketProof) (provider.RelayerMessage, error) { @@ -691,7 +960,9 @@ func (cc *CosmosProvider) MsgTimeoutOnClose(msgTransfer provider.PacketInfo, pro Signer: signer, } - return NewCosmosMessage(assembled), nil + return NewCosmosMessage(assembled, func(signer string) { + assembled.Signer = signer + }), nil } func (cc *CosmosProvider) MsgConnectionOpenInit(info provider.ConnectionInfo, proof provider.ConnectionProof) (provider.RelayerMessage, error) { @@ -711,7 +982,9 @@ func (cc *CosmosProvider) MsgConnectionOpenInit(info provider.ConnectionInfo, pr Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) ConnectionHandshakeProof( @@ -773,7 +1046,9 @@ func (cc *CosmosProvider) MsgConnectionOpenTry(msgOpenInit provider.ConnectionIn Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) MsgConnectionOpenAck(msgOpenTry provider.ConnectionInfo, proof provider.ConnectionProof) (provider.RelayerMessage, error) { @@ -803,7 +1078,9 @@ func (cc *CosmosProvider) MsgConnectionOpenAck(msgOpenTry provider.ConnectionInf Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) ConnectionProof( @@ -834,7 +1111,9 @@ func (cc *CosmosProvider) MsgConnectionOpenConfirm(msgOpenAck provider.Connectio Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) MsgChannelOpenInit(info provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -857,7 +1136,9 @@ func (cc *CosmosProvider) MsgChannelOpenInit(info provider.ChannelInfo, proof pr Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) ChannelProof( @@ -904,7 +1185,9 @@ func (cc *CosmosProvider) MsgChannelOpenTry(msgOpenInit provider.ChannelInfo, pr Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) MsgChannelOpenAck(msgOpenTry provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -922,7 +1205,9 @@ func (cc *CosmosProvider) MsgChannelOpenAck(msgOpenTry provider.ChannelInfo, pro Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) MsgChannelOpenConfirm(msgOpenAck provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -938,7 +1223,9 @@ func (cc *CosmosProvider) MsgChannelOpenConfirm(msgOpenAck provider.ChannelInfo, Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) MsgChannelCloseInit(info provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -952,7 +1239,9 @@ func (cc *CosmosProvider) MsgChannelCloseInit(info provider.ChannelInfo, proof p Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) MsgChannelCloseConfirm(msgCloseInit provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -968,7 +1257,9 @@ func (cc *CosmosProvider) MsgChannelCloseConfirm(msgCloseInit provider.ChannelIn Signer: signer, } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *CosmosProvider) MsgUpdateClientHeader(latestHeader provider.IBCHeader, trustedHeight clienttypes.Height, trustedHeader provider.IBCHeader) (ibcexported.ClientMessage, error) { @@ -1036,7 +1327,9 @@ func (cc *CosmosProvider) MsgSubmitQueryResponse(chainID string, queryID provide FromAddress: signer, } - return NewCosmosMessage(msg), nil + submitQueryRespMsg := NewCosmosMessage(msg, nil).(CosmosMessage) + submitQueryRespMsg.FeegrantDisabled = true + return submitQueryRespMsg, nil } func (cc *CosmosProvider) MsgSubmitMisbehaviour(clientID string, misbehaviour ibcexported.ClientMessage) (provider.RelayerMessage, error) { @@ -1050,7 +1343,9 @@ func (cc *CosmosProvider) MsgSubmitMisbehaviour(clientID string, misbehaviour ib return nil, err } - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } // RelayPacketFromSequence relays a packet with a given seq on src and returns recvPacket msgs, timeoutPacketmsgs and error @@ -1308,11 +1603,11 @@ func (cc *CosmosProvider) UpdateFeesSpent(chain, key, address string, fees sdk.C // MsgRegisterCounterpartyPayee creates an sdk.Msg to broadcast the counterparty address func (cc *CosmosProvider) MsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee string) (provider.RelayerMessage, error) { msg := feetypes.NewMsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee) - return NewCosmosMessage(msg), nil + return NewCosmosMessage(msg, nil), nil } // PrepareFactory mutates the tx factory with the appropriate account number, sequence number, and min gas settings. -func (cc *CosmosProvider) PrepareFactory(txf tx.Factory) (tx.Factory, error) { +func (cc *CosmosProvider) PrepareFactory(txf tx.Factory, signingKey string) (tx.Factory, error) { var ( err error from sdk.AccAddress @@ -1321,7 +1616,7 @@ func (cc *CosmosProvider) PrepareFactory(txf tx.Factory) (tx.Factory, error) { // Get key address and retry if fail if err = retry.Do(func() error { - from, err = cc.GetKeyAddress() + from, err = cc.GetKeyAddressForKey(signingKey) if err != nil { return err } @@ -1333,7 +1628,8 @@ func (cc *CosmosProvider) PrepareFactory(txf tx.Factory) (tx.Factory, error) { cliCtx := client.Context{}.WithClient(cc.RPCClient). WithInterfaceRegistry(cc.Cdc.InterfaceRegistry). WithChainID(cc.PCfg.ChainID). - WithCodec(cc.Cdc.Marshaler) + WithCodec(cc.Cdc.Marshaler). + WithFromAddress(from) // Set the account number and sequence on the transaction factory and retry if fail if err = retry.Do(func() error { @@ -1427,8 +1723,8 @@ func (cc *CosmosProvider) SetWithExtensionOptions(txf tx.Factory) (tx.Factory, e } // CalculateGas simulates a tx to generate the appropriate gas settings before broadcasting a tx. -func (cc *CosmosProvider) CalculateGas(ctx context.Context, txf tx.Factory, msgs ...sdk.Msg) (txtypes.SimulateResponse, uint64, error) { - keyInfo, err := cc.Keybase.Key(cc.PCfg.Key) +func (cc *CosmosProvider) CalculateGas(ctx context.Context, txf tx.Factory, signingKey string, msgs ...sdk.Msg) (txtypes.SimulateResponse, uint64, error) { + keyInfo, err := cc.Keybase.Key(signingKey) if err != nil { return txtypes.SimulateResponse{}, 0, err } diff --git a/relayer/chains/cosmos/tx_test.go b/relayer/chains/cosmos/tx_test.go index a582adc54..25bb02dd2 100644 --- a/relayer/chains/cosmos/tx_test.go +++ b/relayer/chains/cosmos/tx_test.go @@ -15,6 +15,18 @@ import ( "github.com/stretchr/testify/require" ) +type mockAccountSequenceMismatchError struct { + Expected uint64 + Actual uint64 +} + +// func TestHandleAccountSequenceMismatchError(t *testing.T) { +// p := &CosmosProvider{} +// ws := &WalletState{} +// p.handleAccountSequenceMismatchError(ws, mockAccountSequenceMismatchError{Actual: 9, Expected: 10}) +// require.Equal(t, ws.NextAccountSequence, uint64(10)) +// } + func TestCosmosProvider_AdjustEstimatedGas(t *testing.T) { testCases := []struct { name string @@ -75,21 +87,10 @@ func TestCosmosProvider_AdjustEstimatedGas(t *testing.T) { } } -type mockAccountSequenceMismatchError struct { - Expected uint64 - Actual uint64 -} - func (err mockAccountSequenceMismatchError) Error() string { return fmt.Sprintf("account sequence mismatch, expected %d, got %d: incorrect account sequence", err.Expected, err.Actual) } -func TestHandleAccountSequenceMismatchError(t *testing.T) { - p := &CosmosProvider{} - p.handleAccountSequenceMismatchError(mockAccountSequenceMismatchError{Actual: 9, Expected: 10}) - require.Equal(t, p.nextAccountSeq, uint64(10)) -} - type mockTxConfig struct { legacytx.StdTxConfig txBuilder *mockTxBuilder diff --git a/relayer/chains/penumbra/tx.go b/relayer/chains/penumbra/tx.go index 4ef4c8d30..dd90ac098 100644 --- a/relayer/chains/penumbra/tx.go +++ b/relayer/chains/penumbra/tx.go @@ -499,7 +499,9 @@ func (cc *PenumbraProvider) MsgUpdateClient(srcClientId string, dstHeader ibcexp Signer: acc, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) ConnectionOpenInit(srcClientId, dstClientId string, dstPrefix commitmenttypes.MerklePrefix, dstHeader ibcexported.ClientMessage) ([]provider.RelayerMessage, error) { @@ -532,7 +534,9 @@ func (cc *PenumbraProvider) ConnectionOpenInit(srcClientId, dstClientId string, Signer: acc, } - return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg)}, nil + return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + })}, nil } func (cc *PenumbraProvider) ConnectionOpenTry(ctx context.Context, dstQueryProvider provider.QueryProvider, dstHeader ibcexported.ClientMessage, dstPrefix commitmenttypes.MerklePrefix, srcClientId, dstClientId, srcConnId, dstConnId string) ([]provider.RelayerMessage, error) { @@ -597,7 +601,9 @@ func (cc *PenumbraProvider) ConnectionOpenTry(ctx context.Context, dstQueryProvi Signer: acc, } - return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg)}, nil + return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + })}, nil } func (cc *PenumbraProvider) ConnectionOpenAck(ctx context.Context, dstQueryProvider provider.QueryProvider, dstHeader ibcexported.ClientMessage, srcClientId, srcConnId, dstClientId, dstConnId string) ([]provider.RelayerMessage, error) { @@ -647,7 +653,9 @@ func (cc *PenumbraProvider) ConnectionOpenAck(ctx context.Context, dstQueryProvi Signer: acc, } - return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg)}, nil + return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + })}, nil } func (cc *PenumbraProvider) ConnectionOpenConfirm(ctx context.Context, dstQueryProvider provider.QueryProvider, dstHeader ibcexported.ClientMessage, dstConnId, srcClientId, srcConnId string) ([]provider.RelayerMessage, error) { @@ -680,7 +688,9 @@ func (cc *PenumbraProvider) ConnectionOpenConfirm(ctx context.Context, dstQueryP Signer: acc, } - return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg)}, nil + return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + })}, nil } func (cc *PenumbraProvider) ChannelOpenInit(srcClientId, srcConnId, srcPortId, srcVersion, dstPortId string, order chantypes.Order, dstHeader ibcexported.ClientMessage) ([]provider.RelayerMessage, error) { @@ -712,7 +722,9 @@ func (cc *PenumbraProvider) ChannelOpenInit(srcClientId, srcConnId, srcPortId, s Signer: acc, } - return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg)}, nil + return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + })}, nil } func (cc *PenumbraProvider) ChannelOpenTry(ctx context.Context, dstQueryProvider provider.QueryProvider, dstHeader ibcexported.ClientMessage, srcPortId, dstPortId, srcChanId, dstChanId, srcVersion, srcConnectionId, srcClientId string) ([]provider.RelayerMessage, error) { @@ -765,7 +777,9 @@ func (cc *PenumbraProvider) ChannelOpenTry(ctx context.Context, dstQueryProvider Signer: acc, } - return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg)}, nil + return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + })}, nil } func (cc *PenumbraProvider) ChannelOpenAck(ctx context.Context, dstQueryProvider provider.QueryProvider, dstHeader ibcexported.ClientMessage, srcClientId, srcPortId, srcChanId, dstChanId, dstPortId string) ([]provider.RelayerMessage, error) { @@ -802,7 +816,9 @@ func (cc *PenumbraProvider) ChannelOpenAck(ctx context.Context, dstQueryProvider Signer: acc, } - return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg)}, nil + return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + })}, nil } func (cc *PenumbraProvider) ChannelOpenConfirm(ctx context.Context, dstQueryProvider provider.QueryProvider, dstHeader ibcexported.ClientMessage, srcClientId, srcPortId, srcChanId, dstPortId, dstChanId string) ([]provider.RelayerMessage, error) { @@ -836,7 +852,9 @@ func (cc *PenumbraProvider) ChannelOpenConfirm(ctx context.Context, dstQueryProv Signer: acc, } - return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg)}, nil + return []provider.RelayerMessage{updateMsg, cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + })}, nil } func (cc *PenumbraProvider) ChannelCloseInit(srcPortId, srcChanId string) (provider.RelayerMessage, error) { @@ -854,7 +872,9 @@ func (cc *PenumbraProvider) ChannelCloseInit(srcPortId, srcChanId string) (provi Signer: acc, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) ChannelCloseConfirm(ctx context.Context, dstQueryProvider provider.QueryProvider, dsth int64, dstChanId, dstPortId, srcPortId, srcChanId string) (provider.RelayerMessage, error) { @@ -879,7 +899,9 @@ func (cc *PenumbraProvider) ChannelCloseConfirm(ctx context.Context, dstQueryPro Signer: acc, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgUpgradeClient(srcClientId string, consRes *clienttypes.QueryConsensusStateResponse, clientRes *clienttypes.QueryClientStateResponse) (provider.RelayerMessage, error) { @@ -890,9 +912,14 @@ func (cc *PenumbraProvider) MsgUpgradeClient(srcClientId string, consRes *client if acc, err = cc.Address(); err != nil { return nil, err } - return cosmos.NewCosmosMessage(&clienttypes.MsgUpgradeClient{ClientId: srcClientId, ClientState: clientRes.ClientState, + + msgUpgradeClient := &clienttypes.MsgUpgradeClient{ClientId: srcClientId, ClientState: clientRes.ClientState, ConsensusState: consRes.ConsensusState, ProofUpgradeClient: consRes.GetProof(), - ProofUpgradeConsensusState: consRes.ConsensusState.Value, Signer: acc}), nil + ProofUpgradeConsensusState: consRes.ConsensusState.Value, Signer: acc} + + return cosmos.NewCosmosMessage(msgUpgradeClient, func(signer string) { + msgUpgradeClient.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgSubmitMisbehaviour(clientID string, misbehaviour ibcexported.ClientMessage) (provider.RelayerMessage, error) { @@ -960,7 +987,9 @@ func (cc *PenumbraProvider) MsgRelayAcknowledgement(ctx context.Context, dst pro Signer: acc, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } } @@ -988,7 +1017,9 @@ func (cc *PenumbraProvider) MsgTransfer( msg.TimeoutHeight = info.TimeoutHeight } - return cosmos.NewCosmosMessage(msg), nil + msgTransfer := cosmos.NewCosmosMessage(msg, nil).(cosmos.CosmosMessage) + msgTransfer.FeegrantDisabled = true + return msgTransfer, nil } // MsgRelayTimeout constructs the MsgTimeout which is to be sent to the sending chain. @@ -1067,7 +1098,9 @@ func (cc *PenumbraProvider) orderedChannelTimeoutMsg( Signer: acc, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) unorderedChannelTimeoutMsg( @@ -1106,7 +1139,9 @@ func (cc *PenumbraProvider) unorderedChannelTimeoutMsg( NextSequenceRecv: packet.Seq(), Signer: acc, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } // MsgRelayRecvPacket constructs the MsgRecvPacket which is to be sent to the receiving chain. @@ -1145,7 +1180,9 @@ func (cc *PenumbraProvider) MsgRelayRecvPacket(ctx context.Context, dst provider Signer: acc, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } } @@ -1200,7 +1237,9 @@ func (cc *PenumbraProvider) MsgRecvPacket(msgTransfer provider.PacketInfo, proof Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) PacketAcknowledgement(ctx context.Context, msgRecvPacket provider.PacketInfo, height uint64) (provider.PacketProof, error) { @@ -1228,7 +1267,9 @@ func (cc *PenumbraProvider) MsgAcknowledgement(msgRecvPacket provider.PacketInfo Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) PacketReceipt(ctx context.Context, msgTransfer provider.PacketInfo, height uint64) (provider.PacketProof, error) { @@ -1257,7 +1298,9 @@ func (cc *PenumbraProvider) MsgTimeout(msgTransfer provider.PacketInfo, proof pr Signer: signer, } - return cosmos.NewCosmosMessage(assembled), nil + return cosmos.NewCosmosMessage(assembled, func(signer string) { + assembled.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgTimeoutOnClose(msgTransfer provider.PacketInfo, proof provider.PacketProof) (provider.RelayerMessage, error) { @@ -1273,7 +1316,9 @@ func (cc *PenumbraProvider) MsgTimeoutOnClose(msgTransfer provider.PacketInfo, p Signer: signer, } - return cosmos.NewCosmosMessage(assembled), nil + return cosmos.NewCosmosMessage(assembled, func(signer string) { + assembled.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgConnectionOpenInit(info provider.ConnectionInfo, proof provider.ConnectionProof) (provider.RelayerMessage, error) { @@ -1293,7 +1338,9 @@ func (cc *PenumbraProvider) MsgConnectionOpenInit(info provider.ConnectionInfo, Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) ConnectionHandshakeProof(ctx context.Context, msgOpenInit provider.ConnectionInfo, height uint64) (provider.ConnectionProof, error) { @@ -1351,7 +1398,9 @@ func (cc *PenumbraProvider) MsgConnectionOpenTry(msgOpenInit provider.Connection Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgConnectionOpenAck(msgOpenTry provider.ConnectionInfo, proof provider.ConnectionProof) (provider.RelayerMessage, error) { @@ -1381,7 +1430,9 @@ func (cc *PenumbraProvider) MsgConnectionOpenAck(msgOpenTry provider.ConnectionI Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } // NextSeqRecv queries for the appropriate Tendermint proof required to prove the next expected packet sequence number @@ -1428,7 +1479,9 @@ func (cc *PenumbraProvider) MsgConnectionOpenConfirm(msgOpenAck provider.Connect Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgChannelOpenInit(info provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -1451,7 +1504,9 @@ func (cc *PenumbraProvider) MsgChannelOpenInit(info provider.ChannelInfo, proof Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) ChannelProof(ctx context.Context, msg provider.ChannelInfo, height uint64) (provider.ChannelProof, error) { @@ -1494,7 +1549,9 @@ func (cc *PenumbraProvider) MsgChannelOpenTry(msgOpenInit provider.ChannelInfo, Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgChannelOpenAck(msgOpenTry provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -1512,7 +1569,9 @@ func (cc *PenumbraProvider) MsgChannelOpenAck(msgOpenTry provider.ChannelInfo, p Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgChannelOpenConfirm(msgOpenAck provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -1528,7 +1587,9 @@ func (cc *PenumbraProvider) MsgChannelOpenConfirm(msgOpenAck provider.ChannelInf Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgChannelCloseInit(info provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -1542,7 +1603,9 @@ func (cc *PenumbraProvider) MsgChannelCloseInit(info provider.ChannelInfo, proof Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgChannelCloseConfirm(msgCloseInit provider.ChannelInfo, proof provider.ChannelProof) (provider.RelayerMessage, error) { @@ -1558,7 +1621,9 @@ func (cc *PenumbraProvider) MsgChannelCloseConfirm(msgCloseInit provider.Channel Signer: signer, } - return cosmos.NewCosmosMessage(msg), nil + return cosmos.NewCosmosMessage(msg, func(signer string) { + msg.Signer = signer + }), nil } func (cc *PenumbraProvider) MsgUpdateClientHeader(latestHeader provider.IBCHeader, trustedHeight clienttypes.Height, trustedHeader provider.IBCHeader) (ibcexported.ClientMessage, error) { @@ -2231,7 +2296,7 @@ func (cc *PenumbraProvider) MsgSubmitQueryResponse(chainID string, queryID provi panic("implement me") } -func (cc *PenumbraProvider) SendMessagesToMempool(ctx context.Context, msgs []provider.RelayerMessage, memo string, asyncCtx context.Context, asyncCallback func(*provider.RelayerTxResponse, error)) error { +func (cc *PenumbraProvider) SendMessagesToMempool(ctx context.Context, msgs []provider.RelayerMessage, memo string, asyncCtx context.Context, asyncCallback []func(*provider.RelayerTxResponse, error)) error { sendRsp, err := cc.sendMessagesInner(ctx, msgs, memo) cc.log.Debug("Received response from sending messages", zap.Any("response", sendRsp), zap.Error(err)) return err diff --git a/relayer/processor/message_processor.go b/relayer/processor/message_processor.go index 042629eb3..9b9ed250e 100644 --- a/relayer/processor/message_processor.go +++ b/relayer/processor/message_processor.go @@ -381,6 +381,15 @@ func (mp *messageProcessor) sendClientUpdate( dst.log.Debug("Client update broadcast completed") } +type PathProcessorMessageResp struct { + Response *provider.RelayerTxResponse + DestinationChain provider.ChainProvider + SuccessfulTx bool + Error error +} + +var PathProcMessageCollector chan *PathProcessorMessageResp + // sendBatchMessages will send a batch of messages, // then increment metrics counters for successful packet messages. func (mp *messageProcessor) sendBatchMessages( @@ -414,7 +423,7 @@ func (mp *messageProcessor) sendBatchMessages( dst.log.Debug("Will relay messages", fields...) - callback := func(rtr *provider.RelayerTxResponse, err error) { + callback := func(_ *provider.RelayerTxResponse, err error) { // only increment metrics counts for successful packets if err != nil || mp.metrics == nil { return @@ -435,8 +444,23 @@ func (mp *messageProcessor) sendBatchMessages( mp.metrics.IncPacketsRelayed(dst.info.PathName, dst.info.ChainID, channel, port, t.msg.eventType) } } + callbacks := []func(rtr *provider.RelayerTxResponse, err error){callback} + + //During testing, this adds a callback so our test case can inspect the TX results + if PathProcMessageCollector != nil { + testCallback := func(rtr *provider.RelayerTxResponse, err error) { + msgResult := &PathProcessorMessageResp{ + DestinationChain: dst.chainProvider, + Response: rtr, + SuccessfulTx: err == nil, + Error: err, + } + PathProcMessageCollector <- msgResult + } + callbacks = append(callbacks, testCallback) + } - if err := dst.chainProvider.SendMessagesToMempool(broadcastCtx, msgs, mp.memo, ctx, callback); err != nil { + if err := dst.chainProvider.SendMessagesToMempool(broadcastCtx, msgs, mp.memo, ctx, callbacks); err != nil { errFields := []zapcore.Field{ zap.String("path_name", src.info.PathName), zap.String("src_chain_id", src.info.ChainID), @@ -488,9 +512,9 @@ func (mp *messageProcessor) sendSingleMessage( dst.log.Debug(fmt.Sprintf("Will broadcast %s message", msgType), zap.Object("msg", tracker)) // Set callback for packet messages so that we increment prometheus metrics on successful relays. - var callback func(rtr *provider.RelayerTxResponse, err error) + callbacks := []func(rtr *provider.RelayerTxResponse, err error){} if t, ok := tracker.(packetMessageToTrack); ok { - callback = func(rtr *provider.RelayerTxResponse, err error) { + callback := func(_ *provider.RelayerTxResponse, err error) { // only increment metrics counts for successful packets if err != nil || mp.metrics == nil { return @@ -505,9 +529,25 @@ func (mp *messageProcessor) sendSingleMessage( } mp.metrics.IncPacketsRelayed(dst.info.PathName, dst.info.ChainID, channel, port, t.msg.eventType) } + + callbacks = append(callbacks, callback) + } + + //During testing, this adds a callback so our test case can inspect the TX results + if PathProcMessageCollector != nil { + testCallback := func(rtr *provider.RelayerTxResponse, err error) { + msgResult := &PathProcessorMessageResp{ + DestinationChain: dst.chainProvider, + Response: rtr, + SuccessfulTx: err == nil, + Error: err, + } + PathProcMessageCollector <- msgResult + } + callbacks = append(callbacks, testCallback) } - err := dst.chainProvider.SendMessagesToMempool(broadcastCtx, msgs, mp.memo, ctx, callback) + err := dst.chainProvider.SendMessagesToMempool(broadcastCtx, msgs, mp.memo, ctx, callbacks) if err != nil { errFields := []zapcore.Field{ zap.String("path_name", src.info.PathName), diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index a740dd845..a1c150e0a 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -391,7 +391,7 @@ type ChainProvider interface { memo string, asyncCtx context.Context, - asyncCallback func(*RelayerTxResponse, error), + asyncCallbacks []func(*RelayerTxResponse, error), ) error MsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayeeAddr string) (RelayerMessage, error) diff --git a/relayer/strategies.go b/relayer/strategies.go index 047478938..fd2856aad 100644 --- a/relayer/strategies.go +++ b/relayer/strategies.go @@ -8,6 +8,8 @@ import ( "sync" "time" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/avast/retry-go/v4" "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" "github.com/cosmos/relayer/v2/relayer/chains/cosmos" @@ -46,6 +48,8 @@ func StartRelayer( initialBlockHistory uint64, metrics *processor.PrometheusMetrics, ) chan error { + //prevent incorrect bech32 address prefixed addresses when calling AccAddress.String() + sdk.SetAddrCacheEnabled(false) errorChan := make(chan error, 1) switch processorType {