github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/types/address_test.go (about)

     1  package types_test
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"math/rand"
     7  	"strings"
     8  	"testing"
     9  
    10  	evmtypes "github.com/fibonacci-chain/fbc/x/evm/types"
    11  
    12  	"github.com/stretchr/testify/require"
    13  	yaml "gopkg.in/yaml.v2"
    14  
    15  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/ed25519"
    16  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/secp256k1"
    17  
    18  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    19  )
    20  
    21  var invalidStrs = []string{
    22  	"hello, world!",
    23  	"AAA",
    24  	types.Bech32PrefixAccAddr + "AB0C",
    25  	types.Bech32PrefixAccPub + "1234",
    26  	types.Bech32PrefixValAddr + "5678",
    27  	types.Bech32PrefixValPub + "BBAB",
    28  	types.Bech32PrefixConsAddr + "FF04",
    29  	types.Bech32PrefixConsPub + "6789",
    30  }
    31  
    32  func testMarshal(t *testing.T, original interface{}, res interface{}, marshal func() ([]byte, error), unmarshal func([]byte) error) {
    33  	bz, err := marshal()
    34  	require.Nil(t, err)
    35  	err = unmarshal(bz)
    36  	require.Nil(t, err)
    37  	require.Equal(t, original, res)
    38  }
    39  
    40  func TestEmptyAddresses(t *testing.T) {
    41  	require.Equal(t, (types.AccAddress{}).String(), "")
    42  	require.Equal(t, (types.ValAddress{}).String(), "")
    43  	require.Equal(t, (types.ConsAddress{}).String(), "")
    44  
    45  	accAddr, err := types.AccAddressFromBech32("")
    46  	require.True(t, accAddr.Empty())
    47  	require.Error(t, err)
    48  
    49  	valAddr, err := types.ValAddressFromBech32("")
    50  	require.True(t, valAddr.Empty())
    51  	require.Error(t, err)
    52  
    53  	consAddr, err := types.ConsAddressFromBech32("")
    54  	require.True(t, consAddr.Empty())
    55  	require.Error(t, err)
    56  }
    57  
    58  func TestRandBech32PubkeyConsistency(t *testing.T) {
    59  	var pub ed25519.PubKeyEd25519
    60  
    61  	for i := 0; i < 1000; i++ {
    62  		rand.Read(pub[:])
    63  
    64  		mustBech32AccPub := types.MustBech32ifyPubKey(types.Bech32PubKeyTypeAccPub, pub)
    65  		bech32AccPub, err := types.Bech32ifyPubKey(types.Bech32PubKeyTypeAccPub, pub)
    66  		require.Nil(t, err)
    67  		require.Equal(t, bech32AccPub, mustBech32AccPub)
    68  
    69  		mustBech32ValPub := types.MustBech32ifyPubKey(types.Bech32PubKeyTypeValPub, pub)
    70  		bech32ValPub, err := types.Bech32ifyPubKey(types.Bech32PubKeyTypeValPub, pub)
    71  		require.Nil(t, err)
    72  		require.Equal(t, bech32ValPub, mustBech32ValPub)
    73  
    74  		mustBech32ConsPub := types.MustBech32ifyPubKey(types.Bech32PubKeyTypeConsPub, pub)
    75  		bech32ConsPub, err := types.Bech32ifyPubKey(types.Bech32PubKeyTypeConsPub, pub)
    76  		require.Nil(t, err)
    77  		require.Equal(t, bech32ConsPub, mustBech32ConsPub)
    78  
    79  		mustAccPub := types.MustGetPubKeyFromBech32(types.Bech32PubKeyTypeAccPub, bech32AccPub)
    80  		accPub, err := types.GetPubKeyFromBech32(types.Bech32PubKeyTypeAccPub, bech32AccPub)
    81  		require.Nil(t, err)
    82  		require.Equal(t, accPub, mustAccPub)
    83  
    84  		mustValPub := types.MustGetPubKeyFromBech32(types.Bech32PubKeyTypeValPub, bech32ValPub)
    85  		valPub, err := types.GetPubKeyFromBech32(types.Bech32PubKeyTypeValPub, bech32ValPub)
    86  		require.Nil(t, err)
    87  		require.Equal(t, valPub, mustValPub)
    88  
    89  		mustConsPub := types.MustGetPubKeyFromBech32(types.Bech32PubKeyTypeConsPub, bech32ConsPub)
    90  		consPub, err := types.GetPubKeyFromBech32(types.Bech32PubKeyTypeConsPub, bech32ConsPub)
    91  		require.Nil(t, err)
    92  		require.Equal(t, consPub, mustConsPub)
    93  
    94  		require.Equal(t, valPub, accPub)
    95  		require.Equal(t, valPub, consPub)
    96  	}
    97  }
    98  
    99  func TestYAMLMarshalers(t *testing.T) {
   100  	addr := secp256k1.GenPrivKey().PubKey().Address()
   101  
   102  	acc := types.AccAddress(addr)
   103  	val := types.ValAddress(addr)
   104  	cons := types.ConsAddress(addr)
   105  
   106  	got, _ := yaml.Marshal(&acc)
   107  	require.Equal(t, acc.String()+"\n", string(got))
   108  
   109  	got, _ = yaml.Marshal(&val)
   110  	require.Equal(t, val.String()+"\n", string(got))
   111  
   112  	got, _ = yaml.Marshal(&cons)
   113  	require.Equal(t, cons.String()+"\n", string(got))
   114  }
   115  
   116  func TestRandBech32AccAddrConsistency(t *testing.T) {
   117  	var pub ed25519.PubKeyEd25519
   118  
   119  	for i := 0; i < 1000; i++ {
   120  		rand.Read(pub[:])
   121  
   122  		acc := types.AccAddress(pub.Address())
   123  		res := types.AccAddress{}
   124  
   125  		testMarshal(t, &acc, &res, acc.MarshalJSON, (&res).UnmarshalJSON)
   126  		testMarshal(t, &acc, &res, acc.Marshal, (&res).Unmarshal)
   127  
   128  		str := acc.String()
   129  		res, err := types.AccAddressFromBech32(str)
   130  		require.Nil(t, err)
   131  		require.Equal(t, acc, res)
   132  
   133  		str = hex.EncodeToString(acc)
   134  		res, err = types.AccAddressFromHex(str)
   135  		require.Nil(t, err)
   136  		require.Equal(t, acc, res)
   137  	}
   138  
   139  	for _, str := range invalidStrs {
   140  		_, err := types.AccAddressFromHex(str)
   141  		require.NotNil(t, err)
   142  
   143  		_, err = types.AccAddressFromBech32(str)
   144  		require.NotNil(t, err)
   145  
   146  		err = (*types.AccAddress)(nil).UnmarshalJSON([]byte("\"" + str + "\""))
   147  		require.NotNil(t, err)
   148  	}
   149  }
   150  
   151  func TestValAddr(t *testing.T) {
   152  	var pub ed25519.PubKeyEd25519
   153  
   154  	for i := 0; i < 20; i++ {
   155  		rand.Read(pub[:])
   156  
   157  		acc := types.ValAddress(pub.Address())
   158  		res := types.ValAddress{}
   159  
   160  		testMarshal(t, &acc, &res, acc.MarshalJSON, (&res).UnmarshalJSON)
   161  		testMarshal(t, &acc, &res, acc.Marshal, (&res).Unmarshal)
   162  
   163  		str := acc.String()
   164  		res, err := types.ValAddressFromBech32(str)
   165  		require.Nil(t, err)
   166  		require.Equal(t, acc, res)
   167  
   168  		str = hex.EncodeToString(acc)
   169  		res, err = types.ValAddressFromHex(str)
   170  		require.Nil(t, err)
   171  		require.Equal(t, acc, res)
   172  	}
   173  
   174  	for _, str := range invalidStrs {
   175  		_, err := types.ValAddressFromHex(str)
   176  		require.NotNil(t, err)
   177  
   178  		_, err = types.ValAddressFromBech32(str)
   179  		require.NotNil(t, err)
   180  
   181  		err = (*types.ValAddress)(nil).UnmarshalJSON([]byte("\"" + str + "\""))
   182  		require.NotNil(t, err)
   183  	}
   184  }
   185  
   186  func TestConsAddress(t *testing.T) {
   187  	var pub ed25519.PubKeyEd25519
   188  
   189  	for i := 0; i < 20; i++ {
   190  		rand.Read(pub[:])
   191  
   192  		acc := types.ConsAddress(pub.Address())
   193  		res := types.ConsAddress{}
   194  
   195  		testMarshal(t, &acc, &res, acc.MarshalJSON, (&res).UnmarshalJSON)
   196  		testMarshal(t, &acc, &res, acc.Marshal, (&res).Unmarshal)
   197  
   198  		str := acc.String()
   199  		res, err := types.ConsAddressFromBech32(str)
   200  		require.Nil(t, err)
   201  		require.Equal(t, acc, res)
   202  
   203  		str = hex.EncodeToString(acc)
   204  		res, err = types.ConsAddressFromHex(str)
   205  		require.Nil(t, err)
   206  		require.Equal(t, acc, res)
   207  	}
   208  
   209  	for _, str := range invalidStrs {
   210  		_, err := types.ConsAddressFromHex(str)
   211  		require.NotNil(t, err)
   212  
   213  		_, err = types.ConsAddressFromBech32(str)
   214  		require.NotNil(t, err)
   215  
   216  		err = (*types.ConsAddress)(nil).UnmarshalJSON([]byte("\"" + str + "\""))
   217  		require.NotNil(t, err)
   218  	}
   219  }
   220  
   221  const letterBytes = "abcdefghijklmnopqrstuvwxyz"
   222  
   223  func RandString(n int) string {
   224  	b := make([]byte, n)
   225  	for i := range b {
   226  		b[i] = letterBytes[rand.Intn(len(letterBytes))]
   227  	}
   228  	return string(b)
   229  }
   230  
   231  func TestConfiguredPrefix(t *testing.T) {
   232  	var pub ed25519.PubKeyEd25519
   233  	for length := 1; length < 10; length++ {
   234  		for times := 1; times < 20; times++ {
   235  			rand.Read(pub[:])
   236  			// Test if randomly generated prefix of a given length works
   237  			prefix := RandString(length)
   238  
   239  			// Assuming that GetConfig is not sealed.
   240  			config := types.GetConfig()
   241  			config.SetBech32PrefixForAccount(
   242  				prefix+types.PrefixAccount,
   243  				prefix+types.PrefixPublic)
   244  
   245  			acc := types.AccAddress(pub.Address())
   246  			require.True(t, strings.HasPrefix(
   247  				acc.String(),
   248  				prefix+types.PrefixAccount), acc.String())
   249  
   250  			bech32Pub := types.MustBech32ifyPubKey(types.Bech32PubKeyTypeAccPub, pub)
   251  			require.True(t, strings.HasPrefix(
   252  				bech32Pub,
   253  				prefix+types.PrefixPublic))
   254  
   255  			config.SetBech32PrefixForValidator(
   256  				prefix+types.PrefixValidator+types.PrefixAddress,
   257  				prefix+types.PrefixValidator+types.PrefixPublic)
   258  
   259  			val := types.ValAddress(pub.Address())
   260  			require.True(t, strings.HasPrefix(
   261  				val.String(),
   262  				prefix+types.PrefixValidator+types.PrefixAddress))
   263  
   264  			bech32ValPub := types.MustBech32ifyPubKey(types.Bech32PubKeyTypeValPub, pub)
   265  			require.True(t, strings.HasPrefix(
   266  				bech32ValPub,
   267  				prefix+types.PrefixValidator+types.PrefixPublic))
   268  
   269  			config.SetBech32PrefixForConsensusNode(
   270  				prefix+types.PrefixConsensus+types.PrefixAddress,
   271  				prefix+types.PrefixConsensus+types.PrefixPublic)
   272  
   273  			cons := types.ConsAddress(pub.Address())
   274  			require.True(t, strings.HasPrefix(
   275  				cons.String(),
   276  				prefix+types.PrefixConsensus+types.PrefixAddress))
   277  
   278  			bech32ConsPub := types.MustBech32ifyPubKey(types.Bech32PubKeyTypeConsPub, pub)
   279  			require.True(t, strings.HasPrefix(
   280  				bech32ConsPub,
   281  				prefix+types.PrefixConsensus+types.PrefixPublic))
   282  		}
   283  	}
   284  }
   285  
   286  func TestAddressInterface(t *testing.T) {
   287  	var pub ed25519.PubKeyEd25519
   288  	rand.Read(pub[:])
   289  
   290  	addrs := []types.Address{
   291  		types.ConsAddress(pub.Address()),
   292  		types.ValAddress(pub.Address()),
   293  		types.AccAddress(pub.Address()),
   294  	}
   295  
   296  	for _, addr := range addrs {
   297  		switch addr := addr.(type) {
   298  		case types.AccAddress:
   299  			_, err := types.AccAddressFromBech32(addr.String())
   300  			require.Nil(t, err)
   301  		case types.ValAddress:
   302  			_, err := types.ValAddressFromBech32(addr.String())
   303  			require.Nil(t, err)
   304  		case types.ConsAddress:
   305  			_, err := types.ConsAddressFromBech32(addr.String())
   306  			require.Nil(t, err)
   307  		default:
   308  			t.Fail()
   309  		}
   310  	}
   311  
   312  }
   313  
   314  func TestCustomAddressVerifier(t *testing.T) {
   315  	// Create a 10 byte address
   316  	addr := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
   317  	accBech := types.AccAddress(addr).String()
   318  	valBech := types.ValAddress(addr).String()
   319  	consBech := types.ConsAddress(addr).String()
   320  	// Verifiy that the default logic rejects this 10 byte address
   321  	err := types.VerifyAddressFormat(addr)
   322  	require.NotNil(t, err)
   323  	_, err = types.AccAddressFromBech32(accBech)
   324  	require.NotNil(t, err)
   325  	_, err = types.ValAddressFromBech32(valBech)
   326  	require.NotNil(t, err)
   327  	_, err = types.ConsAddressFromBech32(consBech)
   328  	require.NotNil(t, err)
   329  
   330  	// Set a custom address verifier that accepts 10 or 20 byte addresses
   331  	types.GetConfig().SetAddressVerifier(func(bz []byte) error {
   332  		n := len(bz)
   333  		if n == 10 || n == types.AddrLen {
   334  			return nil
   335  		}
   336  		return fmt.Errorf("incorrect address length %d", n)
   337  	})
   338  
   339  	// Verifiy that the custom logic accepts this 10 byte address
   340  	err = types.VerifyAddressFormat(addr)
   341  	require.Nil(t, err)
   342  	_, err = types.AccAddressFromBech32(accBech)
   343  	require.Nil(t, err)
   344  	_, err = types.ValAddressFromBech32(valBech)
   345  	require.Nil(t, err)
   346  	_, err = types.ConsAddressFromBech32(consBech)
   347  	require.Nil(t, err)
   348  }
   349  
   350  func BenchmarkAccAddress_Bech32String(b *testing.B) {
   351  	acc := types.AccAddress(evmtypes.GenerateEthAddress().Bytes())
   352  	prefix := types.GetConfig().GetBech32AccountAddrPrefix()
   353  	b.ResetTimer()
   354  	b.Run("Bench32 origin", func(b *testing.B) {
   355  		b.ReportAllocs()
   356  		for i := 0; i < b.N; i++ {
   357  			_ = acc.Bech32String(prefix)
   358  		}
   359  	})
   360  	b.Run("Bench32 Optimized", func(b *testing.B) {
   361  		b.ReportAllocs()
   362  		for i := 0; i < b.N; i++ {
   363  			_ = acc.Bech32StringOptimized(prefix)
   364  		}
   365  	})
   366  	require.EqualValues(b, acc.Bech32String(prefix), acc.Bech32StringOptimized(prefix))
   367  }
   368  
   369  func BenchmarkAccAddressFromBech32String(b *testing.B) {
   370  	buffer := make([]byte, 32)
   371  	copy(buffer, []byte("test"))
   372  	acc := types.AccAddress(buffer)
   373  	prefix := types.GetConfig().GetBech32AccountAddrPrefix()
   374  	sender := acc.Bech32String(prefix)
   375  	b.ResetTimer()
   376  	b.Run("AccAddressFromBech32", func(b *testing.B) {
   377  		b.ReportAllocs()
   378  		for i := 0; i < b.N; i++ {
   379  			_, err := types.AccAddressFromBech32(sender)
   380  			require.NoError(b, err)
   381  		}
   382  	})
   383  }