/types/address.go
https://github.com/maticnetwork/cosmos-sdk · Go · 730 lines · 468 code · 139 blank · 123 comment · 112 complexity · fc4a64fd8707fa909ec1ff22650d1a46 MD5 · raw file
- package types
- import (
- "bytes"
- "encoding/hex"
- "encoding/json"
- "errors"
- "fmt"
- "strings"
- "gopkg.in/yaml.v2"
- "github.com/tendermint/tendermint/crypto"
- cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
- "github.com/tendermint/tendermint/libs/bech32"
- )
- const (
- // 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)
- // config.SetCoinType(yourCoinType)
- // config.SetFullFundraiserPath(yourFullFundraiserPath)
- // config.Seal()
- // AddrLen defines a valid address length
- AddrLen = 20
- // Bech32PrefixAccAddr defines the Bech32 prefix of an account's address
- Bech32MainPrefix = "cosmos"
- // Atom in https://github.com/satoshilabs/slips/blob/master/slip-0044.md
- CoinType = 118
- // BIP44Prefix is the parts of the BIP44 HD path that are fixed by
- // what we used during the fundraiser.
- FullFundraiserPath = "44'/118'/0'/0/0"
- // 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"
- // Bech32PrefixAccAddr defines the Bech32 prefix of an account's address
- Bech32PrefixAccAddr = Bech32MainPrefix
- // Bech32PrefixAccPub defines the Bech32 prefix of an account's public key
- Bech32PrefixAccPub = Bech32MainPrefix + PrefixPublic
- // Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address
- Bech32PrefixValAddr = Bech32MainPrefix + PrefixValidator + PrefixOperator
- // Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key
- Bech32PrefixValPub = Bech32MainPrefix + PrefixValidator + PrefixOperator + PrefixPublic
- // Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address
- Bech32PrefixConsAddr = Bech32MainPrefix + PrefixValidator + PrefixConsensus
- // Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key
- Bech32PrefixConsPub = Bech32MainPrefix + PrefixValidator + PrefixConsensus + PrefixPublic
- )
- // 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{}
- var _ yaml.Marshaler = AccAddress{}
- var _ yaml.Marshaler = ValAddress{}
- var _ yaml.Marshaler = ConsAddress{}
- // ----------------------------------------------------------------------------
- // account
- // ----------------------------------------------------------------------------
- // AccAddress a wrapper around bytes meant to represent an account address.
- // When marshaled to a string or JSON, it uses Bech32.
- type AccAddress []byte
- // AccAddressFromHex creates an AccAddress from a hex string.
- func AccAddressFromHex(address string) (addr AccAddress, err error) {
- if len(address) == 0 {
- return addr, errors.New("decoding Bech32 address failed: must provide an address")
- }
- bz, err := hex.DecodeString(address)
- if err != nil {
- return nil, err
- }
- return AccAddress(bz), nil
- }
- // VerifyAddressFormat verifies that the provided bytes form a valid address
- // according to the default address rules or a custom address verifier set by
- // GetConfig().SetAddressVerifier()
- func VerifyAddressFormat(bz []byte) error {
- verifier := GetConfig().GetAddressVerifier()
- if verifier != nil {
- return verifier(bz)
- }
- if len(bz) != AddrLen {
- return errors.New("Incorrect address length")
- }
- return nil
- }
- // AccAddressFromBech32 creates an AccAddress from a Bech32 string.
- func AccAddressFromBech32(address string) (addr AccAddress, err error) {
- if len(strings.TrimSpace(address)) == 0 {
- return AccAddress{}, nil
- }
- bech32PrefixAccAddr := GetConfig().GetBech32AccountAddrPrefix()
- bz, err := GetFromBech32(address, bech32PrefixAccAddr)
- if err != nil {
- return nil, err
- }
- err = VerifyAddressFormat(bz)
- if err != nil {
- return nil, err
- }
- return AccAddress(bz), nil
- }
- // Returns boolean for whether two AccAddresses are Equal
- func (aa AccAddress) Equals(aa2 Address) bool {
- if aa.Empty() && aa2.Empty() {
- return true
- }
- return bytes.Equal(aa.Bytes(), aa2.Bytes())
- }
- // Returns boolean for whether an AccAddress is empty
- func (aa AccAddress) Empty() bool {
- if aa == nil {
- return true
- }
- aa2 := AccAddress{}
- return bytes.Equal(aa.Bytes(), aa2.Bytes())
- }
- // 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
- return nil
- }
- // MarshalJSON marshals to JSON using Bech32.
- func (aa AccAddress) MarshalJSON() ([]byte, error) {
- return json.Marshal(aa.String())
- }
- // MarshalYAML marshals to YAML using Bech32.
- func (aa AccAddress) MarshalYAML() (interface{}, error) {
- return aa.String(), nil
- }
- // UnmarshalJSON unmarshals from JSON assuming Bech32 encoding.
- func (aa *AccAddress) UnmarshalJSON(data []byte) error {
- var s string
- err := json.Unmarshal(data, &s)
- if err != nil {
- return err
- }
- aa2, err := AccAddressFromBech32(s)
- if err != nil {
- return err
- }
- *aa = aa2
- return nil
- }
- // 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
- }
- aa2, err := AccAddressFromBech32(s)
- if err != nil {
- return err
- }
- *aa = aa2
- return nil
- }
- // Bytes returns the raw address bytes.
- func (aa AccAddress) Bytes() []byte {
- return aa
- }
- // String implements the Stringer interface.
- func (aa AccAddress) String() string {
- if aa.Empty() {
- return ""
- }
- bech32PrefixAccAddr := GetConfig().GetBech32AccountAddrPrefix()
- bech32Addr, err := bech32.ConvertAndEncode(bech32PrefixAccAddr, aa.Bytes())
- if err != nil {
- panic(err)
- }
- return bech32Addr
- }
- // Format implements the fmt.Formatter interface.
- // nolint: errcheck
- func (aa AccAddress) Format(s fmt.State, verb rune) {
- switch verb {
- case 's':
- s.Write([]byte(aa.String()))
- case 'p':
- s.Write([]byte(fmt.Sprintf("%p", aa)))
- default:
- s.Write([]byte(fmt.Sprintf("%X", []byte(aa))))
- }
- }
- // ----------------------------------------------------------------------------
- // validator operator
- // ----------------------------------------------------------------------------
- // ValAddress defines a wrapper around bytes meant to present a validator's
- // operator. When marshaled to a string or JSON, it uses Bech32.
- type ValAddress []byte
- // ValAddressFromHex creates a ValAddress from a hex string.
- func ValAddressFromHex(address string) (addr ValAddress, err error) {
- if len(address) == 0 {
- return addr, errors.New("decoding Bech32 address failed: must provide an address")
- }
- bz, err := hex.DecodeString(address)
- if err != nil {
- return nil, err
- }
- return ValAddress(bz), nil
- }
- // ValAddressFromBech32 creates a ValAddress from a Bech32 string.
- func ValAddressFromBech32(address string) (addr ValAddress, err error) {
- if len(strings.TrimSpace(address)) == 0 {
- return ValAddress{}, nil
- }
- bech32PrefixValAddr := GetConfig().GetBech32ValidatorAddrPrefix()
- bz, err := GetFromBech32(address, bech32PrefixValAddr)
- if err != nil {
- return nil, err
- }
- err = VerifyAddressFormat(bz)
- if err != nil {
- return nil, err
- }
- return ValAddress(bz), nil
- }
- // Returns boolean for whether two ValAddresses are Equal
- func (va ValAddress) Equals(va2 Address) bool {
- if va.Empty() && va2.Empty() {
- return true
- }
- return bytes.Equal(va.Bytes(), va2.Bytes())
- }
- // Returns boolean for whether an AccAddress is empty
- func (va ValAddress) Empty() bool {
- if va == nil {
- return true
- }
- va2 := ValAddress{}
- return bytes.Equal(va.Bytes(), va2.Bytes())
- }
- // Marshal returns the raw address bytes. It is needed for protobuf
- // compatibility.
- func (va ValAddress) Marshal() ([]byte, error) {
- return va, nil
- }
- // Unmarshal sets the address to the given data. It is needed for protobuf
- // compatibility.
- func (va *ValAddress) Unmarshal(data []byte) error {
- *va = data
- return nil
- }
- // MarshalJSON marshals to JSON using Bech32.
- func (va ValAddress) MarshalJSON() ([]byte, error) {
- return json.Marshal(va.String())
- }
- // MarshalYAML marshals to YAML using Bech32.
- func (va ValAddress) MarshalYAML() (interface{}, error) {
- return va.String(), nil
- }
- // UnmarshalJSON unmarshals from JSON assuming Bech32 encoding.
- func (va *ValAddress) UnmarshalJSON(data []byte) error {
- var s string
- err := json.Unmarshal(data, &s)
- if err != nil {
- return err
- }
- va2, err := ValAddressFromBech32(s)
- if err != nil {
- return err
- }
- *va = va2
- return nil
- }
- // 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
- }
- va2, err := ValAddressFromBech32(s)
- if err != nil {
- return err
- }
- *va = va2
- return nil
- }
- // Bytes returns the raw address bytes.
- func (va ValAddress) Bytes() []byte {
- return va
- }
- // String implements the Stringer interface.
- func (va ValAddress) String() string {
- if va.Empty() {
- return ""
- }
- bech32PrefixValAddr := GetConfig().GetBech32ValidatorAddrPrefix()
- bech32Addr, err := bech32.ConvertAndEncode(bech32PrefixValAddr, va.Bytes())
- if err != nil {
- panic(err)
- }
- return bech32Addr
- }
- // Format implements the fmt.Formatter interface.
- // nolint: errcheck
- func (va ValAddress) Format(s fmt.State, verb rune) {
- switch verb {
- case 's':
- s.Write([]byte(va.String()))
- case 'p':
- s.Write([]byte(fmt.Sprintf("%p", va)))
- default:
- s.Write([]byte(fmt.Sprintf("%X", []byte(va))))
- }
- }
- // ----------------------------------------------------------------------------
- // 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) {
- if len(address) == 0 {
- return addr, errors.New("decoding Bech32 address failed: must provide an address")
- }
- bz, err := hex.DecodeString(address)
- if err != nil {
- return nil, err
- }
- return ConsAddress(bz), nil
- }
- // ConsAddressFromBech32 creates a ConsAddress from a Bech32 string.
- func ConsAddressFromBech32(address string) (addr ConsAddress, err error) {
- if len(strings.TrimSpace(address)) == 0 {
- return ConsAddress{}, nil
- }
- bech32PrefixConsAddr := GetConfig().GetBech32ConsensusAddrPrefix()
- bz, err := GetFromBech32(address, bech32PrefixConsAddr)
- if err != nil {
- return nil, err
- }
- err = VerifyAddressFormat(bz)
- if err != nil {
- return nil, err
- }
- return ConsAddress(bz), nil
- }
- // get ConsAddress from pubkey
- func GetConsAddress(pubkey crypto.PubKey) ConsAddress {
- return ConsAddress(pubkey.Address())
- }
- // Returns boolean for whether two ConsAddress are Equal
- func (ca ConsAddress) Equals(ca2 Address) bool {
- if ca.Empty() && ca2.Empty() {
- return true
- }
- return bytes.Equal(ca.Bytes(), ca2.Bytes())
- }
- // Returns boolean for whether an ConsAddress is empty
- func (ca ConsAddress) Empty() bool {
- if ca == nil {
- return true
- }
- ca2 := ConsAddress{}
- return bytes.Equal(ca.Bytes(), ca2.Bytes())
- }
- // 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())
- }
- // MarshalYAML marshals to YAML using Bech32.
- func (ca ConsAddress) MarshalYAML() (interface{}, error) {
- return ca.String(), nil
- }
- // 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 {
- return err
- }
- ca2, err := ConsAddressFromBech32(s)
- if err != nil {
- return err
- }
- *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
- }
- ca2, err := ConsAddressFromBech32(s)
- if err != nil {
- return err
- }
- *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 {
- if ca.Empty() {
- return ""
- }
- bech32PrefixConsAddr := GetConfig().GetBech32ConsensusAddrPrefix()
- bech32Addr, err := bech32.ConvertAndEncode(bech32PrefixConsAddr, ca.Bytes())
- if err != nil {
- panic(err)
- }
- return bech32Addr
- }
- // Format implements the fmt.Formatter interface.
- // nolint: errcheck
- func (ca ConsAddress) Format(s fmt.State, verb rune) {
- switch verb {
- case 's':
- s.Write([]byte(ca.String()))
- case 'p':
- s.Write([]byte(fmt.Sprintf("%p", ca)))
- default:
- s.Write([]byte(fmt.Sprintf("%X", []byte(ca))))
- }
- }
- // ----------------------------------------------------------------------------
- // auxiliary
- // ----------------------------------------------------------------------------
- // Bech32ifyAccPub returns a Bech32 encoded string containing the
- // Bech32PrefixAccPub prefix for a given account PubKey.
- func Bech32ifyAccPub(pub crypto.PubKey) (string, error) {
- bech32PrefixAccPub := GetConfig().GetBech32AccountPubPrefix()
- return bech32.ConvertAndEncode(bech32PrefixAccPub, pub.Bytes())
- }
- // MustBech32ifyAccPub returns the result of Bech32ifyAccPub panicing on failure.
- func MustBech32ifyAccPub(pub crypto.PubKey) string {
- enc, err := Bech32ifyAccPub(pub)
- if err != nil {
- panic(err)
- }
- return enc
- }
- // Bech32ifyValPub returns a Bech32 encoded string containing the
- // Bech32PrefixValPub prefix for a given validator operator's PubKey.
- func Bech32ifyValPub(pub crypto.PubKey) (string, error) {
- bech32PrefixValPub := GetConfig().GetBech32ValidatorPubPrefix()
- return bech32.ConvertAndEncode(bech32PrefixValPub, pub.Bytes())
- }
- // MustBech32ifyValPub returns the result of Bech32ifyValPub panicing on failure.
- func MustBech32ifyValPub(pub crypto.PubKey) string {
- enc, err := Bech32ifyValPub(pub)
- if err != nil {
- panic(err)
- }
- return enc
- }
- // Bech32ifyConsPub returns a Bech32 encoded string containing the
- // Bech32PrefixConsPub prefixfor a given consensus node's PubKey.
- func Bech32ifyConsPub(pub crypto.PubKey) (string, error) {
- bech32PrefixConsPub := GetConfig().GetBech32ConsensusPubPrefix()
- return bech32.ConvertAndEncode(bech32PrefixConsPub, pub.Bytes())
- }
- // MustBech32ifyConsPub returns the result of Bech32ifyConsPub panicing on
- // failure.
- func MustBech32ifyConsPub(pub crypto.PubKey) string {
- enc, err := Bech32ifyConsPub(pub)
- if err != nil {
- panic(err)
- }
- return enc
- }
- // 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) {
- bech32PrefixAccPub := GetConfig().GetBech32AccountPubPrefix()
- bz, err := GetFromBech32(pubkey, bech32PrefixAccPub)
- if err != nil {
- return nil, err
- }
- pk, err = cryptoAmino.PubKeyFromBytes(bz)
- if err != nil {
- return nil, err
- }
- return pk, nil
- }
- // MustGetAccPubKeyBech32 returns the result of GetAccPubKeyBech32 panicing on
- // failure.
- func MustGetAccPubKeyBech32(pubkey string) (pk crypto.PubKey) {
- pk, err := GetAccPubKeyBech32(pubkey)
- if err != nil {
- panic(err)
- }
- return pk
- }
- // 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) {
- bech32PrefixValPub := GetConfig().GetBech32ValidatorPubPrefix()
- bz, err := GetFromBech32(pubkey, bech32PrefixValPub)
- if err != nil {
- return nil, err
- }
- pk, err = cryptoAmino.PubKeyFromBytes(bz)
- if err != nil {
- return nil, err
- }
- return pk, nil
- }
- // MustGetValPubKeyBech32 returns the result of GetValPubKeyBech32 panicing on
- // failure.
- func MustGetValPubKeyBech32(pubkey string) (pk crypto.PubKey) {
- pk, err := GetValPubKeyBech32(pubkey)
- if err != nil {
- panic(err)
- }
- return pk
- }
- // 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) {
- bech32PrefixConsPub := GetConfig().GetBech32ConsensusPubPrefix()
- bz, err := GetFromBech32(pubkey, bech32PrefixConsPub)
- if err != nil {
- return nil, err
- }
- pk, err = cryptoAmino.PubKeyFromBytes(bz)
- if err != nil {
- return nil, err
- }
- return pk, nil
- }
- // MustGetConsPubKeyBech32 returns the result of GetConsPubKeyBech32 panicing on
- // failure.
- func MustGetConsPubKeyBech32(pubkey string) (pk crypto.PubKey) {
- pk, err := GetConsPubKeyBech32(pubkey)
- if err != nil {
- panic(err)
- }
- return pk
- }
- // GetFromBech32 decodes a bytestring from a Bech32 encoded string.
- func GetFromBech32(bech32str, prefix string) ([]byte, error) {
- if len(bech32str) == 0 {
- return nil, errors.New("decoding Bech32 address failed: must provide an address")
- }
- hrp, bz, err := bech32.DecodeAndConvert(bech32str)
- if err != nil {
- return nil, err
- }
- if hrp != prefix {
- return nil, fmt.Errorf("invalid Bech32 prefix; expected %s, got %s", prefix, hrp)
- }
- return bz, nil
- }