forked from cosmos/cosmos-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mapper.go
123 lines (106 loc) · 2.98 KB
/
mapper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package auth
import (
"fmt"
"reflect"
sdk "github.com/cosmos/cosmos-sdk/types"
wire "github.com/cosmos/cosmos-sdk/wire"
)
var _ sdk.AccountMapper = (*accountMapper)(nil)
// Implements sdk.AccountMapper.
// This AccountMapper encodes/decodes accounts using the
// go-amino (binary) encoding/decoding library.
type accountMapper struct {
// The (unexposed) key used to access the store from the Context.
key sdk.StoreKey
// The prototypical sdk.Account concrete type.
proto sdk.Account
// The wire codec for binary encoding/decoding of accounts.
cdc *wire.Codec
}
// NewAccountMapper returns a new sdk.AccountMapper that
// uses go-amino to (binary) encode and decode concrete sdk.Accounts.
// nolint
func NewAccountMapper(cdc *wire.Codec, key sdk.StoreKey, proto sdk.Account) accountMapper {
return accountMapper{
key: key,
proto: proto,
cdc: cdc,
}
}
// Implements sdk.AccountMapper.
func (am accountMapper) NewAccountWithAddress(ctx sdk.Context, addr sdk.Address) sdk.Account {
acc := am.clonePrototype()
acc.SetAddress(addr)
return acc
}
// Implements sdk.AccountMapper.
func (am accountMapper) GetAccount(ctx sdk.Context, addr sdk.Address) sdk.Account {
store := ctx.KVStore(am.key)
bz := store.Get(addr)
if bz == nil {
return nil
}
acc := am.decodeAccount(bz)
return acc
}
// Implements sdk.AccountMapper.
func (am accountMapper) SetAccount(ctx sdk.Context, acc sdk.Account) {
addr := acc.GetAddress()
store := ctx.KVStore(am.key)
bz := am.encodeAccount(acc)
store.Set(addr, bz)
}
// Implements sdk.AccountMapper.
func (am accountMapper) IterateAccounts(ctx sdk.Context, process func(sdk.Account) (stop bool)) {
store := ctx.KVStore(am.key)
iter := store.Iterator(nil, nil)
for {
if !iter.Valid() {
return
}
val := iter.Value()
acc := am.decodeAccount(val)
if process(acc) {
return
}
iter.Next()
}
}
//----------------------------------------
// misc.
// Creates a new struct (or pointer to struct) from am.proto.
func (am accountMapper) clonePrototype() sdk.Account {
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)
clone, ok := protoRv.Interface().(sdk.Account)
if !ok {
panic(fmt.Sprintf("accountMapper requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt))
}
return clone
}
protoRv := reflect.New(protoRt).Elem()
clone, ok := protoRv.Interface().(sdk.Account)
if !ok {
panic(fmt.Sprintf("accountMapper requires a proto sdk.Account, but %v doesn't implement sdk.Account", protoRt))
}
return clone
}
func (am accountMapper) encodeAccount(acc sdk.Account) []byte {
bz, err := am.cdc.MarshalBinaryBare(acc)
if err != nil {
panic(err)
}
return bz
}
func (am accountMapper) decodeAccount(bz []byte) (acc sdk.Account) {
err := am.cdc.UnmarshalBinaryBare(bz, &acc)
if err != nil {
panic(err)
}
return
}