@agoric/cosmos 0.35.0-u12.0 → 0.35.0-upgrade-14-dev-1eb5b91.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 +24 -0
- package/Makefile +1 -1
- package/ante/ante.go +2 -2
- package/ante/inbound_test.go +8 -0
- package/app/app.go +90 -77
- 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/vm/action.go +130 -0
- package/vm/action_test.go +129 -0
- package/vm/controller.go +0 -6
- package/vm/core_proposals.go +31 -0
- package/x/lien/keeper/account.go +13 -8
- package/x/lien/keeper/keeper_test.go +1 -1
- package/x/swingset/abci.go +25 -33
- package/x/swingset/keeper/keeper.go +61 -4
- package/x/swingset/keeper/migrations.go +7 -2
- package/x/swingset/keeper/msg_server.go +64 -45
- package/x/swingset/keeper/proposal.go +4 -8
- 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/vbank/vbank.go +8 -7
- package/x/vbank/vbank_test.go +10 -10
- package/x/vibc/handler.go +3 -8
- package/x/vibc/ibc.go +56 -104
- package/x/vibc/keeper/keeper.go +4 -4
- package/x/vibc/types/expected_keepers.go +3 -3
- package/x/vibc/types/msgs.go +1 -1
- package/x/vibc/types/msgs.pb.go +1 -1
- package/x/vstorage/keeper/querier_test.go +112 -0
- package/x/swingset/legacy/v32/params.go +0 -37
- package/x/swingset/legacy/v32/params_test.go +0 -133
|
@@ -21,15 +21,13 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer {
|
|
|
21
21
|
var _ types.MsgServer = msgServer{}
|
|
22
22
|
|
|
23
23
|
type deliverInboundAction struct {
|
|
24
|
-
|
|
25
|
-
Peer
|
|
26
|
-
Messages
|
|
27
|
-
Ack
|
|
28
|
-
BlockHeight int64 `json:"blockHeight"`
|
|
29
|
-
BlockTime int64 `json:"blockTime"`
|
|
24
|
+
vm.ActionHeader `actionType:"DELIVER_INBOUND"`
|
|
25
|
+
Peer string `json:"peer"`
|
|
26
|
+
Messages [][]interface{} `json:"messages"`
|
|
27
|
+
Ack uint64 `json:"ack"`
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
func (keeper msgServer) routeAction(ctx sdk.Context, msg vm.ControllerAdmissionMsg, action vm.
|
|
30
|
+
func (keeper msgServer) routeAction(ctx sdk.Context, msg vm.ControllerAdmissionMsg, action vm.Action) error {
|
|
33
31
|
isHighPriority, err := msg.IsHighPriority(ctx, keeper)
|
|
34
32
|
if err != nil {
|
|
35
33
|
return err
|
|
@@ -53,12 +51,9 @@ func (keeper msgServer) DeliverInbound(goCtx context.Context, msg *types.MsgDeli
|
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
action := &deliverInboundAction{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Ack: msg.Ack,
|
|
60
|
-
BlockHeight: ctx.BlockHeight(),
|
|
61
|
-
BlockTime: ctx.BlockTime().Unix(),
|
|
54
|
+
Peer: msg.Submitter.String(),
|
|
55
|
+
Messages: messages,
|
|
56
|
+
Ack: msg.Ack,
|
|
62
57
|
}
|
|
63
58
|
|
|
64
59
|
err := keeper.routeAction(ctx, msg, action)
|
|
@@ -70,26 +65,26 @@ func (keeper msgServer) DeliverInbound(goCtx context.Context, msg *types.MsgDeli
|
|
|
70
65
|
}
|
|
71
66
|
|
|
72
67
|
type walletAction struct {
|
|
73
|
-
|
|
74
|
-
Owner
|
|
75
|
-
Action
|
|
76
|
-
BlockHeight int64 `json:"blockHeight"`
|
|
77
|
-
BlockTime int64 `json:"blockTime"`
|
|
68
|
+
vm.ActionHeader `actionType:"WALLET_ACTION"`
|
|
69
|
+
Owner string `json:"owner"`
|
|
70
|
+
Action string `json:"action"`
|
|
78
71
|
}
|
|
79
72
|
|
|
80
73
|
func (keeper msgServer) WalletAction(goCtx context.Context, msg *types.MsgWalletAction) (*types.MsgWalletActionResponse, error) {
|
|
81
74
|
ctx := sdk.UnwrapSDKContext(goCtx)
|
|
82
75
|
|
|
76
|
+
err := keeper.provisionIfNeeded(ctx, msg.Owner)
|
|
77
|
+
if err != nil {
|
|
78
|
+
return nil, err
|
|
79
|
+
}
|
|
80
|
+
|
|
83
81
|
action := &walletAction{
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
Action: msg.Action,
|
|
87
|
-
BlockHeight: ctx.BlockHeight(),
|
|
88
|
-
BlockTime: ctx.BlockTime().Unix(),
|
|
82
|
+
Owner: msg.Owner.String(),
|
|
83
|
+
Action: msg.Action,
|
|
89
84
|
}
|
|
90
85
|
// fmt.Fprintf(os.Stderr, "Context is %+v\n", ctx)
|
|
91
86
|
|
|
92
|
-
err
|
|
87
|
+
err = keeper.routeAction(ctx, msg, action)
|
|
93
88
|
// fmt.Fprintln(os.Stderr, "Returned from SwingSet", out, err)
|
|
94
89
|
if err != nil {
|
|
95
90
|
return nil, err
|
|
@@ -98,25 +93,25 @@ func (keeper msgServer) WalletAction(goCtx context.Context, msg *types.MsgWallet
|
|
|
98
93
|
}
|
|
99
94
|
|
|
100
95
|
type walletSpendAction struct {
|
|
101
|
-
|
|
102
|
-
Owner
|
|
103
|
-
SpendAction
|
|
104
|
-
BlockHeight int64 `json:"blockHeight"`
|
|
105
|
-
BlockTime int64 `json:"blockTime"`
|
|
96
|
+
vm.ActionHeader `actionType:"WALLET_SPEND_ACTION"`
|
|
97
|
+
Owner string `json:"owner"`
|
|
98
|
+
SpendAction string `json:"spendAction"`
|
|
106
99
|
}
|
|
107
100
|
|
|
108
101
|
func (keeper msgServer) WalletSpendAction(goCtx context.Context, msg *types.MsgWalletSpendAction) (*types.MsgWalletSpendActionResponse, error) {
|
|
109
102
|
ctx := sdk.UnwrapSDKContext(goCtx)
|
|
110
103
|
|
|
104
|
+
err := keeper.provisionIfNeeded(ctx, msg.Owner)
|
|
105
|
+
if err != nil {
|
|
106
|
+
return nil, err
|
|
107
|
+
}
|
|
108
|
+
|
|
111
109
|
action := &walletSpendAction{
|
|
112
|
-
Type: "WALLET_SPEND_ACTION",
|
|
113
110
|
Owner: msg.Owner.String(),
|
|
114
111
|
SpendAction: msg.SpendAction,
|
|
115
|
-
BlockHeight: ctx.BlockHeight(),
|
|
116
|
-
BlockTime: ctx.BlockTime().Unix(),
|
|
117
112
|
}
|
|
118
113
|
// fmt.Fprintf(os.Stderr, "Context is %+v\n", ctx)
|
|
119
|
-
err
|
|
114
|
+
err = keeper.routeAction(ctx, msg, action)
|
|
120
115
|
if err != nil {
|
|
121
116
|
return nil, err
|
|
122
117
|
}
|
|
@@ -124,10 +119,42 @@ func (keeper msgServer) WalletSpendAction(goCtx context.Context, msg *types.MsgW
|
|
|
124
119
|
}
|
|
125
120
|
|
|
126
121
|
type provisionAction struct {
|
|
122
|
+
vm.ActionHeader `actionType:"PLEASE_PROVISION"`
|
|
127
123
|
*types.MsgProvision
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
124
|
+
AutoProvision bool `json:"autoProvision"`
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// provisionIfNeeded generates a provision action if no smart wallet is already
|
|
128
|
+
// provisioned for the account. This assumes that all messages for
|
|
129
|
+
// non-provisioned smart wallets allowed by the admission AnteHandler should
|
|
130
|
+
// auto-provision the smart wallet.
|
|
131
|
+
func (keeper msgServer) provisionIfNeeded(ctx sdk.Context, owner sdk.AccAddress) error {
|
|
132
|
+
// We need to generate a provision action until the smart wallet has
|
|
133
|
+
// been fully provisioned by the controller. This is because a provision is
|
|
134
|
+
// not guaranteed to succeed (e.g. lack of provision pool funds)
|
|
135
|
+
walletState := keeper.GetSmartWalletState(ctx, owner)
|
|
136
|
+
if walletState == types.SmartWalletStateProvisioned {
|
|
137
|
+
return nil
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
msg := &types.MsgProvision{
|
|
141
|
+
Address: owner,
|
|
142
|
+
Submitter: owner,
|
|
143
|
+
PowerFlags: []string{types.PowerFlagSmartWallet},
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
action := &provisionAction{
|
|
147
|
+
MsgProvision: msg,
|
|
148
|
+
AutoProvision: true,
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
err := keeper.routeAction(ctx, msg, action)
|
|
152
|
+
// fmt.Fprintln(os.Stderr, "Returned from SwingSet", out, err)
|
|
153
|
+
if err != nil {
|
|
154
|
+
return err
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return nil
|
|
131
158
|
}
|
|
132
159
|
|
|
133
160
|
func (keeper msgServer) Provision(goCtx context.Context, msg *types.MsgProvision) (*types.MsgProvisionResponse, error) {
|
|
@@ -140,9 +167,6 @@ func (keeper msgServer) Provision(goCtx context.Context, msg *types.MsgProvision
|
|
|
140
167
|
|
|
141
168
|
action := &provisionAction{
|
|
142
169
|
MsgProvision: msg,
|
|
143
|
-
Type: "PLEASE_PROVISION",
|
|
144
|
-
BlockHeight: ctx.BlockHeight(),
|
|
145
|
-
BlockTime: ctx.BlockTime().Unix(),
|
|
146
170
|
}
|
|
147
171
|
|
|
148
172
|
// Create the account, if it doesn't already exist.
|
|
@@ -162,10 +186,8 @@ func (keeper msgServer) Provision(goCtx context.Context, msg *types.MsgProvision
|
|
|
162
186
|
}
|
|
163
187
|
|
|
164
188
|
type installBundleAction struct {
|
|
189
|
+
vm.ActionHeader `actionType:"INSTALL_BUNDLE"`
|
|
165
190
|
*types.MsgInstallBundle
|
|
166
|
-
Type string `json:"type"` // INSTALL_BUNDLE
|
|
167
|
-
BlockHeight int64 `json:"blockHeight"`
|
|
168
|
-
BlockTime int64 `json:"blockTime"`
|
|
169
191
|
}
|
|
170
192
|
|
|
171
193
|
func (keeper msgServer) InstallBundle(goCtx context.Context, msg *types.MsgInstallBundle) (*types.MsgInstallBundleResponse, error) {
|
|
@@ -177,9 +199,6 @@ func (keeper msgServer) InstallBundle(goCtx context.Context, msg *types.MsgInsta
|
|
|
177
199
|
}
|
|
178
200
|
action := &installBundleAction{
|
|
179
201
|
MsgInstallBundle: msg,
|
|
180
|
-
Type: "INSTALL_BUNDLE",
|
|
181
|
-
BlockHeight: ctx.BlockHeight(),
|
|
182
|
-
BlockTime: ctx.BlockTime().Unix(),
|
|
183
202
|
}
|
|
184
203
|
|
|
185
204
|
err = keeper.routeAction(ctx, msg, action)
|
|
@@ -3,23 +3,19 @@ package keeper
|
|
|
3
3
|
import (
|
|
4
4
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
5
5
|
|
|
6
|
+
"github.com/Agoric/agoric-sdk/golang/cosmos/vm"
|
|
6
7
|
"github.com/Agoric/agoric-sdk/golang/cosmos/x/swingset/types"
|
|
7
8
|
)
|
|
8
9
|
|
|
9
10
|
type coreEvalAction struct {
|
|
10
|
-
|
|
11
|
-
Evals
|
|
12
|
-
BlockHeight int64 `json:"blockHeight"`
|
|
13
|
-
BlockTime int64 `json:"blockTime"`
|
|
11
|
+
vm.ActionHeader `actionType:"CORE_EVAL"`
|
|
12
|
+
Evals []types.CoreEval `json:"evals"`
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
// CoreEvalProposal tells SwingSet to evaluate the given JS code.
|
|
17
16
|
func (k Keeper) CoreEvalProposal(ctx sdk.Context, p *types.CoreEvalProposal) error {
|
|
18
17
|
action := &coreEvalAction{
|
|
19
|
-
|
|
20
|
-
Evals: p.Evals,
|
|
21
|
-
BlockHeight: ctx.BlockHeight(),
|
|
22
|
-
BlockTime: ctx.BlockTime().Unix(),
|
|
18
|
+
Evals: p.Evals,
|
|
23
19
|
}
|
|
24
20
|
|
|
25
21
|
return k.PushHighPriorityAction(ctx, action)
|
|
@@ -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
|
+
}
|
package/x/vbank/vbank.go
CHANGED
|
@@ -68,15 +68,15 @@ func (vbu vbankManyBalanceUpdates) Swap(i int, j int) {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
type vbankBalanceUpdate struct {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Updated
|
|
71
|
+
vm.ActionHeader `actionType:"VBANK_BALANCE_UPDATE"`
|
|
72
|
+
Nonce uint64 `json:"nonce"`
|
|
73
|
+
Updated vbankManyBalanceUpdates `json:"updated"`
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
// getBalanceUpdate returns a bridge message containing the current bank balance
|
|
77
77
|
// for the given addresses each for the specified denominations. Coins are used
|
|
78
78
|
// only to track the set of denoms, not for the particular nonzero amounts.
|
|
79
|
-
func getBalanceUpdate(ctx sdk.Context, keeper Keeper, addressToUpdate map[string]sdk.Coins) vm.
|
|
79
|
+
func getBalanceUpdate(ctx sdk.Context, keeper Keeper, addressToUpdate map[string]sdk.Coins) vm.Action {
|
|
80
80
|
nentries := len(addressToUpdate)
|
|
81
81
|
if nentries == 0 {
|
|
82
82
|
return nil
|
|
@@ -84,7 +84,6 @@ func getBalanceUpdate(ctx sdk.Context, keeper Keeper, addressToUpdate map[string
|
|
|
84
84
|
|
|
85
85
|
nonce := keeper.GetNextSequence(ctx)
|
|
86
86
|
event := vbankBalanceUpdate{
|
|
87
|
-
Type: "VBANK_BALANCE_UPDATE",
|
|
88
87
|
Nonce: nonce,
|
|
89
88
|
Updated: make([]vbankSingleBalanceUpdate, 0, nentries),
|
|
90
89
|
}
|
|
@@ -111,7 +110,9 @@ func getBalanceUpdate(ctx sdk.Context, keeper Keeper, addressToUpdate map[string
|
|
|
111
110
|
|
|
112
111
|
// Ensure we have a deterministic order of updates.
|
|
113
112
|
sort.Sort(event.Updated)
|
|
114
|
-
|
|
113
|
+
|
|
114
|
+
// Populate the event default fields (even though event does not embed vm.ActionHeader)
|
|
115
|
+
return vm.PopulateAction(ctx, event)
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
func marshal(event vm.Jsonable) ([]byte, error) {
|
|
@@ -242,7 +243,7 @@ func (ch portHandler) Receive(ctx *vm.ControllerContext, str string) (ret string
|
|
|
242
243
|
return
|
|
243
244
|
}
|
|
244
245
|
|
|
245
|
-
func (am AppModule) PushAction(ctx sdk.Context, action vm.
|
|
246
|
+
func (am AppModule) PushAction(ctx sdk.Context, action vm.Action) error {
|
|
246
247
|
// vbank actions are not triggered by a swingset message in a transaction, so we need to
|
|
247
248
|
// synthesize unique context information.
|
|
248
249
|
// We use a fixed placeholder value for the txHash context, and can simply use `0` for the
|