cosmos-sdk/types/account.go

322 lines
7.4 KiB
Go
Raw Normal View History

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"
"fmt"
2018-03-17 11:18:04 -07:00
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/encoding/amino"
"github.com/tendermint/tendermint/libs/bech32"
2018-01-06 14:22:21 -08:00
)
2018-07-03 21:52:48 -07:00
// Bech32 prefixes
2018-05-28 16:27:34 -07:00
const (
2018-07-04 14:07:06 -07:00
// expected address length
AddrLen = 20
// Bech32 prefixes
2018-05-28 16:27:34 -07:00
Bech32PrefixAccAddr = "cosmosaccaddr"
Bech32PrefixAccPub = "cosmosaccpub"
Bech32PrefixValAddr = "cosmosvaladdr"
Bech32PrefixValPub = "cosmosvalpub"
)
2018-07-06 00:06:53 -07:00
//__________________________________________________________
2018-07-09 16:06:05 -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-07-09 16:06:05 -07:00
// create an AccAddress from a hex string
func AccAddressFromHex(address string) (addr AccAddress, err error) {
2018-07-06 00:06:53 -07:00
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
}
2018-07-09 16:06:05 -07:00
// create an AccAddress from a bech32 string
func AccAddressFromBech32(address string) (addr AccAddress, err error) {
2018-07-06 00:06:53 -07:00
bz, err := GetFromBech32(address, Bech32PrefixAccAddr)
if err != nil {
return nil, err
}
return AccAddress(bz), nil
2018-07-03 21:52:48 -07:00
}
// Marshal needed for protobuf compatibility
2018-07-06 00:06:53 -07:00
func (bz AccAddress) Marshal() ([]byte, error) {
2018-07-03 21:52:48 -07:00
return bz, nil
}
2018-07-03 21:52:48 -07:00
// Unmarshal needed for protobuf compatibility
2018-07-06 00:06:53 -07:00
func (bz *AccAddress) Unmarshal(data []byte) error {
2018-07-03 21:52:48 -07:00
*bz = data
return nil
}
// Marshals to JSON using Bech32
2018-07-06 00:06:53 -07:00
func (bz AccAddress) MarshalJSON() ([]byte, error) {
2018-07-09 16:06:05 -07:00
return json.Marshal(bz.String())
2018-07-03 21:52:48 -07:00
}
// Unmarshals from JSON assuming Bech32 encoding
2018-07-06 00:06:53 -07:00
func (bz *AccAddress) UnmarshalJSON(data []byte) error {
2018-07-09 16:06:05 -07:00
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return nil
2018-07-03 21:52:48 -07:00
}
2018-07-09 16:06:05 -07:00
bz2, err := AccAddressFromBech32(s)
2018-07-03 21:52:48 -07:00
if err != nil {
return err
}
*bz = bz2
return nil
}
// Allow it to fulfill various interfaces in light-client, etc...
2018-07-06 00:06:53 -07:00
func (bz AccAddress) Bytes() []byte {
2018-07-03 21:52:48 -07:00
return bz
}
2018-07-06 00:06:53 -07:00
func (bz AccAddress) String() string {
2018-07-03 21:52:48 -07:00
bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixAccAddr, bz.Bytes())
2018-06-07 15:32:14 -07:00
if err != nil {
panic(err)
}
2018-07-03 21:52:48 -07:00
return bech32Addr
}
// For Printf / Sprintf, returns bech32 when using %s
2018-07-06 00:06:53 -07:00
func (bz AccAddress) Format(s fmt.State, verb rune) {
2018-07-03 21:52:48 -07:00
switch verb {
case 's':
s.Write([]byte(fmt.Sprintf("%s", bz.String())))
case 'p':
s.Write([]byte(fmt.Sprintf("%p", bz)))
default:
s.Write([]byte(fmt.Sprintf("%X", []byte(bz))))
}
2018-06-07 15:32:14 -07:00
}
2018-08-04 22:56:48 -07:00
// Returns boolean for whether two AccAddresses are Equal
func (bz AccAddress) Equals(bz2 AccAddress) bool {
2018-08-16 18:35:17 -07:00
if bz.Empty() && bz2.Empty() {
return true
}
2018-08-22 00:10:11 -07:00
return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0
2018-08-04 22:56:48 -07:00
}
// Returns boolean for whether an AccAddress is empty
func (bz AccAddress) Empty() bool {
2018-08-16 18:35:17 -07:00
if bz == nil {
return true
}
2018-08-04 22:56:48 -07:00
bz2 := AccAddress{}
2018-08-22 00:10:11 -07:00
return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0
2018-08-04 22:56:48 -07:00
}
2018-07-06 00:06:53 -07:00
//__________________________________________________________
2018-07-09 16:06:05 -07:00
// AccAddress a wrapper around bytes meant to represent a validator address
// (from over ABCI). When marshaled to a string or json, it uses bech32
2018-07-06 00:06:53 -07:00
type ValAddress []byte
// create a ValAddress from a hex string
2018-07-09 16:06:05 -07:00
func ValAddressFromHex(address string) (addr ValAddress, err error) {
2018-07-06 00:06:53 -07:00
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
}
2018-07-06 00:06:53 -07:00
// create a ValAddress from a bech32 string
2018-07-09 16:06:05 -07:00
func ValAddressFromBech32(address string) (addr ValAddress, err error) {
2018-07-06 00:06:53 -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-07-06 00:06:53 -07:00
return ValAddress(bz), nil
}
// Marshal needed for protobuf compatibility
func (bz ValAddress) Marshal() ([]byte, error) {
return bz, nil
2018-06-07 15:32:14 -07:00
}
2018-07-06 00:06:53 -07:00
// Unmarshal needed for protobuf compatibility
func (bz *ValAddress) Unmarshal(data []byte) error {
*bz = data
return nil
}
// Marshals to JSON using Bech32
func (bz ValAddress) MarshalJSON() ([]byte, error) {
2018-07-09 16:06:05 -07:00
return json.Marshal(bz.String())
}
2018-07-06 00:06:53 -07:00
// Unmarshals from JSON assuming Bech32 encoding
func (bz *ValAddress) UnmarshalJSON(data []byte) error {
2018-07-09 16:06:05 -07:00
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return nil
2018-07-06 00:06:53 -07:00
}
2018-07-09 16:06:05 -07:00
bz2, 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-07-06 00:06:53 -07:00
*bz = bz2
return nil
2018-06-07 15:32:14 -07:00
}
2018-07-06 00:06:53 -07:00
// Allow it to fulfill various interfaces in light-client, etc...
func (bz ValAddress) Bytes() []byte {
return bz
}
2018-07-06 00:06:53 -07:00
func (bz ValAddress) String() string {
bech32Addr, err := bech32.ConvertAndEncode(Bech32PrefixValAddr, bz.Bytes())
2018-06-07 15:32:14 -07:00
if err != nil {
panic(err)
}
2018-07-06 00:06:53 -07:00
return bech32Addr
2018-06-07 15:32:14 -07:00
}
2018-07-06 00:06:53 -07:00
// For Printf / Sprintf, returns bech32 when using %s
func (bz ValAddress) Format(s fmt.State, verb rune) {
switch verb {
case 's':
s.Write([]byte(fmt.Sprintf("%s", bz.String())))
case 'p':
s.Write([]byte(fmt.Sprintf("%p", bz)))
default:
s.Write([]byte(fmt.Sprintf("%X", []byte(bz))))
2018-03-17 11:18:04 -07:00
}
}
2018-08-04 22:56:48 -07:00
// Returns boolean for whether two ValAddresses are Equal
func (bz ValAddress) Equals(bz2 ValAddress) bool {
2018-08-16 18:35:17 -07:00
if bz.Empty() && bz2.Empty() {
return true
}
2018-08-22 00:10:11 -07:00
return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0
2018-08-04 22:56:48 -07:00
}
// Returns boolean for whether an AccAddress is empty
func (bz ValAddress) Empty() bool {
2018-08-16 18:35:17 -07:00
if bz == nil {
return true
}
2018-08-04 22:56:48 -07:00
bz2 := ValAddress{}
2018-08-22 00:10:11 -07:00
return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0
2018-08-04 22:56:48 -07:00
}
2018-07-06 00:06:53 -07:00
// Bech32ifyAccPub takes AccountPubKey and returns the bech32 encoded string
func Bech32ifyAccPub(pub crypto.PubKey) (string, error) {
return bech32.ConvertAndEncode(Bech32PrefixAccPub, pub.Bytes())
}
// MustBech32ifyAccPub panics on bech32-encoding failure
func MustBech32ifyAccPub(pub crypto.PubKey) string {
enc, err := Bech32ifyAccPub(pub)
if err != nil {
2018-07-06 00:06:53 -07:00
panic(err)
}
2018-07-06 00:06:53 -07:00
return enc
}
// Bech32ifyValPub returns the bech32 encoded string for a validator pubkey
func Bech32ifyValPub(pub crypto.PubKey) (string, error) {
return bech32.ConvertAndEncode(Bech32PrefixValPub, pub.Bytes())
}
2018-07-09 16:06:05 -07:00
// MustBech32ifyValPub panics on bech32-encoding failure
2018-07-06 00:06:53 -07:00
func MustBech32ifyValPub(pub crypto.PubKey) string {
enc, err := Bech32ifyValPub(pub)
if err != nil {
panic(err)
}
2018-07-06 00:06:53 -07:00
return enc
}
// create a Pubkey from a string
func GetAccPubKeyBech32(address string) (pk crypto.PubKey, err error) {
bz, err := GetFromBech32(address, Bech32PrefixAccPub)
if err != nil {
return nil, err
}
pk, err = cryptoAmino.PubKeyFromBytes(bz)
if err != nil {
return nil, err
}
return pk, nil
}
// create an Pubkey from a string, panics on error
func MustGetAccPubKeyBech32(address string) (pk crypto.PubKey) {
pk, err := GetAccPubKeyBech32(address)
if err != nil {
panic(err)
}
return pk
}
2018-06-07 12:36:03 -07:00
// decode a validator public key into a PubKey
2018-06-01 07:23:58 -07:00
func GetValPubKeyBech32(pubkey string) (pk crypto.PubKey, err error) {
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
}
2018-05-28 16:27:34 -07:00
// create an Pubkey from a string, panics on error
func MustGetValPubKeyBech32(address string) (pk crypto.PubKey) {
pk, err := GetValPubKeyBech32(address)
if err != nil {
panic(err)
}
return pk
}
// decode a bytestring from a bech32-encoded string
func GetFromBech32(bech32str, prefix string) ([]byte, error) {
2018-06-01 07:23:58 -07:00
if len(bech32str) == 0 {
return nil, errors.New("decoding bech32 address failed: must provide an address")
2018-05-28 16:27:34 -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 {
return nil, fmt.Errorf("invalid bech32 prefix. Expected %s, Got %s", prefix, hrp)
2018-05-28 16:27:34 -07:00
}
return bz, nil
}