Skip to content

Commit 5d349c2

Browse files
feat(client/v2): get keyring from context (backport #19646) (#20727)
Co-authored-by: Julien Robert <julien@rbrt.fr>
1 parent 5db395b commit 5d349c2

30 files changed

+272
-173
lines changed

.github/workflows/test.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,14 +434,6 @@ jobs:
434434
run: |
435435
cd simapp
436436
go test -mod=readonly -timeout 30m -tags='app_v1 norace ledger test_ledger_mock rocksdb_build' ./...
437-
- name: sonarcloud
438-
if: ${{ env.GIT_DIFF && !github.event.pull_request.draft && env.SONAR_TOKEN != null }}
439-
uses: SonarSource/sonarcloud-github-action@master
440-
env:
441-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
442-
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
443-
with:
444-
projectBaseDir: simapp/
445437
446438
test-collections:
447439
runs-on: ubuntu-latest

client/v2/CHANGELOG.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,21 @@ Ref: https://keepachangelog.com/en/1.0.0/
3636

3737
## [Unreleased]
3838

39-
## [v2.0.0-beta.2] - 2024-XX-XX
39+
## [v2.0.0-beta.2] - 2024-06-19
40+
41+
### Features
42+
43+
* [#19039](https://github.com/cosmos/cosmos-sdk/pull/19039) Add support for pubkey in autocli.
4044

4145
### Improvements
4246

47+
* [#19646](https://github.com/cosmos/cosmos-sdk/pull/19646) Use keyring from command context.
4348
* (deps) [#19810](https://github.com/cosmos/cosmos-sdk/pull/19810) Upgrade SDK version due to prometheus breaking change.
4449
* (deps) [#19810](https://github.com/cosmos/cosmos-sdk/pull/19810) Bump `cosmossdk.io/store` to v1.1.0.
4550
* [#20083](https://github.com/cosmos/cosmos-sdk/pull/20083) Integrate latest version of cosmos-proto and improve version filtering.
4651
* [#19618](https://github.com/cosmos/cosmos-sdk/pull/19618) Marshal enum as string in queries.
4752
* [#19060](https://github.com/cosmos/cosmos-sdk/pull/19060) Use client context from root (or enhanced) command in autocli commands.
48-
* Note, the given command must have a `client.Context` in its context.
53+
* Note, the given command must have a `client.Context` in its context.
4954
* [#19216](https://github.com/cosmos/cosmos-sdk/pull/19216) Do not overwrite TxConfig, use directly the one provided in context. TxConfig should always be set in the `client.Context` in `root.go` of an app.
5055
* [#20266](https://github.com/cosmos/cosmos-sdk/pull/20266) Add ability to override the short description in AutoCLI-generated top-level commands.
5156

@@ -56,6 +61,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
5661
* [#19060](https://github.com/cosmos/cosmos-sdk/pull/19060) Simplify key flag parsing logic in flag handler.
5762
* [#20033](https://github.com/cosmos/cosmos-sdk/pull/20033) Respect output format from client ctx.
5863

64+
### API Breaking Changes
65+
66+
* [#19646](https://github.com/cosmos/cosmos-sdk/pull/19646) Remove keyring from `autocli.AppOptions` and `flag.Builder` options.
67+
5968
## [v2.0.0-beta.1] - 2023-11-07
6069

6170
This is the first tagged version of client/v2.

client/v2/README.md

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ if err := rootCmd.Execute(); err != nil {
7575

7676
### Keyring
7777

78-
`autocli` uses a keyring for key name resolving and signing transactions. Providing a keyring is optional, but if you want to use the `autocli` generated commands to sign transactions, you must provide a keyring.
78+
`autocli` uses a keyring for key name resolving names and signing transactions.
7979

8080
:::tip
81-
This provides a better UX as it allows to resolve key names directly from the keyring in all transactions and commands.
81+
AutoCLI provides a better UX than normal CLI as it allows to resolve key names directly from the keyring in all transactions and commands.
8282

8383
```sh
8484
<appd> q bank balances alice
@@ -87,8 +87,9 @@ This provides a better UX as it allows to resolve key names directly from the ke
8787

8888
:::
8989

90-
The keyring to be provided to `client/v2` must match the `client/v2` keyring interface.
91-
The keyring should be provided in the `appOptions` struct as follows, and can be gotten from the client context:
90+
The keyring used for resolving names and signing transactions is provided via the `client.Context`.
91+
The keyring is then converted to the `client/v2/autocli/keyring` interface.
92+
If no keyring is provided, the `autocli` generated command will not be able to sign transactions, but will still be able to query the chain.
9293

9394
:::tip
9495
The Cosmos SDK keyring and Hubl keyring both implement the `client/v2/autocli/keyring` interface, thanks to the following wrapper:
@@ -99,18 +100,6 @@ keyring.NewAutoCLIKeyring(kb)
99100

100101
:::
101102

102-
:::warning
103-
When using AutoCLI the keyring will only be created once and before any command flag parsing.
104-
:::
105-
106-
```go
107-
// Set the keyring in the appOptions
108-
appOptions.Keyring = keyring
109-
110-
err := autoCliOpts.EnhanceRootCommand(rootCmd)
111-
...
112-
```
113-
114103
## Signing
115104

116105
`autocli` supports signing transactions with the keyring.

client/v2/autocli/app.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77

88
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
99
"cosmossdk.io/client/v2/autocli/flag"
10-
"cosmossdk.io/client/v2/autocli/keyring"
1110
"cosmossdk.io/core/address"
1211
"cosmossdk.io/core/appmodule"
1312
"cosmossdk.io/depinject"
@@ -42,9 +41,6 @@ type AppOptions struct {
4241
ValidatorAddressCodec runtime.ValidatorAddressCodec
4342
ConsensusAddressCodec runtime.ConsensusAddressCodec
4443

45-
// Keyring is the keyring to use for client/v2.
46-
Keyring keyring.Keyring `optional:"true"`
47-
4844
// ClientCtx contains the necessary information needed to execute the commands.
4945
ClientCtx client.Context
5046
}
@@ -72,7 +68,6 @@ func (appOptions AppOptions) EnhanceRootCommand(rootCmd *cobra.Command) error {
7268
AddressCodec: appOptions.AddressCodec,
7369
ValidatorAddressCodec: appOptions.ValidatorAddressCodec,
7470
ConsensusAddressCodec: appOptions.ConsensusAddressCodec,
75-
Keyring: appOptions.Keyring,
7671
},
7772
GetClientConn: func(cmd *cobra.Command) (grpc.ClientConnInterface, error) {
7873
return client.GetClientQueryContext(cmd)

client/v2/autocli/common.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package autocli
22

33
import (
44
"fmt"
5+
"strings"
56

67
"github.com/spf13/cobra"
78
"google.golang.org/protobuf/reflect/protoreflect"
@@ -52,38 +53,35 @@ func (b *Builder) buildMethodCommandCommon(descriptor protoreflect.MethodDescrip
5253
Version: options.Version,
5354
}
5455

55-
binder, err := b.AddMessageFlags(cmd.Context(), cmd.Flags(), inputType, options)
56+
// we need to use a pointer to the context as the correct context is set in the RunE function
57+
// however we need to set the flags before the RunE function is called
58+
ctx := cmd.Context()
59+
binder, err := b.AddMessageFlags(&ctx, cmd.Flags(), inputType, options)
5660
if err != nil {
5761
return nil, err
5862
}
59-
6063
cmd.Args = binder.CobraArgs
6164

6265
cmd.RunE = func(cmd *cobra.Command, args []string) error {
66+
ctx = cmd.Context()
67+
6368
input, err := binder.BuildMessage(args)
6469
if err != nil {
6570
return err
6671
}
6772

6873
// signer related logic, triggers only when there is a signer defined
6974
if binder.SignerInfo.FieldName != "" {
70-
// mark the signer flag as required if defined
71-
// TODO(@julienrbrt): UX improvement by only marking the flag as required when there is more than one key in the keyring;
72-
// when there is only one key, use that key by default.
7375
if binder.SignerInfo.IsFlag {
74-
if err := cmd.MarkFlagRequired(binder.SignerInfo.FieldName); err != nil {
75-
return err
76-
}
77-
7876
// the client context uses the from flag to determine the signer.
7977
// this sets the signer flags to the from flag value if a custom signer flag is set.
80-
if binder.SignerInfo.FieldName != flags.FlagFrom {
81-
signer, err := cmd.Flags().GetString(binder.SignerInfo.FieldName)
82-
if err != nil {
83-
return fmt.Errorf("failed to get signer flag: %w", err)
78+
// marks the custom flag as required.
79+
if binder.SignerInfo.FlagName != flags.FlagFrom {
80+
if err := cmd.MarkFlagRequired(binder.SignerInfo.FlagName); err != nil {
81+
return err
8482
}
8583

86-
if err := cmd.Flags().Set(flags.FlagFrom, signer); err != nil {
84+
if err := cmd.Flags().Set(flags.FlagFrom, cmd.Flag(binder.SignerInfo.FlagName).Value.String()); err != nil {
8785
return err
8886
}
8987
}
@@ -251,6 +249,6 @@ func (b *Builder) outOrStdoutFormat(cmd *cobra.Command, out []byte) error {
251249
}
252250
}
253251

254-
_, err = fmt.Fprintln(cmd.OutOrStdout(), string(out))
255-
return err
252+
cmd.Println(strings.TrimSpace(string(out)))
253+
return nil
256254
}

client/v2/autocli/common_test.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ func initFixture(t *testing.T) *fixture {
5555
kr, err := sdkkeyring.New(sdk.KeyringServiceName(), sdkkeyring.BackendMemory, home, nil, encodingConfig.Codec)
5656
assert.NilError(t, err)
5757

58-
akr, err := sdkkeyring.NewAutoCLIKeyring(kr)
59-
assert.NilError(t, err)
60-
6158
interfaceRegistry := encodingConfig.Codec.InterfaceRegistry()
6259
banktypes.RegisterInterfaces(interfaceRegistry)
6360

@@ -76,7 +73,6 @@ func initFixture(t *testing.T) *fixture {
7673
Builder: flag.Builder{
7774
TypeResolver: protoregistry.GlobalTypes,
7875
FileResolver: protoregistry.GlobalFiles,
79-
Keyring: akr,
8076
AddressCodec: addresscodec.NewBech32Codec("cosmos"),
8177
ValidatorAddressCodec: addresscodec.NewBech32Codec("cosmosvaloper"),
8278
ConsensusAddressCodec: addresscodec.NewBech32Codec("cosmosvalcons"),

client/v2/autocli/flag/address.go

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@ import (
99
"cosmossdk.io/client/v2/autocli/keyring"
1010
"cosmossdk.io/core/address"
1111

12+
"github.com/cosmos/cosmos-sdk/client"
1213
"github.com/cosmos/cosmos-sdk/codec"
1314
"github.com/cosmos/cosmos-sdk/codec/types"
1415
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
16+
sdkkeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
1517
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
1618
)
1719

1820
type addressStringType struct{}
1921

20-
func (a addressStringType) NewValue(_ context.Context, b *Builder) Value {
21-
return &addressValue{addressCodec: b.AddressCodec, keyring: b.Keyring}
22+
func (a addressStringType) NewValue(ctx *context.Context, b *Builder) Value {
23+
return &addressValue{addressCodec: b.AddressCodec, ctx: ctx}
2224
}
2325

2426
func (a addressStringType) DefaultValue() string {
@@ -27,18 +29,19 @@ func (a addressStringType) DefaultValue() string {
2729

2830
type validatorAddressStringType struct{}
2931

30-
func (a validatorAddressStringType) NewValue(_ context.Context, b *Builder) Value {
31-
return &addressValue{addressCodec: b.ValidatorAddressCodec, keyring: b.Keyring}
32+
func (a validatorAddressStringType) NewValue(ctx *context.Context, b *Builder) Value {
33+
return &addressValue{addressCodec: b.ValidatorAddressCodec, ctx: ctx}
3234
}
3335

3436
func (a validatorAddressStringType) DefaultValue() string {
3537
return ""
3638
}
3739

3840
type addressValue struct {
39-
value string
41+
ctx *context.Context
4042
addressCodec address.Codec
41-
keyring keyring.Keyring
43+
44+
value string
4245
}
4346

4447
func (a addressValue) Get(protoreflect.Value) (protoreflect.Value, error) {
@@ -51,7 +54,9 @@ func (a addressValue) String() string {
5154

5255
// Set implements the flag.Value interface for addressValue.
5356
func (a *addressValue) Set(s string) error {
54-
addr, err := a.keyring.LookupAddressByKeyName(s)
57+
// we get the keyring on set, as in NewValue the context is the parent context (before RunE)
58+
keyring := getKeyringFromCtx(a.ctx)
59+
addr, err := keyring.LookupAddressByKeyName(s)
5560
if err == nil {
5661
addrStr, err := a.addressCodec.BytesToString(addr)
5762
if err != nil {
@@ -62,9 +67,11 @@ func (a *addressValue) Set(s string) error {
6267
return nil
6368
}
6469

65-
// failed all validation, just accept the input.
66-
// TODO(@julienrbrt), for final client/v2 2.0.0 revert the logic and
67-
// do a better keyring instantiation.
70+
_, err = a.addressCodec.StringToBytes(s)
71+
if err != nil {
72+
return fmt.Errorf("invalid account address or key name: %w", err)
73+
}
74+
6875
a.value = s
6976

7077
return nil
@@ -76,11 +83,11 @@ func (a addressValue) Type() string {
7683

7784
type consensusAddressStringType struct{}
7885

79-
func (a consensusAddressStringType) NewValue(ctx context.Context, b *Builder) Value {
86+
func (a consensusAddressStringType) NewValue(ctx *context.Context, b *Builder) Value {
8087
return &consensusAddressValue{
8188
addressValue: addressValue{
8289
addressCodec: b.ConsensusAddressCodec,
83-
keyring: b.Keyring,
90+
ctx: ctx,
8491
},
8592
}
8693
}
@@ -102,7 +109,9 @@ func (a consensusAddressValue) String() string {
102109
}
103110

104111
func (a *consensusAddressValue) Set(s string) error {
105-
addr, err := a.keyring.LookupAddressByKeyName(s)
112+
// we get the keyring on set, as in NewValue the context is the parent context (before RunE)
113+
keyring := getKeyringFromCtx(a.ctx)
114+
addr, err := keyring.LookupAddressByKeyName(s)
106115
if err == nil {
107116
addrStr, err := a.addressCodec.BytesToString(addr)
108117
if err != nil {
@@ -127,11 +136,7 @@ func (a *consensusAddressValue) Set(s string) error {
127136
var pk cryptotypes.PubKey
128137
err2 := cdc.UnmarshalInterfaceJSON([]byte(s), &pk)
129138
if err2 != nil {
130-
// failed all validation, just accept the input.
131-
// TODO(@julienrbrt), for final client/v2 2.0.0 revert the logic and
132-
// do a better keyring instantiation.
133-
a.value = s
134-
return nil
139+
return fmt.Errorf("input isn't a pubkey (%w) or is an invalid account address (%w)", err, err2)
135140
}
136141

137142
a.value, err = a.addressCodec.BytesToString(pk.Address())
@@ -141,3 +146,21 @@ func (a *consensusAddressValue) Set(s string) error {
141146

142147
return nil
143148
}
149+
150+
func getKeyringFromCtx(ctx *context.Context) keyring.Keyring {
151+
dctx := *ctx
152+
if dctx != nil {
153+
if clientCtx := dctx.Value(client.ClientContextKey); clientCtx != nil {
154+
k, err := sdkkeyring.NewAutoCLIKeyring(clientCtx.(*client.Context).Keyring)
155+
if err != nil {
156+
panic(fmt.Errorf("failed to create keyring: %w", err))
157+
}
158+
159+
return k
160+
} else if k := dctx.Value(keyring.KeyringContextKey); k != nil {
161+
return k.(*keyring.KeyringImpl)
162+
}
163+
}
164+
165+
return keyring.NoKeyring{}
166+
}

client/v2/autocli/flag/binary.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type binaryType struct{}
1414

1515
var _ Value = (*fileBinaryValue)(nil)
1616

17-
func (f binaryType) NewValue(context.Context, *Builder) Value {
17+
func (f binaryType) NewValue(*context.Context, *Builder) Value {
1818
return &fileBinaryValue{}
1919
}
2020

0 commit comments

Comments
 (0)