2018-01-22 05:44:24 -08:00
|
|
|
package auth
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2018-03-02 01:24:07 -08:00
|
|
|
wire "github.com/cosmos/cosmos-sdk/wire"
|
2018-05-06 22:13:32 -07:00
|
|
|
crypto "github.com/tendermint/go-crypto"
|
2018-01-22 05:44:24 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// This AccountMapper encodes/decodes accounts using the
|
2018-04-06 17:25:08 -07:00
|
|
|
// go-amino (binary) encoding/decoding library.
|
2018-05-06 22:13:32 -07:00
|
|
|
type AccountMapper struct {
|
2018-01-22 05:44:24 -08:00
|
|
|
|
|
|
|
// The (unexposed) key used to access the store from the Context.
|
|
|
|
key sdk.StoreKey
|
|
|
|
|
2018-05-23 19:26:54 -07:00
|
|
|
// The prototypical Account concrete type.
|
|
|
|
proto Account
|
2018-01-22 05:44:24 -08:00
|
|
|
|
|
|
|
// The wire codec for binary encoding/decoding of accounts.
|
|
|
|
cdc *wire.Codec
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewAccountMapper returns a new sdk.AccountMapper that
|
2018-04-06 17:25:08 -07:00
|
|
|
// uses go-amino to (binary) encode and decode concrete sdk.Accounts.
|
2018-04-18 21:49:24 -07:00
|
|
|
// nolint
|
2018-05-23 19:26:54 -07:00
|
|
|
func NewAccountMapper(cdc *wire.Codec, key sdk.StoreKey, proto Account) AccountMapper {
|
2018-05-06 22:13:32 -07:00
|
|
|
return AccountMapper{
|
2018-01-22 05:44:24 -08:00
|
|
|
key: key,
|
|
|
|
proto: proto,
|
|
|
|
cdc: cdc,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-06 22:13:32 -07:00
|
|
|
// Implaements sdk.AccountMapper.
|
2018-05-23 19:26:54 -07:00
|
|
|
func (am AccountMapper) NewAccountWithAddress(ctx sdk.Context, addr sdk.Address) Account {
|
2018-01-22 05:44:24 -08:00
|
|
|
acc := am.clonePrototype()
|
|
|
|
acc.SetAddress(addr)
|
|
|
|
return acc
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implements sdk.AccountMapper.
|
2018-05-23 19:26:54 -07:00
|
|
|
func (am AccountMapper) GetAccount(ctx sdk.Context, addr sdk.Address) Account {
|
2018-01-22 05:44:24 -08:00
|
|
|
store := ctx.KVStore(am.key)
|
|
|
|
bz := store.Get(addr)
|
|
|
|
if bz == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
acc := am.decodeAccount(bz)
|
|
|
|
return acc
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implements sdk.AccountMapper.
|
2018-05-23 19:26:54 -07:00
|
|
|
func (am AccountMapper) SetAccount(ctx sdk.Context, acc Account) {
|
2018-01-22 05:44:24 -08:00
|
|
|
addr := acc.GetAddress()
|
|
|
|
store := ctx.KVStore(am.key)
|
|
|
|
bz := am.encodeAccount(acc)
|
|
|
|
store.Set(addr, bz)
|
|
|
|
}
|
|
|
|
|
2018-04-27 07:59:47 -07:00
|
|
|
// Implements sdk.AccountMapper.
|
2018-05-23 19:26:54 -07:00
|
|
|
func (am AccountMapper) IterateAccounts(ctx sdk.Context, process func(Account) (stop bool)) {
|
2018-04-27 07:59:47 -07:00
|
|
|
store := ctx.KVStore(am.key)
|
|
|
|
iter := store.Iterator(nil, nil)
|
|
|
|
for {
|
|
|
|
if !iter.Valid() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
val := iter.Value()
|
|
|
|
acc := am.decodeAccount(val)
|
2018-04-27 17:00:33 -07:00
|
|
|
if process(acc) {
|
2018-04-27 07:59:47 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
iter.Next()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-06 22:13:32 -07:00
|
|
|
// Returns the PubKey of the account at address
|
|
|
|
func (am AccountMapper) GetPubKey(ctx sdk.Context, addr sdk.Address) (crypto.PubKey, sdk.Error) {
|
|
|
|
acc := am.GetAccount(ctx, addr)
|
|
|
|
if acc == nil {
|
|
|
|
return nil, sdk.ErrUnknownAddress(addr.String())
|
|
|
|
}
|
|
|
|
return acc.GetPubKey(), nil
|
|
|
|
}
|
|
|
|
|
2018-05-23 19:26:54 -07:00
|
|
|
// Sets the PubKey of the account at address
|
|
|
|
func (am AccountMapper) SetPubKey(ctx sdk.Context, addr sdk.Address, newPubKey crypto.PubKey) sdk.Error {
|
2018-05-06 22:13:32 -07:00
|
|
|
acc := am.GetAccount(ctx, addr)
|
|
|
|
if acc == nil {
|
|
|
|
return sdk.ErrUnknownAddress(addr.String())
|
|
|
|
}
|
|
|
|
acc.SetPubKey(newPubKey)
|
|
|
|
am.SetAccount(ctx, acc)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the Sequence of the account at address
|
|
|
|
func (am AccountMapper) GetSequence(ctx sdk.Context, addr sdk.Address) (int64, sdk.Error) {
|
|
|
|
acc := am.GetAccount(ctx, addr)
|
|
|
|
if acc == nil {
|
|
|
|
return 0, sdk.ErrUnknownAddress(addr.String())
|
|
|
|
}
|
|
|
|
return acc.GetSequence(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (am AccountMapper) setSequence(ctx sdk.Context, addr sdk.Address, newSequence int64) sdk.Error {
|
|
|
|
acc := am.GetAccount(ctx, addr)
|
|
|
|
if acc == nil {
|
|
|
|
return sdk.ErrUnknownAddress(addr.String())
|
|
|
|
}
|
|
|
|
acc.SetSequence(newSequence)
|
|
|
|
am.SetAccount(ctx, acc)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-01-22 05:44:24 -08:00
|
|
|
//----------------------------------------
|
|
|
|
// misc.
|
|
|
|
|
|
|
|
// Creates a new struct (or pointer to struct) from am.proto.
|
2018-05-23 19:26:54 -07:00
|
|
|
func (am AccountMapper) clonePrototype() Account {
|
2018-01-22 05:44:24 -08:00
|
|
|
protoRt := reflect.TypeOf(am.proto)
|
|
|
|
if protoRt.Kind() == reflect.Ptr {
|
|
|
|
protoCrt := protoRt.Elem()
|
|
|
|
if protoCrt.Kind() != reflect.Struct {
|
|
|
|
panic("accountMapper requires a struct proto sdk.Account, or a pointer to one")
|
|
|
|
}
|
|
|
|
protoRv := reflect.New(protoCrt)
|
2018-05-23 19:26:54 -07:00
|
|
|
clone, ok := protoRv.Interface().(Account)
|
2018-01-22 05:44:24 -08:00
|
|
|
if !ok {
|
|
|
|
panic(fmt.Sprintf("accountMapper requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt))
|
|
|
|
}
|
|
|
|
return clone
|
|
|
|
}
|
2018-04-18 21:49:24 -07:00
|
|
|
|
|
|
|
protoRv := reflect.New(protoRt).Elem()
|
2018-05-23 19:26:54 -07:00
|
|
|
clone, ok := protoRv.Interface().(Account)
|
2018-04-18 21:49:24 -07:00
|
|
|
if !ok {
|
|
|
|
panic(fmt.Sprintf("accountMapper requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt))
|
|
|
|
}
|
|
|
|
return clone
|
2018-01-22 05:44:24 -08:00
|
|
|
}
|
|
|
|
|
2018-05-23 19:26:54 -07:00
|
|
|
func (am AccountMapper) encodeAccount(acc Account) []byte {
|
2018-04-06 17:25:08 -07:00
|
|
|
bz, err := am.cdc.MarshalBinaryBare(acc)
|
2018-01-22 05:44:24 -08:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return bz
|
|
|
|
}
|
|
|
|
|
2018-05-23 19:26:54 -07:00
|
|
|
func (am AccountMapper) decodeAccount(bz []byte) (acc Account) {
|
2018-04-06 17:25:08 -07:00
|
|
|
err := am.cdc.UnmarshalBinaryBare(bz, &acc)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
2018-01-22 05:44:24 -08:00
|
|
|
}
|
2018-04-06 17:25:08 -07:00
|
|
|
return
|
2018-01-22 05:44:24 -08:00
|
|
|
}
|