cosmos-sdk/types/address_test.go

349 lines
9.1 KiB
Go

package types_test
import (
"encoding/hex"
"fmt"
"math/rand"
"strings"
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/cosmos/cosmos-sdk/types"
)
var invalidStrs = []string{
"hello, world!",
"0xAA",
"AAA",
types.Bech32PrefixAccAddr + "AB0C",
types.Bech32PrefixAccPub + "1234",
types.Bech32PrefixValAddr + "5678",
types.Bech32PrefixValPub + "BBAB",
types.Bech32PrefixConsAddr + "FF04",
types.Bech32PrefixConsPub + "6789",
}
func testMarshal(t *testing.T, original interface{}, res interface{}, marshal func() ([]byte, error), unmarshal func([]byte) error) {
bz, err := marshal()
require.Nil(t, err)
err = unmarshal(bz)
require.Nil(t, err)
require.Equal(t, original, res)
}
func TestEmptyAddresses(t *testing.T) {
require.Equal(t, (types.AccAddress{}).String(), "")
require.Equal(t, (types.ValAddress{}).String(), "")
require.Equal(t, (types.ConsAddress{}).String(), "")
accAddr, err := types.AccAddressFromBech32("")
require.True(t, accAddr.Empty())
require.Nil(t, err)
valAddr, err := types.ValAddressFromBech32("")
require.True(t, valAddr.Empty())
require.Nil(t, err)
consAddr, err := types.ConsAddressFromBech32("")
require.True(t, consAddr.Empty())
require.Nil(t, err)
}
func TestRandBech32PubkeyConsistency(t *testing.T) {
var pub ed25519.PubKeyEd25519
for i := 0; i < 1000; i++ {
rand.Read(pub[:])
mustBech32AccPub := types.MustBech32ifyAccPub(pub)
bech32AccPub, err := types.Bech32ifyAccPub(pub)
require.Nil(t, err)
require.Equal(t, bech32AccPub, mustBech32AccPub)
mustBech32ValPub := types.MustBech32ifyValPub(pub)
bech32ValPub, err := types.Bech32ifyValPub(pub)
require.Nil(t, err)
require.Equal(t, bech32ValPub, mustBech32ValPub)
mustBech32ConsPub := types.MustBech32ifyConsPub(pub)
bech32ConsPub, err := types.Bech32ifyConsPub(pub)
require.Nil(t, err)
require.Equal(t, bech32ConsPub, mustBech32ConsPub)
mustAccPub := types.MustGetAccPubKeyBech32(bech32AccPub)
accPub, err := types.GetAccPubKeyBech32(bech32AccPub)
require.Nil(t, err)
require.Equal(t, accPub, mustAccPub)
mustValPub := types.MustGetValPubKeyBech32(bech32ValPub)
valPub, err := types.GetValPubKeyBech32(bech32ValPub)
require.Nil(t, err)
require.Equal(t, valPub, mustValPub)
mustConsPub := types.MustGetConsPubKeyBech32(bech32ConsPub)
consPub, err := types.GetConsPubKeyBech32(bech32ConsPub)
require.Nil(t, err)
require.Equal(t, consPub, mustConsPub)
require.Equal(t, valPub, accPub)
require.Equal(t, valPub, consPub)
}
}
func TestYAMLMarshalers(t *testing.T) {
addr := secp256k1.GenPrivKey().PubKey().Address()
acc := types.AccAddress(addr)
val := types.ValAddress(addr)
cons := types.ConsAddress(addr)
got, _ := yaml.Marshal(&acc)
require.Equal(t, acc.String()+"\n", string(got))
got, _ = yaml.Marshal(&val)
require.Equal(t, val.String()+"\n", string(got))
got, _ = yaml.Marshal(&cons)
require.Equal(t, cons.String()+"\n", string(got))
}
func TestRandBech32AccAddrConsistency(t *testing.T) {
var pub ed25519.PubKeyEd25519
for i := 0; i < 1000; i++ {
rand.Read(pub[:])
acc := types.AccAddress(pub.Address())
res := types.AccAddress{}
testMarshal(t, &acc, &res, acc.MarshalJSON, (&res).UnmarshalJSON)
testMarshal(t, &acc, &res, acc.Marshal, (&res).Unmarshal)
str := acc.String()
res, err := types.AccAddressFromBech32(str)
require.Nil(t, err)
require.Equal(t, acc, res)
str = hex.EncodeToString(acc)
res, err = types.AccAddressFromHex(str)
require.Nil(t, err)
require.Equal(t, acc, res)
}
for _, str := range invalidStrs {
_, err := types.AccAddressFromHex(str)
require.NotNil(t, err)
_, err = types.AccAddressFromBech32(str)
require.NotNil(t, err)
err = (*types.AccAddress)(nil).UnmarshalJSON([]byte("\"" + str + "\""))
require.NotNil(t, err)
}
}
func TestValAddr(t *testing.T) {
var pub ed25519.PubKeyEd25519
for i := 0; i < 20; i++ {
rand.Read(pub[:])
acc := types.ValAddress(pub.Address())
res := types.ValAddress{}
testMarshal(t, &acc, &res, acc.MarshalJSON, (&res).UnmarshalJSON)
testMarshal(t, &acc, &res, acc.Marshal, (&res).Unmarshal)
str := acc.String()
res, err := types.ValAddressFromBech32(str)
require.Nil(t, err)
require.Equal(t, acc, res)
str = hex.EncodeToString(acc)
res, err = types.ValAddressFromHex(str)
require.Nil(t, err)
require.Equal(t, acc, res)
}
for _, str := range invalidStrs {
_, err := types.ValAddressFromHex(str)
require.NotNil(t, err)
_, err = types.ValAddressFromBech32(str)
require.NotNil(t, err)
err = (*types.ValAddress)(nil).UnmarshalJSON([]byte("\"" + str + "\""))
require.NotNil(t, err)
}
}
func TestConsAddress(t *testing.T) {
var pub ed25519.PubKeyEd25519
for i := 0; i < 20; i++ {
rand.Read(pub[:])
acc := types.ConsAddress(pub.Address())
res := types.ConsAddress{}
testMarshal(t, &acc, &res, acc.MarshalJSON, (&res).UnmarshalJSON)
testMarshal(t, &acc, &res, acc.Marshal, (&res).Unmarshal)
str := acc.String()
res, err := types.ConsAddressFromBech32(str)
require.Nil(t, err)
require.Equal(t, acc, res)
str = hex.EncodeToString(acc)
res, err = types.ConsAddressFromHex(str)
require.Nil(t, err)
require.Equal(t, acc, res)
}
for _, str := range invalidStrs {
_, err := types.ConsAddressFromHex(str)
require.NotNil(t, err)
_, err = types.ConsAddressFromBech32(str)
require.NotNil(t, err)
err = (*types.ConsAddress)(nil).UnmarshalJSON([]byte("\"" + str + "\""))
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+types.PrefixAccount,
prefix+types.PrefixPublic)
acc := types.AccAddress(pub.Address())
require.True(t, strings.HasPrefix(
acc.String(),
prefix+types.PrefixAccount), acc.String())
bech32Pub := types.MustBech32ifyAccPub(pub)
require.True(t, strings.HasPrefix(
bech32Pub,
prefix+types.PrefixPublic))
config.SetBech32PrefixForValidator(
prefix+types.PrefixValidator+types.PrefixAddress,
prefix+types.PrefixValidator+types.PrefixPublic)
val := types.ValAddress(pub.Address())
require.True(t, strings.HasPrefix(
val.String(),
prefix+types.PrefixValidator+types.PrefixAddress))
bech32ValPub := types.MustBech32ifyValPub(pub)
require.True(t, strings.HasPrefix(
bech32ValPub,
prefix+types.PrefixValidator+types.PrefixPublic))
config.SetBech32PrefixForConsensusNode(
prefix+types.PrefixConsensus+types.PrefixAddress,
prefix+types.PrefixConsensus+types.PrefixPublic)
cons := types.ConsAddress(pub.Address())
require.True(t, strings.HasPrefix(
cons.String(),
prefix+types.PrefixConsensus+types.PrefixAddress))
bech32ConsPub := types.MustBech32ifyConsPub(pub)
require.True(t, strings.HasPrefix(
bech32ConsPub,
prefix+types.PrefixConsensus+types.PrefixPublic))
}
}
}
func TestAddressInterface(t *testing.T) {
var pub ed25519.PubKeyEd25519
rand.Read(pub[:])
addrs := []types.Address{
types.ConsAddress(pub.Address()),
types.ValAddress(pub.Address()),
types.AccAddress(pub.Address()),
}
for _, addr := range addrs {
switch addr := addr.(type) {
case types.AccAddress:
_, err := types.AccAddressFromBech32(addr.String())
require.Nil(t, err)
case types.ValAddress:
_, err := types.ValAddressFromBech32(addr.String())
require.Nil(t, err)
case types.ConsAddress:
_, err := types.ConsAddressFromBech32(addr.String())
require.Nil(t, err)
default:
t.Fail()
}
}
}
func TestCustomAddressVerifier(t *testing.T) {
// Create a 10 byte address
addr := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
accBech := types.AccAddress(addr).String()
valBech := types.ValAddress(addr).String()
consBech := types.ConsAddress(addr).String()
// Verifiy that the default logic rejects this 10 byte address
err := types.VerifyAddressFormat(addr)
require.NotNil(t, err)
_, err = types.AccAddressFromBech32(accBech)
require.NotNil(t, err)
_, err = types.ValAddressFromBech32(valBech)
require.NotNil(t, err)
_, err = types.ConsAddressFromBech32(consBech)
require.NotNil(t, err)
// Set a custom address verifier that accepts 10 or 20 byte addresses
types.GetConfig().SetAddressVerifier(func(bz []byte) error {
n := len(bz)
if n == 10 || n == types.AddrLen {
return nil
}
return fmt.Errorf("incorrect address length %d", n)
})
// Verifiy that the custom logic accepts this 10 byte address
err = types.VerifyAddressFormat(addr)
require.Nil(t, err)
_, err = types.AccAddressFromBech32(accBech)
require.Nil(t, err)
_, err = types.ValAddressFromBech32(valBech)
require.Nil(t, err)
_, err = types.ConsAddressFromBech32(consBech)
require.Nil(t, err)
}