@agoric/cosmos 0.35.0-upgrade-14-dev-c8f9e7b.0 → 0.35.0-upgrade-16a-dev-fb592e4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/CHANGELOG.md +121 -77
  2. package/MAINTAINERS.md +3 -0
  3. package/Makefile +36 -26
  4. package/ante/ante.go +7 -9
  5. package/ante/inbound_test.go +3 -2
  6. package/ante/vm_admission.go +2 -1
  7. package/app/app.go +212 -140
  8. package/app/upgrade.go +76 -0
  9. package/cmd/agd/agvm.go +42 -0
  10. package/cmd/agd/main.go +130 -11
  11. package/cmd/libdaemon/main.go +64 -53
  12. package/cmd/libdaemon/main_test.go +2 -1
  13. package/daemon/cmd/root.go +171 -74
  14. package/daemon/cmd/root_test.go +189 -1
  15. package/daemon/main.go +4 -2
  16. package/e2e_test/Makefile +29 -0
  17. package/e2e_test/README.md +100 -0
  18. package/e2e_test/go.mod +217 -0
  19. package/e2e_test/go.sum +1323 -0
  20. package/e2e_test/ibc_conformance_test.go +56 -0
  21. package/e2e_test/pfm_test.go +613 -0
  22. package/e2e_test/util.go +271 -0
  23. package/git-revision.txt +1 -1
  24. package/go.mod +22 -11
  25. package/go.sum +17 -13
  26. package/package.json +9 -5
  27. package/proto/agoric/swingset/genesis.proto +4 -0
  28. package/proto/agoric/swingset/swingset.proto +1 -1
  29. package/proto/agoric/vlocalchain/.clang-format +7 -0
  30. package/proto/agoric/vlocalchain/vlocalchain.proto +31 -0
  31. package/proto/agoric/vtransfer/genesis.proto +18 -0
  32. package/scripts/protocgen.sh +7 -8
  33. package/types/kv_entry_helpers.go +42 -0
  34. package/upgradegaia.sh +8 -8
  35. package/vm/action.go +5 -4
  36. package/vm/action_test.go +31 -11
  37. package/vm/client.go +113 -0
  38. package/vm/client_test.go +182 -0
  39. package/vm/controller.go +17 -40
  40. package/vm/core_proposals.go +22 -2
  41. package/vm/jsonrpcconn/jsonrpcconn.go +160 -0
  42. package/vm/jsonrpcconn/jsonrpcconn_test.go +126 -0
  43. package/vm/proto_json.go +38 -0
  44. package/vm/proto_json_test.go +103 -0
  45. package/vm/server.go +124 -0
  46. package/x/swingset/abci.go +10 -10
  47. package/x/swingset/alias.go +2 -0
  48. package/x/swingset/client/cli/tx.go +4 -0
  49. package/x/swingset/genesis.go +84 -24
  50. package/x/swingset/handler.go +2 -1
  51. package/x/swingset/keeper/extension_snapshotter.go +2 -2
  52. package/x/swingset/keeper/keeper.go +13 -25
  53. package/x/swingset/keeper/msg_server.go +18 -18
  54. package/x/swingset/keeper/proposal.go +3 -3
  55. package/x/swingset/keeper/querier.go +12 -11
  56. package/x/swingset/keeper/swing_store_exports_handler.go +21 -6
  57. package/x/swingset/keeper/test_utils.go +16 -0
  58. package/x/swingset/module.go +7 -7
  59. package/x/swingset/proposal_handler.go +2 -1
  60. package/x/swingset/testing/queue.go +17 -0
  61. package/x/swingset/types/default-params.go +1 -1
  62. package/x/swingset/types/expected_keepers.go +3 -2
  63. package/x/swingset/types/genesis.pb.go +78 -25
  64. package/x/swingset/types/msgs.go +44 -24
  65. package/x/swingset/types/params.go +2 -1
  66. package/x/swingset/types/proposal.go +5 -4
  67. package/x/swingset/types/swingset.pb.go +1 -1
  68. package/x/vbank/genesis.go +0 -2
  69. package/x/vbank/handler.go +2 -1
  70. package/x/vbank/keeper/querier.go +4 -3
  71. package/x/vbank/module.go +0 -5
  72. package/x/vbank/types/msgs.go +0 -12
  73. package/x/vbank/vbank.go +9 -9
  74. package/x/vbank/vbank_test.go +2 -2
  75. package/x/vibc/alias.go +3 -0
  76. package/x/vibc/handler.go +16 -9
  77. package/x/vibc/keeper/keeper.go +102 -65
  78. package/x/vibc/keeper/triggers.go +101 -0
  79. package/x/vibc/module.go +5 -8
  80. package/x/vibc/types/expected_keepers.go +13 -0
  81. package/x/vibc/types/ibc_module.go +336 -0
  82. package/x/vibc/types/receiver.go +170 -0
  83. package/x/vlocalchain/alias.go +19 -0
  84. package/x/vlocalchain/handler.go +21 -0
  85. package/x/vlocalchain/keeper/keeper.go +279 -0
  86. package/x/vlocalchain/keeper/keeper_test.go +97 -0
  87. package/x/vlocalchain/types/codec.go +34 -0
  88. package/x/vlocalchain/types/key.go +27 -0
  89. package/x/vlocalchain/types/msgs.go +16 -0
  90. package/x/vlocalchain/types/vlocalchain.pb.go +1072 -0
  91. package/x/vlocalchain/vlocalchain.go +114 -0
  92. package/x/vlocalchain/vlocalchain_test.go +434 -0
  93. package/x/vstorage/handler.go +2 -1
  94. package/x/vstorage/keeper/grpc_query.go +0 -1
  95. package/x/vstorage/keeper/keeper.go +13 -20
  96. package/x/vstorage/keeper/querier.go +6 -5
  97. package/x/vstorage/keeper/querier_test.go +4 -3
  98. package/x/vstorage/module.go +0 -5
  99. package/x/vstorage/testing/queue.go +27 -0
  100. package/x/vtransfer/alias.go +13 -0
  101. package/x/vtransfer/genesis.go +39 -0
  102. package/x/vtransfer/genesis_test.go +12 -0
  103. package/x/vtransfer/handler.go +20 -0
  104. package/x/vtransfer/ibc_middleware.go +186 -0
  105. package/x/vtransfer/ibc_middleware_test.go +448 -0
  106. package/x/vtransfer/keeper/keeper.go +281 -0
  107. package/x/vtransfer/module.go +124 -0
  108. package/x/vtransfer/types/expected_keepers.go +38 -0
  109. package/x/vtransfer/types/genesis.pb.go +327 -0
  110. package/x/vtransfer/types/key.go +9 -0
  111. package/x/vtransfer/types/msgs.go +9 -0
  112. package/ante/fee.go +0 -96
  113. package/proto/agoric/lien/genesis.proto +0 -25
  114. package/proto/agoric/lien/lien.proto +0 -25
  115. package/x/lien/alias.go +0 -17
  116. package/x/lien/genesis.go +0 -58
  117. package/x/lien/genesis_test.go +0 -101
  118. package/x/lien/keeper/account.go +0 -290
  119. package/x/lien/keeper/keeper.go +0 -255
  120. package/x/lien/keeper/keeper_test.go +0 -623
  121. package/x/lien/lien.go +0 -205
  122. package/x/lien/lien_test.go +0 -533
  123. package/x/lien/module.go +0 -115
  124. package/x/lien/spec/01_concepts.md +0 -146
  125. package/x/lien/spec/02_messages.md +0 -96
  126. package/x/lien/types/accountkeeper.go +0 -81
  127. package/x/lien/types/accountstate.go +0 -27
  128. package/x/lien/types/expected_keepers.go +0 -18
  129. package/x/lien/types/genesis.pb.go +0 -567
  130. package/x/lien/types/key.go +0 -25
  131. package/x/lien/types/lien.pb.go +0 -403
  132. package/x/vibc/ibc.go +0 -394
  133. /package/{src/index.cjs → index.cjs} +0 -0
@@ -0,0 +1,114 @@
1
+ package vlocalchain
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "fmt"
7
+
8
+ sdk "github.com/cosmos/cosmos-sdk/types"
9
+
10
+ "github.com/Agoric/agoric-sdk/golang/cosmos/vm"
11
+ "github.com/Agoric/agoric-sdk/golang/cosmos/x/vlocalchain/keeper"
12
+ "github.com/Agoric/agoric-sdk/golang/cosmos/x/vlocalchain/types"
13
+ )
14
+
15
+ var _ vm.PortHandler = (*portHandler)(nil)
16
+
17
+ type portHandler struct {
18
+ keeper keeper.Keeper
19
+ }
20
+
21
+ type portMessage struct {
22
+ Type string `json:"type"`
23
+ Address string `json:"address,omitempty"`
24
+ Messages json.RawMessage `json:"messages,omitempty"`
25
+ }
26
+
27
+ func NewReceiver(keeper keeper.Keeper) portHandler {
28
+ return portHandler{keeper: keeper}
29
+ }
30
+
31
+ func (h portHandler) Receive(cctx context.Context, str string) (ret string, err error) {
32
+ var msg portMessage
33
+ err = json.Unmarshal([]byte(str), &msg)
34
+ if err != nil {
35
+ return
36
+ }
37
+
38
+ switch msg.Type {
39
+ case "VLOCALCHAIN_ALLOCATE_ADDRESS":
40
+ addr := h.keeper.AllocateAddress(cctx)
41
+ var bz []byte
42
+ if bz, err = json.Marshal(addr.String()); err != nil {
43
+ return
44
+ }
45
+ ret = string(bz)
46
+
47
+ case "VLOCALCHAIN_QUERY_MANY":
48
+ // Copy the JSON messages string into a CosmosTx object so we can
49
+ // deserialize it with just proto3 JSON.
50
+ cosmosTxBz := []byte(`{"messages":` + string(msg.Messages) + `}`)
51
+
52
+ var qms []types.QueryRequest
53
+ qms, err = h.keeper.DeserializeRequests(cosmosTxBz)
54
+ if err != nil {
55
+ return
56
+ }
57
+
58
+ var errs []error
59
+ resps := make([]interface{}, len(qms))
60
+ for i, qm := range qms {
61
+ var qr *types.QueryResponse
62
+ qr, err = h.keeper.Query(cctx, qm)
63
+ if err == nil {
64
+ // Only fill out the response if the query was successful.
65
+ resps[i] = qr
66
+ } else {
67
+ errs = append(errs, err) // Accumulate errors
68
+ resps[i] = &types.QueryResponse{Error: err.Error()}
69
+ }
70
+ }
71
+
72
+ bz, err := vm.ProtoJSONMarshalSlice(resps)
73
+ if err != nil {
74
+ return "", err
75
+ }
76
+
77
+ switch len(errs) {
78
+ case 0:
79
+ err = nil
80
+ case 1:
81
+ err = errs[0]
82
+ case len(resps):
83
+ err = fmt.Errorf("all queries in batch failed: %v", errs)
84
+ default:
85
+ // Let them inspect the individual errors manually.
86
+ }
87
+ return string(bz), err
88
+
89
+ case "VLOCALCHAIN_EXECUTE_TX":
90
+ origCtx := sdk.UnwrapSDKContext(cctx)
91
+
92
+ // Copy the JSON messages string into a CosmosTx object so we can
93
+ // deserialize it with just proto3 JSON.
94
+ cosmosTxBz := []byte(`{"messages":` + string(msg.Messages) + `}`)
95
+
96
+ var msgs []sdk.Msg
97
+ if msgs, err = h.keeper.DeserializeTxMessages(cosmosTxBz); err != nil {
98
+ return
99
+ }
100
+
101
+ var resps []interface{}
102
+ resps, err = h.keeper.ExecuteTx(origCtx, msg.Address, msgs)
103
+ if err != nil {
104
+ return
105
+ }
106
+
107
+ // Marshal the responses to proto3 JSON.
108
+ bz, e := vm.ProtoJSONMarshalSlice(resps)
109
+ return string(bz), e
110
+ default:
111
+ err = fmt.Errorf("unrecognized message type %s", msg.Type)
112
+ }
113
+ return
114
+ }
@@ -0,0 +1,434 @@
1
+ package vlocalchain_test
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "strings"
7
+ "testing"
8
+ "time"
9
+
10
+ "github.com/Agoric/agoric-sdk/golang/cosmos/app/params"
11
+ "github.com/Agoric/agoric-sdk/golang/cosmos/vm"
12
+ "github.com/Agoric/agoric-sdk/golang/cosmos/x/vlocalchain"
13
+ "github.com/Agoric/agoric-sdk/golang/cosmos/x/vlocalchain/types"
14
+
15
+ "github.com/cosmos/cosmos-sdk/baseapp"
16
+ "github.com/cosmos/cosmos-sdk/store"
17
+ storetypes "github.com/cosmos/cosmos-sdk/store/types"
18
+ sdk "github.com/cosmos/cosmos-sdk/types"
19
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
20
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
21
+ transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"
22
+ "github.com/tendermint/tendermint/libs/log"
23
+
24
+ "github.com/gogo/protobuf/jsonpb"
25
+ "github.com/gogo/protobuf/proto"
26
+ tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
27
+ dbm "github.com/tendermint/tm-db"
28
+ )
29
+
30
+ var (
31
+ vlocalchainStoreKey = sdk.NewKVStoreKey(types.StoreKey)
32
+ )
33
+
34
+ const (
35
+ firstAddr = "cosmos1uupflqrldlpkktssnzgp3r03ff6kz4u4kzd92pjgsfddye7grrlqt9rmmt"
36
+ msgAllocateAddress = `{"type":"VLOCALCHAIN_ALLOCATE_ADDRESS"}`
37
+ )
38
+
39
+ type mockBank struct {
40
+ banktypes.UnimplementedQueryServer
41
+ banktypes.UnimplementedMsgServer
42
+ balances map[string]sdk.Coins
43
+ failToSend error
44
+ }
45
+
46
+ var _ banktypes.QueryServer = (*mockBank)(nil)
47
+ var _ banktypes.MsgServer = (*mockBank)(nil)
48
+
49
+ func (b *mockBank) AllBalances(cctx context.Context, req *banktypes.QueryAllBalancesRequest) (*banktypes.QueryAllBalancesResponse, error) {
50
+ addr, err := sdk.AccAddressFromBech32(req.Address)
51
+ if err != nil {
52
+ return nil, err
53
+ }
54
+
55
+ var resp banktypes.QueryAllBalancesResponse
56
+ resp.Balances = sdk.Coins{}
57
+ if coins, ok := b.balances[addr.String()]; ok {
58
+ resp.Balances = coins
59
+ }
60
+ return &resp, nil
61
+ }
62
+
63
+ func (b *mockBank) Send(cctx context.Context, req *banktypes.MsgSend) (*banktypes.MsgSendResponse, error) {
64
+ if b.failToSend != nil {
65
+ return nil, b.failToSend
66
+ }
67
+ return &banktypes.MsgSendResponse{}, nil
68
+ }
69
+
70
+ type mockTransfer struct {
71
+ transfertypes.UnimplementedQueryServer
72
+ transfertypes.UnimplementedMsgServer
73
+ }
74
+
75
+ var _ transfertypes.QueryServer = (*mockTransfer)(nil)
76
+ var _ transfertypes.MsgServer = (*mockTransfer)(nil)
77
+
78
+ func (t *mockTransfer) Transfer(cctx context.Context, msg *transfertypes.MsgTransfer) (*transfertypes.MsgTransferResponse, error) {
79
+ return &transfertypes.MsgTransferResponse{Sequence: 1}, nil
80
+ }
81
+
82
+ type mockStaking struct {
83
+ stakingtypes.UnimplementedMsgServer
84
+ stakingtypes.UnimplementedQueryServer
85
+ }
86
+
87
+ var _ stakingtypes.MsgServer = (*mockStaking)(nil)
88
+ var _ stakingtypes.QueryServer = (*mockStaking)(nil)
89
+
90
+ func (s *mockStaking) Undelegate(cctx context.Context, msg *stakingtypes.MsgUndelegate) (*stakingtypes.MsgUndelegateResponse, error) {
91
+ return &stakingtypes.MsgUndelegateResponse{CompletionTime: time.Now().UTC()}, nil
92
+ }
93
+
94
+ func (s *mockStaking) UnbondingDelegation(cctx context.Context, req *stakingtypes.QueryUnbondingDelegationRequest) (*stakingtypes.QueryUnbondingDelegationResponse, error) {
95
+ unbondingDelegation := stakingtypes.UnbondingDelegation{
96
+ DelegatorAddress: req.DelegatorAddr,
97
+ ValidatorAddress: "cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj",
98
+ Entries: []stakingtypes.UnbondingDelegationEntry{
99
+ {
100
+ CreationHeight: 100,
101
+ CompletionTime: time.Now().UTC().Add(time.Hour * 24 * 7),
102
+ InitialBalance: sdk.NewInt(1000),
103
+ Balance: sdk.NewInt(500),
104
+ },
105
+ },
106
+ }
107
+ return &stakingtypes.QueryUnbondingDelegationResponse{Unbond: unbondingDelegation}, nil
108
+ }
109
+
110
+ // makeTestKit creates a minimal Keeper and Context for use in testing.
111
+ func makeTestKit(bank *mockBank, transfer *mockTransfer, staking *mockStaking) (vm.PortHandler, context.Context) {
112
+ encodingConfig := params.MakeEncodingConfig()
113
+ cdc := encodingConfig.Marshaler
114
+
115
+ txRouter := baseapp.NewMsgServiceRouter()
116
+ txRouter.SetInterfaceRegistry(encodingConfig.InterfaceRegistry)
117
+ queryRouter := baseapp.NewGRPCQueryRouter()
118
+ queryRouter.SetInterfaceRegistry(encodingConfig.InterfaceRegistry)
119
+
120
+ banktypes.RegisterInterfaces(encodingConfig.InterfaceRegistry)
121
+ banktypes.RegisterMsgServer(txRouter, bank)
122
+ banktypes.RegisterQueryServer(queryRouter, bank)
123
+ transfertypes.RegisterInterfaces(encodingConfig.InterfaceRegistry)
124
+ transfertypes.RegisterMsgServer(txRouter, transfer)
125
+ transfertypes.RegisterQueryServer(queryRouter, transfer)
126
+ stakingtypes.RegisterInterfaces(encodingConfig.InterfaceRegistry)
127
+ stakingtypes.RegisterMsgServer(txRouter, staking)
128
+ stakingtypes.RegisterQueryServer(queryRouter, staking)
129
+
130
+
131
+ // create a new Keeper
132
+ keeper := vlocalchain.NewKeeper(cdc, vlocalchainStoreKey, txRouter, queryRouter)
133
+
134
+ db := dbm.NewMemDB()
135
+ ms := store.NewCommitMultiStore(db)
136
+ ms.MountStoreWithDB(vlocalchainStoreKey, storetypes.StoreTypeIAVL, db)
137
+ err := ms.LoadLatestVersion()
138
+ if err != nil {
139
+ panic(err)
140
+ }
141
+
142
+ // create a new SDK Context
143
+ ctx := sdk.NewContext(ms, tmproto.Header{}, false, log.NewNopLogger()).WithBlockHeight(998)
144
+
145
+ handler := vm.NewProtectedPortHandler(vlocalchain.NewReceiver(keeper))
146
+
147
+ // create a new Go context
148
+ cctx := sdk.WrapSDKContext(ctx)
149
+ return handler, cctx
150
+ }
151
+
152
+ func TestAllocateAddress(t *testing.T) {
153
+ bank := &mockBank{}
154
+ transfer := &mockTransfer{}
155
+ staking := &mockStaking{}
156
+ handler, cctx := makeTestKit(bank, transfer, staking)
157
+
158
+ addrs := map[string]bool{
159
+ firstAddr: false,
160
+ "cosmos1yj40fakym8kf4wvgz9tky7k9f3v9msm3t7frscrmkjsdkxkpsfkqgeczkg": false,
161
+ "cosmos1s76vryj7m8k8nm9le65a4plhf5rym5sumtt2n0vwnk5l6k4cwuhsj56ujj": false,
162
+ "cosmos1c5hplwyxk5jr2dsygjqepzfqvfukwduq9c4660aah76krf99m6gs0k7hvl": false,
163
+ "cosmos1ys3a7mtna3cad0wxcs4ddukn37stexjdvns8jfdn4uerlr95y4xqnrypf6": false,
164
+ }
165
+ numToTest := len(addrs)
166
+ for i := 0; i < numToTest; i++ {
167
+ // receive the message
168
+ ret, err := handler.Receive(cctx, msgAllocateAddress)
169
+ if err != nil {
170
+ t.Fatalf("unexpected error[%d]: %v", i, err)
171
+ }
172
+ if ret == "" {
173
+ t.Fatalf("expected non-empty address[%d]", i)
174
+ }
175
+ var addr string
176
+ if err := json.Unmarshal([]byte(ret), &addr); err != nil {
177
+ t.Fatalf("unexpected error unmarshalling address string[%d]: %v: %v", i, ret, err)
178
+ }
179
+
180
+ already, ok := addrs[addr]
181
+ if !ok {
182
+ t.Fatalf("unexpected address[%d]: %v", i, addr)
183
+ }
184
+ if already {
185
+ t.Fatalf("unexpected duplicate address[%d]: %v", i, addr)
186
+ }
187
+ addrs[addr] = true
188
+ }
189
+ }
190
+
191
+ func TestQuery(t *testing.T) {
192
+ alreadyAddr := sdk.MustBech32ifyAddressBytes("cosmos", []byte("already"))
193
+ nonexistentAddr := sdk.MustBech32ifyAddressBytes("cosmos", []byte("nonexistent"))
194
+ bank := &mockBank{balances: map[string]sdk.Coins{
195
+ firstAddr: []sdk.Coin{sdk.NewCoin("fresh", sdk.NewInt(123))},
196
+ alreadyAddr: []sdk.Coin{sdk.NewCoin("stale", sdk.NewInt(321))},
197
+ }}
198
+ transfer := &mockTransfer{}
199
+ staking := &mockStaking{}
200
+ handler, cctx := makeTestKit(bank, transfer, staking)
201
+
202
+ // get balances
203
+ testCases := []struct {
204
+ name string
205
+ addr string
206
+ failure string
207
+ expected sdk.Coins
208
+ }{
209
+ {"nonexistent", nonexistentAddr, "", sdk.Coins{}},
210
+ {"already", alreadyAddr, "", bank.balances[alreadyAddr]},
211
+ {"first", firstAddr, "", bank.balances[firstAddr]},
212
+ {"badaddr", "cosmos11111111111", "decoding bech32 failed: invalid separator index 16", sdk.Coins{}},
213
+ }
214
+
215
+ for _, tc := range testCases {
216
+ tc := tc
217
+ ctx := sdk.UnwrapSDKContext(cctx)
218
+ t.Run(tc.name, func(t *testing.T) {
219
+ msgGetBalances := `{"type":"VLOCALCHAIN_QUERY_MANY","messages":[{"@type":"/cosmos.bank.v1beta1.QueryAllBalancesRequest","address":"` + tc.addr + `"}]}`
220
+ t.Logf("query request: %v", msgGetBalances)
221
+ ret, err := handler.Receive(cctx, msgGetBalances)
222
+ t.Logf("query response: %v", ret)
223
+ if tc.failure != "" {
224
+ if err == nil {
225
+ t.Fatalf("expected error %v, not nil with return %v", tc.failure, ret)
226
+ } else if err.Error() != tc.failure {
227
+ t.Fatalf("expected error %v, not %v", tc.failure, err)
228
+ }
229
+ return
230
+ }
231
+ if err != nil {
232
+ t.Fatalf("unexpected error: %v", err)
233
+ }
234
+ if err == nil && ret == "" {
235
+ t.Fatalf("expected non-empty json")
236
+ }
237
+
238
+ // Unmarshal the responses.
239
+ s := `{"responses":` + ret + `}`
240
+
241
+ unmarshaler := jsonpb.Unmarshaler{}
242
+ var qrs types.QueryResponses
243
+ if err = unmarshaler.Unmarshal(strings.NewReader(s), &qrs); err != nil {
244
+ t.Fatalf("unexpected error unmarshalling reply: %v: %v", ret, err)
245
+ }
246
+
247
+ resps := qrs.Responses
248
+ if len(resps) != 1 {
249
+ t.Fatalf("expected responses length 1, got %v", len(resps))
250
+ }
251
+ if resps[0].Error != "" {
252
+ t.Fatalf("unexpected error response: %v", resps[0].Error)
253
+ }
254
+ if resps[0].Height != ctx.BlockHeight() {
255
+ t.Fatalf("expected height %v, got %v", ctx.BlockHeight(), resps[0].Height)
256
+ }
257
+
258
+ // Unmarshal the Any.
259
+ var pb banktypes.QueryAllBalancesResponse
260
+ if err = proto.Unmarshal(resps[0].Reply.Value, &pb); err != nil {
261
+ t.Fatalf("unexpected error unmarshalling reply: %v: %v", ret, err)
262
+ }
263
+
264
+ if !pb.Balances.IsEqual(tc.expected) {
265
+ t.Errorf("unexpected balance: expected %v, got %v", tc.expected, pb.Balances)
266
+ }
267
+ })
268
+ }
269
+
270
+ t.Run("UnbondingDelegation", func(t *testing.T) {
271
+ // create a new message
272
+ msg := `{"type":"VLOCALCHAIN_QUERY_MANY","messages":[{"@type":"/cosmos.staking.v1beta1.QueryUnbondingDelegationRequest","delegator_addr":"` + firstAddr + `","validator_addr":"cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj"}]}`
273
+ t.Logf("query request: %v", msg)
274
+ ret, err := handler.Receive(cctx, msg)
275
+ t.Logf("query response: %v", ret)
276
+ if err != nil {
277
+ t.Fatalf("unexpected error: %v", err)
278
+ }
279
+ if ret == "" {
280
+ t.Fatalf("expected non-empty json")
281
+ }
282
+
283
+ // Unmarshal the JSON response
284
+ var respJSON []map[string]interface{}
285
+ if err := json.Unmarshal([]byte(ret), &respJSON); err != nil {
286
+ t.Fatalf("unexpected error unmarshalling JSON response: %v", err)
287
+ }
288
+
289
+ // Check the response fields
290
+ if len(respJSON) != 1 {
291
+ t.Fatalf("expected 1 response, got %d", len(respJSON))
292
+ }
293
+ resp := respJSON[0]
294
+
295
+ replyAny, ok := resp["reply"].(map[string]interface{})
296
+ if !ok {
297
+ t.Fatalf("expected reply field to be a map, got %v", resp["reply"])
298
+ }
299
+
300
+ unbond, ok := replyAny["unbond"].(map[string]interface{})
301
+ if !ok {
302
+ t.Fatalf("expected unbond field to be a map, got %v", replyAny["unbond"])
303
+ }
304
+
305
+ // Check the field names and values
306
+ if unbond["delegatorAddress"] != firstAddr {
307
+ t.Errorf("expected delegatorAddress %s, got %v", firstAddr, unbond["delegator_address"])
308
+ }
309
+ if unbond["validatorAddress"] != "cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj" {
310
+ t.Errorf("expected validatorAddress cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj, got %v", unbond["validator_address"])
311
+ }
312
+
313
+ entries, ok := unbond["entries"].([]interface{})
314
+ if !ok || len(entries) != 1 {
315
+ t.Fatalf("expected 1 unbonding delegation entry, got %v", entries)
316
+ }
317
+ entry, ok := entries[0].(map[string]interface{})
318
+ if !ok {
319
+ t.Fatalf("expected unbonding delegation entry to be a map, got %v", entries[0])
320
+ }
321
+ if entry["creationHeight"] != "100" {
322
+ t.Errorf("expected creationHeight \"100\", got %v", entry["creation_height"])
323
+ }
324
+ if entry["balance"] != "500" {
325
+ t.Errorf("expected balance \"500\", got %v", entry["balance"])
326
+ }
327
+ if _, ok := entry["completionTime"]; !ok {
328
+ t.Error("expected completionTime field in the response")
329
+ }
330
+ })
331
+ }
332
+
333
+ func TestExecuteTx(t *testing.T) {
334
+ alreadyAddr := sdk.MustBech32ifyAddressBytes("cosmos", []byte("already"))
335
+ bank := &mockBank{balances: map[string]sdk.Coins{
336
+ firstAddr: []sdk.Coin{sdk.NewCoin("fresh", sdk.NewInt(123))},
337
+ alreadyAddr: []sdk.Coin{sdk.NewCoin("stale", sdk.NewInt(321))},
338
+ }}
339
+ transfer := &mockTransfer{}
340
+ staking := &mockStaking{}
341
+ handler, cctx := makeTestKit(bank, transfer, staking)
342
+
343
+ // create a new message
344
+ msg := `{"type":"VLOCALCHAIN_ALLOCATE_ADDRESS"}`
345
+ ret, err := handler.Receive(cctx, msg)
346
+ if err != nil {
347
+ t.Fatalf("unexpected error: %s", err)
348
+ }
349
+ if ret == "" {
350
+ t.Fatalf("expected non-empty json")
351
+ }
352
+ var addr string
353
+ if err := json.Unmarshal([]byte(ret), &addr); err != nil {
354
+ t.Fatalf("unexpected error unmarshalling address string: %v: %s", ret, err)
355
+ }
356
+ if addr != firstAddr {
357
+ t.Fatalf("expected address %v, got %v", firstAddr, addr)
358
+ }
359
+
360
+ testCases := []struct {
361
+ name string
362
+ signerAddress string
363
+ fromAddress string
364
+ toAddress string
365
+ failure string
366
+ }{
367
+ {"valid", addr, addr, alreadyAddr, ""},
368
+ {"parse error", `"` + addr, firstAddr, alreadyAddr, "invalid character 'c' after object key:value pair"},
369
+ {"invalid address", addr, alreadyAddr, alreadyAddr, "required signer cosmos1v9k8yetpv3us7src8u does not match actual signer"},
370
+ {"unauth", alreadyAddr, addr, alreadyAddr, "required signer cosmos1uupflqrldlpkktssnzgp3r03ff6kz4u4kzd92pjgsfddye7grrlqt9rmmt does not match actual signer"},
371
+ }
372
+ for _, tc := range testCases {
373
+ tc := tc
374
+ t.Run(tc.name, func(t *testing.T) {
375
+
376
+ // create a new message
377
+ msg := `{"type":"VLOCALCHAIN_EXECUTE_TX","address":"` + tc.signerAddress +
378
+ `","messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"` +
379
+ tc.fromAddress + `","to_address":"` + tc.toAddress +
380
+ `","amount":[{"denom":"fresh","amount":"100"}]}]}`
381
+
382
+ ret, err = handler.Receive(cctx, msg)
383
+ if tc.failure != "" {
384
+ if err == nil {
385
+ t.Fatalf("expected error %v, not nil with return %v", tc.failure, ret)
386
+ }
387
+ if err.Error() != tc.failure {
388
+ t.Fatalf("expected error %v, not %v", tc.failure, err)
389
+ }
390
+ return
391
+ }
392
+
393
+ if err != nil {
394
+ t.Fatalf("unexpected error: %s", err)
395
+ }
396
+ if ret == "" {
397
+ t.Fatalf("expected non-empty json")
398
+ }
399
+ if ret != "[{}]" {
400
+ t.Fatalf("expected response [{}], not %v", ret)
401
+ }
402
+ })
403
+ }
404
+
405
+ t.Run("MsgUndelegate", func(t *testing.T) {
406
+ // create a new message
407
+ msg := `{"type":"VLOCALCHAIN_EXECUTE_TX","address":"` + addr +
408
+ `","messages":[{"@type":"/cosmos.staking.v1beta1.MsgUndelegate","delegatorAddress":"` +
409
+ addr + `","validatorAddress":"cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj","amount":{"denom":"stake","amount":"100"}}]}`
410
+
411
+ ret, err := handler.Receive(cctx, msg)
412
+ if err != nil {
413
+ t.Fatalf("unexpected error: %s", err)
414
+ }
415
+ if ret == "" {
416
+ t.Fatalf("expected non-empty json")
417
+ }
418
+
419
+ // Unmarshal the response
420
+ var resp []map[string]interface{}
421
+ if err := json.Unmarshal([]byte(ret), &resp); err != nil {
422
+ t.Fatalf("unexpected error unmarshalling response: %v", err)
423
+ }
424
+
425
+ // Check the response fields
426
+ if len(resp) != 1 {
427
+ t.Fatalf("expected 1 response, got %d", len(resp))
428
+ }
429
+
430
+ if _, ok := resp[0]["completionTime"]; !ok {
431
+ t.Error("expected 'completionTime' field in response")
432
+ }
433
+ })
434
+ }
@@ -3,6 +3,7 @@ package vstorage
3
3
  import (
4
4
  "fmt"
5
5
 
6
+ sdkioerrors "cosmossdk.io/errors"
6
7
  sdk "github.com/cosmos/cosmos-sdk/types"
7
8
  sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
8
9
  )
@@ -11,6 +12,6 @@ import (
11
12
  func NewHandler(k Keeper) sdk.Handler {
12
13
  return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
13
14
  errMsg := fmt.Sprintf("Unrecognized vstorage Msg type: %T", msg)
14
- return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
15
+ return nil, sdkioerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
15
16
  }
16
17
  }
@@ -94,7 +94,6 @@ var capDataRemotableValueFormats = map[string]string{
94
94
  // }
95
95
  //
96
96
  // ```
97
- // cf. https://github.com/Agoric/agoric-sdk/blob/6e5b422b80e47c4dac151404f43faea5ab41e9b0/scripts/get-flattened-publication.sh
98
97
  func flatten(input interface{}, output map[string]interface{}, key string, top bool) error {
99
98
  // Act on the raw representation of a Remotable.
100
99
  if remotable, ok := input.(*capdata.CapdataRemotable); ok {
@@ -10,6 +10,7 @@ import (
10
10
  "strconv"
11
11
  "strings"
12
12
 
13
+ sdkmath "cosmossdk.io/math"
13
14
  storetypes "github.com/cosmos/cosmos-sdk/store/types"
14
15
  sdk "github.com/cosmos/cosmos-sdk/types"
15
16
  db "github.com/tendermint/tm-db"
@@ -21,8 +22,8 @@ import (
21
22
  // StreamCell is an envelope representing a sequence of values written at a path in a single block.
22
23
  // It is persisted to storage as a { "blockHeight": "<digits>", "values": ["...", ...] } JSON text
23
24
  // that off-chain consumers rely upon.
24
- // Many of those consumers *also* rely upon the strings of "values" being valid JSON text
25
- // (cf. scripts/get-flattened-publication.sh), but we do not enforce that in this package.
25
+ // Many of those consumers *also* rely upon the strings of "values" being valid JSON text,
26
+ // but we do not enforce that in this package.
26
27
  type StreamCell struct {
27
28
  BlockHeight string `json:"blockHeight"`
28
29
  Values []string `json:"values"`
@@ -51,14 +52,6 @@ var _ ChangeManager = (*BatchingChangeManager)(nil)
51
52
  // 2 ** 256 - 1
52
53
  var MaxSDKInt = sdk.NewIntFromBigInt(new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil), big.NewInt(1)))
53
54
 
54
- // TODO: Use bytes.CutPrefix once we can rely upon go >= 1.20.
55
- func cutPrefix(s, prefix []byte) (after []byte, found bool) {
56
- if !bytes.HasPrefix(s, prefix) {
57
- return s, false
58
- }
59
- return s[len(prefix):], true
60
- }
61
-
62
55
  // Keeper maintains the link to data storage and exposes getter/setter methods
63
56
  // for the various parts of the state machine
64
57
  type Keeper struct {
@@ -163,7 +156,7 @@ func (k Keeper) ExportStorageFromPrefix(ctx sdk.Context, pathPrefix string) []*t
163
156
  if !strings.HasPrefix(path, pathPrefix) {
164
157
  continue
165
158
  }
166
- value, hasPrefix := cutPrefix(rawValue, types.EncodedDataPrefix)
159
+ value, hasPrefix := bytes.CutPrefix(rawValue, types.EncodedDataPrefix)
167
160
  if !hasPrefix {
168
161
  panic(fmt.Errorf("value at path %q starts with unexpected prefix", path))
169
162
  }
@@ -265,7 +258,7 @@ func (k Keeper) GetEntry(ctx sdk.Context, path string) agoric.KVEntry {
265
258
  if bytes.Equal(rawValue, types.EncodedNoDataValue) {
266
259
  return agoric.NewKVEntryWithNoValue(path)
267
260
  }
268
- value, hasPrefix := cutPrefix(rawValue, types.EncodedDataPrefix)
261
+ value, hasPrefix := bytes.CutPrefix(rawValue, types.EncodedDataPrefix)
269
262
  if !hasPrefix {
270
263
  panic(fmt.Errorf("value at path %q starts with unexpected prefix", path))
271
264
  }
@@ -428,7 +421,7 @@ func (k Keeper) GetNoDataValue() []byte {
428
421
  return types.EncodedNoDataValue
429
422
  }
430
423
 
431
- func (k Keeper) getIntValue(ctx sdk.Context, path string) (sdk.Int, error) {
424
+ func (k Keeper) GetIntValue(ctx sdk.Context, path string) (sdkmath.Int, error) {
432
425
  indexEntry := k.GetEntry(ctx, path)
433
426
  if !indexEntry.HasValue() {
434
427
  return sdk.NewInt(0), nil
@@ -441,14 +434,14 @@ func (k Keeper) getIntValue(ctx sdk.Context, path string) (sdk.Int, error) {
441
434
  return index, nil
442
435
  }
443
436
 
444
- func (k Keeper) GetQueueLength(ctx sdk.Context, queuePath string) (sdk.Int, error) {
445
- head, err := k.getIntValue(ctx, queuePath+".head")
437
+ func (k Keeper) GetQueueLength(ctx sdk.Context, queuePath string) (sdkmath.Int, error) {
438
+ head, err := k.GetIntValue(ctx, queuePath+".head")
446
439
  if err != nil {
447
- return sdk.NewInt(0), err
440
+ return sdkmath.NewInt(0), err
448
441
  }
449
- tail, err := k.getIntValue(ctx, queuePath+".tail")
442
+ tail, err := k.GetIntValue(ctx, queuePath+".tail")
450
443
  if err != nil {
451
- return sdk.NewInt(0), err
444
+ return sdkmath.NewInt(0), err
452
445
  }
453
446
  // The tail index is exclusive
454
447
  return tail.Sub(head), nil
@@ -457,12 +450,12 @@ func (k Keeper) GetQueueLength(ctx sdk.Context, queuePath string) (sdk.Int, erro
457
450
  func (k Keeper) PushQueueItem(ctx sdk.Context, queuePath string, value string) error {
458
451
  // Get the current queue tail, defaulting to zero if its vstorage doesn't exist.
459
452
  // The `tail` is the value of the next index to be inserted
460
- tail, err := k.getIntValue(ctx, queuePath+".tail")
453
+ tail, err := k.GetIntValue(ctx, queuePath+".tail")
461
454
  if err != nil {
462
455
  return err
463
456
  }
464
457
 
465
- if tail.Equal(MaxSDKInt) {
458
+ if tail.GTE(MaxSDKInt) {
466
459
  return errors.New(queuePath + " overflow")
467
460
  }
468
461
  nextTail := tail.Add(sdk.NewInt(1))