Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(client): use address codec #17503

Merged
merged 15 commits into from
Aug 23, 2023
4 changes: 2 additions & 2 deletions client/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err
payer, _ := flagSet.GetString(flags.FlagFeePayer)

if payer != "" {
payerAcc, err := sdk.AccAddressFromBech32(payer)
payerAcc, err := clientCtx.AddressCodec.StringToBytes(payer)
if err != nil {
return clientCtx, err
}
Expand All @@ -264,7 +264,7 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err
granter, _ := flagSet.GetString(flags.FlagFeeGranter)

if granter != "" {
granterAcc, err := sdk.AccAddressFromBech32(granter)
granterAcc, err := clientCtx.AddressCodec.StringToBytes(granter)
if err != nil {
return clientCtx, err
}
Expand Down
29 changes: 27 additions & 2 deletions client/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"google.golang.org/grpc"
"sigs.k8s.io/yaml"

"cosmossdk.io/core/address"

"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
Expand Down Expand Up @@ -65,6 +67,11 @@ type Context struct {

// CmdContext is the context.Context from the Cobra command.
CmdContext context.Context

// Address codecs
AddressCodec address.Codec
ValidatorAddressCodec address.Codec
ConsensusAddressCodec address.Codec
}

// WithCmdContext returns a copy of the context with an updated context.Context,
Expand Down Expand Up @@ -292,6 +299,24 @@ func (ctx Context) WithPreprocessTxHook(preprocessFn PreprocessTxFn) Context {
return ctx
}

// WithAddressCodec returns the context with the provided address codec.
func (ctx Context) WithAddressCodec(addressCodec address.Codec) Context {
ctx.AddressCodec = addressCodec
return ctx
}

// WithValidatorAddressCodec returns the context with the provided validator address codec.
func (ctx Context) WithValidatorAddressCodec(validatorAddressCodec address.Codec) Context {
ctx.ValidatorAddressCodec = validatorAddressCodec
return ctx
}

// WithConsensusAddressCodec returns the context with the provided consensus address codec.
func (ctx Context) WithConsensusAddressCodec(consensusAddressCodec address.Codec) Context {
ctx.ConsensusAddressCodec = consensusAddressCodec
return ctx
}

// PrintString prints the raw string to ctx.Output if it's defined, otherwise to os.Stdout
func (ctx Context) PrintString(str string) error {
return ctx.PrintBytes([]byte(str))
Expand Down Expand Up @@ -365,11 +390,11 @@ func GetFromFields(clientCtx Context, kr keyring.Keyring, from string) (sdk.AccA
return nil, "", 0, nil
}

addr, err := sdk.AccAddressFromBech32(from)
addr, err := clientCtx.AddressCodec.StringToBytes(from)
switch {
case clientCtx.Simulate:
if err != nil {
return nil, "", 0, fmt.Errorf("a valid bech32 address must be provided in simulation mode: %w", err)
return nil, "", 0, fmt.Errorf("a valid address must be provided in simulation mode: %w", err)
}

return addr, "", 0, nil
Expand Down
27 changes: 13 additions & 14 deletions client/debug/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,27 +193,26 @@ $ %s debug pubkey-raw cosmos1e0jnq2sun3dzjh8p2xq95kk0expwmd7shwjpfg

func AddrCmd() *cobra.Command {
return &cobra.Command{
Use: "addr [address]",
Short: "Convert an address between hex and bech32",
Long: fmt.Sprintf(`Convert an address between hex encoding and bech32.

Example:
$ %s debug addr cosmos1e0jnq2sun3dzjh8p2xq95kk0expwmd7shwjpfg
`, version.AppName),
Args: cobra.ExactArgs(1),
Use: "addr [address]",
Short: "Convert an address between hex and bech32",
Example: fmt.Sprintf("%s debug addr cosmos1e0jnq2sun3dzjh8p2xq95kk0expwmd7shwjpfg", version.AppName),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
addrString := args[0]
var addr []byte
clientCtx := client.GetClientContextFromCmd(cmd)

addrString := args[0]
// try hex, then bech32
var err error
var (
addr []byte
err error
)
addr, err = hex.DecodeString(addrString)
if err != nil {
var err2 error
addr, err2 = sdk.AccAddressFromBech32(addrString)
addr, err2 = clientCtx.AddressCodec.StringToBytes(addrString)
if err2 != nil {
var err3 error
addr, err3 = sdk.ValAddressFromBech32(addrString)
addr, err3 = clientCtx.ValidatorAddressCodec.StringToBytes(addrString)

if err3 != nil {
return fmt.Errorf("expected hex or bech32. Got errors: hex: %v, bech32 acc: %v, bech32 val: %v", err, err2, err3)
Expand Down Expand Up @@ -264,7 +263,7 @@ func PrefixesCmd() *cobra.Command {
return &cobra.Command{
Use: "prefixes",
Short: "List prefixes used for Human-Readable Part (HRP) in Bech32",
Long: "List prefixes used in Bech32 addresses.",
Long: "List prefixes used in Bech32 addresses. NOTE, if the chain does not use the Cosmos SDK global config, this will not be accurate.",
Example: fmt.Sprintf("$ %s debug prefixes", version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
cmd.Printf("Bech32 Acc: %s\n", sdk.GetConfig().GetBech32AccountAddrPrefix())
Expand Down
19 changes: 12 additions & 7 deletions client/keys/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
return err
}

return printCreate(cmd, k, false, "", outputFormat)
return printCreate(ctx, cmd, k, false, "", outputFormat)
}
}

Expand All @@ -200,7 +200,7 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
return err
}

return printCreate(cmd, k, false, "", outputFormat)
return printCreate(ctx, cmd, k, false, "", outputFormat)
}

coinType, _ := cmd.Flags().GetUint32(flagCoinType)
Expand All @@ -223,7 +223,7 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
return err
}

return printCreate(cmd, k, false, "", outputFormat)
return printCreate(ctx, cmd, k, false, "", outputFormat)
}

// Get bip39 mnemonic
Expand Down Expand Up @@ -297,14 +297,19 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
mnemonic = ""
}

return printCreate(cmd, k, showMnemonic, mnemonic, outputFormat)
return printCreate(ctx, cmd, k, showMnemonic, mnemonic, outputFormat)
}

func printCreate(cmd *cobra.Command, k *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error {
func printCreate(ctx client.Context, cmd *cobra.Command, k *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error {
switch outputFormat {
case flags.OutputFormatText:
cmd.PrintErrln()
if err := printKeyringRecord(cmd.OutOrStdout(), k, MkAccKeyOutput, outputFormat); err != nil {
ko, err := MkAccKeyOutput(k, ctx.AddressCodec)
if err != nil {
return err
}

if err := printKeyringRecord(cmd.OutOrStdout(), ko, outputFormat); err != nil {
return err
}

Expand All @@ -315,7 +320,7 @@ func printCreate(cmd *cobra.Command, k *keyring.Record, showMnemonic bool, mnemo
}
}
case flags.OutputFormatJSON:
out, err := MkAccKeyOutput(k)
out, err := MkAccKeyOutput(k, ctx.AddressCodec)
if err != nil {
return err
}
Expand Down
24 changes: 21 additions & 3 deletions client/keys/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/testutil"
Expand All @@ -31,7 +32,14 @@ func Test_runAddCmdBasic(t *testing.T) {
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
require.NoError(t, err)

clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn).WithCodec(cdc)
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithInput(mockIn).
WithCodec(cdc).
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")).
WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons"))

ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)

t.Cleanup(func() {
Expand Down Expand Up @@ -197,7 +205,10 @@ func Test_runAddCmdDryRun(t *testing.T) {
clientCtx := client.Context{}.
WithCodec(cdc).
WithKeyringDir(kbHome).
WithKeyring(kb)
WithKeyring(kb).
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")).
WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons"))
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)

path := sdk.GetConfig().GetFullBIP44Path()
Expand Down Expand Up @@ -238,7 +249,14 @@ func TestAddRecoverFileBackend(t *testing.T) {
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kbHome := t.TempDir()

clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn).WithCodec(cdc)
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithInput(mockIn).
WithCodec(cdc).
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")).
WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons"))

ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)

cmd.SetArgs([]string{
Expand Down
2 changes: 1 addition & 1 deletion client/keys/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func runListCmd(cmd *cobra.Command, _ []string) error {
}

if ok, _ := cmd.Flags().GetBool(flagListNames); !ok {
return printKeyringRecords(cmd.OutOrStdout(), records, clientCtx.OutputFormat)
return printKeyringRecords(clientCtx, cmd.OutOrStdout(), records, clientCtx.OutputFormat)
}

for _, k := range records {
Expand Down
8 changes: 7 additions & 1 deletion client/keys/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/testutil"
Expand Down Expand Up @@ -42,7 +43,12 @@ func Test_runListCmd(t *testing.T) {
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome2, mockIn, cdc)
assert.NilError(t, err)

clientCtx := client.Context{}.WithKeyring(kb)
clientCtx := client.Context{}.
WithKeyring(kb).
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")).
WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons"))

ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)

path := "" // sdk.GetConfig().GetFullBIP44Path()
Expand Down
8 changes: 7 additions & 1 deletion client/keys/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec"
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
Expand Down Expand Up @@ -71,7 +72,12 @@ func (s *MigrateTestSuite) Test_runListAndShowCmd() {
s.Require().True(ok)
s.Require().NoError(setter.SetItem(item))

clientCtx := client.Context{}.WithKeyring(kb)
clientCtx := client.Context{}.
WithKeyring(kb).
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
WithValidatorAddressCodec(addresscodec.NewBech32Codec("cosmosvaloper")).
WithConsensusAddressCodec(addresscodec.NewBech32Codec("cosmosvalcons"))

ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)

cmd.SetArgs([]string{
Expand Down
38 changes: 21 additions & 17 deletions client/keys/output.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package keys

import (
"cosmossdk.io/core/address"

"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// Use protobuf interface marshaler rather then generic JSON
Expand All @@ -21,65 +22,68 @@ type KeyOutput struct {
}

// NewKeyOutput creates a default KeyOutput instance without Mnemonic, Threshold and PubKeys
func NewKeyOutput(name string, keyType keyring.KeyType, a sdk.Address, pk cryptotypes.PubKey) (KeyOutput, error) {
func NewKeyOutput(name string, keyType keyring.KeyType, addr []byte, pk cryptotypes.PubKey, addressCodec address.Codec) (KeyOutput, error) {
apk, err := codectypes.NewAnyWithValue(pk)
if err != nil {
return KeyOutput{}, err
}

bz, err := codec.ProtoMarshalJSON(apk, nil)
if err != nil {
return KeyOutput{}, err
}

addrStr, err := addressCodec.BytesToString(addr)
if err != nil {
return KeyOutput{}, err
}

return KeyOutput{
Name: name,
Type: keyType.String(),
Address: a.String(),
Address: addrStr,
PubKey: string(bz),
}, nil
}

// MkConsKeyOutput create a KeyOutput in with "cons" Bech32 prefixes.
func MkConsKeyOutput(k *keyring.Record) (KeyOutput, error) {
// MkConsKeyOutput create a KeyOutput for consensus addresses.
func MkConsKeyOutput(k *keyring.Record, consensusAddressCodec address.Codec) (KeyOutput, error) {
pk, err := k.GetPubKey()
if err != nil {
return KeyOutput{}, err
}
addr := sdk.ConsAddress(pk.Address())
return NewKeyOutput(k.Name, k.GetType(), addr, pk)
return NewKeyOutput(k.Name, k.GetType(), pk.Address(), pk, consensusAddressCodec)
}

// MkValKeyOutput create a KeyOutput in with "val" Bech32 prefixes.
func MkValKeyOutput(k *keyring.Record) (KeyOutput, error) {
// MkValKeyOutput create a KeyOutput for validator addresses.
func MkValKeyOutput(k *keyring.Record, validatorAddressCodec address.Codec) (KeyOutput, error) {
pk, err := k.GetPubKey()
if err != nil {
return KeyOutput{}, err
}

addr := sdk.ValAddress(pk.Address())

return NewKeyOutput(k.Name, k.GetType(), addr, pk)
return NewKeyOutput(k.Name, k.GetType(), pk.Address(), pk, validatorAddressCodec)
}

// MkAccKeyOutput create a KeyOutput in with "acc" Bech32 prefixes. If the
// public key is a multisig public key, then the threshold and constituent
// public keys will be added.
func MkAccKeyOutput(k *keyring.Record) (KeyOutput, error) {
func MkAccKeyOutput(k *keyring.Record, addressCodec address.Codec) (KeyOutput, error) {
pk, err := k.GetPubKey()
if err != nil {
return KeyOutput{}, err
}
addr := sdk.AccAddress(pk.Address())
return NewKeyOutput(k.Name, k.GetType(), addr, pk)
return NewKeyOutput(k.Name, k.GetType(), pk.Address(), pk, addressCodec)
}

// MkAccKeysOutput returns a slice of KeyOutput objects, each with the "acc"
// Bech32 prefixes, given a slice of Record objects. It returns an error if any
// call to MkKeyOutput fails.
func MkAccKeysOutput(records []*keyring.Record) ([]KeyOutput, error) {
func MkAccKeysOutput(records []*keyring.Record, addressCodec address.Codec) ([]KeyOutput, error) {
kos := make([]KeyOutput, len(records))
var err error
for i, r := range records {
kos[i], err = MkAccKeyOutput(r)
kos[i], err = MkAccKeyOutput(r, addressCodec)
if err != nil {
return nil, err
}
Expand Down
Loading
Loading