2018-01-07 12:27:56 -08:00
|
|
|
package types
|
2018-01-06 14:22:21 -08:00
|
|
|
|
|
|
|
import (
|
2018-08-04 22:56:48 -07:00
|
|
|
"bytes"
|
2018-03-17 11:18:04 -07:00
|
|
|
"encoding/hex"
|
2018-07-09 16:06:05 -07:00
|
|
|
"encoding/json"
|
2018-03-17 11:18:04 -07:00
|
|
|
"errors"
|
2018-05-26 14:21:29 -07:00
|
|
|
"fmt"
|
2019-02-08 15:54:40 -08:00
|
|
|
"strings"
|
2021-02-25 03:01:03 -08:00
|
|
|
"sync"
|
2018-03-17 11:18:04 -07:00
|
|
|
|
2021-04-06 16:33:54 -07:00
|
|
|
"github.com/hashicorp/golang-lru/simplelru"
|
2021-09-24 07:37:34 -07:00
|
|
|
"sigs.k8s.io/yaml"
|
2021-04-06 16:33:54 -07:00
|
|
|
|
2020-11-09 08:01:43 -08:00
|
|
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
2021-03-02 19:53:28 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/internal/conv"
|
2021-02-01 05:17:44 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/types/address"
|
2020-05-12 09:53:30 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/types/bech32"
|
2021-02-01 05:17:44 -08:00
|
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
2018-01-06 14:22:21 -08:00
|
|
|
)
|
|
|
|
|
2018-05-28 16:27:34 -07:00
|
|
|
const (
|
2019-06-04 05:59:14 -07:00
|
|
|
// Constants defined here are the defaults value for address.
|
|
|
|
// You can use the specific values for your project.
|
|
|
|
// Add the follow lines to the `main()` of your server.
|
|
|
|
//
|
|
|
|
// config := sdk.GetConfig()
|
|
|
|
// config.SetBech32PrefixForAccount(yourBech32PrefixAccAddr, yourBech32PrefixAccPub)
|
|
|
|
// config.SetBech32PrefixForValidator(yourBech32PrefixValAddr, yourBech32PrefixValPub)
|
|
|
|
// config.SetBech32PrefixForConsensusNode(yourBech32PrefixConsAddr, yourBech32PrefixConsPub)
|
2021-02-22 07:14:09 -08:00
|
|
|
// config.SetPurpose(yourPurpose)
|
2019-06-04 05:59:14 -07:00
|
|
|
// config.SetCoinType(yourCoinType)
|
|
|
|
// config.Seal()
|
|
|
|
|
2020-11-18 10:42:45 -08:00
|
|
|
// Bech32MainPrefix defines the main SDK Bech32 prefix of an account's address
|
2019-02-18 13:35:08 -08:00
|
|
|
Bech32MainPrefix = "cosmos"
|
|
|
|
|
2021-02-22 07:14:09 -08:00
|
|
|
// Purpose is the ATOM purpose as defined in SLIP44 (https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
|
|
|
|
Purpose = 44
|
|
|
|
|
2020-11-18 10:42:45 -08:00
|
|
|
// CoinType is the ATOM coin type as defined in SLIP44 (https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
|
2019-05-30 05:46:38 -07:00
|
|
|
CoinType = 118
|
|
|
|
|
2020-11-18 10:42:45 -08:00
|
|
|
// FullFundraiserPath is the parts of the BIP44 HD path that are fixed by
|
|
|
|
// what we used during the ATOM fundraiser.
|
|
|
|
FullFundraiserPath = "m/44'/118'/0'/0/0"
|
2019-05-30 05:46:38 -07:00
|
|
|
|
2019-02-18 13:35:08 -08:00
|
|
|
// PrefixAccount is the prefix for account keys
|
|
|
|
PrefixAccount = "acc"
|
|
|
|
// PrefixValidator is the prefix for validator keys
|
|
|
|
PrefixValidator = "val"
|
|
|
|
// PrefixConsensus is the prefix for consensus keys
|
|
|
|
PrefixConsensus = "cons"
|
|
|
|
// PrefixPublic is the prefix for public keys
|
|
|
|
PrefixPublic = "pub"
|
|
|
|
// PrefixOperator is the prefix for operator keys
|
|
|
|
PrefixOperator = "oper"
|
|
|
|
|
|
|
|
// PrefixAddress is the prefix for addresses
|
|
|
|
PrefixAddress = "addr"
|
2018-07-04 14:07:06 -07:00
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Bech32PrefixAccAddr defines the Bech32 prefix of an account's address
|
2019-02-18 13:35:08 -08:00
|
|
|
Bech32PrefixAccAddr = Bech32MainPrefix
|
2018-08-30 21:06:44 -07:00
|
|
|
// Bech32PrefixAccPub defines the Bech32 prefix of an account's public key
|
2019-02-18 13:35:08 -08:00
|
|
|
Bech32PrefixAccPub = Bech32MainPrefix + PrefixPublic
|
2018-08-30 21:06:44 -07:00
|
|
|
// Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address
|
2019-02-18 13:35:08 -08:00
|
|
|
Bech32PrefixValAddr = Bech32MainPrefix + PrefixValidator + PrefixOperator
|
2018-08-30 21:06:44 -07:00
|
|
|
// Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key
|
2019-02-18 13:35:08 -08:00
|
|
|
Bech32PrefixValPub = Bech32MainPrefix + PrefixValidator + PrefixOperator + PrefixPublic
|
2018-08-30 21:06:44 -07:00
|
|
|
// Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address
|
2019-02-18 13:35:08 -08:00
|
|
|
Bech32PrefixConsAddr = Bech32MainPrefix + PrefixValidator + PrefixConsensus
|
2018-08-30 21:06:44 -07:00
|
|
|
// Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key
|
2019-02-18 13:35:08 -08:00
|
|
|
Bech32PrefixConsPub = Bech32MainPrefix + PrefixValidator + PrefixConsensus + PrefixPublic
|
2018-05-28 16:27:34 -07:00
|
|
|
)
|
|
|
|
|
2021-03-02 19:53:28 -08:00
|
|
|
// cache variables
|
|
|
|
var (
|
|
|
|
// AccAddress.String() is expensive and if unoptimized dominantly showed up in profiles,
|
|
|
|
// yet has no mechanisms to trivially cache the result given that AccAddress is a []byte type.
|
2021-03-25 06:51:34 -07:00
|
|
|
accAddrMu sync.Mutex
|
2021-03-02 19:53:28 -08:00
|
|
|
accAddrCache *simplelru.LRU
|
2021-03-25 06:51:34 -07:00
|
|
|
consAddrMu sync.Mutex
|
2021-03-02 19:53:28 -08:00
|
|
|
consAddrCache *simplelru.LRU
|
2021-03-25 06:51:34 -07:00
|
|
|
valAddrMu sync.Mutex
|
2021-03-02 19:53:28 -08:00
|
|
|
valAddrCache *simplelru.LRU
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
var err error
|
|
|
|
// in total the cache size is 61k entries. Key is 32 bytes and value is around 50-70 bytes.
|
|
|
|
// That will make around 92 * 61k * 2 (LRU) bytes ~ 11 MB
|
|
|
|
if accAddrCache, err = simplelru.NewLRU(60000, nil); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
if consAddrCache, err = simplelru.NewLRU(500, nil); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
if valAddrCache, err = simplelru.NewLRU(500, nil); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-04 14:09:39 -08:00
|
|
|
// Address is a common interface for different types of addresses used by the SDK
|
|
|
|
type Address interface {
|
|
|
|
Equals(Address) bool
|
|
|
|
Empty() bool
|
|
|
|
Marshal() ([]byte, error)
|
|
|
|
MarshalJSON() ([]byte, error)
|
|
|
|
Bytes() []byte
|
|
|
|
String() string
|
|
|
|
Format(s fmt.State, verb rune)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that different address types implement the interface
|
|
|
|
var _ Address = AccAddress{}
|
|
|
|
var _ Address = ValAddress{}
|
|
|
|
var _ Address = ConsAddress{}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// account
|
|
|
|
// ----------------------------------------------------------------------------
|
2018-07-06 00:06:53 -07:00
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// AccAddress a wrapper around bytes meant to represent an account address.
|
|
|
|
// When marshaled to a string or JSON, it uses Bech32.
|
2018-07-06 00:06:53 -07:00
|
|
|
type AccAddress []byte
|
2018-07-03 21:52:48 -07:00
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// AccAddressFromHex creates an AccAddress from a hex string.
|
2018-07-09 16:06:05 -07:00
|
|
|
func AccAddressFromHex(address string) (addr AccAddress, err error) {
|
2020-03-04 09:49:59 -08:00
|
|
|
bz, err := addressBytesFromHexString(address)
|
|
|
|
return AccAddress(bz), err
|
2018-07-06 00:06:53 -07:00
|
|
|
}
|
|
|
|
|
2019-05-02 12:36:42 -07:00
|
|
|
// VerifyAddressFormat verifies that the provided bytes form a valid address
|
|
|
|
// according to the default address rules or a custom address verifier set by
|
2021-08-25 04:17:18 -07:00
|
|
|
// GetConfig().SetAddressVerifier().
|
|
|
|
// TODO make an issue to get rid of global Config
|
|
|
|
// ref: https://github.com/cosmos/cosmos-sdk/issues/9690
|
2019-05-02 12:36:42 -07:00
|
|
|
func VerifyAddressFormat(bz []byte) error {
|
|
|
|
verifier := GetConfig().GetAddressVerifier()
|
|
|
|
if verifier != nil {
|
|
|
|
return verifier(bz)
|
2019-05-16 08:25:32 -07:00
|
|
|
}
|
2021-02-01 05:17:44 -08:00
|
|
|
|
|
|
|
if len(bz) == 0 {
|
|
|
|
return sdkerrors.Wrap(sdkerrors.ErrUnknownAddress, "addresses cannot be empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(bz) > address.MaxAddrLen {
|
|
|
|
return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "address max length is %d, got %d", address.MaxAddrLen, len(bz))
|
2019-05-02 12:36:42 -07:00
|
|
|
}
|
2021-02-01 05:17:44 -08:00
|
|
|
|
2019-05-02 12:36:42 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// AccAddressFromBech32 creates an AccAddress from a Bech32 string.
|
2018-07-09 16:06:05 -07:00
|
|
|
func AccAddressFromBech32(address string) (addr AccAddress, err error) {
|
2019-02-08 15:54:40 -08:00
|
|
|
if len(strings.TrimSpace(address)) == 0 {
|
2020-08-04 12:15:58 -07:00
|
|
|
return AccAddress{}, errors.New("empty address string is not allowed")
|
2019-02-08 15:54:40 -08:00
|
|
|
}
|
|
|
|
|
2018-10-31 12:13:13 -07:00
|
|
|
bech32PrefixAccAddr := GetConfig().GetBech32AccountAddrPrefix()
|
2019-02-08 15:54:40 -08:00
|
|
|
|
2018-10-31 12:13:13 -07:00
|
|
|
bz, err := GetFromBech32(address, bech32PrefixAccAddr)
|
2018-07-06 00:06:53 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-08-30 21:06:44 -07:00
|
|
|
|
2019-05-02 12:36:42 -07:00
|
|
|
err = VerifyAddressFormat(bz)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2019-02-08 15:54:40 -08:00
|
|
|
}
|
|
|
|
|
2018-07-06 00:06:53 -07:00
|
|
|
return AccAddress(bz), nil
|
2018-07-03 21:52:48 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Returns boolean for whether two AccAddresses are Equal
|
2019-01-04 14:09:39 -08:00
|
|
|
func (aa AccAddress) Equals(aa2 Address) bool {
|
2018-08-30 21:06:44 -07:00
|
|
|
if aa.Empty() && aa2.Empty() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2019-02-08 12:45:23 -08:00
|
|
|
return bytes.Equal(aa.Bytes(), aa2.Bytes())
|
2018-08-30 21:06:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns boolean for whether an AccAddress is empty
|
|
|
|
func (aa AccAddress) Empty() bool {
|
2021-03-02 19:53:28 -08:00
|
|
|
return aa == nil || len(aa) == 0
|
2018-05-26 14:21:29 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Marshal returns the raw address bytes. It is needed for protobuf
|
|
|
|
// compatibility.
|
|
|
|
func (aa AccAddress) Marshal() ([]byte, error) {
|
|
|
|
return aa, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unmarshal sets the address to the given data. It is needed for protobuf
|
|
|
|
// compatibility.
|
|
|
|
func (aa *AccAddress) Unmarshal(data []byte) error {
|
|
|
|
*aa = data
|
2018-07-03 21:52:48 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// MarshalJSON marshals to JSON using Bech32.
|
|
|
|
func (aa AccAddress) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(aa.String())
|
2018-07-03 21:52:48 -07:00
|
|
|
}
|
|
|
|
|
2019-05-31 06:14:35 -07:00
|
|
|
// MarshalYAML marshals to YAML using Bech32.
|
|
|
|
func (aa AccAddress) MarshalYAML() (interface{}, error) {
|
|
|
|
return aa.String(), nil
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// UnmarshalJSON unmarshals from JSON assuming Bech32 encoding.
|
|
|
|
func (aa *AccAddress) UnmarshalJSON(data []byte) error {
|
2018-07-09 16:06:05 -07:00
|
|
|
var s string
|
|
|
|
err := json.Unmarshal(data, &s)
|
2020-09-25 03:25:37 -07:00
|
|
|
|
2018-07-09 16:06:05 -07:00
|
|
|
if err != nil {
|
2018-09-01 04:14:17 -07:00
|
|
|
return err
|
2018-07-03 21:52:48 -07:00
|
|
|
}
|
2020-08-04 12:15:58 -07:00
|
|
|
if s == "" {
|
|
|
|
*aa = AccAddress{}
|
|
|
|
return nil
|
|
|
|
}
|
2018-07-03 21:52:48 -07:00
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
aa2, err := AccAddressFromBech32(s)
|
2018-07-03 21:52:48 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-08-30 21:06:44 -07:00
|
|
|
|
|
|
|
*aa = aa2
|
2018-07-03 21:52:48 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-05-31 06:14:35 -07:00
|
|
|
// UnmarshalYAML unmarshals from JSON assuming Bech32 encoding.
|
|
|
|
func (aa *AccAddress) UnmarshalYAML(data []byte) error {
|
|
|
|
var s string
|
|
|
|
err := yaml.Unmarshal(data, &s)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-08-04 12:15:58 -07:00
|
|
|
if s == "" {
|
|
|
|
*aa = AccAddress{}
|
|
|
|
return nil
|
|
|
|
}
|
2019-05-31 06:14:35 -07:00
|
|
|
|
|
|
|
aa2, err := AccAddressFromBech32(s)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*aa = aa2
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Bytes returns the raw address bytes.
|
|
|
|
func (aa AccAddress) Bytes() []byte {
|
|
|
|
return aa
|
2018-07-03 21:52:48 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// String implements the Stringer interface.
|
2021-03-02 19:53:28 -08:00
|
|
|
func (aa AccAddress) String() string {
|
2019-02-08 15:54:40 -08:00
|
|
|
if aa.Empty() {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2021-03-02 19:53:28 -08:00
|
|
|
var key = conv.UnsafeBytesToStr(aa)
|
2021-03-25 06:51:34 -07:00
|
|
|
accAddrMu.Lock()
|
|
|
|
defer accAddrMu.Unlock()
|
2021-03-16 10:48:54 -07:00
|
|
|
addr, ok := accAddrCache.Get(key)
|
|
|
|
if ok {
|
2021-03-02 19:53:28 -08:00
|
|
|
return addr.(string)
|
2018-06-07 15:32:14 -07:00
|
|
|
}
|
2021-03-25 06:51:34 -07:00
|
|
|
return cacheBech32Addr(GetConfig().GetBech32AccountAddrPrefix(), aa, accAddrCache, key)
|
2018-07-03 21:52:48 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Format implements the fmt.Formatter interface.
|
2018-08-31 15:22:37 -07:00
|
|
|
// nolint: errcheck
|
2018-08-30 21:06:44 -07:00
|
|
|
func (aa AccAddress) Format(s fmt.State, verb rune) {
|
2018-07-03 21:52:48 -07:00
|
|
|
switch verb {
|
|
|
|
case 's':
|
2019-02-08 12:45:23 -08:00
|
|
|
s.Write([]byte(aa.String()))
|
2018-07-03 21:52:48 -07:00
|
|
|
case 'p':
|
2018-08-30 21:06:44 -07:00
|
|
|
s.Write([]byte(fmt.Sprintf("%p", aa)))
|
2018-07-03 21:52:48 -07:00
|
|
|
default:
|
2018-08-30 21:06:44 -07:00
|
|
|
s.Write([]byte(fmt.Sprintf("%X", []byte(aa))))
|
2018-07-03 21:52:48 -07:00
|
|
|
}
|
2018-06-07 15:32:14 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
2018-09-08 01:44:58 -07:00
|
|
|
// validator operator
|
2018-08-30 21:06:44 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
2018-08-04 22:56:48 -07:00
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// ValAddress defines a wrapper around bytes meant to present a validator's
|
|
|
|
// operator. When marshaled to a string or JSON, it uses Bech32.
|
2018-07-06 00:06:53 -07:00
|
|
|
type ValAddress []byte
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// ValAddressFromHex creates a ValAddress from a hex string.
|
2018-07-09 16:06:05 -07:00
|
|
|
func ValAddressFromHex(address string) (addr ValAddress, err error) {
|
2020-03-04 09:49:59 -08:00
|
|
|
bz, err := addressBytesFromHexString(address)
|
|
|
|
return ValAddress(bz), err
|
2018-05-26 14:21:29 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// ValAddressFromBech32 creates a ValAddress from a Bech32 string.
|
2018-07-09 16:06:05 -07:00
|
|
|
func ValAddressFromBech32(address string) (addr ValAddress, err error) {
|
2019-02-08 15:54:40 -08:00
|
|
|
if len(strings.TrimSpace(address)) == 0 {
|
2020-08-04 12:15:58 -07:00
|
|
|
return ValAddress{}, errors.New("empty address string is not allowed")
|
2019-02-08 15:54:40 -08:00
|
|
|
}
|
|
|
|
|
2018-10-31 12:13:13 -07:00
|
|
|
bech32PrefixValAddr := GetConfig().GetBech32ValidatorAddrPrefix()
|
2019-02-08 15:54:40 -08:00
|
|
|
|
2018-10-31 12:13:13 -07:00
|
|
|
bz, err := GetFromBech32(address, bech32PrefixValAddr)
|
2018-06-07 15:32:14 -07:00
|
|
|
if err != nil {
|
2018-07-06 00:06:53 -07:00
|
|
|
return nil, err
|
2018-06-07 15:32:14 -07:00
|
|
|
}
|
2018-08-30 21:06:44 -07:00
|
|
|
|
2019-05-02 12:36:42 -07:00
|
|
|
err = VerifyAddressFormat(bz)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2019-02-08 15:54:40 -08:00
|
|
|
}
|
|
|
|
|
2018-07-06 00:06:53 -07:00
|
|
|
return ValAddress(bz), nil
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Returns boolean for whether two ValAddresses are Equal
|
2019-01-04 14:09:39 -08:00
|
|
|
func (va ValAddress) Equals(va2 Address) bool {
|
2018-08-30 21:06:44 -07:00
|
|
|
if va.Empty() && va2.Empty() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2019-02-08 12:45:23 -08:00
|
|
|
return bytes.Equal(va.Bytes(), va2.Bytes())
|
2018-08-30 21:06:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns boolean for whether an AccAddress is empty
|
|
|
|
func (va ValAddress) Empty() bool {
|
2021-03-02 19:53:28 -08:00
|
|
|
return va == nil || len(va) == 0
|
2018-08-30 21:06:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Marshal returns the raw address bytes. It is needed for protobuf
|
|
|
|
// compatibility.
|
|
|
|
func (va ValAddress) Marshal() ([]byte, error) {
|
|
|
|
return va, nil
|
2018-06-07 15:32:14 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Unmarshal sets the address to the given data. It is needed for protobuf
|
|
|
|
// compatibility.
|
|
|
|
func (va *ValAddress) Unmarshal(data []byte) error {
|
|
|
|
*va = data
|
2018-07-06 00:06:53 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// MarshalJSON marshals to JSON using Bech32.
|
|
|
|
func (va ValAddress) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(va.String())
|
2018-05-26 14:21:29 -07:00
|
|
|
}
|
|
|
|
|
2019-05-31 06:14:35 -07:00
|
|
|
// MarshalYAML marshals to YAML using Bech32.
|
|
|
|
func (va ValAddress) MarshalYAML() (interface{}, error) {
|
|
|
|
return va.String(), nil
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// UnmarshalJSON unmarshals from JSON assuming Bech32 encoding.
|
|
|
|
func (va *ValAddress) UnmarshalJSON(data []byte) error {
|
2018-07-09 16:06:05 -07:00
|
|
|
var s string
|
2018-08-30 21:06:44 -07:00
|
|
|
|
2018-07-09 16:06:05 -07:00
|
|
|
err := json.Unmarshal(data, &s)
|
|
|
|
if err != nil {
|
2019-03-06 03:38:18 -08:00
|
|
|
return err
|
2018-07-06 00:06:53 -07:00
|
|
|
}
|
2020-08-04 12:15:58 -07:00
|
|
|
if s == "" {
|
|
|
|
*va = ValAddress{}
|
|
|
|
return nil
|
|
|
|
}
|
2018-07-06 00:06:53 -07:00
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
va2, err := ValAddressFromBech32(s)
|
2018-06-07 15:32:14 -07:00
|
|
|
if err != nil {
|
2018-07-06 00:06:53 -07:00
|
|
|
return err
|
2018-06-07 15:32:14 -07:00
|
|
|
}
|
2018-08-30 21:06:44 -07:00
|
|
|
|
|
|
|
*va = va2
|
2018-07-06 00:06:53 -07:00
|
|
|
return nil
|
2018-06-07 15:32:14 -07:00
|
|
|
}
|
|
|
|
|
2019-05-31 06:14:35 -07:00
|
|
|
// UnmarshalYAML unmarshals from YAML assuming Bech32 encoding.
|
|
|
|
func (va *ValAddress) UnmarshalYAML(data []byte) error {
|
|
|
|
var s string
|
|
|
|
|
|
|
|
err := yaml.Unmarshal(data, &s)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-08-04 12:15:58 -07:00
|
|
|
if s == "" {
|
|
|
|
*va = ValAddress{}
|
|
|
|
return nil
|
|
|
|
}
|
2019-05-31 06:14:35 -07:00
|
|
|
|
|
|
|
va2, err := ValAddressFromBech32(s)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*va = va2
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Bytes returns the raw address bytes.
|
|
|
|
func (va ValAddress) Bytes() []byte {
|
|
|
|
return va
|
2018-05-26 14:21:29 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// String implements the Stringer interface.
|
|
|
|
func (va ValAddress) String() string {
|
2019-02-08 15:54:40 -08:00
|
|
|
if va.Empty() {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2021-03-02 19:53:28 -08:00
|
|
|
var key = conv.UnsafeBytesToStr(va)
|
2021-03-25 06:51:34 -07:00
|
|
|
valAddrMu.Lock()
|
|
|
|
defer valAddrMu.Unlock()
|
2021-03-16 10:48:54 -07:00
|
|
|
addr, ok := valAddrCache.Get(key)
|
|
|
|
if ok {
|
2021-03-02 19:53:28 -08:00
|
|
|
return addr.(string)
|
2018-06-07 15:32:14 -07:00
|
|
|
}
|
2021-03-25 06:51:34 -07:00
|
|
|
return cacheBech32Addr(GetConfig().GetBech32ValidatorAddrPrefix(), va, valAddrCache, key)
|
2018-06-07 15:32:14 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Format implements the fmt.Formatter interface.
|
2018-08-31 15:22:37 -07:00
|
|
|
// nolint: errcheck
|
2018-08-30 21:06:44 -07:00
|
|
|
func (va ValAddress) Format(s fmt.State, verb rune) {
|
2018-07-06 00:06:53 -07:00
|
|
|
switch verb {
|
|
|
|
case 's':
|
2019-02-08 12:45:23 -08:00
|
|
|
s.Write([]byte(va.String()))
|
2018-07-06 00:06:53 -07:00
|
|
|
case 'p':
|
2018-08-30 21:06:44 -07:00
|
|
|
s.Write([]byte(fmt.Sprintf("%p", va)))
|
2018-07-06 00:06:53 -07:00
|
|
|
default:
|
2018-08-30 21:06:44 -07:00
|
|
|
s.Write([]byte(fmt.Sprintf("%X", []byte(va))))
|
2018-03-17 11:18:04 -07:00
|
|
|
}
|
|
|
|
}
|
2018-05-26 14:21:29 -07:00
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// consensus node
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// ConsAddress defines a wrapper around bytes meant to present a consensus node.
|
|
|
|
// When marshaled to a string or JSON, it uses Bech32.
|
|
|
|
type ConsAddress []byte
|
|
|
|
|
|
|
|
// ConsAddressFromHex creates a ConsAddress from a hex string.
|
|
|
|
func ConsAddressFromHex(address string) (addr ConsAddress, err error) {
|
2020-03-04 09:49:59 -08:00
|
|
|
bz, err := addressBytesFromHexString(address)
|
|
|
|
return ConsAddress(bz), err
|
2018-08-30 21:06:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// ConsAddressFromBech32 creates a ConsAddress from a Bech32 string.
|
|
|
|
func ConsAddressFromBech32(address string) (addr ConsAddress, err error) {
|
2019-02-08 15:54:40 -08:00
|
|
|
if len(strings.TrimSpace(address)) == 0 {
|
2020-08-04 12:15:58 -07:00
|
|
|
return ConsAddress{}, errors.New("empty address string is not allowed")
|
2019-02-08 15:54:40 -08:00
|
|
|
}
|
|
|
|
|
2018-10-31 12:13:13 -07:00
|
|
|
bech32PrefixConsAddr := GetConfig().GetBech32ConsensusAddrPrefix()
|
2019-02-08 15:54:40 -08:00
|
|
|
|
2018-10-31 12:13:13 -07:00
|
|
|
bz, err := GetFromBech32(address, bech32PrefixConsAddr)
|
2018-08-30 21:06:44 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-05-02 12:36:42 -07:00
|
|
|
err = VerifyAddressFormat(bz)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2019-02-08 15:54:40 -08:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
return ConsAddress(bz), nil
|
|
|
|
}
|
|
|
|
|
2018-09-24 21:09:31 -07:00
|
|
|
// get ConsAddress from pubkey
|
2020-11-09 08:01:43 -08:00
|
|
|
func GetConsAddress(pubkey cryptotypes.PubKey) ConsAddress {
|
2018-09-24 21:09:31 -07:00
|
|
|
return ConsAddress(pubkey.Address())
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Returns boolean for whether two ConsAddress are Equal
|
2019-01-04 14:09:39 -08:00
|
|
|
func (ca ConsAddress) Equals(ca2 Address) bool {
|
2018-08-30 21:06:44 -07:00
|
|
|
if ca.Empty() && ca2.Empty() {
|
2018-08-16 18:35:17 -07:00
|
|
|
return true
|
|
|
|
}
|
2018-08-30 21:06:44 -07:00
|
|
|
|
2019-02-08 12:45:23 -08:00
|
|
|
return bytes.Equal(ca.Bytes(), ca2.Bytes())
|
2018-08-04 22:56:48 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Returns boolean for whether an ConsAddress is empty
|
|
|
|
func (ca ConsAddress) Empty() bool {
|
2021-03-02 19:53:28 -08:00
|
|
|
return ca == nil || len(ca) == 0
|
2018-08-30 21:06:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Marshal returns the raw address bytes. It is needed for protobuf
|
|
|
|
// compatibility.
|
|
|
|
func (ca ConsAddress) Marshal() ([]byte, error) {
|
|
|
|
return ca, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unmarshal sets the address to the given data. It is needed for protobuf
|
|
|
|
// compatibility.
|
|
|
|
func (ca *ConsAddress) Unmarshal(data []byte) error {
|
|
|
|
*ca = data
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalJSON marshals to JSON using Bech32.
|
|
|
|
func (ca ConsAddress) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(ca.String())
|
|
|
|
}
|
|
|
|
|
2019-05-31 06:14:35 -07:00
|
|
|
// MarshalYAML marshals to YAML using Bech32.
|
|
|
|
func (ca ConsAddress) MarshalYAML() (interface{}, error) {
|
|
|
|
return ca.String(), nil
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// UnmarshalJSON unmarshals from JSON assuming Bech32 encoding.
|
|
|
|
func (ca *ConsAddress) UnmarshalJSON(data []byte) error {
|
|
|
|
var s string
|
|
|
|
|
|
|
|
err := json.Unmarshal(data, &s)
|
|
|
|
if err != nil {
|
2019-03-06 03:38:18 -08:00
|
|
|
return err
|
2018-08-30 21:06:44 -07:00
|
|
|
}
|
2020-08-04 12:15:58 -07:00
|
|
|
if s == "" {
|
|
|
|
*ca = ConsAddress{}
|
|
|
|
return nil
|
|
|
|
}
|
2018-08-30 21:06:44 -07:00
|
|
|
|
|
|
|
ca2, err := ConsAddressFromBech32(s)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-05-31 06:14:35 -07:00
|
|
|
*ca = ca2
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalYAML unmarshals from YAML assuming Bech32 encoding.
|
|
|
|
func (ca *ConsAddress) UnmarshalYAML(data []byte) error {
|
|
|
|
var s string
|
|
|
|
|
|
|
|
err := yaml.Unmarshal(data, &s)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-08-04 12:15:58 -07:00
|
|
|
if s == "" {
|
|
|
|
*ca = ConsAddress{}
|
|
|
|
return nil
|
|
|
|
}
|
2019-05-31 06:14:35 -07:00
|
|
|
|
|
|
|
ca2, err := ConsAddressFromBech32(s)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
*ca = ca2
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bytes returns the raw address bytes.
|
|
|
|
func (ca ConsAddress) Bytes() []byte {
|
|
|
|
return ca
|
|
|
|
}
|
|
|
|
|
|
|
|
// String implements the Stringer interface.
|
|
|
|
func (ca ConsAddress) String() string {
|
2019-02-08 15:54:40 -08:00
|
|
|
if ca.Empty() {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2021-03-02 19:53:28 -08:00
|
|
|
var key = conv.UnsafeBytesToStr(ca)
|
2021-03-25 06:51:34 -07:00
|
|
|
consAddrMu.Lock()
|
|
|
|
defer consAddrMu.Unlock()
|
2021-03-16 10:48:54 -07:00
|
|
|
addr, ok := consAddrCache.Get(key)
|
|
|
|
if ok {
|
2021-03-02 19:53:28 -08:00
|
|
|
return addr.(string)
|
2018-08-30 21:06:44 -07:00
|
|
|
}
|
2021-03-25 06:51:34 -07:00
|
|
|
return cacheBech32Addr(GetConfig().GetBech32ConsensusAddrPrefix(), ca, consAddrCache, key)
|
2018-08-30 21:06:44 -07:00
|
|
|
}
|
|
|
|
|
2020-01-29 01:48:53 -08:00
|
|
|
// Bech32ifyAddressBytes returns a bech32 representation of address bytes.
|
|
|
|
// Returns an empty sting if the byte slice is 0-length. Returns an error if the bech32 conversion
|
|
|
|
// fails or the prefix is empty.
|
|
|
|
func Bech32ifyAddressBytes(prefix string, bs []byte) (string, error) {
|
|
|
|
if len(bs) == 0 {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
if len(prefix) == 0 {
|
|
|
|
return "", errors.New("prefix cannot be empty")
|
|
|
|
}
|
|
|
|
return bech32.ConvertAndEncode(prefix, bs)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MustBech32ifyAddressBytes returns a bech32 representation of address bytes.
|
|
|
|
// Returns an empty sting if the byte slice is 0-length. It panics if the bech32 conversion
|
|
|
|
// fails or the prefix is empty.
|
|
|
|
func MustBech32ifyAddressBytes(prefix string, bs []byte) string {
|
|
|
|
s, err := Bech32ifyAddressBytes(prefix, bs)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// Format implements the fmt.Formatter interface.
|
2018-08-31 15:22:37 -07:00
|
|
|
// nolint: errcheck
|
2018-08-30 21:06:44 -07:00
|
|
|
func (ca ConsAddress) Format(s fmt.State, verb rune) {
|
|
|
|
switch verb {
|
|
|
|
case 's':
|
2019-02-08 12:45:23 -08:00
|
|
|
s.Write([]byte(ca.String()))
|
2018-08-30 21:06:44 -07:00
|
|
|
case 'p':
|
|
|
|
s.Write([]byte(fmt.Sprintf("%p", ca)))
|
|
|
|
default:
|
|
|
|
s.Write([]byte(fmt.Sprintf("%X", []byte(ca))))
|
|
|
|
}
|
2018-08-04 22:56:48 -07:00
|
|
|
}
|
|
|
|
|
2018-08-30 21:06:44 -07:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// auxiliary
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2021-03-25 07:53:22 -07:00
|
|
|
var errBech32EmptyAddress = errors.New("decoding Bech32 address failed: must provide a non empty address")
|
2018-08-30 21:06:44 -07:00
|
|
|
|
|
|
|
// GetFromBech32 decodes a bytestring from a Bech32 encoded string.
|
2018-06-11 13:09:29 -07:00
|
|
|
func GetFromBech32(bech32str, prefix string) ([]byte, error) {
|
2018-06-01 07:23:58 -07:00
|
|
|
if len(bech32str) == 0 {
|
2021-03-25 07:53:22 -07:00
|
|
|
return nil, errBech32EmptyAddress
|
2018-05-28 16:27:34 -07:00
|
|
|
}
|
2018-08-30 21:06:44 -07:00
|
|
|
|
2018-06-01 07:23:58 -07:00
|
|
|
hrp, bz, err := bech32.DecodeAndConvert(bech32str)
|
2018-05-28 16:27:34 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if hrp != prefix {
|
2018-08-30 21:06:44 -07:00
|
|
|
return nil, fmt.Errorf("invalid Bech32 prefix; expected %s, got %s", prefix, hrp)
|
2018-05-28 16:27:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return bz, nil
|
|
|
|
}
|
2020-03-04 09:49:59 -08:00
|
|
|
|
|
|
|
func addressBytesFromHexString(address string) ([]byte, error) {
|
|
|
|
if len(address) == 0 {
|
|
|
|
return nil, errors.New("decoding Bech32 address failed: must provide an address")
|
|
|
|
}
|
|
|
|
|
|
|
|
return hex.DecodeString(address)
|
|
|
|
}
|
2021-03-02 19:53:28 -08:00
|
|
|
|
2021-03-25 06:51:34 -07:00
|
|
|
// cacheBech32Addr is not concurrency safe. Concurrent access to cache causes race condition.
|
|
|
|
func cacheBech32Addr(prefix string, addr []byte, cache *simplelru.LRU, cacheKey string) string {
|
2021-03-02 19:53:28 -08:00
|
|
|
bech32Addr, err := bech32.ConvertAndEncode(prefix, addr)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
cache.Add(cacheKey, bech32Addr)
|
|
|
|
return bech32Addr
|
|
|
|
}
|