-
Notifications
You must be signed in to change notification settings - Fork 0
/
kvstore.go
167 lines (141 loc) · 4.6 KB
/
kvstore.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package kvstore
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/tendermint/tendermint/abci/types"
)
// Define the module name
const ModuleName = "kvstore"
// Define the key-value pair data structure
type KeyValuePair struct {
Key string `json:"key"`
Value string `json:"value"`
}
// Define the module message types and their corresponding handlers
type MsgCreateKeyValuePair struct {
Key string `json:"key"`
Value string `json:"value"`
}
func NewMsgCreateKeyValuePair(key, value string) MsgCreateKeyValuePair {
return MsgCreateKeyValuePair{
Key: key,
Value: value,
}
}
func (msg MsgCreateKeyValuePair) Route() string { return ModuleName }
func (msg MsgCreateKeyValuePair) Type() string { return "create_key_value_pair" }
func (msg MsgCreateKeyValuePair) ValidateBasic() error {
if len(msg.Key) == 0 || len(msg.Value) == 0 {
return fmt.Errorf("key and value cannot be empty")
}
return nil
}
func (msg MsgCreateKeyValuePair) GetSignBytes() []byte {
return sdk.MustSortJSON(msg.cdc.MustMarshalJSON(&msg))
}
func (msg MsgCreateKeyValuePair) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{sdk.AccAddress(msg.From)}
}
func handleMsgCreateKeyValuePair(ctx sdk.Context, k Keeper, msg MsgCreateKeyValuePair) (*sdk.Result, error) {
if err := k.CreateKeyValuePair(ctx, msg.Key, msg.Value); err != nil {
return nil, err
}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}
// Define the module query types and their corresponding handlers
type QueryGetKeyValuePair struct {
Key string `json:"key"`
}
func NewQueryGetKeyValuePair(key string) QueryGetKeyValuePair {
return QueryGetKeyValuePair{
Key: key,
}
}
func (query QueryGetKeyValuePair) Route() string { return ModuleName }
func (query QueryGetKeyValuePair) Type() string { return "get_key_value_pair" }
func (query QueryGetKeyValuePair) ValidateBasic() error {
if len(query.Key) == 0 {
return fmt.Errorf("key cannot be empty")
}
return nil
}
func handleQueryGetKeyValuePair(ctx sdk.Context, k Keeper, query QueryGetKeyValuePair) ([]byte, error) {
value, err := k.GetKeyValuePair(ctx, query.Key)
if err != nil {
return nil, err
}
return ModuleCdc.MustMarshalJSON(value), nil
}
// Define the module keeper to manage the state of the module
type Keeper struct {
keyValueStoreKey sdk.StoreKey
cdc *codec.Codec
}
func NewKeeper(keyValueStoreKey sdk.StoreKey, cdc *codec.Codec) Keeper {
return Keeper{
keyValueStoreKey: keyValueStoreKey,
cdc: cdc,
}
}
func (k Keeper) KeyValueExists(ctx sdk.Context, key string) bool {
store := ctx.KVStore(k.keyValueStoreKey)
return store.Has([]byte(key))
}
func (k Keeper) GetKeyValuePair(ctx sdk.Context, key string) (*KeyValuePair, error) {
store := ctx.KVStore(k.keyValueStoreKey)
if !k.KeyValueExists(ctx, key) {
return nil, fmt.Errorf("key-value pair not found")
}
value := store.Get([]byte(key))
var keyValuePair KeyValuePair
k.cdc.MustUnmarshalBinaryBare(value, &keyValuePair)
return &keyValuePair, nil
}
func (k Keeper) SetKeyValuePair(ctx sdk.Context, keyValuePair KeyValuePair) {
store := ctx.KVStore(k.keyValueStoreKey)
store.Set([]byte(keyValuePair.Key), k.cdc.MustMarshalBinaryBare(&keyValuePair))
}
// Register the module and its types with the SDK
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterConcrete(MsgCreateKeyValuePair{}, "kvstore/CreateKeyValuePair", nil)
cdc.RegisterConcrete(QueryGetKeyValuePair{}, "kvstore/GetKeyValuePair", nil)
cdc.RegisterConcrete(KeyValuePair{}, "kvstore/KeyValuePair", nil)
}
func NewQuerier(k Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
switch path[0] {
case "get":
return queryGetKeyValuePair(ctx, path[1:], req, k)
default:
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown kvstore query endpoint")
}
}
}
func queryGetKeyValuePair(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
key := path[0]
query := NewQueryGetKeyValuePair(key)
bz, err := k.cdc.MarshalJSON(query)
if err != nil {
return nil, err
}
res, err := abciQueryWithData(ctx, "custom/kvstore/get", bz)
if err != nil {
return nil, err
}
if res.Code != abci.CodeTypeOK {
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, res.Log)
}
var value KeyValuePair
if err := k.cdc.UnmarshalBinaryBare(res.Value, &value); err != nil {
return nil, err
}
return k.cdc.MustMarshalJSON(value), nil
}
func abciQueryWithData(ctx sdk.Context, path string, data []byte) (abci.ResponseQuery, error) {
req := abci.RequestQuery{
Path: path,
Data: data,
}
return ctx.Query(req)
}