Merge PR #2614: Configurable Bech32 prefix for SDK users

This commit is contained in:
svaishnavy 2018-10-31 20:13:13 +01:00 committed by Christopher Goes
parent fcf5b7764b
commit 9cf53f25f7
9 changed files with 213 additions and 12 deletions

View File

@ -26,6 +26,7 @@ FEATURES
* Gaia
* SDK
* (#1336) Mechanism for SDK Users to configure their own Bech32 prefixes instead of using the default cosmos prefixes.
* Tendermint

View File

@ -15,6 +15,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
@ -47,6 +48,12 @@ func main() {
cobra.EnableCommandSorting = false
cdc := app.MakeCodec()
config := sdk.GetConfig()
config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub)
config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub)
config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub)
config.Seal()
// TODO: setup keybase, viper object, etc. to be passed into
// the below functions and eliminate global vars, like we do
// with the cdc

View File

@ -18,10 +18,18 @@ import (
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
gaiaInit "github.com/cosmos/cosmos-sdk/cmd/gaia/init"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func main() {
cdc := app.MakeCodec()
config := sdk.GetConfig()
config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub)
config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub)
config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub)
config.Seal()
ctx := server.NewDefaultContext()
cobra.EnableCommandSorting = false
rootCmd := &cobra.Command{

View File

@ -19,6 +19,13 @@ import (
)
func init() {
config := sdk.GetConfig()
config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub)
config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub)
config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub)
config.Seal()
rootCmd.AddCommand(txCmd)
rootCmd.AddCommand(pubkeyCmd)
rootCmd.AddCommand(addrCmd)

View File

@ -21,6 +21,8 @@ import (
coolcmd "github.com/cosmos/cosmos-sdk/examples/democoin/x/cool/client/cli"
powcmd "github.com/cosmos/cosmos-sdk/examples/democoin/x/pow/client/cli"
simplestakingcmd "github.com/cosmos/cosmos-sdk/examples/democoin/x/simplestake/client/cli"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// rootCmd is the entry point for this binary
@ -38,6 +40,13 @@ func main() {
// get the codec
cdc := app.MakeCodec()
// Setup certain SDK config
config := sdk.GetConfig()
config.SetBech32PrefixForAccount("demoacc", "demopub")
config.SetBech32PrefixForValidator("demoval", "demovalpub")
config.SetBech32PrefixForConsensusNode("democons", "democonspub")
config.Seal()
// TODO: setup keybase, viper object, etc. to be passed into
// the below functions and eliminate global vars, like we do
// with the cdc

View File

@ -23,6 +23,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/examples/democoin/app"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
@ -135,6 +136,14 @@ func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, _ io.Writer) (j
func main() {
cdc := app.MakeCodec()
// Setup certain SDK config
config := sdk.GetConfig()
config.SetBech32PrefixForAccount("demoacc", "demopub")
config.SetBech32PrefixForValidator("demoval", "demovalpub")
config.SetBech32PrefixForConsensusNode("democons", "democonspub")
config.Seal()
ctx := server.NewDefaultContext()
rootCmd := &cobra.Command{

View File

@ -55,7 +55,8 @@ func AccAddressFromHex(address string) (addr AccAddress, err error) {
// AccAddressFromBech32 creates an AccAddress from a Bech32 string.
func AccAddressFromBech32(address string) (addr AccAddress, err error) {
bz, err := GetFromBech32(address, Bech32PrefixAccAddr)
bech32PrefixAccAddr := GetConfig().GetBech32AccountAddrPrefix()
bz, err := GetFromBech32(address, bech32PrefixAccAddr)
if err != nil {
return nil, err
}
@ -124,7 +125,8 @@ func (aa AccAddress) Bytes() []byte {
// String implements the Stringer interface.
func (aa AccAddress) String() string {
bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixAccAddr, aa.Bytes())
bech32PrefixAccAddr := GetConfig().GetBech32AccountAddrPrefix()
bech32Addr, err := bech32.ConvertAndEncode(bech32PrefixAccAddr, aa.Bytes())
if err != nil {
panic(err)
}
@ -169,7 +171,8 @@ func ValAddressFromHex(address string) (addr ValAddress, err error) {
// ValAddressFromBech32 creates a ValAddress from a Bech32 string.
func ValAddressFromBech32(address string) (addr ValAddress, err error) {
bz, err := GetFromBech32(address, Bech32PrefixValAddr)
bech32PrefixValAddr := GetConfig().GetBech32ValidatorAddrPrefix()
bz, err := GetFromBech32(address, bech32PrefixValAddr)
if err != nil {
return nil, err
}
@ -239,7 +242,8 @@ func (va ValAddress) Bytes() []byte {
// String implements the Stringer interface.
func (va ValAddress) String() string {
bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixValAddr, va.Bytes())
bech32PrefixValAddr := GetConfig().GetBech32ValidatorAddrPrefix()
bech32Addr, err := bech32.ConvertAndEncode(bech32PrefixValAddr, va.Bytes())
if err != nil {
panic(err)
}
@ -284,7 +288,8 @@ func ConsAddressFromHex(address string) (addr ConsAddress, err error) {
// ConsAddressFromBech32 creates a ConsAddress from a Bech32 string.
func ConsAddressFromBech32(address string) (addr ConsAddress, err error) {
bz, err := GetFromBech32(address, Bech32PrefixConsAddr)
bech32PrefixConsAddr := GetConfig().GetBech32ConsensusAddrPrefix()
bz, err := GetFromBech32(address, bech32PrefixConsAddr)
if err != nil {
return nil, err
}
@ -359,7 +364,8 @@ func (ca ConsAddress) Bytes() []byte {
// String implements the Stringer interface.
func (ca ConsAddress) String() string {
bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixConsAddr, ca.Bytes())
bech32PrefixConsAddr := GetConfig().GetBech32ConsensusAddrPrefix()
bech32Addr, err := bech32.ConvertAndEncode(bech32PrefixConsAddr, ca.Bytes())
if err != nil {
panic(err)
}
@ -387,7 +393,8 @@ func (ca ConsAddress) Format(s fmt.State, verb rune) {
// Bech32ifyAccPub returns a Bech32 encoded string containing the
// Bech32PrefixAccPub prefix for a given account PubKey.
func Bech32ifyAccPub(pub crypto.PubKey) (string, error) {
return bech32.ConvertAndEncode(Bech32PrefixAccPub, pub.Bytes())
bech32PrefixAccPub := GetConfig().GetBech32AccountPubPrefix()
return bech32.ConvertAndEncode(bech32PrefixAccPub, pub.Bytes())
}
// MustBech32ifyAccPub returns the result of Bech32ifyAccPub panicing on failure.
@ -403,7 +410,8 @@ func MustBech32ifyAccPub(pub crypto.PubKey) string {
// Bech32ifyValPub returns a Bech32 encoded string containing the
// Bech32PrefixValPub prefix for a given validator operator's PubKey.
func Bech32ifyValPub(pub crypto.PubKey) (string, error) {
return bech32.ConvertAndEncode(Bech32PrefixValPub, pub.Bytes())
bech32PrefixValPub := GetConfig().GetBech32ValidatorPubPrefix()
return bech32.ConvertAndEncode(bech32PrefixValPub, pub.Bytes())
}
// MustBech32ifyValPub returns the result of Bech32ifyValPub panicing on failure.
@ -419,7 +427,8 @@ func MustBech32ifyValPub(pub crypto.PubKey) string {
// Bech32ifyConsPub returns a Bech32 encoded string containing the
// Bech32PrefixConsPub prefixfor a given consensus node's PubKey.
func Bech32ifyConsPub(pub crypto.PubKey) (string, error) {
return bech32.ConvertAndEncode(Bech32PrefixConsPub, pub.Bytes())
bech32PrefixConsPub := GetConfig().GetBech32ConsensusPubPrefix()
return bech32.ConvertAndEncode(bech32PrefixConsPub, pub.Bytes())
}
// MustBech32ifyConsPub returns the result of Bech32ifyConsPub panicing on
@ -436,7 +445,8 @@ func MustBech32ifyConsPub(pub crypto.PubKey) string {
// GetAccPubKeyBech32 creates a PubKey for an account with a given public key
// string using the Bech32 Bech32PrefixAccPub prefix.
func GetAccPubKeyBech32(pubkey string) (pk crypto.PubKey, err error) {
bz, err := GetFromBech32(pubkey, Bech32PrefixAccPub)
bech32PrefixAccPub := GetConfig().GetBech32AccountPubPrefix()
bz, err := GetFromBech32(pubkey, bech32PrefixAccPub)
if err != nil {
return nil, err
}
@ -463,7 +473,8 @@ func MustGetAccPubKeyBech32(pubkey string) (pk crypto.PubKey) {
// GetValPubKeyBech32 creates a PubKey for a validator's operator with a given
// public key string using the Bech32 Bech32PrefixValPub prefix.
func GetValPubKeyBech32(pubkey string) (pk crypto.PubKey, err error) {
bz, err := GetFromBech32(pubkey, Bech32PrefixValPub)
bech32PrefixValPub := GetConfig().GetBech32ValidatorPubPrefix()
bz, err := GetFromBech32(pubkey, bech32PrefixValPub)
if err != nil {
return nil, err
}
@ -490,7 +501,8 @@ func MustGetValPubKeyBech32(pubkey string) (pk crypto.PubKey) {
// GetConsPubKeyBech32 creates a PubKey for a consensus node with a given public
// key string using the Bech32 Bech32PrefixConsPub prefix.
func GetConsPubKeyBech32(pubkey string) (pk crypto.PubKey, err error) {
bz, err := GetFromBech32(pubkey, Bech32PrefixConsPub)
bech32PrefixConsPub := GetConfig().GetBech32ConsensusPubPrefix()
bz, err := GetFromBech32(pubkey, bech32PrefixConsPub)
if err != nil {
return nil, err
}

View File

@ -9,6 +9,8 @@ import (
"github.com/tendermint/tendermint/crypto/ed25519"
"strings"
"github.com/cosmos/cosmos-sdk/types"
)
@ -178,3 +180,44 @@ func TestConsAddress(t *testing.T) {
require.NotNil(t, err)
}
}
const letterBytes = "abcdefghijklmnopqrstuvwxyz"
func RandString(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand.Intn(len(letterBytes))]
}
return string(b)
}
func TestConfiguredPrefix(t *testing.T) {
var pub ed25519.PubKeyEd25519
for length := 1; length < 10; length++ {
for times := 1; times < 20; times++ {
rand.Read(pub[:])
// Test if randomly generated prefix of a given length works
prefix := RandString(length)
// Assuming that GetConfig is not sealed.
config := types.GetConfig()
config.SetBech32PrefixForAccount(prefix+"acc", prefix+"pub")
acc := types.AccAddress(pub.Address())
require.True(t, strings.HasPrefix(acc.String(), prefix+"acc"))
bech32Pub := types.MustBech32ifyAccPub(pub)
require.True(t, strings.HasPrefix(bech32Pub, prefix+"pub"))
config.SetBech32PrefixForValidator(prefix+"valaddr", prefix+"valpub")
val := types.ValAddress(pub.Address())
require.True(t, strings.HasPrefix(val.String(), prefix+"valaddr"))
bech32ValPub := types.MustBech32ifyValPub(pub)
require.True(t, strings.HasPrefix(bech32ValPub, prefix+"valpub"))
config.SetBech32PrefixForConsensusNode(prefix+"consaddr", prefix+"conspub")
cons := types.ConsAddress(pub.Address())
require.True(t, strings.HasPrefix(cons.String(), prefix+"consaddr"))
bech32ConsPub := types.MustBech32ifyConsPub(pub)
require.True(t, strings.HasPrefix(bech32ConsPub, prefix+"conspub"))
}
}
}

105
types/config.go Normal file
View File

@ -0,0 +1,105 @@
package types
import (
"sync"
)
// Config is the structure that holds the SDK configuration parameters.
// This could be used to initialize certain configuration parameters for the SDK.
type Config struct {
mtx sync.RWMutex
sealed bool
bech32AddressPrefix map[string]string
}
var (
// Initializing an instance of Config
sdkConfig = &Config{
sealed: false,
bech32AddressPrefix: map[string]string{
"account_addr": Bech32PrefixAccAddr,
"validator_addr": Bech32PrefixValAddr,
"consensus_addr": Bech32PrefixConsAddr,
"account_pub": Bech32PrefixAccPub,
"validator_pub": Bech32PrefixValPub,
"consensus_pub": Bech32PrefixConsPub,
},
}
)
// GetConfig returns the config instance for the SDK.
func GetConfig() *Config {
return sdkConfig
}
func (config *Config) assertNotSealed() {
config.mtx.Lock()
defer config.mtx.Unlock()
if config.sealed {
panic("Config is sealed")
}
}
// SetBech32PrefixForAccount builds the Config with Bech32 addressPrefix and publKeyPrefix for accounts
// and returns the config instance
func (config *Config) SetBech32PrefixForAccount(addressPrefix, pubKeyPrefix string) {
config.assertNotSealed()
config.bech32AddressPrefix["account_addr"] = addressPrefix
config.bech32AddressPrefix["account_pub"] = pubKeyPrefix
}
// SetBech32PrefixForValidator builds the Config with Bech32 addressPrefix and publKeyPrefix for validators
// and returns the config instance
func (config *Config) SetBech32PrefixForValidator(addressPrefix, pubKeyPrefix string) {
config.assertNotSealed()
config.bech32AddressPrefix["validator_addr"] = addressPrefix
config.bech32AddressPrefix["validator_pub"] = pubKeyPrefix
}
// SetBech32PrefixForConsensusNode builds the Config with Bech32 addressPrefix and publKeyPrefix for consensus nodes
// and returns the config instance
func (config *Config) SetBech32PrefixForConsensusNode(addressPrefix, pubKeyPrefix string) {
config.assertNotSealed()
config.bech32AddressPrefix["consensus_addr"] = addressPrefix
config.bech32AddressPrefix["consensus_pub"] = pubKeyPrefix
}
// 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()
config.sealed = true
return config
}
// GetBech32AccountAddrPrefix returns the Bech32 prefix for account address
func (config *Config) GetBech32AccountAddrPrefix() string {
return config.bech32AddressPrefix["account_addr"]
}
// GetBech32ValidatorAddrPrefix returns the Bech32 prefix for validator address
func (config *Config) GetBech32ValidatorAddrPrefix() string {
return config.bech32AddressPrefix["validator_addr"]
}
// GetBech32ConsensusAddrPrefix returns the Bech32 prefix for consensus node address
func (config *Config) GetBech32ConsensusAddrPrefix() string {
return config.bech32AddressPrefix["consensus_addr"]
}
// GetBech32AccountPubPrefix returns the Bech32 prefix for account public key
func (config *Config) GetBech32AccountPubPrefix() string {
return config.bech32AddressPrefix["account_pub"]
}
// GetBech32ValidatorPubPrefix returns the Bech32 prefix for validator public key
func (config *Config) GetBech32ValidatorPubPrefix() string {
return config.bech32AddressPrefix["validator_pub"]
}
// GetBech32ConsensusPubPrefix returns the Bech32 prefix for consensus node public key
func (config *Config) GetBech32ConsensusPubPrefix() string {
return config.bech32AddressPrefix["consensus_pub"]
}