@agoric/cosmos 0.35.0-u11wf.0 → 0.35.0-u13.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/CHANGELOG.md +44 -0
- package/Makefile +1 -1
- package/ante/ante.go +2 -2
- package/ante/inbound_test.go +8 -0
- package/app/app.go +46 -131
- package/app/export.go +0 -3
- package/app/sim_test.go +4 -4
- package/daemon/cmd/root.go +0 -2
- package/git-revision.txt +1 -1
- package/go.mod +56 -46
- package/go.sum +453 -154
- package/package.json +2 -2
- package/x/lien/keeper/account.go +13 -8
- package/x/swingset/keeper/keeper.go +39 -0
- package/x/swingset/keeper/migrations.go +7 -2
- package/x/swingset/keeper/msg_server.go +52 -5
- package/x/swingset/types/default-params.go +22 -16
- package/x/swingset/types/expected_keepers.go +11 -0
- package/x/swingset/types/msgs.go +43 -2
- package/x/swingset/types/params.go +74 -0
- package/x/swingset/types/params_test.go +116 -0
- package/x/vibc/ibc.go +26 -27
- package/x/vibc/keeper/keeper.go +5 -19
- package/x/vibc/types/expected_keepers.go +5 -4
- package/x/vibc/types/msgs.go +1 -1
- package/x/vibc/types/msgs.pb.go +1 -1
- package/x/vstorage/keeper/querier.go +31 -11
- package/x/vstorage/keeper/querier_test.go +112 -0
- package/x/vstorage/types/path_keys.go +22 -10
- package/x/vstorage/types/path_keys_test.go +84 -18
- package/app/const.go +0 -6
- package/x/swingset/legacy/v32/params.go +0 -37
- package/x/swingset/legacy/v32/params_test.go +0 -133
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/cosmos",
|
|
3
|
-
"version": "0.35.0-
|
|
3
|
+
"version": "0.35.0-u13.0",
|
|
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": "
|
|
38
|
+
"gitHead": "5a6cdeb0c18ae9700d706445acf402f8d1e873c3"
|
|
39
39
|
}
|
package/x/lien/keeper/account.go
CHANGED
|
@@ -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
|
-
//
|
|
20
|
-
//
|
|
19
|
+
// - non-module accounts are expected to obey the GenesisAccount interface,
|
|
20
|
+
// i.e. to have a Validate() method;
|
|
21
21
|
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
22
|
+
// - UnpackInterfacesMessage is needed for unpacking accounts embedded
|
|
23
|
+
// in an Any message;
|
|
24
24
|
//
|
|
25
|
-
//
|
|
25
|
+
// - MarshalYAML() is used for String rendering;
|
|
26
26
|
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
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
|
-
|
|
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 :=
|
|
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
|
|
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
|
|
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
|
|
129
|
-
BlockHeight
|
|
130
|
-
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
|
|
15
|
-
BeansPerInboundTx
|
|
16
|
-
BeansPerBlockComputeLimit
|
|
17
|
-
BeansPerMessage
|
|
18
|
-
BeansPerMessageByte
|
|
19
|
-
BeansPerMinFeeDebit
|
|
20
|
-
BeansPerStorageByte
|
|
21
|
-
BeansPerVatCreation
|
|
22
|
-
BeansPerXsnapComputron
|
|
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
|
|
47
|
-
DefaultBeansPerInboundTx
|
|
48
|
-
DefaultBeansPerMessage
|
|
49
|
-
DefaultBeansPerMessageByte
|
|
50
|
-
DefaultBeansPerMinFeeDebit
|
|
51
|
-
DefaultBeansPerStorageByte
|
|
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(
|
|
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
|
}
|
package/x/swingset/types/msgs.go
CHANGED
|
@@ -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
|
-
//
|
|
275
|
-
//
|
|
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
|
+
}
|