Skip to content

Commit

Permalink
add wasm extra proposal (#3091)
Browse files Browse the repository at this point in the history
* add wasm extra proposal

* update

* fix compile error

* update gas factor

* fix load gas reg from db

* updategasReg with simulater

* update

* optimized code

* update

* optimized code

* optimized code

---------

Co-authored-by: KamiD <[email protected]>
  • Loading branch information
zjg555543 and KamiD authored Apr 10, 2023
1 parent 3210d53 commit a4c6b66
Show file tree
Hide file tree
Showing 22 changed files with 400 additions and 31 deletions.
3 changes: 3 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ var (
wasmclient.UnpinCodesProposalHandler,
wasmclient.UpdateDeploymentWhitelistProposalHandler,
wasmclient.UpdateWASMContractMethodBlockedListProposalHandler,
wasmclient.GetCmdExtraProposal,
),
params.AppModuleBasic{},
crisis.AppModuleBasic{},
Expand Down Expand Up @@ -775,6 +776,8 @@ func NewOKExChainApp(
if err := app.ParamsKeeper.ApplyEffectiveUpgrade(ctx); err != nil {
tmos.Exit(fmt.Sprintf("failed apply effective upgrade height info: %s", err))
}

app.WasmKeeper.UpdateGasRegister(ctx)
}

app.ScopedIBCKeeper = scopedIBCKeeper
Expand Down
1 change: 1 addition & 0 deletions libs/ibc-go/testing/simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ var (
wasmclient.UnpinCodesProposalHandler,
wasmclient.UpdateDeploymentWhitelistProposalHandler,
wasmclient.UpdateWASMContractMethodBlockedListProposalHandler,
wasmclient.GetCmdExtraProposal,
),
params.AppModuleBasic{},
crisis.AppModuleBasic{},
Expand Down
5 changes: 5 additions & 0 deletions x/gov/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/okex/exchain/x/params"
paramstypes "github.com/okex/exchain/x/params/types"
stakingkeeper "github.com/okex/exchain/x/staking"
wasmtypes "github.com/okex/exchain/x/wasm/types"
)

type AnteDecorator struct {
Expand Down Expand Up @@ -50,6 +51,10 @@ func (ad AnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne
if err := ad.pk.CheckMsgSubmitProposal(ctx, msg); err != nil {
return ctx, err
}
case *wasmtypes.ExtraProposal:
if !ad.sk.IsValidator(ctx, msg.Proposer) {
return ctx, wasmtypes.ErrProposerMustBeValidator
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions x/gov/types/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
const (
MaxDescriptionLength int = 5000
MaxTitleLength int = 140
MaxExtraBodyLength int = 5000
MaxExtraActionLength int = 140
)

// Content defines an interface that a proposal must implement. It contains
Expand Down
57 changes: 57 additions & 0 deletions x/wasm/client/cli/gov_custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import (
"github.com/okex/exchain/libs/cosmos-sdk/codec"
interfacetypes "github.com/okex/exchain/libs/cosmos-sdk/codec/types"
sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
"github.com/okex/exchain/libs/cosmos-sdk/version"
"github.com/okex/exchain/libs/cosmos-sdk/x/auth"
"github.com/okex/exchain/libs/cosmos-sdk/x/auth/client/utils"
"github.com/okex/exchain/x/gov"
govcli "github.com/okex/exchain/x/gov/client/cli"
utils2 "github.com/okex/exchain/x/wasm/client/utils"
"github.com/okex/exchain/x/wasm/types"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand Down Expand Up @@ -124,3 +126,58 @@ func ProposalUpdateWASMContractMethodBlockedListCmd(cdcP *codec.CodecProxy, reg

return cmd
}

// GetCmdExtraProposal implements a command handler for submitting extra proposal transaction
func GetCmdExtraProposal(cdcP *codec.CodecProxy, reg interfacetypes.InterfaceRegistry) *cobra.Command {
return &cobra.Command{
Use: "wasm-extra [proposal-file]",
Args: cobra.ExactArgs(1),
Short: "Submit a proposal for wasm extra.",
Long: strings.TrimSpace(
fmt.Sprintf(`Submit a proposal for wasm extra along with an initial deposit.
The proposal details must be supplied via a JSON file.
Example:
$ %s tx gov submit-proposal wasm-extra <path/to/proposal.json> --from=<key_or_address>
Where proposal.json contains like these:
# modify wasm gas factor
{
"title":"modify wasm gas factor",
"description":"modify wasm gas factor",
"action": "GasFactor",
"extra": "{\"factor\":240000000}",
"deposit":[
{
"denom":"%s",
"amount":"100.000000000000000000"
}
]
}
`, version.ClientName, sdk.DefaultBondDenom,
)),
RunE: func(cmd *cobra.Command, args []string) error {
cdc := cdcP.GetCdc()
inBuf := bufio.NewReader(cmd.InOrStdin())
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
cliCtx := context.NewCLIContext().WithCodec(cdc)

proposalJson, err := utils2.ParseExtraProposalJSON(cdc, args[0])
if err != nil {
return err
}

proposal := types.ExtraProposal{
Title: proposalJson.Title,
Description: proposalJson.Description,
Action: proposalJson.Action,
Extra: proposalJson.Extra,
}

if err := proposal.ValidateBasic(); err != nil {
return err
}

msg := gov.NewMsgSubmitProposal(&proposal, proposalJson.Deposit, cliCtx.GetFromAddress())
return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
},
}
}
3 changes: 1 addition & 2 deletions x/wasm/client/cli/gov_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"fmt"
"strconv"

"github.com/spf13/cobra"

clientCtx "github.com/okex/exchain/libs/cosmos-sdk/client/context"
"github.com/okex/exchain/libs/cosmos-sdk/codec"
codectypes "github.com/okex/exchain/libs/cosmos-sdk/codec/types"
Expand All @@ -16,6 +14,7 @@ import (
govcli "github.com/okex/exchain/x/gov/client/cli"
govtypes "github.com/okex/exchain/x/gov/types"
"github.com/okex/exchain/x/wasm/types"
"github.com/spf13/cobra"
)

//func ProposalStoreCodeCmd() *cobra.Command {
Expand Down
3 changes: 3 additions & 0 deletions x/wasm/client/proposal_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ var UpdateDeploymentWhitelistProposalHandler = govclient.NewProposalHandler(cli.

// UpdateWASMContractMethodBlockedListProposalHandler is a custom proposal handler which defines methods blacklist of a contract.
var UpdateWASMContractMethodBlockedListProposalHandler = govclient.NewProposalHandler(cli.ProposalUpdateWASMContractMethodBlockedListCmd, rest.EmptyProposalRestHandler)

// GetCmdExtraProposal is a custom proposal handler which extra proposal.
var GetCmdExtraProposal = govclient.NewProposalHandler(cli.GetCmdExtraProposal, rest.EmptyProposalRestHandler)
26 changes: 26 additions & 0 deletions x/wasm/client/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package utils
import (
"bytes"
"compress/gzip"
"io/ioutil"

"github.com/okex/exchain/libs/cosmos-sdk/codec"
sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
)

var (
Expand Down Expand Up @@ -36,3 +40,25 @@ func GzipIt(input []byte) ([]byte, error) {

return b.Bytes(), nil
}

// ExtraProposalJSON defines a ExtraProposal with a deposit used to parse
// manage treasures proposals from a JSON file.
type ExtraProposalJSON struct {
Title string `json:"title" yaml:"title"`
Description string `json:"description" yaml:"description"`
Deposit sdk.SysCoins `json:"deposit" yaml:"deposit"`
Action string `json:"action" yaml:"action"`
Extra string `json:"extra" yaml:"extra"`
}

// ParseExtraProposalJSON parses json from proposal file to ExtraProposalJSON struct
func ParseExtraProposalJSON(cdc *codec.Codec, proposalFilePath string) (
proposal ExtraProposalJSON, err error) {
contents, err := ioutil.ReadFile(proposalFilePath)
if err != nil {
return
}

cdc.MustUnmarshalJSON(contents, &proposal)
return
}
6 changes: 6 additions & 0 deletions x/wasm/keeper/contract_keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type decoratedKeeper interface {
updateContractMethodBlockedList(ctx sdk.Context, blockedMethods *types.ContractMethods, isDelete bool) error

GetParams(ctx sdk.Context) types.Params

InvokeExtraProposal(ctx sdk.Context, action string, extra string) error
}

type PermissionedKeeper struct {
Expand Down Expand Up @@ -99,3 +101,7 @@ func (p PermissionedKeeper) UpdateContractMethodBlockedList(ctx sdk.Context, blo
func (p PermissionedKeeper) GetParams(ctx sdk.Context) types.Params {
return p.nested.GetParams(ctx)
}

func (p PermissionedKeeper) InvokeExtraProposal(ctx sdk.Context, action string, extra string) error {
return p.nested.InvokeExtraProposal(ctx, action, extra)
}
26 changes: 22 additions & 4 deletions x/wasm/keeper/gas_register.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
// Please note that all gas prices returned to wasmvm should have this multiplied.
// Benchmarks and numbers were discussed in: https://github.com/okex/exchain/pull/634#issuecomment-938055852
DefaultGasMultiplier uint64 = 38_000_000
BaseGasMultiplier uint64 = 1_000_000
// DefaultInstanceCost is how much SDK gas we charge each time we load a WASM instance.
// Creating a new instance is costly, and this helps put a recursion limit to contracts calling contracts.
// Benchmarks and numbers were discussed in: https://github.com/okex/exchain/pull/634#issuecomment-938056803
Expand Down Expand Up @@ -70,6 +71,12 @@ type GasRegister interface {
ToWasmVMGas(source sdk.Gas) uint64
// FromWasmVMGas converts from wasmvm gas to sdk gas
FromWasmVMGas(source uint64) sdk.Gas

// GetGasMultiplier
GetGasMultiplier() uint64

// UpdateGasMultiplier
UpdateGasMultiplier(gasMultiplier uint64) bool
}

// WasmGasRegisterConfig config type
Expand Down Expand Up @@ -116,16 +123,16 @@ type WasmGasRegister struct {
}

// NewDefaultWasmGasRegister creates instance with default values
func NewDefaultWasmGasRegister() WasmGasRegister {
func NewDefaultWasmGasRegister() *WasmGasRegister {
return NewWasmGasRegister(DefaultGasRegisterConfig())
}

// NewWasmGasRegister constructor
func NewWasmGasRegister(c WasmGasRegisterConfig) WasmGasRegister {
func NewWasmGasRegister(c WasmGasRegisterConfig) *WasmGasRegister {
if c.GasMultiplier == 0 {
panic(sdkerrors.Wrap(sdkerrors.ErrLogic, "GasMultiplier can not be 0"))
panic(sdkerrors.Wrap(sdkerrors.ErrLogic, "GasFactor can not be 0"))
}
return WasmGasRegister{
return &WasmGasRegister{
c: c,
}
}
Expand Down Expand Up @@ -225,3 +232,14 @@ func (g WasmGasRegister) ToWasmVMGas(source storetypes.Gas) uint64 {
func (g WasmGasRegister) FromWasmVMGas(source uint64) sdk.Gas {
return source / g.c.GasMultiplier
}

// GetGasMultiplier
func (g WasmGasRegister) GetGasMultiplier() uint64 {
return g.c.GasMultiplier
}

// UpdateGasMultiplier
func (g *WasmGasRegister) UpdateGasMultiplier(gasMultiplier uint64) bool {
g.c.GasMultiplier = gasMultiplier
return true
}
57 changes: 57 additions & 0 deletions x/wasm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,63 @@ func (k Keeper) GetParams(ctx sdk.Context) types.Params {
return params
}

func (k Keeper) InvokeExtraProposal(ctx sdk.Context, action string, extra string) error {
switch action {
case types.ActionModifyGasFactor:
return k.modifyGasFactor(ctx, extra)
}

return nil
}

// UpdateGasRegister warning, only use it in beginblock
func (k *Keeper) UpdateGasRegister(ctx sdk.Context) {
if ctx.IsCheckTx() || ctx.IsTraceTx() {
return
}

gasFactor := k.GetGasFactor(ctx)
if gasFactor != k.gasRegister.GetGasMultiplier() {
k.gasRegister.UpdateGasMultiplier(gasFactor)
}
return
}

func (k *Keeper) modifyGasFactor(ctx sdk.Context, extra string) error {
result, err := types.NewActionModifyGasFactor(extra)
if err != nil {
return err
}

value := result.MulInt64(int64(BaseGasMultiplier)).TruncateInt64()
if value <= 0 {
return types.ErrCodeInvalidGasFactor
}
k.SetGasFactor(ctx, uint64(value))
return nil
}

// get the gas factor
func (k Keeper) GetGasFactor(ctx sdk.Context) uint64 {
store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)

if !store.Has(types.KeyGasFactorPrefix) {
return DefaultGasMultiplier
}

b := store.Get(types.KeyGasFactorPrefix)
if b != nil {
return sdk.BigEndianToUint64(b)
}
return DefaultGasMultiplier
}

// set the gas factor
func (k Keeper) SetGasFactor(ctx sdk.Context, factor uint64) {
store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
store.Set(types.KeyGasFactorPrefix, sdk.Uint64ToBigEndian(factor))
}

func (k Keeper) SetParams(ctx sdk.Context, ps types.Params) {
watcher.SetParams(ps)
k.paramSpace.SetParamSet(ctx, &ps)
Expand Down
6 changes: 6 additions & 0 deletions x/wasm/keeper/proposal_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func NewWasmProposalHandlerX(k types.ContractOpsKeeper, enabledProposalTypes []t
return handleUpdateInstantiateConfigProposal(ctx, k, *c)
case *types.UpdateDeploymentWhitelistProposal:
return handleUpdateDeploymentWhitelistProposal(ctx, k, *c)
case *types.ExtraProposal:
return handleExtraProposal(ctx, k, *c)
case *types.UpdateWASMContractMethodBlockedListProposal:
return handleUpdateWASMContractMethodBlockedListProposal(ctx, k, *c)
default:
Expand Down Expand Up @@ -286,6 +288,10 @@ func handleUpdateDeploymentWhitelistProposal(ctx sdk.Context, k types.ContractOp
return nil
}

func handleExtraProposal(ctx sdk.Context, k types.ContractOpsKeeper, p types.ExtraProposal) (err error) {
return k.InvokeExtraProposal(ctx, p.Action, p.Extra)
}

func handleUpdateWASMContractMethodBlockedListProposal(ctx sdk.Context, k types.ContractOpsKeeper, p types.UpdateWASMContractMethodBlockedListProposal) error {
if err := p.ValidateBasic(); err != nil {
return err
Expand Down
8 changes: 8 additions & 0 deletions x/wasm/keeper/wasmtesting/gas_register.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,11 @@ func (m MockGasRegister) FromWasmVMGas(source uint64) sdk.Gas {
}
return m.FromWasmVMGasFn(source)
}

func (m MockGasRegister) GetGasMultiplier() uint64 {
return 0
}

func (m *MockGasRegister) UpdateGasMultiplier(gasMultiplier uint64) bool {
return true
}
3 changes: 2 additions & 1 deletion x/wasm/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,13 @@ func (AppModule) QuerierRoute() string {
//}

// BeginBlock returns the begin blocker for the wasm module.
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
watcher.NewHeight()
if tmtypes.DownloadDelta {
keeper.GetWasmParamsCache().SetNeedParamsUpdate()
keeper.GetWasmParamsCache().SetNeedBlockedUpdate()
}
am.keeper.UpdateGasRegister(ctx)
}

// EndBlock returns the end blocker for the wasm module. It returns no validator
Expand Down
7 changes: 7 additions & 0 deletions x/wasm/proto/proposal_custom.proto
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@ message Method {
string name = 1;
string extra = 2;
}

message ExtraProposal {
string title = 1;
string description = 2;
string action = 3;
string extra = 4;
}
2 changes: 2 additions & 0 deletions x/wasm/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func RegisterLegacyAminoCodec(cdc *codec.Codec) { //nolint:staticcheck
cdc.RegisterConcrete(&UpdateInstantiateConfigProposal{}, "wasm/UpdateInstantiateConfigProposal", nil)
cdc.RegisterConcrete(&UpdateDeploymentWhitelistProposal{}, "wasm/UpdateDeploymentWhitelistProposal", nil)
cdc.RegisterConcrete(&UpdateWASMContractMethodBlockedListProposal{}, "wasm/UpdateWASMContractMethodBlockedListProposal", nil)
cdc.RegisterConcrete(&ExtraProposal{}, "wasm/ExtraProposal", nil)
}

func RegisterInterfaces(registry types.InterfaceRegistry) {
Expand Down Expand Up @@ -69,6 +70,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
&UpdateInstantiateConfigProposal{},
&UpdateDeploymentWhitelistProposal{},
&UpdateWASMContractMethodBlockedListProposal{},
&ExtraProposal{},
)

registry.RegisterInterface("ContractInfoExtension", (*ContractInfoExtension)(nil))
Expand Down
Loading

0 comments on commit a4c6b66

Please sign in to comment.