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

[0.39.0] client/keys/parse: honor config changes #6340

Merged
merged 1 commit into from
Jun 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 37 additions & 17 deletions client/keys/parse.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package keys

import (
"context"
"encoding/hex"
"errors"
"fmt"
"io"
"strings"

"github.com/spf13/cobra"
Expand All @@ -17,14 +19,15 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

var config = sdk.GetConfig()
var bech32Prefixes = []string{
config.GetBech32AccountAddrPrefix(),
config.GetBech32AccountPubPrefix(),
config.GetBech32ValidatorAddrPrefix(),
config.GetBech32ValidatorPubPrefix(),
config.GetBech32ConsensusAddrPrefix(),
config.GetBech32ConsensusPubPrefix(),
func bech32Prefixes(config *sdk.Config) []string {
return []string{
config.GetBech32AccountAddrPrefix(),
config.GetBech32AccountPubPrefix(),
config.GetBech32ValidatorAddrPrefix(),
config.GetBech32ValidatorPubPrefix(),
config.GetBech32ConsensusAddrPrefix(),
config.GetBech32ConsensusPubPrefix(),
}
}

type hexOutput struct {
Expand All @@ -44,13 +47,16 @@ type bech32Output struct {
Formats []string `json:"formats"`
}

func newBech32Output(bs []byte) bech32Output {
func newBech32Output(config *sdk.Config, bs []byte) bech32Output {
bech32Prefixes := bech32Prefixes(config)
out := bech32Output{Formats: make([]string, len(bech32Prefixes))}

for i, prefix := range bech32Prefixes {
bech32Addr, err := bech32.ConvertAndEncode(prefix, bs)
if err != nil {
panic(err)
}

out.Formats[i] = bech32Addr
}

Expand Down Expand Up @@ -83,38 +89,52 @@ hexadecimal into bech32 cosmos prefixed format and vice versa.
return cmd
}

func parseKey(_ *cobra.Command, args []string) error {
func parseKey(cmd *cobra.Command, args []string) error {
config, _ := sdk.GetSealedConfig(context.Background())

return doParseKey(cmd, config, args)
}

func doParseKey(cmd *cobra.Command, config *sdk.Config, args []string) error {
addr := strings.TrimSpace(args[0])
outstream := cmd.OutOrStdout()

if len(addr) == 0 {
return errors.New("couldn't parse empty input")
}
if !(runFromBech32(addr) || runFromHex(addr)) {

if !(runFromBech32(outstream, addr) || runFromHex(config, outstream, addr)) {
return errors.New("couldn't find valid bech32 nor hex data")
}

return nil
}

// print info from bech32
func runFromBech32(bech32str string) bool {
func runFromBech32(w io.Writer, bech32str string) bool {
hrp, bz, err := bech32.DecodeAndConvert(bech32str)
if err != nil {
return false
}
displayParseKeyInfo(newHexOutput(hrp, bz))

displayParseKeyInfo(w, newHexOutput(hrp, bz))

return true
}

// print info from hex
func runFromHex(hexstr string) bool {
func runFromHex(config *sdk.Config, w io.Writer, hexstr string) bool {
bz, err := hex.DecodeString(hexstr)
if err != nil {
return false
}
displayParseKeyInfo(newBech32Output(bz))

displayParseKeyInfo(w, newBech32Output(config, bz))

return true
}

func displayParseKeyInfo(stringer fmt.Stringer) {
func displayParseKeyInfo(w io.Writer, stringer fmt.Stringer) {
var out []byte
var err error

Expand All @@ -136,5 +156,5 @@ func displayParseKeyInfo(stringer fmt.Stringer) {
panic(err)
}

fmt.Println(string(out))
_, _ = fmt.Fprintln(w, string(out))
}
5 changes: 4 additions & 1 deletion client/keys/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ package keys
import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
)

func TestParseKey(t *testing.T) {
bech32str := "cosmos104ytdpvrx9284zd50v9ep8c6j7pua7dkk0x3ek"
hexstr := "EB5AE9872103497EC092EF901027049E4F39200C60040D3562CD7F104A39F62E6E5A39A818F4"

config := sdk.NewConfig()

tests := []struct {
name string
args []string
Expand All @@ -23,7 +26,7 @@ func TestParseKey(t *testing.T) {
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.wantErr, parseKey(nil, tt.args) != nil)
require.Equal(t, tt.wantErr, doParseKey(ParseKeyStringCommand(), config, tt.args) != nil)
})
}
}
47 changes: 37 additions & 10 deletions types/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package types

import (
"context"
"sync"

"github.com/cosmos/cosmos-sdk/version"
Expand All @@ -19,19 +20,19 @@ type Config struct {
mtx sync.RWMutex
coinType uint32
sealed bool
sealedch chan struct{}
}

// cosmos-sdk wide global singleton
var sdkConfig *Config

// GetConfig returns the config instance for the SDK.
func GetConfig() *Config {
if sdkConfig != nil {
return sdkConfig
}
var (
sdkConfig *Config
initConfig sync.Once
)

sdkConfig = &Config{
sealed: false,
// New returns a new Config with default values.
func NewConfig() *Config {
return &Config{
sealedch: make(chan struct{}),
bech32AddressPrefix: map[string]string{
"account_addr": Bech32PrefixAccAddr,
"validator_addr": Bech32PrefixValAddr,
Expand All @@ -44,9 +45,27 @@ func GetConfig() *Config {
fullFundraiserPath: FullFundraiserPath,
txEncoder: nil,
}
}

// GetConfig returns the config instance for the SDK.
func GetConfig() *Config {
initConfig.Do(func() {
sdkConfig = NewConfig()
})
return sdkConfig
}

// GetSealedConfig returns the config instance for the SDK if/once it is sealed.
func GetSealedConfig(ctx context.Context) (*Config, error) {
config := GetConfig()
select {
case <-config.sealedch:
return config, nil
case <-ctx.Done():
return nil, ctx.Err()
}
}

func (config *Config) assertNotSealed() {
config.mtx.Lock()
defer config.mtx.Unlock()
Expand Down Expand Up @@ -108,9 +127,17 @@ func (config *Config) SetFullFundraiserPath(fullFundraiserPath string) {
// Seal seals the config such that the config state could not be modified further
func (config *Config) Seal() *Config {
config.mtx.Lock()
defer config.mtx.Unlock()

if config.sealed {
config.mtx.Unlock()
return config
}

// signal sealed after state exposed/unlocked
config.sealed = true
config.mtx.Unlock()
close(config.sealedch)

return config
}

Expand Down
50 changes: 50 additions & 0 deletions types/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package types_test

import (
"errors"
"testing"

"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
)

func TestConfig_SetCoinType(t *testing.T) {
config := sdk.NewConfig()
config.SetCoinType(1)
require.Equal(t, uint32(1), config.GetCoinType())
config.SetCoinType(99)
require.Equal(t, uint32(99), config.GetCoinType())

config.Seal()
require.Panics(t, func() { config.SetCoinType(99) })
}

func TestConfig_SetTxEncoder(t *testing.T) {
mockErr := errors.New("test")
config := sdk.NewConfig()
require.Nil(t, config.GetTxEncoder())
encFunc := sdk.TxEncoder(func(tx sdk.Tx) ([]byte, error) { return nil, nil })
config.SetTxEncoder(encFunc)
_, err := config.GetTxEncoder()(sdk.Tx(nil))
require.Error(t, mockErr, err)

config.Seal()
require.Panics(t, func() { config.SetTxEncoder(encFunc) })
}

func TestConfig_SetFullFundraiserPath(t *testing.T) {
config := sdk.NewConfig()
config.SetFullFundraiserPath("test/path")
require.Equal(t, "test/path", config.GetFullFundraiserPath())

config.SetFullFundraiserPath("test/poth")
require.Equal(t, "test/poth", config.GetFullFundraiserPath())

config.Seal()
require.Panics(t, func() { config.SetFullFundraiserPath("x/test/path") })
}

func TestKeyringServiceName(t *testing.T) {
require.Equal(t, sdk.DefaultKeyringServiceName, sdk.KeyringServiceName())
}