@agoric/cosmos 0.34.2-orchestration-dev-096c4e8.0 → 0.34.2-other-dev-3eb1a1d.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 (90) hide show
  1. package/MAINTAINERS.md +3 -0
  2. package/Makefile +38 -34
  3. package/ante/ante.go +1 -4
  4. package/ante/inbound_test.go +2 -2
  5. package/app/app.go +198 -137
  6. package/app/upgrade.go +248 -0
  7. package/cmd/agd/agvm.go +3 -3
  8. package/cmd/agd/find_binary.go +2 -2
  9. package/cmd/agd/main.go +9 -10
  10. package/cmd/libdaemon/main.go +13 -13
  11. package/daemon/cmd/root.go +235 -92
  12. package/daemon/cmd/root_test.go +189 -1
  13. package/daemon/main.go +3 -2
  14. package/git-revision.txt +1 -1
  15. package/go.mod +14 -11
  16. package/go.sum +20 -19
  17. package/index.cjs +1 -1
  18. package/package.json +4 -3
  19. package/proto/agoric/swingset/genesis.proto +4 -0
  20. package/proto/agoric/swingset/swingset.proto +26 -1
  21. package/proto/agoric/vbank/vbank.proto +7 -0
  22. package/proto/agoric/vtransfer/genesis.proto +18 -0
  23. package/scripts/protocgen.sh +7 -8
  24. package/types/kv_entry_helpers.go +42 -0
  25. package/upgradegaia.sh +8 -8
  26. package/util/util.go +21 -0
  27. package/vm/action.go +1 -1
  28. package/vm/client.go +15 -13
  29. package/vm/client_test.go +34 -36
  30. package/vm/controller.go +3 -38
  31. package/vm/core_proposals.go +22 -2
  32. package/vm/proto_json.go +38 -0
  33. package/vm/proto_json_test.go +103 -0
  34. package/vm/server.go +106 -5
  35. package/x/swingset/alias.go +2 -0
  36. package/x/swingset/config.go +234 -0
  37. package/x/swingset/genesis.go +178 -40
  38. package/x/swingset/keeper/extension_snapshotter.go +2 -2
  39. package/x/swingset/keeper/keeper.go +24 -27
  40. package/x/swingset/keeper/swing_store_exports_handler.go +14 -3
  41. package/x/swingset/keeper/test_utils.go +16 -0
  42. package/x/swingset/module.go +24 -9
  43. package/x/swingset/testing/queue.go +17 -0
  44. package/x/swingset/types/default-params.go +31 -5
  45. package/x/swingset/types/expected_keepers.go +2 -2
  46. package/x/swingset/types/genesis.pb.go +78 -25
  47. package/x/swingset/types/msgs.go +53 -12
  48. package/x/swingset/types/params.go +53 -43
  49. package/x/swingset/types/params_test.go +75 -9
  50. package/x/swingset/types/swingset.pb.go +387 -57
  51. package/x/vbank/README.md +6 -1
  52. package/x/vbank/genesis.go +0 -2
  53. package/x/vbank/keeper/keeper.go +4 -9
  54. package/x/vbank/keeper/migrations.go +30 -0
  55. package/x/vbank/module.go +8 -7
  56. package/x/vbank/types/key.go +3 -3
  57. package/x/vbank/types/msgs.go +0 -12
  58. package/x/vbank/types/params.go +43 -2
  59. package/x/vbank/types/vbank.pb.go +105 -36
  60. package/x/vbank/vbank.go +8 -13
  61. package/x/vbank/vbank_test.go +14 -9
  62. package/x/vibc/alias.go +1 -1
  63. package/x/vibc/module.go +2 -7
  64. package/x/vibc/types/ibc_module.go +9 -3
  65. package/x/vibc/types/receiver.go +17 -7
  66. package/x/vlocalchain/handler.go +2 -1
  67. package/x/vlocalchain/keeper/keeper.go +24 -8
  68. package/x/vlocalchain/keeper/keeper_test.go +65 -1
  69. package/x/vlocalchain/types/expected_keepers.go +12 -0
  70. package/x/vlocalchain/vlocalchain.go +27 -22
  71. package/x/vlocalchain/vlocalchain_test.go +163 -8
  72. package/x/vstorage/keeper/grpc_query.go +0 -1
  73. package/x/vstorage/keeper/keeper.go +9 -17
  74. package/x/vstorage/module.go +0 -5
  75. package/x/vstorage/testing/queue.go +28 -0
  76. package/x/vtransfer/alias.go +13 -0
  77. package/x/vtransfer/genesis.go +39 -0
  78. package/x/vtransfer/genesis_test.go +12 -0
  79. package/x/vtransfer/handler.go +20 -0
  80. package/x/vtransfer/ibc_middleware.go +186 -0
  81. package/x/vtransfer/ibc_middleware_test.go +449 -0
  82. package/x/vtransfer/keeper/keeper.go +282 -0
  83. package/x/vtransfer/module.go +124 -0
  84. package/x/vtransfer/types/baseaddr.go +156 -0
  85. package/x/vtransfer/types/baseaddr_test.go +167 -0
  86. package/x/vtransfer/types/expected_keepers.go +38 -0
  87. package/x/vtransfer/types/genesis.pb.go +328 -0
  88. package/x/vtransfer/types/key.go +9 -0
  89. package/x/vtransfer/types/msgs.go +9 -0
  90. package/ante/fee.go +0 -97
@@ -14,7 +14,7 @@ import (
14
14
  )
15
15
 
16
16
  var (
17
- _ vm.PortHandler = Receiver{}
17
+ _ vm.PortHandler = (*Receiver)(nil)
18
18
  _ exported.Acknowledgement = (*rawAcknowledgement)(nil)
19
19
  )
20
20
 
@@ -83,18 +83,28 @@ func (r rawAcknowledgement) Success() bool {
83
83
  return true
84
84
  }
85
85
 
86
- func (ir Receiver) Receive(cctx context.Context, str string) (ret string, err error) {
86
+ // Receive implements vm.PortHandler. It unmarshals the string as JSON text
87
+ // representing an IBC portMessage object. If the resulting type is
88
+ // "IBC_METHOD" it dispatches on method ("sendPacket"/"receiveExecuted"/etc.)
89
+ // and calls the corresponding method of the wrapped ReceiverImpl.
90
+ //
91
+ // Otherwise, it requires the wrapped ReceiverImpl to be a vm.PortHandler
92
+ // and delegates to the Receive method of that PortHandler.
93
+ func (ir Receiver) Receive(cctx context.Context, jsonRequest string) (jsonReply string, err error) {
87
94
  ctx := sdk.UnwrapSDKContext(cctx)
88
95
  impl := ir.impl
89
96
 
90
97
  msg := new(portMessage)
91
- err = json.Unmarshal([]byte(str), &msg)
98
+ err = json.Unmarshal([]byte(jsonRequest), &msg)
92
99
  if err != nil {
93
100
  return "", err
94
101
  }
95
102
 
96
103
  if msg.Type != "IBC_METHOD" {
97
- return "", fmt.Errorf(`channel handler only accepts messages of "type": "IBC_METHOD"`)
104
+ if receiver, ok := impl.(vm.PortHandler); ok {
105
+ return receiver.Receive(cctx, jsonRequest)
106
+ }
107
+ return "", fmt.Errorf(`channel handler only accepts messages of "type": "IBC_METHOD"; got %q`, msg.Type)
98
108
  }
99
109
 
100
110
  switch msg.Method {
@@ -116,7 +126,7 @@ func (ir Receiver) Receive(cctx context.Context, str string) (ret string, err er
116
126
  packet.Sequence = seq
117
127
  bytes, err := json.Marshal(&packet)
118
128
  if err == nil {
119
- ret = string(bytes)
129
+ jsonReply = string(bytes)
120
130
  }
121
131
  }
122
132
 
@@ -153,8 +163,8 @@ func (ir Receiver) Receive(cctx context.Context, str string) (ret string, err er
153
163
  err = fmt.Errorf("unrecognized method %s", msg.Method)
154
164
  }
155
165
 
156
- if ret == "" && err == nil {
157
- ret = "true"
166
+ if jsonReply == "" && err == nil {
167
+ jsonReply = "true"
158
168
  }
159
169
  return
160
170
  }
@@ -3,6 +3,7 @@ package vlocalchain
3
3
  import (
4
4
  "fmt"
5
5
 
6
+ sdkioerrors "cosmossdk.io/errors"
6
7
  "github.com/Agoric/agoric-sdk/golang/cosmos/x/vlocalchain/keeper"
7
8
  sdk "github.com/cosmos/cosmos-sdk/types"
8
9
  sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@@ -14,7 +15,7 @@ func NewHandler(keeper keeper.Keeper) sdk.Handler {
14
15
  switch msg := msg.(type) {
15
16
  default:
16
17
  errMsg := fmt.Sprintf("Unrecognized vlocalchain Msg type: %T", msg)
17
- return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
18
+ return nil, sdkioerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
18
19
  }
19
20
  }
20
21
  }
@@ -28,6 +28,7 @@ type Keeper struct {
28
28
  cdc codec.Codec
29
29
  msgRouter types.MsgRouter
30
30
  queryRouter types.GRPCQueryRouter
31
+ acctKeeper types.AccountKeeper
31
32
  }
32
33
 
33
34
  // NewKeeper creates a new dIBC Keeper instance
@@ -36,12 +37,14 @@ func NewKeeper(
36
37
  key storetypes.StoreKey,
37
38
  msgRouter types.MsgRouter,
38
39
  queryRouter types.GRPCQueryRouter,
40
+ acctKeeper types.AccountKeeper,
39
41
  ) Keeper {
40
42
  return Keeper{
41
43
  key: key,
42
44
  cdc: cdc,
43
45
  msgRouter: msgRouter,
44
46
  queryRouter: queryRouter,
47
+ acctKeeper: acctKeeper,
45
48
  }
46
49
  }
47
50
 
@@ -266,14 +269,27 @@ func (k Keeper) AllocateAddress(cctx context.Context) sdk.AccAddress {
266
269
  localchainModuleAcc := sdkaddress.Module(types.ModuleName, []byte("localchain"))
267
270
  header := ctx.BlockHeader()
268
271
 
269
- // Increment our sequence number.
270
- seq := store.Get(types.KeyLastSequence)
271
- seq = types.NextSequence(seq)
272
- store.Set(types.KeyLastSequence, seq)
272
+ // Loop until we find an unused address.
273
+ for {
274
+ // Increment our sequence number.
275
+ seq := store.Get(types.KeyLastSequence)
276
+ seq = types.NextSequence(seq)
277
+ store.Set(types.KeyLastSequence, seq)
273
278
 
274
- buf := seq
275
- buf = append(buf, header.AppHash...)
276
- buf = append(buf, header.DataHash...)
279
+ buf := seq
280
+ buf = append(buf, header.AppHash...)
281
+ buf = append(buf, header.DataHash...)
277
282
 
278
- return sdkaddress.Derive(localchainModuleAcc, buf)
283
+ addr := sdkaddress.Derive(localchainModuleAcc, buf)
284
+ if k.acctKeeper.HasAccount(ctx, addr) {
285
+ continue
286
+ }
287
+
288
+ // We found an unused address, so create an account for it.
289
+ acct := k.acctKeeper.NewAccountWithAddress(ctx, addr)
290
+ k.acctKeeper.SetAccount(ctx, acct)
291
+
292
+ // All good, return the address.
293
+ return addr
294
+ }
279
295
  }
@@ -1,6 +1,14 @@
1
1
  package keeper
2
2
 
3
- import "testing"
3
+ import (
4
+ "testing"
5
+
6
+ "github.com/stretchr/testify/require"
7
+
8
+ "github.com/Agoric/agoric-sdk/golang/cosmos/app/params"
9
+ sdk "github.com/cosmos/cosmos-sdk/types"
10
+ banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
11
+ )
4
12
 
5
13
  func TestKeeper_ParseRequestTypeURL(t *testing.T) {
6
14
  testCases := []struct {
@@ -30,3 +38,59 @@ func TestKeeper_ParseRequestTypeURL(t *testing.T) {
30
38
  })
31
39
  }
32
40
  }
41
+
42
+ func TestKeeper_DeserializeTxMessages(t *testing.T) {
43
+ encodingConfig := params.MakeEncodingConfig()
44
+ cdc := encodingConfig.Marshaler
45
+
46
+ banktypes.RegisterInterfaces(encodingConfig.InterfaceRegistry)
47
+
48
+ keeper := NewKeeper(cdc, nil, nil, nil, nil)
49
+
50
+ expectedMsgSend := []sdk.Msg{
51
+ &banktypes.MsgSend{
52
+ FromAddress: "cosmos1abc",
53
+ ToAddress: "cosmos1xyz",
54
+ Amount: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(100))),
55
+ },
56
+ }
57
+
58
+ testCases := []struct {
59
+ name string
60
+ json string
61
+ expected []sdk.Msg
62
+ wantErr bool
63
+ }{
64
+ {
65
+ name: "camelCase keys",
66
+ json: `{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","fromAddress":"cosmos1abc","toAddress":"cosmos1xyz","amount":[{"denom":"stake","amount":"100"}]}]}`,
67
+ expected: expectedMsgSend,
68
+ wantErr: false,
69
+ },
70
+ {
71
+ name: "snake_case keys",
72
+ json: `{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"cosmos1abc","to_address":"cosmos1xyz","amount":[{"denom":"stake","amount":"100"}]}]}`,
73
+ expected: expectedMsgSend,
74
+ wantErr: false,
75
+ },
76
+ {
77
+ name: "misspelled key",
78
+ json: `{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_addresss":"cosmos1abc","to_address":"cosmos1xyz","amount":[{"denom":"stake","amount":"100"}]}]}`,
79
+ expected: expectedMsgSend,
80
+ wantErr: true,
81
+ },
82
+ }
83
+
84
+ for _, tc := range testCases {
85
+ t.Run(tc.name, func(t *testing.T) {
86
+ msgs, err := keeper.DeserializeTxMessages([]byte(tc.json))
87
+
88
+ if tc.wantErr {
89
+ require.Error(t, err)
90
+ } else {
91
+ require.NoError(t, err)
92
+ require.Equal(t, tc.expected, msgs)
93
+ }
94
+ })
95
+ }
96
+ }
@@ -0,0 +1,12 @@
1
+ package types
2
+
3
+ import (
4
+ sdk "github.com/cosmos/cosmos-sdk/types"
5
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
6
+ )
7
+
8
+ type AccountKeeper interface {
9
+ NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
10
+ HasAccount(ctx sdk.Context, addr sdk.AccAddress) bool
11
+ SetAccount(ctx sdk.Context, acc authtypes.AccountI)
12
+ }
@@ -6,7 +6,6 @@ import (
6
6
  "fmt"
7
7
 
8
8
  sdk "github.com/cosmos/cosmos-sdk/types"
9
- "github.com/gogo/protobuf/jsonpb"
10
9
 
11
10
  "github.com/Agoric/agoric-sdk/golang/cosmos/vm"
12
11
  "github.com/Agoric/agoric-sdk/golang/cosmos/x/vlocalchain/keeper"
@@ -45,7 +44,7 @@ func (h portHandler) Receive(cctx context.Context, str string) (ret string, err
45
44
  }
46
45
  ret = string(bz)
47
46
 
48
- case "VLOCALCHAIN_QUERY":
47
+ case "VLOCALCHAIN_QUERY_MANY":
49
48
  // Copy the JSON messages string into a CosmosTx object so we can
50
49
  // deserialize it with just proto3 JSON.
51
50
  cosmosTxBz := []byte(`{"messages":` + string(msg.Messages) + `}`)
@@ -56,28 +55,36 @@ func (h portHandler) Receive(cctx context.Context, str string) (ret string, err
56
55
  return
57
56
  }
58
57
 
59
- // We need jsonpb for its access to the global registry.
60
- marshaller := jsonpb.Marshaler{EmitDefaults: true, OrigName: true}
61
-
62
- var s string
63
- resps := make([]json.RawMessage, len(qms))
58
+ var errs []error
59
+ resps := make([]interface{}, len(qms))
64
60
  for i, qm := range qms {
65
61
  var qr *types.QueryResponse
66
62
  qr, err = h.keeper.Query(cctx, qm)
67
- if err != nil {
68
- return
69
- }
70
- if s, err = marshaller.MarshalToString(qr); err != nil {
71
- return
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()}
72
69
  }
73
- resps[i] = []byte(s)
74
70
  }
75
71
 
76
- var bz []byte
77
- if bz, err = json.Marshal(resps); err != nil {
78
- return
72
+ bz, err := vm.ProtoJSONMarshalSlice(resps)
73
+ if err != nil {
74
+ return "", err
79
75
  }
80
- ret = string(bz)
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
81
88
 
82
89
  case "VLOCALCHAIN_EXECUTE_TX":
83
90
  origCtx := sdk.UnwrapSDKContext(cctx)
@@ -97,11 +104,9 @@ func (h portHandler) Receive(cctx context.Context, str string) (ret string, err
97
104
  return
98
105
  }
99
106
 
100
- var bz []byte
101
- if bz, err = json.Marshal(resps); err != nil {
102
- return
103
- }
104
- ret = string(bz)
107
+ // Marshal the responses to proto3 JSON.
108
+ bz, e := vm.ProtoJSONMarshalSlice(resps)
109
+ return string(bz), e
105
110
  default:
106
111
  err = fmt.Errorf("unrecognized message type %s", msg.Type)
107
112
  }
@@ -5,6 +5,7 @@ import (
5
5
  "encoding/json"
6
6
  "strings"
7
7
  "testing"
8
+ "time"
8
9
 
9
10
  "github.com/Agoric/agoric-sdk/golang/cosmos/app/params"
10
11
  "github.com/Agoric/agoric-sdk/golang/cosmos/vm"
@@ -15,7 +16,9 @@ import (
15
16
  "github.com/cosmos/cosmos-sdk/store"
16
17
  storetypes "github.com/cosmos/cosmos-sdk/store/types"
17
18
  sdk "github.com/cosmos/cosmos-sdk/types"
19
+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
18
20
  banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
21
+ stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
19
22
  transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"
20
23
  "github.com/tendermint/tendermint/libs/log"
21
24
 
@@ -34,6 +37,25 @@ const (
34
37
  msgAllocateAddress = `{"type":"VLOCALCHAIN_ALLOCATE_ADDRESS"}`
35
38
  )
36
39
 
40
+ type mockAccounts struct {
41
+ existing map[string]bool
42
+ }
43
+
44
+ var _ types.AccountKeeper = (*mockAccounts)(nil)
45
+
46
+ func (a *mockAccounts) NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI {
47
+ return authtypes.NewBaseAccountWithAddress(addr)
48
+ }
49
+
50
+ func (a *mockAccounts) HasAccount(ctx sdk.Context, addr sdk.AccAddress) bool {
51
+ existing := a.existing[addr.String()]
52
+ return existing
53
+ }
54
+
55
+ func (a *mockAccounts) SetAccount(ctx sdk.Context, acc authtypes.AccountI) {
56
+ a.existing[acc.GetAddress().String()] = true
57
+ }
58
+
37
59
  type mockBank struct {
38
60
  banktypes.UnimplementedQueryServer
39
61
  banktypes.UnimplementedMsgServer
@@ -77,8 +99,36 @@ func (t *mockTransfer) Transfer(cctx context.Context, msg *transfertypes.MsgTran
77
99
  return &transfertypes.MsgTransferResponse{Sequence: 1}, nil
78
100
  }
79
101
 
102
+ type mockStaking struct {
103
+ stakingtypes.UnimplementedMsgServer
104
+ stakingtypes.UnimplementedQueryServer
105
+ }
106
+
107
+ var _ stakingtypes.MsgServer = (*mockStaking)(nil)
108
+ var _ stakingtypes.QueryServer = (*mockStaking)(nil)
109
+
110
+ func (s *mockStaking) Undelegate(cctx context.Context, msg *stakingtypes.MsgUndelegate) (*stakingtypes.MsgUndelegateResponse, error) {
111
+ return &stakingtypes.MsgUndelegateResponse{CompletionTime: time.Now().UTC()}, nil
112
+ }
113
+
114
+ func (s *mockStaking) UnbondingDelegation(cctx context.Context, req *stakingtypes.QueryUnbondingDelegationRequest) (*stakingtypes.QueryUnbondingDelegationResponse, error) {
115
+ unbondingDelegation := stakingtypes.UnbondingDelegation{
116
+ DelegatorAddress: req.DelegatorAddr,
117
+ ValidatorAddress: "cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj",
118
+ Entries: []stakingtypes.UnbondingDelegationEntry{
119
+ {
120
+ CreationHeight: 100,
121
+ CompletionTime: time.Now().UTC().Add(time.Hour * 24 * 7),
122
+ InitialBalance: sdk.NewInt(1000),
123
+ Balance: sdk.NewInt(500),
124
+ },
125
+ },
126
+ }
127
+ return &stakingtypes.QueryUnbondingDelegationResponse{Unbond: unbondingDelegation}, nil
128
+ }
129
+
80
130
  // makeTestKit creates a minimal Keeper and Context for use in testing.
81
- func makeTestKit(bank *mockBank, transfer *mockTransfer) (vm.PortHandler, context.Context) {
131
+ func makeTestKit(bank *mockBank, transfer *mockTransfer, staking *mockStaking, accts *mockAccounts) (vm.PortHandler, context.Context) {
82
132
  encodingConfig := params.MakeEncodingConfig()
83
133
  cdc := encodingConfig.Marshaler
84
134
 
@@ -93,9 +143,12 @@ func makeTestKit(bank *mockBank, transfer *mockTransfer) (vm.PortHandler, contex
93
143
  transfertypes.RegisterInterfaces(encodingConfig.InterfaceRegistry)
94
144
  transfertypes.RegisterMsgServer(txRouter, transfer)
95
145
  transfertypes.RegisterQueryServer(queryRouter, transfer)
146
+ stakingtypes.RegisterInterfaces(encodingConfig.InterfaceRegistry)
147
+ stakingtypes.RegisterMsgServer(txRouter, staking)
148
+ stakingtypes.RegisterQueryServer(queryRouter, staking)
96
149
 
97
150
  // create a new Keeper
98
- keeper := vlocalchain.NewKeeper(cdc, vlocalchainStoreKey, txRouter, queryRouter)
151
+ keeper := vlocalchain.NewKeeper(cdc, vlocalchainStoreKey, txRouter, queryRouter, accts)
99
152
 
100
153
  db := dbm.NewMemDB()
101
154
  ms := store.NewCommitMultiStore(db)
@@ -118,13 +171,16 @@ func makeTestKit(bank *mockBank, transfer *mockTransfer) (vm.PortHandler, contex
118
171
  func TestAllocateAddress(t *testing.T) {
119
172
  bank := &mockBank{}
120
173
  transfer := &mockTransfer{}
121
- handler, cctx := makeTestKit(bank, transfer)
174
+ staking := &mockStaking{}
175
+ acct := &mockAccounts{existing: map[string]bool{
176
+ firstAddr: true,
177
+ "cosmos1c5hplwyxk5jr2dsygjqepzfqvfukwduq9c4660aah76krf99m6gs0k7hvl": true,
178
+ }}
179
+ handler, cctx := makeTestKit(bank, transfer, staking, acct)
122
180
 
123
181
  addrs := map[string]bool{
124
- firstAddr: false,
125
182
  "cosmos1yj40fakym8kf4wvgz9tky7k9f3v9msm3t7frscrmkjsdkxkpsfkqgeczkg": false,
126
183
  "cosmos1s76vryj7m8k8nm9le65a4plhf5rym5sumtt2n0vwnk5l6k4cwuhsj56ujj": false,
127
- "cosmos1c5hplwyxk5jr2dsygjqepzfqvfukwduq9c4660aah76krf99m6gs0k7hvl": false,
128
184
  "cosmos1ys3a7mtna3cad0wxcs4ddukn37stexjdvns8jfdn4uerlr95y4xqnrypf6": false,
129
185
  }
130
186
  numToTest := len(addrs)
@@ -150,6 +206,9 @@ func TestAllocateAddress(t *testing.T) {
150
206
  t.Fatalf("unexpected duplicate address[%d]: %v", i, addr)
151
207
  }
152
208
  addrs[addr] = true
209
+ if !acct.existing[addr] {
210
+ t.Fatalf("expected address[%d]: %v to be added to accounts", i, addr)
211
+ }
153
212
  }
154
213
  }
155
214
 
@@ -161,7 +220,9 @@ func TestQuery(t *testing.T) {
161
220
  alreadyAddr: []sdk.Coin{sdk.NewCoin("stale", sdk.NewInt(321))},
162
221
  }}
163
222
  transfer := &mockTransfer{}
164
- handler, cctx := makeTestKit(bank, transfer)
223
+ staking := &mockStaking{}
224
+ accts := &mockAccounts{existing: map[string]bool{}}
225
+ handler, cctx := makeTestKit(bank, transfer, staking, accts)
165
226
 
166
227
  // get balances
167
228
  testCases := []struct {
@@ -180,7 +241,7 @@ func TestQuery(t *testing.T) {
180
241
  tc := tc
181
242
  ctx := sdk.UnwrapSDKContext(cctx)
182
243
  t.Run(tc.name, func(t *testing.T) {
183
- msgGetBalances := `{"type":"VLOCALCHAIN_QUERY","messages":[{"@type":"/cosmos.bank.v1beta1.QueryAllBalancesRequest","address":"` + tc.addr + `"}]}`
244
+ msgGetBalances := `{"type":"VLOCALCHAIN_QUERY_MANY","messages":[{"@type":"/cosmos.bank.v1beta1.QueryAllBalancesRequest","address":"` + tc.addr + `"}]}`
184
245
  t.Logf("query request: %v", msgGetBalances)
185
246
  ret, err := handler.Receive(cctx, msgGetBalances)
186
247
  t.Logf("query response: %v", ret)
@@ -230,6 +291,68 @@ func TestQuery(t *testing.T) {
230
291
  }
231
292
  })
232
293
  }
294
+
295
+ t.Run("UnbondingDelegation", func(t *testing.T) {
296
+ // create a new message
297
+ msg := `{"type":"VLOCALCHAIN_QUERY_MANY","messages":[{"@type":"/cosmos.staking.v1beta1.QueryUnbondingDelegationRequest","delegator_addr":"` + firstAddr + `","validator_addr":"cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj"}]}`
298
+ t.Logf("query request: %v", msg)
299
+ ret, err := handler.Receive(cctx, msg)
300
+ t.Logf("query response: %v", ret)
301
+ if err != nil {
302
+ t.Fatalf("unexpected error: %v", err)
303
+ }
304
+ if ret == "" {
305
+ t.Fatalf("expected non-empty json")
306
+ }
307
+
308
+ // Unmarshal the JSON response
309
+ var respJSON []map[string]interface{}
310
+ if err := json.Unmarshal([]byte(ret), &respJSON); err != nil {
311
+ t.Fatalf("unexpected error unmarshalling JSON response: %v", err)
312
+ }
313
+
314
+ // Check the response fields
315
+ if len(respJSON) != 1 {
316
+ t.Fatalf("expected 1 response, got %d", len(respJSON))
317
+ }
318
+ resp := respJSON[0]
319
+
320
+ replyAny, ok := resp["reply"].(map[string]interface{})
321
+ if !ok {
322
+ t.Fatalf("expected reply field to be a map, got %v", resp["reply"])
323
+ }
324
+
325
+ unbond, ok := replyAny["unbond"].(map[string]interface{})
326
+ if !ok {
327
+ t.Fatalf("expected unbond field to be a map, got %v", replyAny["unbond"])
328
+ }
329
+
330
+ // Check the field names and values
331
+ if unbond["delegatorAddress"] != firstAddr {
332
+ t.Errorf("expected delegatorAddress %s, got %v", firstAddr, unbond["delegator_address"])
333
+ }
334
+ if unbond["validatorAddress"] != "cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj" {
335
+ t.Errorf("expected validatorAddress cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj, got %v", unbond["validator_address"])
336
+ }
337
+
338
+ entries, ok := unbond["entries"].([]interface{})
339
+ if !ok || len(entries) != 1 {
340
+ t.Fatalf("expected 1 unbonding delegation entry, got %v", entries)
341
+ }
342
+ entry, ok := entries[0].(map[string]interface{})
343
+ if !ok {
344
+ t.Fatalf("expected unbonding delegation entry to be a map, got %v", entries[0])
345
+ }
346
+ if entry["creationHeight"] != "100" {
347
+ t.Errorf("expected creationHeight \"100\", got %v", entry["creation_height"])
348
+ }
349
+ if entry["balance"] != "500" {
350
+ t.Errorf("expected balance \"500\", got %v", entry["balance"])
351
+ }
352
+ if _, ok := entry["completionTime"]; !ok {
353
+ t.Error("expected completionTime field in the response")
354
+ }
355
+ })
233
356
  }
234
357
 
235
358
  func TestExecuteTx(t *testing.T) {
@@ -239,7 +362,9 @@ func TestExecuteTx(t *testing.T) {
239
362
  alreadyAddr: []sdk.Coin{sdk.NewCoin("stale", sdk.NewInt(321))},
240
363
  }}
241
364
  transfer := &mockTransfer{}
242
- handler, cctx := makeTestKit(bank, transfer)
365
+ staking := &mockStaking{}
366
+ accts := &mockAccounts{existing: map[string]bool{}}
367
+ handler, cctx := makeTestKit(bank, transfer, staking, accts)
243
368
 
244
369
  // create a new message
245
370
  msg := `{"type":"VLOCALCHAIN_ALLOCATE_ADDRESS"}`
@@ -302,4 +427,34 @@ func TestExecuteTx(t *testing.T) {
302
427
  }
303
428
  })
304
429
  }
430
+
431
+ t.Run("MsgUndelegate", func(t *testing.T) {
432
+ // create a new message
433
+ msg := `{"type":"VLOCALCHAIN_EXECUTE_TX","address":"` + addr +
434
+ `","messages":[{"@type":"/cosmos.staking.v1beta1.MsgUndelegate","delegatorAddress":"` +
435
+ addr + `","validatorAddress":"cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj","amount":{"denom":"stake","amount":"100"}}]}`
436
+
437
+ ret, err := handler.Receive(cctx, msg)
438
+ if err != nil {
439
+ t.Fatalf("unexpected error: %s", err)
440
+ }
441
+ if ret == "" {
442
+ t.Fatalf("expected non-empty json")
443
+ }
444
+
445
+ // Unmarshal the response
446
+ var resp []map[string]interface{}
447
+ if err := json.Unmarshal([]byte(ret), &resp); err != nil {
448
+ t.Fatalf("unexpected error unmarshalling response: %v", err)
449
+ }
450
+
451
+ // Check the response fields
452
+ if len(resp) != 1 {
453
+ t.Fatalf("expected 1 response, got %d", len(resp))
454
+ }
455
+
456
+ if _, ok := resp[0]["completionTime"]; !ok {
457
+ t.Error("expected 'completionTime' field in response")
458
+ }
459
+ })
305
460
  }
@@ -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 {
@@ -22,8 +22,8 @@ import (
22
22
  // StreamCell is an envelope representing a sequence of values written at a path in a single block.
23
23
  // It is persisted to storage as a { "blockHeight": "<digits>", "values": ["...", ...] } JSON text
24
24
  // that off-chain consumers rely upon.
25
- // Many of those consumers *also* rely upon the strings of "values" being valid JSON text
26
- // (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.
27
27
  type StreamCell struct {
28
28
  BlockHeight string `json:"blockHeight"`
29
29
  Values []string `json:"values"`
@@ -52,14 +52,6 @@ var _ ChangeManager = (*BatchingChangeManager)(nil)
52
52
  // 2 ** 256 - 1
53
53
  var MaxSDKInt = sdk.NewIntFromBigInt(new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil), big.NewInt(1)))
54
54
 
55
- // TODO: Use bytes.CutPrefix once we can rely upon go >= 1.20.
56
- func cutPrefix(s, prefix []byte) (after []byte, found bool) {
57
- if !bytes.HasPrefix(s, prefix) {
58
- return s, false
59
- }
60
- return s[len(prefix):], true
61
- }
62
-
63
55
  // Keeper maintains the link to data storage and exposes getter/setter methods
64
56
  // for the various parts of the state machine
65
57
  type Keeper struct {
@@ -164,7 +156,7 @@ func (k Keeper) ExportStorageFromPrefix(ctx sdk.Context, pathPrefix string) []*t
164
156
  if !strings.HasPrefix(path, pathPrefix) {
165
157
  continue
166
158
  }
167
- value, hasPrefix := cutPrefix(rawValue, types.EncodedDataPrefix)
159
+ value, hasPrefix := bytes.CutPrefix(rawValue, types.EncodedDataPrefix)
168
160
  if !hasPrefix {
169
161
  panic(fmt.Errorf("value at path %q starts with unexpected prefix", path))
170
162
  }
@@ -266,7 +258,7 @@ func (k Keeper) GetEntry(ctx sdk.Context, path string) agoric.KVEntry {
266
258
  if bytes.Equal(rawValue, types.EncodedNoDataValue) {
267
259
  return agoric.NewKVEntryWithNoValue(path)
268
260
  }
269
- value, hasPrefix := cutPrefix(rawValue, types.EncodedDataPrefix)
261
+ value, hasPrefix := bytes.CutPrefix(rawValue, types.EncodedDataPrefix)
270
262
  if !hasPrefix {
271
263
  panic(fmt.Errorf("value at path %q starts with unexpected prefix", path))
272
264
  }
@@ -429,7 +421,7 @@ func (k Keeper) GetNoDataValue() []byte {
429
421
  return types.EncodedNoDataValue
430
422
  }
431
423
 
432
- func (k Keeper) getIntValue(ctx sdk.Context, path string) (sdkmath.Int, error) {
424
+ func (k Keeper) GetIntValue(ctx sdk.Context, path string) (sdkmath.Int, error) {
433
425
  indexEntry := k.GetEntry(ctx, path)
434
426
  if !indexEntry.HasValue() {
435
427
  return sdk.NewInt(0), nil
@@ -443,11 +435,11 @@ func (k Keeper) getIntValue(ctx sdk.Context, path string) (sdkmath.Int, error) {
443
435
  }
444
436
 
445
437
  func (k Keeper) GetQueueLength(ctx sdk.Context, queuePath string) (sdkmath.Int, error) {
446
- head, err := k.getIntValue(ctx, queuePath+".head")
438
+ head, err := k.GetIntValue(ctx, queuePath+".head")
447
439
  if err != nil {
448
440
  return sdkmath.NewInt(0), err
449
441
  }
450
- tail, err := k.getIntValue(ctx, queuePath+".tail")
442
+ tail, err := k.GetIntValue(ctx, queuePath+".tail")
451
443
  if err != nil {
452
444
  return sdkmath.NewInt(0), err
453
445
  }
@@ -458,12 +450,12 @@ func (k Keeper) GetQueueLength(ctx sdk.Context, queuePath string) (sdkmath.Int,
458
450
  func (k Keeper) PushQueueItem(ctx sdk.Context, queuePath string, value string) error {
459
451
  // Get the current queue tail, defaulting to zero if its vstorage doesn't exist.
460
452
  // The `tail` is the value of the next index to be inserted
461
- tail, err := k.getIntValue(ctx, queuePath+".tail")
453
+ tail, err := k.GetIntValue(ctx, queuePath+".tail")
462
454
  if err != nil {
463
455
  return err
464
456
  }
465
457
 
466
- if tail.Equal(MaxSDKInt) {
458
+ if tail.GTE(MaxSDKInt) {
467
459
  return errors.New(queuePath + " overflow")
468
460
  }
469
461
  nextTail := tail.Add(sdk.NewInt(1))
@@ -4,7 +4,6 @@ import (
4
4
  "context"
5
5
  "encoding/json"
6
6
 
7
- "github.com/gorilla/mux"
8
7
  "github.com/grpc-ecosystem/grpc-gateway/runtime"
9
8
  "github.com/spf13/cobra"
10
9
 
@@ -57,10 +56,6 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod
57
56
  return ValidateGenesis(&data)
58
57
  }
59
58
 
60
- // Register rest routes
61
- func (AppModuleBasic) RegisterRESTRoutes(ctx client.Context, rtr *mux.Router) {
62
- }
63
-
64
59
  func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
65
60
  _ = types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
66
61
  }