@agoric/cosmos 0.35.0-mainnet1B-dev-cfa7cb2.0 → 0.35.0-mainnet1B-dev-b0c1f78.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/cosmos",
3
- "version": "0.35.0-mainnet1B-dev-cfa7cb2.0+cfa7cb2",
3
+ "version": "0.35.0-mainnet1B-dev-b0c1f78.0+b0c1f78",
4
4
  "description": "Connect JS to the Cosmos blockchain SDK",
5
5
  "parsers": {
6
6
  "js": "mjs"
@@ -35,5 +35,5 @@
35
35
  "publishConfig": {
36
36
  "access": "public"
37
37
  },
38
- "gitHead": "cfa7cb2bf1aa80bc60741a0eb5ba884995e8ee4c"
38
+ "gitHead": "b0c1f788a06e8593426319de068acd64a390d349"
39
39
  }
@@ -16,16 +16,16 @@ import (
16
16
  // In addition to the methods declared in authtypes.AccountI, additional
17
17
  // expectations are enforced dynamically through casting and reflection:
18
18
  //
19
- // - non-module accounts are expected to obey the GenesisAccount interface,
20
- // i.e. to have a Validate() method;
19
+ // - non-module accounts are expected to obey the GenesisAccount interface,
20
+ // i.e. to have a Validate() method;
21
21
  //
22
- // - UnpackInterfacesMessage is needed for unpacking accounts embedded
23
- // in an Any message;
22
+ // - UnpackInterfacesMessage is needed for unpacking accounts embedded
23
+ // in an Any message;
24
24
  //
25
- // - MarshalYAML() is used for String rendering;
25
+ // - MarshalYAML() is used for String rendering;
26
26
  //
27
- // - protobuf Messages are expected to implement a number of "XXX"-prefixed
28
- // methods not visible in the Message interface.
27
+ // - protobuf Messages are expected to implement a number of "XXX"-prefixed
28
+ // methods not visible in the Message interface.
29
29
  //
30
30
  // Declaring the expected methods here allows them to implicitly fall through
31
31
  // to an embedded omniAccount.
@@ -116,7 +116,7 @@ func (uva unlockedVestingAccount) GetOriginalVesting() sdk.Coins {
116
116
  return sdk.NewCoins()
117
117
  }
118
118
 
119
- //GetDelegatedFree implements the vestexported.VestingAccount interface.
119
+ // GetDelegatedFree implements the vestexported.VestingAccount interface.
120
120
  func (uva unlockedVestingAccount) GetDelegatedFree() sdk.Coins {
121
121
  return uva.lien.Delegated
122
122
  }
@@ -172,6 +172,11 @@ func (fca fakeClawbackAccount) PostReward(ctx sdk.Context, reward sdk.Coins, act
172
172
  return nil
173
173
  }
174
174
 
175
+ // ReturnGrants implements the vestexported.ClawbackVestingAccountI interface.
176
+ func (fca fakeClawbackAccount) ReturnGrants(ctx sdk.Context, action vestexported.ReturnGrantAction) error {
177
+ return action.TakeGrants(ctx, fca.omniGrantAccount) // XXX or just fail here
178
+ }
179
+
175
180
  // LienAccount wraps an omniClawbackAccount to implement lien encumbrance.
176
181
  // The LockedCoins() method is the maximum of the coins locked for
177
182
  // liens, and the coins locked in the underlying VestingAccount.
@@ -37,6 +37,12 @@ const (
37
37
  StoragePathSwingStore = "swingStore"
38
38
  )
39
39
 
40
+ const (
41
+ // WalletStoragePathSegment matches the value of WALLET_STORAGE_PATH_SEGMENT
42
+ // packages/vats/src/core/startWalletFactory.js
43
+ WalletStoragePathSegment = "wallet"
44
+ )
45
+
40
46
  const (
41
47
  stateKey = "state"
42
48
  swingStoreKeyPrefix = "swingStore."
@@ -151,6 +157,20 @@ func (k Keeper) IsHighPriorityAddress(ctx sdk.Context, addr sdk.AccAddress) (boo
151
157
  return k.vstorageKeeper.HasEntry(ctx, path), nil
152
158
  }
153
159
 
160
+ // GetSmartWalletState returns the provision state of the smart wallet for the account address
161
+ func (k Keeper) GetSmartWalletState(ctx sdk.Context, addr sdk.AccAddress) types.SmartWalletState {
162
+ // walletStoragePath is path of `walletStorageNode` constructed in
163
+ // `provideSmartWallet` from packages/smart-wallet/src/walletFactory.js
164
+ walletStoragePath := StoragePathCustom + "." + WalletStoragePathSegment + "." + addr.String()
165
+
166
+ // TODO: implement a pending provision state
167
+ if k.vstorageKeeper.HasEntry(ctx, walletStoragePath) {
168
+ return types.SmartWalletStateProvisioned
169
+ }
170
+
171
+ return types.SmartWalletStateNone
172
+ }
173
+
154
174
  func (k Keeper) InboundQueueLength(ctx sdk.Context) (int32, error) {
155
175
  size := sdk.NewInt(0)
156
176
 
@@ -315,6 +335,25 @@ func (k Keeper) ChargeBeans(ctx sdk.Context, addr sdk.AccAddress, beans sdk.Uint
315
335
  return nil
316
336
  }
317
337
 
338
+ // ChargeForSmartWallet charges the fee for provisioning a smart wallet.
339
+ func (k Keeper) ChargeForSmartWallet(ctx sdk.Context, addr sdk.AccAddress) error {
340
+ beansPerUnit := k.GetBeansPerUnit(ctx)
341
+ beans := beansPerUnit[types.BeansPerSmartWalletProvision]
342
+ err := k.ChargeBeans(ctx, addr, beans)
343
+ if err != nil {
344
+ return err
345
+ }
346
+
347
+ // TODO: mark that a smart wallet provision is pending. However in that case,
348
+ // auto-provisioning should still be performed (but without fees being charged),
349
+ // until the controller actually provisions the smart wallet (the operation may
350
+ // transiently fail, requiring retries until success).
351
+ // However the provisioning code is not currently idempotent, and has side
352
+ // effects when the smart wallet is already provisioned.
353
+
354
+ return nil
355
+ }
356
+
318
357
  // makeFeeMenu returns a map from power flag to its fee. In the case of duplicates, the
319
358
  // first one wins.
320
359
  func makeFeeMenu(powerFlagFees []types.PowerFlagFee) map[string]sdk.Coins {
@@ -1,7 +1,7 @@
1
1
  package keeper
2
2
 
3
3
  import (
4
- v32 "github.com/Agoric/agoric-sdk/golang/cosmos/x/swingset/legacy/v32"
4
+ "github.com/Agoric/agoric-sdk/golang/cosmos/x/swingset/types"
5
5
  sdk "github.com/cosmos/cosmos-sdk/types"
6
6
  )
7
7
 
@@ -17,8 +17,13 @@ func NewMigrator(keeper Keeper) Migrator {
17
17
 
18
18
  // Migrate1to2 migrates from version 1 to 2.
19
19
  func (m Migrator) Migrate1to2(ctx sdk.Context) error {
20
+ return m.MigrateParams(ctx)
21
+ }
22
+
23
+ // MigrateParams migrates params by setting new params to their default value
24
+ func (m Migrator) MigrateParams(ctx sdk.Context) error {
20
25
  params := m.keeper.GetParams(ctx)
21
- newParams, err := v32.UpdateParams(params)
26
+ newParams, err := types.UpdateParams(params)
22
27
  if err != nil {
23
28
  return err
24
29
  }
@@ -80,6 +80,11 @@ type walletAction struct {
80
80
  func (keeper msgServer) WalletAction(goCtx context.Context, msg *types.MsgWalletAction) (*types.MsgWalletActionResponse, error) {
81
81
  ctx := sdk.UnwrapSDKContext(goCtx)
82
82
 
83
+ err := keeper.provisionIfNeeded(ctx, msg.Owner)
84
+ if err != nil {
85
+ return nil, err
86
+ }
87
+
83
88
  action := &walletAction{
84
89
  Type: "WALLET_ACTION",
85
90
  Owner: msg.Owner.String(),
@@ -89,7 +94,7 @@ func (keeper msgServer) WalletAction(goCtx context.Context, msg *types.MsgWallet
89
94
  }
90
95
  // fmt.Fprintf(os.Stderr, "Context is %+v\n", ctx)
91
96
 
92
- err := keeper.routeAction(ctx, msg, action)
97
+ err = keeper.routeAction(ctx, msg, action)
93
98
  // fmt.Fprintln(os.Stderr, "Returned from SwingSet", out, err)
94
99
  if err != nil {
95
100
  return nil, err
@@ -108,6 +113,11 @@ type walletSpendAction struct {
108
113
  func (keeper msgServer) WalletSpendAction(goCtx context.Context, msg *types.MsgWalletSpendAction) (*types.MsgWalletSpendActionResponse, error) {
109
114
  ctx := sdk.UnwrapSDKContext(goCtx)
110
115
 
116
+ err := keeper.provisionIfNeeded(ctx, msg.Owner)
117
+ if err != nil {
118
+ return nil, err
119
+ }
120
+
111
121
  action := &walletSpendAction{
112
122
  Type: "WALLET_SPEND_ACTION",
113
123
  Owner: msg.Owner.String(),
@@ -116,7 +126,7 @@ func (keeper msgServer) WalletSpendAction(goCtx context.Context, msg *types.MsgW
116
126
  BlockTime: ctx.BlockTime().Unix(),
117
127
  }
118
128
  // fmt.Fprintf(os.Stderr, "Context is %+v\n", ctx)
119
- err := keeper.routeAction(ctx, msg, action)
129
+ err = keeper.routeAction(ctx, msg, action)
120
130
  if err != nil {
121
131
  return nil, err
122
132
  }
@@ -125,9 +135,46 @@ func (keeper msgServer) WalletSpendAction(goCtx context.Context, msg *types.MsgW
125
135
 
126
136
  type provisionAction struct {
127
137
  *types.MsgProvision
128
- Type string `json:"type"` // PLEASE_PROVISION
129
- BlockHeight int64 `json:"blockHeight"`
130
- BlockTime int64 `json:"blockTime"`
138
+ Type string `json:"type"` // PLEASE_PROVISION
139
+ BlockHeight int64 `json:"blockHeight"`
140
+ BlockTime int64 `json:"blockTime"`
141
+ AutoProvision bool `json:"autoProvision"`
142
+ }
143
+
144
+ // provisionIfNeeded generates a provision action if no smart wallet is already
145
+ // provisioned for the account. This assumes that all messages for
146
+ // non-provisioned smart wallets allowed by the admission AnteHandler should
147
+ // auto-provision the smart wallet.
148
+ func (keeper msgServer) provisionIfNeeded(ctx sdk.Context, owner sdk.AccAddress) error {
149
+ // We need to generate a provision action until the smart wallet has
150
+ // been fully provisioned by the controller. This is because a provision is
151
+ // not guaranteed to succeed (e.g. lack of provision pool funds)
152
+ walletState := keeper.GetSmartWalletState(ctx, owner)
153
+ if walletState == types.SmartWalletStateProvisioned {
154
+ return nil
155
+ }
156
+
157
+ msg := &types.MsgProvision{
158
+ Address: owner,
159
+ Submitter: owner,
160
+ PowerFlags: []string{types.PowerFlagSmartWallet},
161
+ }
162
+
163
+ action := &provisionAction{
164
+ MsgProvision: msg,
165
+ Type: "PLEASE_PROVISION",
166
+ BlockHeight: ctx.BlockHeight(),
167
+ BlockTime: ctx.BlockTime().Unix(),
168
+ AutoProvision: true,
169
+ }
170
+
171
+ err := keeper.routeAction(ctx, msg, action)
172
+ // fmt.Fprintln(os.Stderr, "Returned from SwingSet", out, err)
173
+ if err != nil {
174
+ return err
175
+ }
176
+
177
+ return nil
131
178
  }
132
179
 
133
180
  func (keeper msgServer) Provision(goCtx context.Context, msg *types.MsgProvision) (*types.MsgProvisionResponse, error) {
@@ -11,20 +11,24 @@ import (
11
11
  // experience if they don't.
12
12
 
13
13
  const (
14
- BeansPerFeeUnit = "feeUnit"
15
- BeansPerInboundTx = "inboundTx"
16
- BeansPerBlockComputeLimit = "blockComputeLimit"
17
- BeansPerMessage = "message"
18
- BeansPerMessageByte = "messageByte"
19
- BeansPerMinFeeDebit = "minFeeDebit"
20
- BeansPerStorageByte = "storageByte"
21
- BeansPerVatCreation = "vatCreation"
22
- BeansPerXsnapComputron = "xsnapComputron"
14
+ BeansPerFeeUnit = "feeUnit"
15
+ BeansPerInboundTx = "inboundTx"
16
+ BeansPerBlockComputeLimit = "blockComputeLimit"
17
+ BeansPerMessage = "message"
18
+ BeansPerMessageByte = "messageByte"
19
+ BeansPerMinFeeDebit = "minFeeDebit"
20
+ BeansPerStorageByte = "storageByte"
21
+ BeansPerVatCreation = "vatCreation"
22
+ BeansPerXsnapComputron = "xsnapComputron"
23
+ BeansPerSmartWalletProvision = "smartWalletProvision"
23
24
 
24
25
  // QueueSize keys.
25
26
  // Keep up-to-date with updateQueueAllowed() in packanges/cosmic-swingset/src/launch-chain.js
26
27
  QueueInbound = "inbound"
27
28
  QueueInboundMempool = "inbound_mempool"
29
+
30
+ // PowerFlags.
31
+ PowerFlagSmartWallet = "SMART_WALLET"
28
32
  )
29
33
 
30
34
  var (
@@ -43,17 +47,18 @@ var (
43
47
 
44
48
  // TODO: create the cost model we want, and update these to be more principled.
45
49
  // These defaults currently make deploying an ag-solo cost less than $1.00.
46
- DefaultBeansPerFeeUnit = sdk.NewUint(1_000_000_000_000) // $1
47
- DefaultBeansPerInboundTx = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(100)) // $0.01
48
- DefaultBeansPerMessage = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(1_000)) // $0.001
49
- DefaultBeansPerMessageByte = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(50_000)) // $0.00002
50
- DefaultBeansPerMinFeeDebit = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(5)) // $0.2
51
- DefaultBeansPerStorageByte = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(500)) // $0.002
50
+ DefaultBeansPerFeeUnit = sdk.NewUint(1_000_000_000_000) // $1
51
+ DefaultBeansPerInboundTx = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(100)) // $0.01
52
+ DefaultBeansPerMessage = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(1_000)) // $0.001
53
+ DefaultBeansPerMessageByte = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(50_000)) // $0.00002
54
+ DefaultBeansPerMinFeeDebit = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(5)) // $0.2
55
+ DefaultBeansPerStorageByte = DefaultBeansPerFeeUnit.Quo(sdk.NewUint(500)) // $0.002
56
+ DefaultBeansPerSmartWalletProvision = DefaultBeansPerFeeUnit // $1
52
57
 
53
58
  DefaultBootstrapVatConfig = "@agoric/vats/decentral-core-config.json"
54
59
 
55
60
  DefaultPowerFlagFees = []PowerFlagFee{
56
- NewPowerFlagFee("SMART_WALLET", sdk.NewCoins(sdk.NewInt64Coin("ubld", 10_000_000))),
61
+ NewPowerFlagFee(PowerFlagSmartWallet, sdk.NewCoins(sdk.NewInt64Coin("ubld", 10_000_000))),
57
62
  }
58
63
 
59
64
  DefaultInboundQueueMax = int32(1_000)
@@ -75,5 +80,6 @@ func DefaultBeansPerUnit() []StringBeans {
75
80
  NewStringBeans(BeansPerStorageByte, DefaultBeansPerStorageByte),
76
81
  NewStringBeans(BeansPerVatCreation, DefaultBeansPerVatCreation),
77
82
  NewStringBeans(BeansPerXsnapComputron, DefaultBeansPerXsnapComputron),
83
+ NewStringBeans(BeansPerSmartWalletProvision, DefaultBeansPerSmartWalletProvision),
78
84
  }
79
85
  }
@@ -5,6 +5,15 @@ import (
5
5
  authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
6
6
  )
7
7
 
8
+ type SmartWalletState uint8
9
+
10
+ const (
11
+ SmartWalletStateUnspecified SmartWalletState = iota
12
+ SmartWalletStateNone
13
+ SmartWalletStatePending
14
+ SmartWalletStateProvisioned
15
+ )
16
+
8
17
  type AccountKeeper interface {
9
18
  GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
10
19
  NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
@@ -15,4 +24,6 @@ type SwingSetKeeper interface {
15
24
  GetBeansPerUnit(ctx sdk.Context) map[string]sdk.Uint
16
25
  ChargeBeans(ctx sdk.Context, addr sdk.AccAddress, beans sdk.Uint) error
17
26
  IsHighPriorityAddress(ctx sdk.Context, addr sdk.AccAddress) (bool, error)
27
+ GetSmartWalletState(ctx sdk.Context, addr sdk.AccAddress) SmartWalletState
28
+ ChargeForSmartWallet(ctx sdk.Context, addr sdk.AccAddress) error
18
29
  }
@@ -48,6 +48,33 @@ func chargeAdmission(ctx sdk.Context, keeper SwingSetKeeper, addr sdk.AccAddress
48
48
  return keeper.ChargeBeans(ctx, addr, beans)
49
49
  }
50
50
 
51
+ // checkSmartWalletProvisioned verifies if a smart wallet message (MsgWalletAction
52
+ // and MsgWalletSpendAction) can be delivered for the owner's address. A message
53
+ // is allowed if a smart wallet is already provisioned for the address, or if the
54
+ // provisioning fee is charged successfully.
55
+ // All messages for non-provisioned smart wallets allowed here will result in
56
+ // an auto-provision action generated by the msg server.
57
+ func checkSmartWalletProvisioned(ctx sdk.Context, keeper SwingSetKeeper, addr sdk.AccAddress) error {
58
+ walletState := keeper.GetSmartWalletState(ctx, addr)
59
+
60
+ switch walletState {
61
+ case SmartWalletStateProvisioned:
62
+ // The address already has a smart wallet
63
+ return nil
64
+ case SmartWalletStatePending:
65
+ // A provision (either explicit or automatic) may be pending execution in
66
+ // the controller, or if we ever allow multiple swingset messages per
67
+ // transaction, a previous message may have provisioned the wallet.
68
+ return nil
69
+ default:
70
+ // Charge for the smart wallet.
71
+ // This is a separate charge from the smart wallet action which triggered the check
72
+ // TODO: Currently this call does not mark the smart wallet provisioning as
73
+ // pending, resulting in multiple provisioning charges for the owner.
74
+ return keeper.ChargeForSmartWallet(ctx, addr)
75
+ }
76
+ }
77
+
51
78
  func NewMsgDeliverInbound(msgs *Messages, submitter sdk.AccAddress) *MsgDeliverInbound {
52
79
  return &MsgDeliverInbound{
53
80
  Messages: msgs.Messages,
@@ -137,6 +164,11 @@ func (msg MsgWalletAction) CheckAdmissibility(ctx sdk.Context, data interface{})
137
164
  return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "data must be a SwingSetKeeper, not a %T", data)
138
165
  }
139
166
 
167
+ err := checkSmartWalletProvisioned(ctx, keeper, msg.Owner)
168
+ if err != nil {
169
+ return err
170
+ }
171
+
140
172
  return chargeAdmission(ctx, keeper, msg.Owner, []string{msg.Action}, 0)
141
173
  }
142
174
 
@@ -204,6 +236,11 @@ func (msg MsgWalletSpendAction) CheckAdmissibility(ctx sdk.Context, data interfa
204
236
  return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "data must be a SwingSetKeeper, not a %T", data)
205
237
  }
206
238
 
239
+ err := checkSmartWalletProvisioned(ctx, keeper, msg.Owner)
240
+ if err != nil {
241
+ return err
242
+ }
243
+
207
244
  return chargeAdmission(ctx, keeper, msg.Owner, []string{msg.SpendAction}, 0)
208
245
  }
209
246
 
@@ -271,8 +308,12 @@ func (msg MsgProvision) ValidateBasic() error {
271
308
 
272
309
  // CheckAdmissibility implements the vm.ControllerAdmissionMsg interface.
273
310
  func (msg MsgProvision) CheckAdmissibility(ctx sdk.Context, data interface{}) error {
274
- // We have our own fee charging mechanism within Swingset itself,
275
- // so there are no admission restriction here.
311
+ // TODO: consider disallowing a provision message for a smart wallet if the
312
+ // smart wallet is already provisioned or pending provisioning. However we
313
+ // currently do not track whether a smart wallet is pending provisioning.
314
+
315
+ // For explicitly provisioning, swingset will take care of charging,
316
+ // so we skip admission fees.
276
317
  return nil
277
318
  }
278
319
 
@@ -163,3 +163,77 @@ func validateQueueMax(i interface{}) error {
163
163
  }
164
164
  return nil
165
165
  }
166
+
167
+ // UpdateParams appends any missing params, configuring them to their defaults,
168
+ // then returning the updated params or an error. Existing params are not
169
+ // modified, regardless of their value, and they are not removed if they no
170
+ // longer appear in the defaults.
171
+ func UpdateParams(params Params) (Params, error) {
172
+ newBpu, err := appendMissingDefaultBeansPerUnit(params.BeansPerUnit, DefaultBeansPerUnit())
173
+ if err != nil {
174
+ return params, err
175
+ }
176
+ newPff, err := appendMissingDefaultPowerFlagFees(params.PowerFlagFees, DefaultPowerFlagFees)
177
+ if err != nil {
178
+ return params, err
179
+ }
180
+ newQm, err := appendMissingDefaultQueueSize(params.QueueMax, DefaultQueueMax)
181
+ if err != nil {
182
+ return params, err
183
+ }
184
+
185
+ params.BeansPerUnit = newBpu
186
+ params.PowerFlagFees = newPff
187
+ params.QueueMax = newQm
188
+ return params, nil
189
+ }
190
+
191
+ // appendMissingDefaultBeansPerUnit appends the default beans per unit entries
192
+ // not in the list of bean costs already, returning the possibly-updated list,
193
+ // or an error.
194
+ func appendMissingDefaultBeansPerUnit(bpu []StringBeans, defaultBpu []StringBeans) ([]StringBeans, error) {
195
+ existingBpu := make(map[string]struct{}, len(bpu))
196
+ for _, ob := range bpu {
197
+ existingBpu[ob.Key] = struct{}{}
198
+ }
199
+
200
+ for _, b := range defaultBpu {
201
+ if _, exists := existingBpu[b.Key]; !exists {
202
+ bpu = append(bpu, b)
203
+ }
204
+ }
205
+ return bpu, nil
206
+ }
207
+
208
+ // appendMissingDefaultPowerFlagFees appends the default power flag fee entries
209
+ // not in the list of power flags already, returning the possibly-updated list,
210
+ // or an error.
211
+ func appendMissingDefaultPowerFlagFees(pff []PowerFlagFee, defaultPff []PowerFlagFee) ([]PowerFlagFee, error) {
212
+ existingPff := make(map[string]struct{}, len(pff))
213
+ for _, of := range pff {
214
+ existingPff[of.PowerFlag] = struct{}{}
215
+ }
216
+
217
+ for _, f := range defaultPff {
218
+ if _, exists := existingPff[f.PowerFlag]; !exists {
219
+ pff = append(pff, f)
220
+ }
221
+ }
222
+ return pff, nil
223
+ }
224
+
225
+ // appendMissingDefaultQueueSize appends the default queue size entries not in
226
+ // the list of sizes already, returning the possibly-updated list, or an error.
227
+ func appendMissingDefaultQueueSize(qs []QueueSize, defaultQs []QueueSize) ([]QueueSize, error) {
228
+ existingQs := make(map[string]struct{}, len(qs))
229
+ for _, os := range qs {
230
+ existingQs[os.Key] = struct{}{}
231
+ }
232
+
233
+ for _, s := range defaultQs {
234
+ if _, exists := existingQs[s.Key]; !exists {
235
+ qs = append(qs, s)
236
+ }
237
+ }
238
+ return qs, nil
239
+ }
@@ -0,0 +1,116 @@
1
+ package types
2
+
3
+ import (
4
+ "reflect"
5
+ "testing"
6
+
7
+ sdk "github.com/cosmos/cosmos-sdk/types"
8
+ )
9
+
10
+ type beans = StringBeans
11
+
12
+ func TestAddStorageBeanCost(t *testing.T) {
13
+ var defaultStorageCost beans
14
+ for _, b := range DefaultParams().BeansPerUnit {
15
+ if b.Key == BeansPerStorageByte {
16
+ defaultStorageCost = b
17
+ }
18
+ }
19
+ if defaultStorageCost.Key == "" {
20
+ t.Fatalf("no beans per storage byte in default params")
21
+ }
22
+
23
+ for _, tt := range []struct {
24
+ name string
25
+ in []beans
26
+ want []beans
27
+ }{
28
+ {
29
+ name: "empty",
30
+ in: []beans{},
31
+ want: []beans{defaultStorageCost},
32
+ },
33
+ {
34
+ name: "already_only_same",
35
+ in: []beans{defaultStorageCost},
36
+ want: []beans{defaultStorageCost},
37
+ },
38
+ {
39
+ name: "already_only_different",
40
+ in: []beans{NewStringBeans(BeansPerStorageByte, sdk.NewUint(123))},
41
+ want: []beans{NewStringBeans(BeansPerStorageByte, sdk.NewUint(123))},
42
+ },
43
+ {
44
+ name: "already_same",
45
+ in: []beans{
46
+ NewStringBeans("foo", sdk.NewUint(123)),
47
+ defaultStorageCost,
48
+ NewStringBeans("bar", sdk.NewUint(456)),
49
+ },
50
+ want: []beans{
51
+ NewStringBeans("foo", sdk.NewUint(123)),
52
+ defaultStorageCost,
53
+ NewStringBeans("bar", sdk.NewUint(456)),
54
+ },
55
+ },
56
+ {
57
+ name: "already_different",
58
+ in: []beans{
59
+ NewStringBeans("foo", sdk.NewUint(123)),
60
+ NewStringBeans(BeansPerStorageByte, sdk.NewUint(789)),
61
+ NewStringBeans("bar", sdk.NewUint(456)),
62
+ },
63
+ want: []beans{
64
+ NewStringBeans("foo", sdk.NewUint(123)),
65
+ NewStringBeans(BeansPerStorageByte, sdk.NewUint(789)),
66
+ NewStringBeans("bar", sdk.NewUint(456)),
67
+ },
68
+ },
69
+ {
70
+ name: "missing",
71
+ in: []beans{
72
+ NewStringBeans("foo", sdk.NewUint(123)),
73
+ NewStringBeans("bar", sdk.NewUint(456)),
74
+ },
75
+ want: []beans{
76
+ NewStringBeans("foo", sdk.NewUint(123)),
77
+ NewStringBeans("bar", sdk.NewUint(456)),
78
+ defaultStorageCost,
79
+ },
80
+ },
81
+ } {
82
+ t.Run(tt.name, func(t *testing.T) {
83
+ got, err := appendMissingDefaultBeansPerUnit(tt.in, []StringBeans{defaultStorageCost})
84
+ if err != nil {
85
+ t.Errorf("got error %v", err)
86
+ } else if !reflect.DeepEqual(got, tt.want) {
87
+ t.Errorf("want %v, got %v", tt.want, got)
88
+ }
89
+ })
90
+ }
91
+ }
92
+
93
+ func TestUpdateParams(t *testing.T) {
94
+
95
+ in := Params{
96
+ BeansPerUnit: []beans{},
97
+ BootstrapVatConfig: "baz",
98
+ FeeUnitPrice: sdk.NewCoins(sdk.NewInt64Coin("denom", 789)),
99
+ PowerFlagFees: []PowerFlagFee{},
100
+ QueueMax: []QueueSize{},
101
+ }
102
+ want := Params{
103
+ BeansPerUnit: DefaultBeansPerUnit(),
104
+ BootstrapVatConfig: "baz",
105
+ FeeUnitPrice: sdk.NewCoins(sdk.NewInt64Coin("denom", 789)),
106
+ PowerFlagFees: DefaultPowerFlagFees,
107
+ QueueMax: DefaultQueueMax,
108
+ }
109
+ got, err := UpdateParams(in)
110
+ if err != nil {
111
+ t.Fatalf("UpdateParam error %v", err)
112
+ }
113
+ if !reflect.DeepEqual(got, want) {
114
+ t.Errorf("got %v, want %v", got, want)
115
+ }
116
+ }
package/x/vibc/ibc.go CHANGED
@@ -7,11 +7,11 @@ import (
7
7
  "github.com/Agoric/agoric-sdk/golang/cosmos/vm"
8
8
  sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
9
9
  capability "github.com/cosmos/cosmos-sdk/x/capability/types"
10
- channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types"
11
- porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types"
12
- host "github.com/cosmos/ibc-go/v3/modules/core/24-host"
10
+ channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types"
11
+ porttypes "github.com/cosmos/ibc-go/v4/modules/core/05-port/types"
12
+ host "github.com/cosmos/ibc-go/v4/modules/core/24-host"
13
13
 
14
- "github.com/cosmos/ibc-go/v3/modules/core/exported"
14
+ "github.com/cosmos/ibc-go/v4/modules/core/exported"
15
15
 
16
16
  sdk "github.com/cosmos/cosmos-sdk/types"
17
17
  )
@@ -167,8 +167,8 @@ func (im IBCModule) OnChanOpenInit(
167
167
  channelCap *capability.Capability,
168
168
  counterparty channeltypes.Counterparty,
169
169
  version string,
170
- ) error {
171
- return sdkerrors.Wrap(
170
+ ) (string, error) {
171
+ return "", sdkerrors.Wrap(
172
172
  channeltypes.ErrChannelNotFound,
173
173
  fmt.Sprintf("vibc does not allow synthetic channelOpenInit for port %s", portID),
174
174
  )
@@ -224,15 +224,15 @@ func (im IBCModule) OnChanOpenTry(
224
224
  }
225
225
 
226
226
  type channelOpenAckEvent struct {
227
- Type string `json:"type"` // IBC
228
- Event string `json:"event"` // channelOpenAck
229
- PortID string `json:"portID"`
230
- ChannelID string `json:"channelID"`
231
- CounterpartyVersion string `json:"counterpartyVersion"`
232
- Counterparty channeltypes.Counterparty `json:"counterparty"`
233
- ConnectionHops []string `json:"connectionHops"`
234
- BlockHeight int64 `json:"blockHeight"`
235
- BlockTime int64 `json:"blockTime"`
227
+ Type string `json:"type"` // IBC
228
+ Event string `json:"event"` // channelOpenAck
229
+ PortID string `json:"portID"`
230
+ ChannelID string `json:"channelID"`
231
+ CounterpartyVersion string `json:"counterpartyVersion"`
232
+ Counterparty channeltypes.Counterparty `json:"counterparty"`
233
+ ConnectionHops []string `json:"connectionHops"`
234
+ BlockHeight int64 `json:"blockHeight"`
235
+ BlockTime int64 `json:"blockTime"`
236
236
  }
237
237
 
238
238
  func (im IBCModule) OnChanOpenAck(
@@ -248,15 +248,15 @@ func (im IBCModule) OnChanOpenAck(
248
248
 
249
249
  channel.Counterparty.ChannelId = counterpartyChannelID
250
250
  event := channelOpenAckEvent{
251
- Type: "IBC_EVENT",
252
- Event: "channelOpenAck",
253
- PortID: portID,
254
- ChannelID: channelID,
255
- CounterpartyVersion: counterpartyVersion,
256
- Counterparty: channel.Counterparty,
257
- ConnectionHops: channel.ConnectionHops,
258
- BlockHeight: ctx.BlockHeight(),
259
- BlockTime: ctx.BlockTime().Unix(),
251
+ Type: "IBC_EVENT",
252
+ Event: "channelOpenAck",
253
+ PortID: portID,
254
+ ChannelID: channelID,
255
+ CounterpartyVersion: counterpartyVersion,
256
+ Counterparty: channel.Counterparty,
257
+ ConnectionHops: channel.ConnectionHops,
258
+ BlockHeight: ctx.BlockHeight(),
259
+ BlockTime: ctx.BlockTime().Unix(),
260
260
  }
261
261
 
262
262
  return im.PushAction(ctx, event)
@@ -373,7 +373,7 @@ func (im IBCModule) OnRecvPacket(
373
373
 
374
374
  err := im.PushAction(ctx, event)
375
375
  if err != nil {
376
- return channeltypes.NewErrorAcknowledgement(err.Error())
376
+ return channeltypes.NewErrorAcknowledgement(err)
377
377
  }
378
378
 
379
379
  return nil