diff --git a/app/app.go b/app/app.go
index 569522587d..a646d208a5 100644
--- a/app/app.go
+++ b/app/app.go
@@ -506,6 +506,11 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b
// `loadLatest` is set to true.
ctx := app.BaseApp.NewUncachedContext(true, tmproto.Header{})
app.capabilityKeeper.InitializeAndSeal(ctx)
+
+ // Initialize pinned codes in wasmvm as they are not persisted there
+ if err := app.wasmKeeper.InitializePinnedCodes(ctx); err != nil {
+ panic(err)
+ }
}
app.scopedIBCKeeper = scopedIBCKeeper
diff --git a/doc/proto.md b/doc/proto.md
index 262d98b8a1..a1ae498748 100644
--- a/doc/proto.md
+++ b/doc/proto.md
@@ -18,7 +18,9 @@
- [ClearAdminProposal](#cosmwasm.wasm.v1beta1.ClearAdminProposal)
- [InstantiateContractProposal](#cosmwasm.wasm.v1beta1.InstantiateContractProposal)
- [MigrateContractProposal](#cosmwasm.wasm.v1beta1.MigrateContractProposal)
+ - [PinCodesProposal](#cosmwasm.wasm.v1beta1.PinCodesProposal)
- [StoreCodeProposal](#cosmwasm.wasm.v1beta1.StoreCodeProposal)
+ - [UnpinCodesProposal](#cosmwasm.wasm.v1beta1.UnpinCodesProposal)
- [UpdateAdminProposal](#cosmwasm.wasm.v1beta1.UpdateAdminProposal)
- [x/wasm/internal/types/query.proto](#x/wasm/internal/types/query.proto)
@@ -94,6 +96,7 @@ Code struct encompasses CodeInfo and CodeBytes
| code_id | [uint64](#uint64) | | |
| code_info | [CodeInfo](#cosmwasm.wasm.v1beta1.CodeInfo) | | |
| code_bytes | [bytes](#bytes) | | |
+| pinned | [bool](#bool) | | Pinned to wasmvm cache |
@@ -294,6 +297,23 @@ MigrateContractProposal gov proposal content type to migrate a contract.
+
+
+### PinCodesProposal
+PinCodesProposal gov proposal content type to pin a set of code ids in the wasmvm cache.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| title | [string](#string) | | Title is a short summary |
+| description | [string](#string) | | Description is a human readable text |
+| code_ids | [uint64](#uint64) | repeated | CodeIDs references the new WASM codes |
+
+
+
+
+
+
### StoreCodeProposal
@@ -315,6 +335,23 @@ StoreCodeProposal gov proposal content type to submit WASM code to the system
+
+
+### UnpinCodesProposal
+UnpinCodesProposal gov proposal content type to unpin a set of code ids in the wasmvm cache.
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| title | [string](#string) | | Title is a short summary |
+| description | [string](#string) | | Description is a human readable text |
+| code_ids | [uint64](#uint64) | repeated | CodeIDs references the WASM codes |
+
+
+
+
+
+
### UpdateAdminProposal
@@ -943,7 +980,7 @@ CodeInfo is data for the uploaded contract WASM code
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
-| code_hash | [bytes](#bytes) | | CodeHash is the unique CodeID |
+| code_hash | [bytes](#bytes) | | CodeHash is the unique identifier created by wasmvm |
| creator | [string](#string) | | Creator address who initially stored the code |
| source | [string](#string) | | Source is a valid absolute HTTPS URI to the contract's source code, optional |
| builder | [string](#string) | | Builder is a valid docker image name with tag, optional |
diff --git a/go.mod b/go.mod
index 77cdeeb003..ed2b82abed 100644
--- a/go.mod
+++ b/go.mod
@@ -21,6 +21,7 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.7.0
+ github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca
github.com/tendermint/tendermint v0.34.8
github.com/tendermint/tm-db v0.6.4
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 // indirect
diff --git a/go.sum b/go.sum
index 8c3454428d..9d6c3efb41 100644
--- a/go.sum
+++ b/go.sum
@@ -17,10 +17,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4=
-github.com/CosmWasm/wasmvm v0.13.1-0.20210125204657-16df1fdaf712 h1:8gMCeYi0In+3R+ox44SfXoY9a7KXngH8sDwsg+eLwB4=
-github.com/CosmWasm/wasmvm v0.13.1-0.20210125204657-16df1fdaf712/go.mod h1:Id107qllDJyJjVQQsKMOy2YYF98sqPJ2t+jX1QES40A=
-github.com/CosmWasm/wasmvm v0.14.0-alpha1 h1:n6cKrufXvaAzDaUfw1wEr39hNBLv3BY2usUnShmAFwQ=
-github.com/CosmWasm/wasmvm v0.14.0-alpha1/go.mod h1:Id107qllDJyJjVQQsKMOy2YYF98sqPJ2t+jX1QES40A=
github.com/CosmWasm/wasmvm v0.14.0-alpha2 h1:IF+ZNYe6XxKmAZaAzX/Y2dXB1v3l+J0+Vyz69CtojOQ=
github.com/CosmWasm/wasmvm v0.14.0-alpha2/go.mod h1:Id107qllDJyJjVQQsKMOy2YYF98sqPJ2t+jX1QES40A=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
diff --git a/x/wasm/internal/keeper/bench_test.go b/x/wasm/internal/keeper/bench_test.go
new file mode 100644
index 0000000000..42fe9cf6a5
--- /dev/null
+++ b/x/wasm/internal/keeper/bench_test.go
@@ -0,0 +1,55 @@
+package keeper
+
+import (
+ "github.com/CosmWasm/wasmd/x/wasm/internal/types"
+ "github.com/stretchr/testify/require"
+ "github.com/syndtr/goleveldb/leveldb/opt"
+ dbm "github.com/tendermint/tm-db"
+ "testing"
+)
+
+func BenchmarkExecution(b *testing.B) {
+
+ specs := map[string]struct {
+ pinned bool
+ db func() dbm.DB
+ }{
+ "unpinned, memory db": {
+ db: func() dbm.DB { return dbm.NewMemDB() },
+ },
+ "pinned, memory db": {
+ db: func() dbm.DB { return dbm.NewMemDB() },
+ pinned: true,
+ },
+ "unpinned, level db": {
+ db: func() dbm.DB {
+ levelDB, err := dbm.NewGoLevelDBWithOpts("testing", b.TempDir(), &opt.Options{BlockCacher: opt.NoCacher})
+ require.NoError(b, err)
+ return levelDB
+ },
+ },
+ "pinned, level db": {
+ db: func() dbm.DB {
+ levelDB, err := dbm.NewGoLevelDBWithOpts("testing", b.TempDir(), &opt.Options{BlockCacher: opt.NoCacher})
+ require.NoError(b, err)
+ return levelDB
+ },
+ pinned: true,
+ },
+ }
+ for name, spec := range specs {
+ b.Run(name, func(b *testing.B) {
+ wasmConfig := types.WasmConfig{MemoryCacheSize: 0}
+ ctx, keepers := createTestInput(b, false, SupportedFeatures, nil, nil, wasmConfig, spec.db())
+ example := InstantiateHackatomExampleContract(b, ctx, keepers)
+ if spec.pinned {
+ require.NoError(b, keepers.WasmKeeper.PinCode(ctx, example.CodeID))
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := keepers.WasmKeeper.QuerySmart(ctx, example.Contract, []byte(`{"verifier":{}}`))
+ require.NoError(b, err)
+ }
+ })
+ }
+}
diff --git a/x/wasm/internal/keeper/genesis.go b/x/wasm/internal/keeper/genesis.go
index 809f91ed97..391b45f936 100644
--- a/x/wasm/internal/keeper/genesis.go
+++ b/x/wasm/internal/keeper/genesis.go
@@ -27,6 +27,11 @@ func InitGenesis(ctx sdk.Context, keeper *Keeper, data types.GenesisState, staki
if code.CodeID > maxCodeID {
maxCodeID = code.CodeID
}
+ if code.Pinned {
+ if err := keeper.PinCode(ctx, code.CodeID); err != nil {
+ return nil, sdkerrors.Wrapf(err, "contract number %d", i)
+ }
+ }
}
var maxContractID int
@@ -88,6 +93,7 @@ func ExportGenesis(ctx sdk.Context, keeper *Keeper) *types.GenesisState {
CodeID: codeID,
CodeInfo: info,
CodeBytes: bytecode,
+ Pinned: keeper.IsPinnedCode(ctx, codeID),
})
return false
})
@@ -104,7 +110,6 @@ func ExportGenesis(ctx sdk.Context, keeper *Keeper) *types.GenesisState {
}
// redact contract info
contract.Created = nil
-
genState.Contracts = append(genState.Contracts, types.Contract{
ContractAddress: addr.String(),
ContractInfo: contract,
diff --git a/x/wasm/internal/keeper/genesis_test.go b/x/wasm/internal/keeper/genesis_test.go
index f2f389a7ee..c3de008a16 100644
--- a/x/wasm/internal/keeper/genesis_test.go
+++ b/x/wasm/internal/keeper/genesis_test.go
@@ -51,15 +51,21 @@ func TestGenesisExportImport(t *testing.T) {
contract types.ContractInfo
stateModels []types.Model
history []types.ContractCodeHistoryEntry
+ pinned bool
)
f.Fuzz(&codeInfo)
f.Fuzz(&contract)
f.Fuzz(&stateModels)
f.NilChance(0).Fuzz(&history)
+ f.Fuzz(&pinned)
creatorAddr, err := sdk.AccAddressFromBech32(codeInfo.Creator)
require.NoError(t, err)
codeID, err := srcKeeper.Create(srcCtx, creatorAddr, wasmCode, codeInfo.Source, codeInfo.Builder, &codeInfo.InstantiateConfig)
require.NoError(t, err)
+ if pinned {
+ srcKeeper.PinCode(srcCtx, codeID)
+ }
+
contract.CodeID = codeID
contractAddr := srcKeeper.generateContractAddress(srcCtx, codeID)
srcKeeper.storeContractInfo(srcCtx, contractAddr, &contract)
@@ -217,6 +223,24 @@ func TestGenesisInit(t *testing.T) {
},
Params: types.DefaultParams(),
}},
+ "codes with same checksum can be pinned": {
+ src: types.GenesisState{
+ Codes: []types.Code{
+ {
+ CodeID: firstCodeID,
+ CodeInfo: myCodeInfo,
+ CodeBytes: wasmCode,
+ Pinned: true,
+ },
+ {
+ CodeID: 2,
+ CodeInfo: myCodeInfo,
+ CodeBytes: wasmCode,
+ Pinned: true,
+ },
+ },
+ Params: types.DefaultParams(),
+ }},
"happy path: code id in info and contract do match": {
src: types.GenesisState{
Codes: []types.Code{{
@@ -405,6 +429,9 @@ func TestGenesisInit(t *testing.T) {
spec.msgHandlerMock.verifyCalls(t)
spec.stakingMock.verifyCalls(t)
assert.Equal(t, spec.stakingMock.validatorUpdate, gotValidatorSet)
+ for _, c := range spec.src.Codes {
+ assert.Equal(t, c.Pinned, keeper.IsPinnedCode(ctx, c.CodeID))
+ }
})
}
}
diff --git a/x/wasm/internal/keeper/keeper.go b/x/wasm/internal/keeper/keeper.go
index 2721b262a1..c48592320b 100644
--- a/x/wasm/internal/keeper/keeper.go
+++ b/x/wasm/internal/keeper/keeper.go
@@ -100,7 +100,6 @@ func NewKeeper(
if err != nil {
panic(err)
}
-
// set KeyTable if it has not already been set
if !paramSpace.HasKeyTable() {
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
@@ -220,7 +219,9 @@ func (k Keeper) Instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A
}
func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins, authZ AuthorizationPolicy) (sdk.AccAddress, []byte, error) {
- ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: init")
+ if !k.IsPinnedCode(ctx, codeID) {
+ ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: init")
+ }
// create contract address
contractAddress := k.generateContractAddress(ctx, codeID)
@@ -317,13 +318,15 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A
// Execute executes the contract instance
func (k Keeper) Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) (*sdk.Result, error) {
- ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: execute")
-
contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddress)
if err != nil {
return nil, err
}
+ if !k.IsPinnedCode(ctx, contractInfo.CodeID) {
+ ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: execute")
+ }
+
// add more funds
if !coins.IsZero() {
if k.bankKeeper.BlockedAddr(caller) {
@@ -371,7 +374,9 @@ func (k Keeper) Migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller
}
func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newCodeID uint64, msg []byte, authZ AuthorizationPolicy) (*sdk.Result, error) {
- ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: migrate")
+ if !k.IsPinnedCode(ctx, newCodeID) {
+ ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: migrate")
+ }
contractInfo := k.GetContractInfo(ctx, contractAddress)
if contractInfo == nil {
@@ -444,13 +449,15 @@ func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller
// another native Go module directly. Thus, the keeper doesn't place any access controls on it, that is the
// responsibility or the app developer (who passes the wasm.Keeper in app.go)
func (k Keeper) Sudo(ctx sdk.Context, contractAddress sdk.AccAddress, msg []byte) (*sdk.Result, error) {
- ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: sudo")
-
contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddress)
if err != nil {
return nil, err
}
+ if !k.IsPinnedCode(ctx, contractInfo.CodeID) {
+ ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: sudo")
+ }
+
env := types.NewEnv(ctx, contractAddress)
// prepare querier
@@ -536,12 +543,14 @@ func (k Keeper) GetContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress)
// QuerySmart queries the smart contract itself.
func (k Keeper) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) {
- ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: query")
-
- _, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr)
+ contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr)
if err != nil {
return nil, err
}
+ if !k.IsPinnedCode(ctx, contractInfo.CodeID) {
+ ctx.GasMeter().ConsumeGas(InstanceCost, "Loading CosmWasm module: query")
+ }
+
// prepare querier
querier := QueryHandler{
Ctx: ctx,
@@ -577,12 +586,12 @@ func (k Keeper) contractInstance(ctx sdk.Context, contractAddress sdk.AccAddress
var contractInfo types.ContractInfo
k.cdc.MustUnmarshalBinaryBare(contractBz, &contractInfo)
- contractInfoBz := store.Get(types.GetCodeKey(contractInfo.CodeID))
- if contractInfoBz == nil {
- return contractInfo, types.CodeInfo{}, prefix.Store{}, sdkerrors.Wrap(types.ErrNotFound, "contract info")
+ codeInfoBz := store.Get(types.GetCodeKey(contractInfo.CodeID))
+ if codeInfoBz == nil {
+ return contractInfo, types.CodeInfo{}, prefix.Store{}, sdkerrors.Wrap(types.ErrNotFound, "code info")
}
var codeInfo types.CodeInfo
- k.cdc.MustUnmarshalBinaryBare(contractInfoBz, &codeInfo)
+ k.cdc.MustUnmarshalBinaryBare(codeInfoBz, &codeInfo)
prefixStoreKey := types.GetContractStorePrefix(contractAddress)
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), prefixStoreKey)
return contractInfo, codeInfo, prefixStore, nil
@@ -693,6 +702,59 @@ func (k Keeper) dispatchMessages(ctx sdk.Context, contractAddr sdk.AccAddress, i
return nil
}
+// PinCode pins the wasm contract in wasmvm cache
+func (k Keeper) PinCode(ctx sdk.Context, codeID uint64) error {
+ codeInfo := k.GetCodeInfo(ctx, codeID)
+ if codeInfo == nil {
+ return sdkerrors.Wrap(types.ErrNotFound, "code info")
+ }
+
+ if err := k.wasmer.Pin(codeInfo.CodeHash); err != nil {
+ return sdkerrors.Wrap(types.ErrPinContractFailed, err.Error())
+ }
+ store := ctx.KVStore(k.storeKey)
+ // store 1 byte to not run into `nil` debugging issues
+ store.Set(types.GetPinnedCodeIndexPrefix(codeID), []byte{1})
+ return nil
+}
+
+// UnpinCode removes the wasm contract from wasmvm cache
+func (k Keeper) UnpinCode(ctx sdk.Context, codeID uint64) error {
+ codeInfo := k.GetCodeInfo(ctx, codeID)
+ if codeInfo == nil {
+ return sdkerrors.Wrap(types.ErrNotFound, "code info")
+ }
+ if err := k.wasmer.Unpin(codeInfo.CodeHash); err != nil {
+ return sdkerrors.Wrap(types.ErrUnpinContractFailed, err.Error())
+ }
+
+ store := ctx.KVStore(k.storeKey)
+ store.Delete(types.GetPinnedCodeIndexPrefix(codeID))
+ return nil
+}
+
+// IsPinnedCode returns true when codeID is pinned in wasmvm cache
+func (k Keeper) IsPinnedCode(ctx sdk.Context, codeID uint64) bool {
+ store := ctx.KVStore(k.storeKey)
+ return store.Has(types.GetPinnedCodeIndexPrefix(codeID))
+}
+
+// InitializePinnedCodes updates wasmvm to pin to cache all contracts marked as pinned
+func (k Keeper) InitializePinnedCodes(ctx sdk.Context) error {
+ store := prefix.NewStore(ctx.KVStore(k.storeKey), types.PinnedCodeIndexPrefix)
+ iter := store.Iterator(nil, nil)
+ for ; iter.Valid(); iter.Next() {
+ codeInfo := k.GetCodeInfo(ctx, types.ParsePinnedCodeIndex(iter.Value()))
+ if codeInfo == nil {
+ return sdkerrors.Wrap(types.ErrNotFound, "code info")
+ }
+ if err := k.wasmer.Pin(codeInfo.CodeHash); err != nil {
+ return sdkerrors.Wrap(types.ErrPinContractFailed, err.Error())
+ }
+ }
+ return nil
+}
+
func gasForContract(ctx sdk.Context) uint64 {
meter := ctx.GasMeter()
if meter.IsOutOfGas() {
diff --git a/x/wasm/internal/keeper/keeper_test.go b/x/wasm/internal/keeper/keeper_test.go
index 8afa6cd3f9..e938302521 100644
--- a/x/wasm/internal/keeper/keeper_test.go
+++ b/x/wasm/internal/keeper/keeper_test.go
@@ -282,7 +282,7 @@ func TestInstantiate(t *testing.T) {
gasAfter := ctx.GasMeter().GasConsumed()
if types.EnableGasVerification {
- require.Equal(t, uint64(0x118c0), gasAfter-gasBefore)
+ require.Equal(t, uint64(0x11ca8), gasAfter-gasBefore)
}
// ensure it is stored properly
@@ -515,7 +515,7 @@ func TestExecute(t *testing.T) {
// make sure gas is properly deducted from ctx
gasAfter := ctx.GasMeter().GasConsumed()
if types.EnableGasVerification {
- require.Equal(t, uint64(0x11d39), gasAfter-gasBefore)
+ require.Equal(t, uint64(0x12121), gasAfter-gasBefore)
}
// ensure bob now exists and got both payments released
bobAcct = accKeeper.GetAccount(ctx, bob)
diff --git a/x/wasm/internal/keeper/proposal_handler.go b/x/wasm/internal/keeper/proposal_handler.go
index 937996e2e4..878c6a9fc9 100644
--- a/x/wasm/internal/keeper/proposal_handler.go
+++ b/x/wasm/internal/keeper/proposal_handler.go
@@ -2,6 +2,8 @@ package keeper
import (
"fmt"
+ "strconv"
+ "strings"
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -9,8 +11,18 @@ import (
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
)
+// governing contains a subset of the wasm keeper used by gov processes
+type governing interface {
+ create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, source string, builder string, instantiateAccess *types.AccessConfig, authZ AuthorizationPolicy) (codeID uint64, err error)
+ instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins, authZ AuthorizationPolicy) (sdk.AccAddress, []byte, error)
+ migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newCodeID uint64, msg []byte, authZ AuthorizationPolicy) (*sdk.Result, error)
+ setContractAdmin(ctx sdk.Context, contractAddress, caller, newAdmin sdk.AccAddress, authZ AuthorizationPolicy) error
+ PinCode(ctx sdk.Context, codeID uint64) error
+ UnpinCode(ctx sdk.Context, codeID uint64) error
+}
+
// NewWasmProposalHandler creates a new governance Handler for wasm proposals
-func NewWasmProposalHandler(k Keeper, enabledProposalTypes []types.ProposalType) govtypes.Handler {
+func NewWasmProposalHandler(k governing, enabledProposalTypes []types.ProposalType) govtypes.Handler {
enabledTypes := make(map[string]struct{}, len(enabledProposalTypes))
for i := range enabledProposalTypes {
enabledTypes[string(enabledProposalTypes[i])] = struct{}{}
@@ -33,13 +45,17 @@ func NewWasmProposalHandler(k Keeper, enabledProposalTypes []types.ProposalType)
return handleUpdateAdminProposal(ctx, k, *c)
case *types.ClearAdminProposal:
return handleClearAdminProposal(ctx, k, *c)
+ case *types.PinCodesProposal:
+ return handlePinCodesProposal(ctx, k, *c)
+ case *types.UnpinCodesProposal:
+ return handleUnpinCodesProposal(ctx, k, *c)
default:
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized wasm proposal content type: %T", c)
}
}
}
-func handleStoreCodeProposal(ctx sdk.Context, k Keeper, p types.StoreCodeProposal) error {
+func handleStoreCodeProposal(ctx sdk.Context, k governing, p types.StoreCodeProposal) error {
if err := p.ValidateBasic(); err != nil {
return err
}
@@ -62,7 +78,7 @@ func handleStoreCodeProposal(ctx sdk.Context, k Keeper, p types.StoreCodeProposa
return nil
}
-func handleInstantiateProposal(ctx sdk.Context, k Keeper, p types.InstantiateContractProposal) error {
+func handleInstantiateProposal(ctx sdk.Context, k governing, p types.InstantiateContractProposal) error {
if err := p.ValidateBasic(); err != nil {
return err
}
@@ -90,7 +106,7 @@ func handleInstantiateProposal(ctx sdk.Context, k Keeper, p types.InstantiateCon
return nil
}
-func handleMigrateProposal(ctx sdk.Context, k Keeper, p types.MigrateContractProposal) error {
+func handleMigrateProposal(ctx sdk.Context, k governing, p types.MigrateContractProposal) error {
if err := p.ValidateBasic(); err != nil {
return err
}
@@ -125,7 +141,7 @@ func handleMigrateProposal(ctx sdk.Context, k Keeper, p types.MigrateContractPro
return nil
}
-func handleUpdateAdminProposal(ctx sdk.Context, k Keeper, p types.UpdateAdminProposal) error {
+func handleUpdateAdminProposal(ctx sdk.Context, k governing, p types.UpdateAdminProposal) error {
if err := p.ValidateBasic(); err != nil {
return err
}
@@ -151,7 +167,7 @@ func handleUpdateAdminProposal(ctx sdk.Context, k Keeper, p types.UpdateAdminPro
return nil
}
-func handleClearAdminProposal(ctx sdk.Context, k Keeper, p types.ClearAdminProposal) error {
+func handleClearAdminProposal(ctx sdk.Context, k governing, p types.ClearAdminProposal) error {
if err := p.ValidateBasic(); err != nil {
return err
}
@@ -171,3 +187,49 @@ func handleClearAdminProposal(ctx sdk.Context, k Keeper, p types.ClearAdminPropo
ctx.EventManager().EmitEvent(ourEvent)
return nil
}
+
+func handlePinCodesProposal(ctx sdk.Context, k governing, p types.PinCodesProposal) error {
+ if err := p.ValidateBasic(); err != nil {
+ return err
+ }
+ for _, v := range p.CodeIDs {
+ if err := k.PinCode(ctx, v); err != nil {
+ return sdkerrors.Wrapf(err, "code id: %d", v)
+ }
+ }
+ s := make([]string, len(p.CodeIDs))
+ for i, v := range p.CodeIDs {
+ s[i] = strconv.FormatUint(v, 10)
+ }
+ ourEvent := sdk.NewEvent(
+ types.EventTypePinCode,
+ sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
+ sdk.NewAttribute(types.AttributeKeyCodeIDs, strings.Join(s, ",")),
+ )
+ ctx.EventManager().EmitEvent(ourEvent)
+
+ return nil
+}
+
+func handleUnpinCodesProposal(ctx sdk.Context, k governing, p types.UnpinCodesProposal) error {
+ if err := p.ValidateBasic(); err != nil {
+ return err
+ }
+ for _, v := range p.CodeIDs {
+ if err := k.UnpinCode(ctx, v); err != nil {
+ return sdkerrors.Wrapf(err, "code id: %d", v)
+ }
+ }
+ s := make([]string, len(p.CodeIDs))
+ for i, v := range p.CodeIDs {
+ s[i] = strconv.FormatUint(v, 10)
+ }
+ ourEvent := sdk.NewEvent(
+ types.EventTypeUnpinCode,
+ sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
+ sdk.NewAttribute(types.AttributeKeyCodeIDs, strings.Join(s, ",")),
+ )
+ ctx.EventManager().EmitEvent(ourEvent)
+
+ return nil
+}
diff --git a/x/wasm/internal/keeper/proposal_integration_test.go b/x/wasm/internal/keeper/proposal_integration_test.go
index 95f4105198..0807feee41 100644
--- a/x/wasm/internal/keeper/proposal_integration_test.go
+++ b/x/wasm/internal/keeper/proposal_integration_test.go
@@ -4,6 +4,9 @@ import (
"bytes"
"encoding/hex"
"encoding/json"
+ "errors"
+ "github.com/CosmWasm/wasmd/x/wasm/internal/keeper/wasmtesting"
+ wasmvm "github.com/CosmWasm/wasmvm"
"io/ioutil"
"testing"
@@ -346,3 +349,178 @@ func TestUpdateParamsProposal(t *testing.T) {
})
}
}
+
+func TestPinCodesProposal(t *testing.T) {
+ ctx, keepers := CreateTestInput(t, false, "staking", nil, nil)
+ govKeeper, wasmKeeper := keepers.GovKeeper, keepers.WasmKeeper
+
+ mock := wasmtesting.MockWasmer{
+ CreateFn: wasmtesting.NoOpCreateFn,
+ AnalyzeCodeFn: wasmtesting.WithoutIBCAnalyzeFn,
+ }
+ var (
+ hackatom = StoreHackatomExampleContract(t, ctx, keepers)
+ hackatomDuplicate = StoreHackatomExampleContract(t, ctx, keepers)
+ otherContract = StoreRandomContract(t, ctx, keepers, &mock)
+ gotPinnedChecksums []wasmvm.Checksum
+ )
+ checksumCollector := func(checksum wasmvm.Checksum) error {
+ gotPinnedChecksums = append(gotPinnedChecksums, checksum)
+ return nil
+ }
+ specs := map[string]struct {
+ srcCodeIDs []uint64
+ mockFn func(checksum wasmvm.Checksum) error
+ expPinned []wasmvm.Checksum
+ expErr bool
+ }{
+ "pin one": {
+ srcCodeIDs: []uint64{hackatom.CodeID},
+ mockFn: checksumCollector,
+ },
+ "pin multiple": {
+ srcCodeIDs: []uint64{hackatom.CodeID, otherContract.CodeID},
+ mockFn: checksumCollector,
+ },
+ "pin same code id": {
+ srcCodeIDs: []uint64{hackatom.CodeID, hackatomDuplicate.CodeID},
+ mockFn: checksumCollector,
+ },
+ "pin non existing code id": {
+ srcCodeIDs: []uint64{999},
+ mockFn: checksumCollector,
+ expErr: true,
+ },
+ "pin empty code id list": {
+ srcCodeIDs: []uint64{},
+ mockFn: checksumCollector,
+ expErr: true,
+ },
+ "wasmvm failed with error": {
+ srcCodeIDs: []uint64{hackatom.CodeID},
+ mockFn: func(_ wasmvm.Checksum) error {
+ return errors.New("test, ignore")
+ },
+ expErr: true,
+ },
+ }
+ parentCtx := ctx
+ for msg, spec := range specs {
+ t.Run(msg, func(t *testing.T) {
+ gotPinnedChecksums = nil
+ ctx, _ := parentCtx.CacheContext()
+ mock.PinFn = spec.mockFn
+ proposal := types.PinCodesProposal{
+ Title: "Foo",
+ Description: "Bar",
+ CodeIDs: spec.srcCodeIDs,
+ }
+
+ // when stored
+ storedProposal, gotErr := govKeeper.SubmitProposal(ctx, &proposal)
+ if spec.expErr {
+ require.Error(t, gotErr)
+ return
+ }
+ require.NoError(t, gotErr)
+
+ // and proposal execute
+ handler := govKeeper.Router().GetRoute(storedProposal.ProposalRoute())
+ gotErr = handler(ctx, storedProposal.GetContent())
+ require.NoError(t, gotErr)
+
+ // then
+ for i := range spec.srcCodeIDs {
+ c := wasmKeeper.GetCodeInfo(ctx, spec.srcCodeIDs[i])
+ require.Equal(t, wasmvm.Checksum(c.CodeHash), gotPinnedChecksums[i])
+ }
+ })
+ }
+}
+func TestUnpinCodesProposal(t *testing.T) {
+ ctx, keepers := CreateTestInput(t, false, "staking", nil, nil)
+ govKeeper, wasmKeeper := keepers.GovKeeper, keepers.WasmKeeper
+
+ mock := wasmtesting.MockWasmer{
+ CreateFn: wasmtesting.NoOpCreateFn,
+ AnalyzeCodeFn: wasmtesting.WithoutIBCAnalyzeFn,
+ }
+ var (
+ hackatom = StoreHackatomExampleContract(t, ctx, keepers)
+ hackatomDuplicate = StoreHackatomExampleContract(t, ctx, keepers)
+ otherContract = StoreRandomContract(t, ctx, keepers, &mock)
+ gotUnpinnedChecksums []wasmvm.Checksum
+ )
+ checksumCollector := func(checksum wasmvm.Checksum) error {
+ gotUnpinnedChecksums = append(gotUnpinnedChecksums, checksum)
+ return nil
+ }
+ specs := map[string]struct {
+ srcCodeIDs []uint64
+ mockFn func(checksum wasmvm.Checksum) error
+ expUnpinned []wasmvm.Checksum
+ expErr bool
+ }{
+ "unpin one": {
+ srcCodeIDs: []uint64{hackatom.CodeID},
+ mockFn: checksumCollector,
+ },
+ "unpin multiple": {
+ srcCodeIDs: []uint64{hackatom.CodeID, otherContract.CodeID},
+ mockFn: checksumCollector,
+ },
+ "unpin same code id": {
+ srcCodeIDs: []uint64{hackatom.CodeID, hackatomDuplicate.CodeID},
+ mockFn: checksumCollector,
+ },
+ "unpin non existing code id": {
+ srcCodeIDs: []uint64{999},
+ mockFn: checksumCollector,
+ expErr: true,
+ },
+ "unpin empty code id list": {
+ srcCodeIDs: []uint64{},
+ mockFn: checksumCollector,
+ expErr: true,
+ },
+ "wasmvm failed with error": {
+ srcCodeIDs: []uint64{hackatom.CodeID},
+ mockFn: func(_ wasmvm.Checksum) error {
+ return errors.New("test, ignore")
+ },
+ expErr: true,
+ },
+ }
+ parentCtx := ctx
+ for msg, spec := range specs {
+ t.Run(msg, func(t *testing.T) {
+ gotUnpinnedChecksums = nil
+ ctx, _ := parentCtx.CacheContext()
+ mock.UnpinFn = spec.mockFn
+ proposal := types.UnpinCodesProposal{
+ Title: "Foo",
+ Description: "Bar",
+ CodeIDs: spec.srcCodeIDs,
+ }
+
+ // when stored
+ storedProposal, gotErr := govKeeper.SubmitProposal(ctx, &proposal)
+ if spec.expErr {
+ require.Error(t, gotErr)
+ return
+ }
+ require.NoError(t, gotErr)
+
+ // and proposal execute
+ handler := govKeeper.Router().GetRoute(storedProposal.ProposalRoute())
+ gotErr = handler(ctx, storedProposal.GetContent())
+ require.NoError(t, gotErr)
+
+ // then
+ for i := range spec.srcCodeIDs {
+ c := wasmKeeper.GetCodeInfo(ctx, spec.srcCodeIDs[i])
+ require.Equal(t, wasmvm.Checksum(c.CodeHash), gotUnpinnedChecksums[i])
+ }
+ })
+ }
+}
diff --git a/x/wasm/internal/keeper/recurse_test.go b/x/wasm/internal/keeper/recurse_test.go
index 5a45725a06..01fd965568 100644
--- a/x/wasm/internal/keeper/recurse_test.go
+++ b/x/wasm/internal/keeper/recurse_test.go
@@ -57,9 +57,9 @@ func initRecurseContract(t *testing.T) (contract sdk.AccAddress, creator sdk.Acc
func TestGasCostOnQuery(t *testing.T) {
const (
- GasNoWork uint64 = 43_074
+ GasNoWork uint64 = 44_074
// Note: about 100 SDK gas (10k wasmer gas) for each round of sha256
- GasWork50 uint64 = 48_744 // this is a little shy of 50k gas - to keep an eye on the limit
+ GasWork50 uint64 = 49_744 // this is a little shy of 50k gas - to keep an eye on the limit
GasReturnUnhashed uint64 = 287
GasReturnHashed uint64 = 262
@@ -224,7 +224,7 @@ func TestLimitRecursiveQueryGas(t *testing.T) {
const (
// Note: about 100 SDK gas (10k wasmer gas) for each round of sha256
- GasWork2k uint64 = 271_797 // = InstanceCost + x // we have 6x gas used in cpu than in the instance
+ GasWork2k uint64 = 272_797 // = InstanceCost + x // we have 6x gas used in cpu than in the instance
// This is overhead for calling into a sub-contract
GasReturnHashed uint64 = 265
)
diff --git a/x/wasm/internal/keeper/test_common.go b/x/wasm/internal/keeper/test_common.go
index 712e32f532..3f04f7caef 100644
--- a/x/wasm/internal/keeper/test_common.go
+++ b/x/wasm/internal/keeper/test_common.go
@@ -4,11 +4,6 @@ import (
"encoding/binary"
"encoding/json"
"fmt"
- "github.com/tendermint/tendermint/libs/rand"
- "io/ioutil"
- "testing"
- "time"
-
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
@@ -40,7 +35,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
- transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer"
+ "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer"
ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"
ibc "github.com/cosmos/cosmos-sdk/x/ibc/core"
ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host"
@@ -63,10 +58,20 @@ import (
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/libs/log"
+ "github.com/tendermint/tendermint/libs/rand"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
+ "io/ioutil"
+ "time"
)
+type TestingT interface {
+ Errorf(format string, args ...interface{})
+ FailNow()
+ TempDir() string
+ Helper()
+}
+
var ModuleBasics = module.NewBasicManager(
auth.AppModuleBasic{},
bank.AppModuleBasic{},
@@ -86,11 +91,11 @@ var ModuleBasics = module.NewBasicManager(
transfer.AppModuleBasic{},
)
-func MakeTestCodec(t *testing.T) codec.Marshaler {
+func MakeTestCodec(t TestingT) codec.Marshaler {
return MakeEncodingConfig(t).Marshaler
}
-func MakeEncodingConfig(_ *testing.T) params2.EncodingConfig {
+func MakeEncodingConfig(_ TestingT) params2.EncodingConfig {
amino := codec.NewLegacyAmino()
interfaceRegistry := codectypes.NewInterfaceRegistry()
marshaler := codec.NewProtoCodec(interfaceRegistry)
@@ -128,12 +133,28 @@ type TestKeepers struct {
}
// CreateDefaultTestInput common settings for CreateTestInput
-func CreateDefaultTestInput(t *testing.T) (sdk.Context, TestKeepers) {
+func CreateDefaultTestInput(t TestingT) (sdk.Context, TestKeepers) {
return CreateTestInput(t, false, "staking", nil, nil)
}
// encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default)
-func CreateTestInput(t *testing.T, isCheckTx bool, supportedFeatures string, encoders *MessageEncoders, queriers *QueryPlugins) (sdk.Context, TestKeepers) {
+func CreateTestInput(t TestingT, isCheckTx bool, supportedFeatures string, encoders *MessageEncoders, queriers *QueryPlugins) (sdk.Context, TestKeepers) {
+ // Load default wasm config
+ wasmConfig := types.DefaultWasmConfig()
+ db := dbm.NewMemDB()
+ return createTestInput(t, isCheckTx, supportedFeatures, encoders, queriers, wasmConfig, db)
+}
+
+// encoders can be nil to accept the defaults, or set it to override some of the message handlers (like default)
+func createTestInput(
+ t TestingT,
+ isCheckTx bool,
+ supportedFeatures string,
+ encoders *MessageEncoders,
+ queriers *QueryPlugins,
+ wasmConfig types.WasmConfig,
+ db dbm.DB,
+) (sdk.Context, TestKeepers) {
tempDir := t.TempDir()
keyWasm := sdk.NewKVStoreKey(types.StoreKey)
@@ -148,7 +169,6 @@ func CreateTestInput(t *testing.T, isCheckTx bool, supportedFeatures string, enc
keyCapability := sdk.NewKVStoreKey(capabilitytypes.StoreKey)
keyCapabilityTransient := storetypes.NewMemoryStoreKey(capabilitytypes.MemStoreKey)
- db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(keyWasm, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
@@ -260,9 +280,6 @@ func CreateTestInput(t *testing.T, isCheckTx bool, supportedFeatures string, enc
stakingtypes.RegisterQueryServer(querier, stakingkeeper.Querier{Keeper: stakingKeeper})
distributiontypes.RegisterQueryServer(querier, distKeeper)
- // Load default wasm config
- wasmConfig := types.DefaultWasmConfig()
-
keeper := NewKeeper(
appCodec,
keyWasm,
@@ -290,7 +307,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, supportedFeatures string, enc
AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(paramsKeeper)).
AddRoute(distributiontypes.RouterKey, distribution.NewCommunityPoolSpendProposalHandler(distKeeper)).
- AddRoute(types.RouterKey, NewWasmProposalHandler(keeper, types.EnableAllProposals))
+ AddRoute(types.RouterKey, NewWasmProposalHandler(&keeper, types.EnableAllProposals))
govKeeper := govkeeper.NewKeeper(
appCodec, keyGov, paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable()), authKeeper, bankKeeper, stakingKeeper, govRouter,
@@ -388,12 +405,12 @@ func handleExecute(ctx sdk.Context, k *Keeper, msg *types.MsgExecuteContract) (*
return res, nil
}
-func RandomAccountAddress(_ *testing.T) sdk.AccAddress {
+func RandomAccountAddress(_ TestingT) sdk.AccAddress {
_, _, addr := keyPubAddr()
return addr
}
-func RandomBech32AccountAddress(t *testing.T) string {
+func RandomBech32AccountAddress(t TestingT) string {
return RandomAccountAddress(t).String()
}
@@ -404,19 +421,19 @@ type ExampleContract struct {
CodeID uint64
}
-func StoreHackatomExampleContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) ExampleContract {
+func StoreHackatomExampleContract(t TestingT, ctx sdk.Context, keepers TestKeepers) ExampleContract {
return StoreExampleContract(t, ctx, keepers, "./testdata/hackatom.wasm")
}
-func StoreBurnerExampleContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) ExampleContract {
+func StoreBurnerExampleContract(t TestingT, ctx sdk.Context, keepers TestKeepers) ExampleContract {
return StoreExampleContract(t, ctx, keepers, "./testdata/burner.wasm")
}
-func StoreIBCReflectContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) ExampleContract {
+func StoreIBCReflectContract(t TestingT, ctx sdk.Context, keepers TestKeepers) ExampleContract {
return StoreExampleContract(t, ctx, keepers, "./testdata/ibc_reflect.wasm")
}
-func StoreReflectContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) uint64 {
+func StoreReflectContract(t TestingT, ctx sdk.Context, keepers TestKeepers) uint64 {
wasmCode, err := ioutil.ReadFile("./testdata/reflect.wasm")
require.NoError(t, err)
@@ -426,7 +443,7 @@ func StoreReflectContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) ui
return codeID
}
-func StoreExampleContract(t *testing.T, ctx sdk.Context, keepers TestKeepers, wasmFile string) ExampleContract {
+func StoreExampleContract(t TestingT, ctx sdk.Context, keepers TestKeepers, wasmFile string) ExampleContract {
anyAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000))
creator, _, creatorAddr := keyPubAddr()
fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, creatorAddr, anyAmount)
@@ -447,7 +464,7 @@ type ExampleContractInstance struct {
}
// SeedNewContractInstance sets the mock wasmerEngine in keeper and calls store + instantiate to init the contract's metadata
-func SeedNewContractInstance(t *testing.T, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) ExampleContractInstance {
+func SeedNewContractInstance(t TestingT, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) ExampleContractInstance {
t.Helper()
exampleContract := StoreRandomContract(t, ctx, keepers, mock)
contractAddr, _, err := keepers.WasmKeeper.Instantiate(ctx, exampleContract.CodeID, exampleContract.CreatorAddr, exampleContract.CreatorAddr, []byte(`{}`), "", nil)
@@ -459,7 +476,7 @@ func SeedNewContractInstance(t *testing.T, ctx sdk.Context, keepers TestKeepers,
}
// StoreRandomContract sets the mock wasmerEngine in keeper and calls store
-func StoreRandomContract(t *testing.T, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) ExampleContract {
+func StoreRandomContract(t TestingT, ctx sdk.Context, keepers TestKeepers, mock types.WasmerEngine) ExampleContract {
t.Helper()
anyAmount := sdk.NewCoins(sdk.NewInt64Coin("denom", 1000))
creator, _, creatorAddr := keyPubAddr()
@@ -482,7 +499,7 @@ type HackatomExampleInstance struct {
}
// InstantiateHackatomExampleContract load and instantiate the "./testdata/hackatom.wasm" contract
-func InstantiateHackatomExampleContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) HackatomExampleInstance {
+func InstantiateHackatomExampleContract(t TestingT, ctx sdk.Context, keepers TestKeepers) HackatomExampleInstance {
contract := StoreHackatomExampleContract(t, ctx, keepers)
verifier, _, verifierAddr := keyPubAddr()
@@ -513,7 +530,7 @@ type HackatomExampleInitMsg struct {
Beneficiary sdk.AccAddress `json:"beneficiary"`
}
-func (m HackatomExampleInitMsg) GetBytes(t *testing.T) []byte {
+func (m HackatomExampleInitMsg) GetBytes(t TestingT) []byte {
initMsgBz, err := json.Marshal(m)
require.NoError(t, err)
return initMsgBz
@@ -527,7 +544,7 @@ type IBCReflectExampleInstance struct {
}
// InstantiateIBCReflectContract load and instantiate the "./testdata/ibc_reflect.wasm" contract
-func InstantiateIBCReflectContract(t *testing.T, ctx sdk.Context, keepers TestKeepers) IBCReflectExampleInstance {
+func InstantiateIBCReflectContract(t TestingT, ctx sdk.Context, keepers TestKeepers) IBCReflectExampleInstance {
reflectID := StoreReflectContract(t, ctx, keepers)
ibcReflectID := StoreIBCReflectContract(t, ctx, keepers).CodeID
@@ -550,7 +567,7 @@ type IBCReflectInitMsg struct {
ReflectCodeID uint64 `json:"reflect_code_id"`
}
-func (m IBCReflectInitMsg) GetBytes(t *testing.T) []byte {
+func (m IBCReflectInitMsg) GetBytes(t TestingT) []byte {
initMsgBz, err := json.Marshal(m)
require.NoError(t, err)
return initMsgBz
@@ -560,19 +577,19 @@ type BurnerExampleInitMsg struct {
Payout sdk.AccAddress `json:"payout"`
}
-func (m BurnerExampleInitMsg) GetBytes(t *testing.T) []byte {
+func (m BurnerExampleInitMsg) GetBytes(t TestingT) []byte {
initMsgBz, err := json.Marshal(m)
require.NoError(t, err)
return initMsgBz
}
-func createFakeFundedAccount(t *testing.T, ctx sdk.Context, am authkeeper.AccountKeeper, bank bankkeeper.Keeper, coins sdk.Coins) sdk.AccAddress {
+func createFakeFundedAccount(t TestingT, ctx sdk.Context, am authkeeper.AccountKeeper, bank bankkeeper.Keeper, coins sdk.Coins) sdk.AccAddress {
_, _, addr := keyPubAddr()
fundAccounts(t, ctx, am, bank, addr, coins)
return addr
}
-func fundAccounts(t *testing.T, ctx sdk.Context, am authkeeper.AccountKeeper, bank bankkeeper.Keeper, addr sdk.AccAddress, coins sdk.Coins) {
+func fundAccounts(t TestingT, ctx sdk.Context, am authkeeper.AccountKeeper, bank bankkeeper.Keeper, addr sdk.AccAddress, coins sdk.Coins) {
acc := am.NewAccountWithAddress(ctx, addr)
am.SetAccount(ctx, acc)
require.NoError(t, bank.SetBalances(ctx, addr, coins))
diff --git a/x/wasm/internal/keeper/wasmtesting/mock_engine.go b/x/wasm/internal/keeper/wasmtesting/mock_engine.go
index 9af8f45794..c2da0fa419 100644
--- a/x/wasm/internal/keeper/wasmtesting/mock_engine.go
+++ b/x/wasm/internal/keeper/wasmtesting/mock_engine.go
@@ -30,6 +30,8 @@ type MockWasmer struct {
IBCPacketReceiveFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCReceiveResponse, uint64, error)
IBCPacketAckFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCAcknowledgement, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error)
IBCPacketTimeoutFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacket, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error)
+ PinFn func(checksum wasmvm.Checksum) error
+ UnpinFn func(checksum wasmvm.Checksum) error
}
func (m *MockWasmer) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannel, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (uint64, error) {
@@ -138,6 +140,20 @@ func (m *MockWasmer) Cleanup() {
m.CleanupFn()
}
+func (m *MockWasmer) Pin(checksum wasmvm.Checksum) error {
+ if m.PinFn == nil {
+ panic("not supposed to be called!")
+ }
+ return m.PinFn(checksum)
+}
+
+func (m *MockWasmer) Unpin(checksum wasmvm.Checksum) error {
+ if m.UnpinFn == nil {
+ panic("not supposed to be called!")
+ }
+ return m.UnpinFn(checksum)
+}
+
var AlwaysPanicMockWasmer = &MockWasmer{}
// selfCallingInstMockWasmer prepares a Wasmer mock that calls itself on instantiation.
diff --git a/x/wasm/internal/types/codec.go b/x/wasm/internal/types/codec.go
index 1ea87a299a..edfe0ab3ab 100644
--- a/x/wasm/internal/types/codec.go
+++ b/x/wasm/internal/types/codec.go
@@ -17,6 +17,8 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&MsgMigrateContract{}, "wasm/MsgMigrateContract", nil)
cdc.RegisterConcrete(&MsgUpdateAdmin{}, "wasm/MsgUpdateAdmin", nil)
cdc.RegisterConcrete(&MsgClearAdmin{}, "wasm/MsgClearAdmin", nil)
+ cdc.RegisterConcrete(&PinCodesProposal{}, "wasm/PinCodesProposal", nil)
+ cdc.RegisterConcrete(&UnpinCodesProposal{}, "wasm/UnpinCodesProposal", nil)
cdc.RegisterConcrete(&StoreCodeProposal{}, "wasm/StoreCodeProposal", nil)
cdc.RegisterConcrete(&InstantiateContractProposal{}, "wasm/InstantiateContractProposal", nil)
@@ -44,6 +46,8 @@ func RegisterInterfaces(registry types.InterfaceRegistry) {
&MigrateContractProposal{},
&UpdateAdminProposal{},
&ClearAdminProposal{},
+ &PinCodesProposal{},
+ &UnpinCodesProposal{},
)
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
diff --git a/x/wasm/internal/types/errors.go b/x/wasm/internal/types/errors.go
index 5de0725ee1..5e8799913f 100644
--- a/x/wasm/internal/types/errors.go
+++ b/x/wasm/internal/types/errors.go
@@ -57,4 +57,10 @@ var (
// ErrUnsupportedForContract error when a feature is used that is not supported for/ by this contract
ErrUnsupportedForContract = sdkErrors.Register(DefaultCodespace, 17, "unsupported for this contract")
+
+ // ErrPinContractFailed error for pinning contract failures
+ ErrPinContractFailed = sdkErrors.Register(DefaultCodespace, 18, "pinning contract failed")
+
+ // ErrUnpinContractFailed error for unpinning contract failures
+ ErrUnpinContractFailed = sdkErrors.Register(DefaultCodespace, 19, "unpinning contract failed")
)
diff --git a/x/wasm/internal/types/events.go b/x/wasm/internal/types/events.go
new file mode 100644
index 0000000000..2f48e5847c
--- /dev/null
+++ b/x/wasm/internal/types/events.go
@@ -0,0 +1,12 @@
+package types
+
+const (
+ EventTypePinCode = "pin_code"
+ EventTypeUnpinCode = "unpin_code"
+)
+const ( // event attributes
+ AttributeKeyContract = "contract_address"
+ AttributeKeyCodeID = "code_id"
+ AttributeKeyCodeIDs = "code_ids"
+ AttributeKeySigner = "signer"
+)
diff --git a/x/wasm/internal/types/genesis.pb.go b/x/wasm/internal/types/genesis.pb.go
index 067c8e5a64..25cd5d06d2 100644
--- a/x/wasm/internal/types/genesis.pb.go
+++ b/x/wasm/internal/types/genesis.pb.go
@@ -207,6 +207,8 @@ type Code struct {
CodeID uint64 `protobuf:"varint,1,opt,name=code_id,json=codeId,proto3" json:"code_id,omitempty"`
CodeInfo CodeInfo `protobuf:"bytes,2,opt,name=code_info,json=codeInfo,proto3" json:"code_info"`
CodeBytes []byte `protobuf:"bytes,3,opt,name=code_bytes,json=codeBytes,proto3" json:"code_bytes,omitempty"`
+ // Pinned to wasmvm cache
+ Pinned bool `protobuf:"varint,4,opt,name=pinned,proto3" json:"pinned,omitempty"`
}
func (m *Code) Reset() { *m = Code{} }
@@ -263,6 +265,13 @@ func (m *Code) GetCodeBytes() []byte {
return nil
}
+func (m *Code) GetPinned() bool {
+ if m != nil {
+ return m.Pinned
+ }
+ return false
+}
+
// Contract struct encompasses ContractAddress, ContractInfo, and ContractState
type Contract struct {
ContractAddress string `protobuf:"bytes,1,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"`
@@ -390,47 +399,48 @@ func init() {
}
var fileDescriptor_52f9f2715025dba8 = []byte{
- // 638 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x94, 0xc1, 0x6e, 0xd3, 0x40,
- 0x10, 0x86, 0xe3, 0x26, 0x4e, 0x93, 0x69, 0xa0, 0xd5, 0xb6, 0x88, 0x28, 0xa5, 0x4e, 0x49, 0x2e,
- 0xad, 0x80, 0x98, 0x96, 0x23, 0x27, 0xdc, 0x22, 0x9a, 0x56, 0x45, 0xc8, 0x95, 0x40, 0xea, 0x25,
- 0x72, 0xec, 0xa9, 0xb1, 0xa8, 0xbd, 0x21, 0xbb, 0x29, 0xf1, 0x4b, 0x20, 0xc4, 0x53, 0xf5, 0xd8,
- 0x23, 0xa7, 0x08, 0xa5, 0x37, 0x9e, 0x02, 0xed, 0x7a, 0xed, 0xba, 0xa2, 0x2e, 0x17, 0x27, 0x33,
- 0xfb, 0xcf, 0xb7, 0x33, 0xb3, 0xb3, 0x0b, 0xdd, 0xa9, 0xf9, 0xcd, 0x61, 0xa1, 0x19, 0x44, 0x1c,
- 0xc7, 0x91, 0x73, 0x6e, 0xf2, 0x78, 0x84, 0xcc, 0xf4, 0x31, 0x42, 0x16, 0xb0, 0xde, 0x68, 0x4c,
- 0x39, 0x25, 0x8f, 0x5c, 0xca, 0x42, 0x21, 0xeb, 0xc9, 0xcf, 0xc5, 0xce, 0x10, 0xb9, 0xb3, 0xd3,
- 0x5a, 0xf3, 0xa9, 0x4f, 0xa5, 0xc2, 0x14, 0xff, 0x12, 0x71, 0xeb, 0xe9, 0xdd, 0x44, 0xf9, 0x55,
- 0x12, 0xa3, 0x40, 0x32, 0x4d, 0xd6, 0x3b, 0x97, 0x3a, 0x34, 0xde, 0x25, 0x19, 0x9c, 0x70, 0x87,
- 0x23, 0x79, 0x0d, 0xd5, 0x91, 0x33, 0x76, 0x42, 0xd6, 0xd4, 0x36, 0xb5, 0xad, 0xa5, 0xdd, 0x8d,
- 0xde, 0x9d, 0x19, 0xf5, 0x3e, 0x48, 0x91, 0x55, 0xb9, 0x9c, 0xb5, 0x4b, 0xb6, 0x0a, 0x21, 0x87,
- 0xa0, 0xbb, 0xd4, 0x43, 0xd6, 0x5c, 0xd8, 0x2c, 0x6f, 0x2d, 0xed, 0xae, 0x17, 0xc4, 0xee, 0x51,
- 0x0f, 0xad, 0xc7, 0x22, 0xf2, 0xcf, 0xac, 0xbd, 0x2c, 0x23, 0x9e, 0xd3, 0x30, 0xe0, 0x18, 0x8e,
- 0x78, 0x6c, 0x27, 0x08, 0x72, 0x0a, 0x75, 0x97, 0x46, 0x7c, 0xec, 0xb8, 0x9c, 0x35, 0xcb, 0x92,
- 0xd7, 0x2e, 0xe4, 0x25, 0x3a, 0x6b, 0x5d, 0x31, 0x57, 0xb3, 0xc8, 0x1c, 0xf7, 0x06, 0x27, 0xd8,
- 0x0c, 0xbf, 0x4e, 0x30, 0x72, 0x91, 0x35, 0x2b, 0xf7, 0xb2, 0x4f, 0x94, 0xee, 0x86, 0x9d, 0x45,
- 0xe6, 0xd9, 0x99, 0x93, 0x0c, 0xa1, 0xe6, 0x63, 0x34, 0x08, 0x99, 0xcf, 0x9a, 0xba, 0x44, 0x3f,
- 0x2b, 0x40, 0xe7, 0xfb, 0x2e, 0x8c, 0x63, 0xe6, 0x33, 0xab, 0xa5, 0xb6, 0x21, 0x29, 0x24, 0xb7,
- 0xcb, 0xa2, 0x9f, 0x88, 0x5a, 0x3f, 0x17, 0x60, 0x51, 0x05, 0x90, 0x7d, 0x00, 0xc6, 0xe9, 0x18,
- 0x07, 0xa2, 0x6d, 0xea, 0xd0, 0xba, 0x05, 0x3b, 0x1e, 0x33, 0xff, 0x44, 0x68, 0xc5, 0x01, 0x1c,
- 0x94, 0xec, 0x3a, 0x4b, 0x0d, 0x32, 0x84, 0xb5, 0x20, 0x62, 0xdc, 0x89, 0x78, 0xe0, 0x70, 0xc1,
- 0x4a, 0x5a, 0xd5, 0x5c, 0x90, 0xbc, 0x17, 0xc5, 0xbc, 0xfe, 0x4d, 0x54, 0x7a, 0x0c, 0x07, 0x25,
- 0x7b, 0x35, 0xf8, 0xd7, 0x4d, 0x3e, 0xc2, 0x0a, 0x4e, 0xd1, 0x9d, 0xe4, 0xf9, 0x65, 0xc9, 0xdf,
- 0x2e, 0xe6, 0xbf, 0x4d, 0x22, 0x72, 0xec, 0x65, 0xbc, 0xed, 0xb2, 0x74, 0x28, 0xb3, 0x49, 0xd8,
- 0xf9, 0xae, 0x41, 0x45, 0xd6, 0xd2, 0x85, 0x45, 0xd1, 0x8b, 0x41, 0xe0, 0xc9, 0x76, 0x54, 0x2c,
- 0x98, 0xcf, 0xda, 0x55, 0xb1, 0xd4, 0xdf, 0xb7, 0xab, 0x62, 0xa9, 0xef, 0x11, 0x4b, 0x8c, 0x97,
- 0x10, 0x45, 0x67, 0x54, 0x55, 0xd9, 0xbe, 0x67, 0x5c, 0xfb, 0xd1, 0x19, 0x55, 0xc3, 0x5e, 0x73,
- 0x95, 0x4d, 0x36, 0x00, 0x24, 0x63, 0x18, 0x73, 0x64, 0xb2, 0x94, 0x86, 0x2d, 0xa9, 0x96, 0x70,
- 0x74, 0xae, 0x34, 0xa8, 0x65, 0xc5, 0x6f, 0xc3, 0x4a, 0x5a, 0xf4, 0xc0, 0xf1, 0xbc, 0x31, 0xb2,
- 0xe4, 0x86, 0xd5, 0xed, 0xe5, 0xd4, 0xff, 0x26, 0x71, 0x93, 0xf7, 0xf0, 0x20, 0x93, 0xe6, 0xd2,
- 0xeb, 0xfe, 0x67, 0xfa, 0x73, 0x29, 0x36, 0xdc, 0x9c, 0x8f, 0xf4, 0xe1, 0x61, 0xc6, 0x63, 0x62,
- 0xd8, 0xd4, 0x75, 0x7a, 0x52, 0xd4, 0x75, 0xea, 0xe1, 0xb9, 0x22, 0x65, 0x99, 0xc8, 0x29, 0xed,
- 0x58, 0x50, 0x4b, 0x2f, 0x04, 0xd9, 0x84, 0x6a, 0xe0, 0x0d, 0xbe, 0x60, 0x2c, 0xeb, 0x68, 0x58,
- 0xf5, 0xf9, 0xac, 0xad, 0xf7, 0xf7, 0x8f, 0x30, 0xb6, 0xf5, 0xc0, 0x3b, 0xc2, 0x98, 0xac, 0x81,
- 0x7e, 0xe1, 0x9c, 0x4f, 0x50, 0x16, 0x50, 0xb1, 0x13, 0xc3, 0x3a, 0xbc, 0x9c, 0x1b, 0xda, 0xd5,
- 0xdc, 0xd0, 0x7e, 0xcf, 0x0d, 0xed, 0xc7, 0xb5, 0x51, 0xba, 0xba, 0x36, 0x4a, 0xbf, 0xae, 0x8d,
- 0xd2, 0xe9, 0x4b, 0x3f, 0xe0, 0x9f, 0x27, 0xc3, 0x9e, 0x4b, 0x43, 0x73, 0x8f, 0xb2, 0xf0, 0x93,
- 0x78, 0xb9, 0x44, 0x6a, 0x9e, 0x39, 0x55, 0xbf, 0xb7, 0xdf, 0xb1, 0x61, 0x55, 0xbe, 0x62, 0xaf,
- 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x65, 0x4f, 0x62, 0x92, 0x5c, 0x05, 0x00, 0x00,
+ // 656 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x94, 0xc1, 0x6e, 0xd3, 0x4c,
+ 0x10, 0xc7, 0xe3, 0x26, 0x4e, 0x93, 0x69, 0xbe, 0xaf, 0xd5, 0xb6, 0x80, 0x95, 0x52, 0x27, 0x24,
+ 0x97, 0x56, 0x40, 0x4c, 0xcb, 0x91, 0x13, 0x6e, 0x11, 0x4d, 0xab, 0x22, 0xe4, 0x4a, 0x20, 0xf5,
+ 0x12, 0x39, 0xf6, 0xd4, 0x58, 0xd4, 0xde, 0x90, 0xdd, 0x94, 0xe4, 0x2d, 0x10, 0x0f, 0xc1, 0xb3,
+ 0xf4, 0xd8, 0x23, 0xa7, 0x08, 0xa5, 0x37, 0x9e, 0x02, 0xed, 0x7a, 0xe3, 0xb8, 0xa2, 0x2e, 0x17,
+ 0x27, 0x33, 0xfb, 0x9f, 0xdf, 0xce, 0xcc, 0xce, 0x2e, 0xb4, 0xc7, 0xd6, 0x57, 0x97, 0x45, 0x56,
+ 0x18, 0x73, 0x1c, 0xc6, 0xee, 0x85, 0xc5, 0x27, 0x03, 0x64, 0x56, 0x80, 0x31, 0xb2, 0x90, 0x75,
+ 0x06, 0x43, 0xca, 0x29, 0x79, 0xe0, 0x51, 0x16, 0x09, 0x59, 0x47, 0x7e, 0x2e, 0x77, 0xfb, 0xc8,
+ 0xdd, 0xdd, 0xfa, 0x46, 0x40, 0x03, 0x2a, 0x15, 0x96, 0xf8, 0x97, 0x88, 0xeb, 0x4f, 0xee, 0x26,
+ 0xca, 0xaf, 0x92, 0x98, 0x39, 0x92, 0x71, 0xb2, 0xde, 0xba, 0xd2, 0xa1, 0xf6, 0x36, 0xc9, 0xe0,
+ 0x94, 0xbb, 0x1c, 0xc9, 0x2b, 0x28, 0x0f, 0xdc, 0xa1, 0x1b, 0x31, 0x43, 0x6b, 0x6a, 0xdb, 0x2b,
+ 0x7b, 0x5b, 0x9d, 0x3b, 0x33, 0xea, 0xbc, 0x97, 0x22, 0xbb, 0x74, 0x35, 0x6d, 0x14, 0x1c, 0x15,
+ 0x42, 0x8e, 0x40, 0xf7, 0xa8, 0x8f, 0xcc, 0x58, 0x6a, 0x16, 0xb7, 0x57, 0xf6, 0x36, 0x73, 0x62,
+ 0xf7, 0xa9, 0x8f, 0xf6, 0x23, 0x11, 0xf9, 0x7b, 0xda, 0x58, 0x95, 0x11, 0xcf, 0x68, 0x14, 0x72,
+ 0x8c, 0x06, 0x7c, 0xe2, 0x24, 0x08, 0x72, 0x06, 0x55, 0x8f, 0xc6, 0x7c, 0xe8, 0x7a, 0x9c, 0x19,
+ 0x45, 0xc9, 0x6b, 0xe4, 0xf2, 0x12, 0x9d, 0xbd, 0xa9, 0x98, 0xeb, 0x69, 0x64, 0x86, 0xbb, 0xc0,
+ 0x09, 0x36, 0xc3, 0x2f, 0x23, 0x8c, 0x3d, 0x64, 0x46, 0xe9, 0x5e, 0xf6, 0xa9, 0xd2, 0x2d, 0xd8,
+ 0x69, 0x64, 0x96, 0x9d, 0x3a, 0x49, 0x1f, 0x2a, 0x01, 0xc6, 0xbd, 0x88, 0x05, 0xcc, 0xd0, 0x25,
+ 0xfa, 0x69, 0x0e, 0x3a, 0xdb, 0x77, 0x61, 0x9c, 0xb0, 0x80, 0xd9, 0x75, 0xb5, 0x0d, 0x99, 0x43,
+ 0x32, 0xbb, 0x2c, 0x07, 0x89, 0xa8, 0xfe, 0x7d, 0x09, 0x96, 0x55, 0x00, 0x39, 0x00, 0x60, 0x9c,
+ 0x0e, 0xb1, 0x27, 0xda, 0xa6, 0x0e, 0xad, 0x9d, 0xb3, 0xe3, 0x09, 0x0b, 0x4e, 0x85, 0x56, 0x1c,
+ 0xc0, 0x61, 0xc1, 0xa9, 0xb2, 0xb9, 0x41, 0xfa, 0xb0, 0x11, 0xc6, 0x8c, 0xbb, 0x31, 0x0f, 0x5d,
+ 0x2e, 0x58, 0x49, 0xab, 0x8c, 0x25, 0xc9, 0x7b, 0x9e, 0xcf, 0xeb, 0x2e, 0xa2, 0xe6, 0xc7, 0x70,
+ 0x58, 0x70, 0xd6, 0xc3, 0xbf, 0xdd, 0xe4, 0x03, 0xac, 0xe1, 0x18, 0xbd, 0x51, 0x96, 0x5f, 0x94,
+ 0xfc, 0x9d, 0x7c, 0xfe, 0x9b, 0x24, 0x22, 0xc3, 0x5e, 0xc5, 0xdb, 0x2e, 0x5b, 0x87, 0x22, 0x1b,
+ 0x45, 0xad, 0x1f, 0x1a, 0x94, 0x64, 0x2d, 0x6d, 0x58, 0x16, 0xbd, 0xe8, 0x85, 0xbe, 0x6c, 0x47,
+ 0xc9, 0x86, 0xd9, 0xb4, 0x51, 0x16, 0x4b, 0xdd, 0x03, 0xa7, 0x2c, 0x96, 0xba, 0x3e, 0xb1, 0xc5,
+ 0x78, 0x09, 0x51, 0x7c, 0x4e, 0x55, 0x95, 0x8d, 0x7b, 0xc6, 0xb5, 0x1b, 0x9f, 0x53, 0x35, 0xec,
+ 0x15, 0x4f, 0xd9, 0x64, 0x0b, 0x40, 0x32, 0xfa, 0x13, 0x8e, 0x4c, 0x96, 0x52, 0x73, 0x24, 0xd5,
+ 0x16, 0x0e, 0xf2, 0x10, 0xca, 0x83, 0x30, 0x8e, 0xd1, 0x37, 0x4a, 0x4d, 0x6d, 0xbb, 0xe2, 0x28,
+ 0xab, 0x75, 0xad, 0x41, 0x25, 0x6d, 0xca, 0x0e, 0xac, 0xcd, 0x9b, 0xd1, 0x73, 0x7d, 0x7f, 0x88,
+ 0x2c, 0xb9, 0x79, 0x55, 0x67, 0x75, 0xee, 0x7f, 0x9d, 0xb8, 0xc9, 0x3b, 0xf8, 0x2f, 0x95, 0x66,
+ 0xd2, 0x6e, 0xff, 0xe3, 0x56, 0x64, 0x52, 0xaf, 0x79, 0x19, 0x1f, 0xe9, 0xc2, 0xff, 0x29, 0x8f,
+ 0x89, 0x21, 0x54, 0xd7, 0xec, 0x71, 0xde, 0x69, 0x50, 0x1f, 0x2f, 0x14, 0x29, 0xcd, 0x44, 0x4e,
+ 0x6f, 0xcb, 0x86, 0xca, 0xfc, 0xa2, 0x90, 0x26, 0x94, 0x43, 0xbf, 0xf7, 0x19, 0x27, 0xb2, 0x8e,
+ 0x9a, 0x5d, 0x9d, 0x4d, 0x1b, 0x7a, 0xf7, 0xe0, 0x18, 0x27, 0x8e, 0x1e, 0xfa, 0xc7, 0x38, 0x21,
+ 0x1b, 0xa0, 0x5f, 0xba, 0x17, 0x23, 0x94, 0x05, 0x94, 0x9c, 0xc4, 0xb0, 0x8f, 0xae, 0x66, 0xa6,
+ 0x76, 0x3d, 0x33, 0xb5, 0x5f, 0x33, 0x53, 0xfb, 0x76, 0x63, 0x16, 0xae, 0x6f, 0xcc, 0xc2, 0xcf,
+ 0x1b, 0xb3, 0x70, 0xf6, 0x22, 0x08, 0xf9, 0xa7, 0x51, 0xbf, 0xe3, 0xd1, 0xc8, 0xda, 0xa7, 0x2c,
+ 0xfa, 0x28, 0x5e, 0x34, 0x91, 0x9a, 0x6f, 0x8d, 0xd5, 0xef, 0xed, 0xf7, 0xad, 0x5f, 0x96, 0xaf,
+ 0xdb, 0xcb, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa3, 0xad, 0xe9, 0xdd, 0x74, 0x05, 0x00, 0x00,
}
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
@@ -637,6 +647,16 @@ func (m *Code) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
+ if m.Pinned {
+ i--
+ if m.Pinned {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i--
+ dAtA[i] = 0x20
+ }
if len(m.CodeBytes) > 0 {
i -= len(m.CodeBytes)
copy(dAtA[i:], m.CodeBytes)
@@ -860,6 +880,9 @@ func (m *Code) Size() (n int) {
if l > 0 {
n += 1 + l + sovGenesis(uint64(l))
}
+ if m.Pinned {
+ n += 2
+ }
return n
}
@@ -1401,6 +1424,26 @@ func (m *Code) Unmarshal(dAtA []byte) error {
m.CodeBytes = []byte{}
}
iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Pinned", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenesis
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Pinned = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipGenesis(dAtA[iNdEx:])
diff --git a/x/wasm/internal/types/genesis.proto b/x/wasm/internal/types/genesis.proto
index 1564306278..b7c2df4b45 100644
--- a/x/wasm/internal/types/genesis.proto
+++ b/x/wasm/internal/types/genesis.proto
@@ -32,6 +32,8 @@ message Code {
uint64 code_id = 1 [(gogoproto.customname) = "CodeID"];
CodeInfo code_info = 2 [(gogoproto.nullable) = false];
bytes code_bytes = 3;
+ // Pinned to wasmvm cache
+ bool pinned = 4;
}
// Contract struct encompasses ContractAddress, ContractInfo, and ContractState
diff --git a/x/wasm/internal/types/keys.go b/x/wasm/internal/types/keys.go
index a92d7465a1..e0415ca0d4 100644
--- a/x/wasm/internal/types/keys.go
+++ b/x/wasm/internal/types/keys.go
@@ -21,12 +21,6 @@ const (
RouterKey = ModuleName
)
-const ( // event attributes
- AttributeKeyContract = "contract_address"
- AttributeKeyCodeID = "code_id"
- AttributeKeySigner = "signer"
-)
-
// nolint
var (
CodeKeyPrefix = []byte{0x01}
@@ -35,6 +29,7 @@ var (
SequenceKeyPrefix = []byte{0x04}
ContractCodeHistoryElementPrefix = []byte{0x05}
ContractByCodeIDAndCreatedSecondaryIndexPrefix = []byte{0x06}
+ PinnedCodeIndexPrefix = []byte{0x07}
KeyLastCodeID = append(SequenceKeyPrefix, []byte("lastCodeId")...)
KeyLastInstanceID = append(SequenceKeyPrefix, []byte("lastContractId")...)
@@ -96,3 +91,17 @@ func GetContractCodeHistoryElementPrefix(contractAddr sdk.AccAddress) []byte {
copy(r[prefixLen:], contractAddr)
return r
}
+
+// GetPinnedCodeIndexPrefix returns the key prefix for a code id pinned into the wasmvm cache
+func GetPinnedCodeIndexPrefix(codeID uint64) []byte {
+ prefixLen := len(PinnedCodeIndexPrefix)
+ r := make([]byte, prefixLen+8)
+ copy(r[0:], PinnedCodeIndexPrefix)
+ copy(r[prefixLen:], sdk.Uint64ToBigEndian(codeID))
+ return r
+}
+
+// ParsePinnedCodeIndex converts the serialized code ID back.
+func ParsePinnedCodeIndex(s []byte) uint64 {
+ return sdk.BigEndianToUint64(s)
+}
diff --git a/x/wasm/internal/types/proposal.go b/x/wasm/internal/types/proposal.go
index 7ab985b630..57d8c36b1e 100644
--- a/x/wasm/internal/types/proposal.go
+++ b/x/wasm/internal/types/proposal.go
@@ -18,6 +18,8 @@ const (
ProposalTypeMigrateContract ProposalType = "MigrateContract"
ProposalTypeUpdateAdmin ProposalType = "UpdateAdmin"
ProposalTypeClearAdmin ProposalType = "ClearAdmin"
+ ProposalTypePinCodes ProposalType = "PinCodes"
+ ProposalTypeUnpinCodes ProposalType = "UnpinCodes"
)
// DisableAllProposals contains no wasm gov types.
@@ -30,6 +32,8 @@ var EnableAllProposals = []ProposalType{
ProposalTypeMigrateContract,
ProposalTypeUpdateAdmin,
ProposalTypeClearAdmin,
+ ProposalTypePinCodes,
+ ProposalTypeUnpinCodes,
}
// ConvertToProposals maps each key to a ProposalType and returns a typed list.
@@ -56,11 +60,15 @@ func init() { // register new content types with the sdk
govtypes.RegisterProposalType(string(ProposalTypeMigrateContract))
govtypes.RegisterProposalType(string(ProposalTypeUpdateAdmin))
govtypes.RegisterProposalType(string(ProposalTypeClearAdmin))
+ govtypes.RegisterProposalType(string(ProposalTypePinCodes))
+ govtypes.RegisterProposalType(string(ProposalTypeUnpinCodes))
govtypes.RegisterProposalTypeCodec(StoreCodeProposal{}, "wasm/StoreCodeProposal")
govtypes.RegisterProposalTypeCodec(InstantiateContractProposal{}, "wasm/InstantiateContractProposal")
govtypes.RegisterProposalTypeCodec(MigrateContractProposal{}, "wasm/MigrateContractProposal")
govtypes.RegisterProposalTypeCodec(UpdateAdminProposal{}, "wasm/UpdateAdminProposal")
govtypes.RegisterProposalTypeCodec(ClearAdminProposal{}, "wasm/ClearAdminProposal")
+ govtypes.RegisterProposalTypeCodec(PinCodesProposal{}, "wasm/PinCodesProposal")
+ govtypes.RegisterProposalTypeCodec(UnpinCodesProposal{}, "wasm/UnpinCodesProposal")
}
// ProposalRoute returns the routing key of a parameter change proposal.
@@ -345,6 +353,70 @@ func (p ClearAdminProposal) String() string {
`, p.Title, p.Description, p.Contract)
}
+// ProposalRoute returns the routing key of a parameter change proposal.
+func (p PinCodesProposal) ProposalRoute() string { return RouterKey }
+
+// GetTitle returns the title of the proposal
+func (p *PinCodesProposal) GetTitle() string { return p.Title }
+
+// GetDescription returns the human readable description of the proposal
+func (p PinCodesProposal) GetDescription() string { return p.Description }
+
+// ProposalType returns the type
+func (p PinCodesProposal) ProposalType() string { return string(ProposalTypePinCodes) }
+
+// ValidateBasic validates the proposal
+func (p PinCodesProposal) ValidateBasic() error {
+ if err := validateProposalCommons(p.Title, p.Description); err != nil {
+ return err
+ }
+ if len(p.CodeIDs) == 0 {
+ return sdkerrors.Wrap(ErrEmpty, "code ids")
+ }
+ return nil
+}
+
+// String implements the Stringer interface.
+func (p PinCodesProposal) String() string {
+ return fmt.Sprintf(`Pin Wasm Codes Proposal:
+ Title: %s
+ Description: %s
+ Codes: %v
+`, p.Title, p.Description, p.CodeIDs)
+}
+
+// ProposalRoute returns the routing key of a parameter change proposal.
+func (p UnpinCodesProposal) ProposalRoute() string { return RouterKey }
+
+// GetTitle returns the title of the proposal
+func (p *UnpinCodesProposal) GetTitle() string { return p.Title }
+
+// GetDescription returns the human readable description of the proposal
+func (p UnpinCodesProposal) GetDescription() string { return p.Description }
+
+// ProposalType returns the type
+func (p UnpinCodesProposal) ProposalType() string { return string(ProposalTypeUnpinCodes) }
+
+// ValidateBasic validates the proposal
+func (p UnpinCodesProposal) ValidateBasic() error {
+ if err := validateProposalCommons(p.Title, p.Description); err != nil {
+ return err
+ }
+ if len(p.CodeIDs) == 0 {
+ return sdkerrors.Wrap(ErrEmpty, "code ids")
+ }
+ return nil
+}
+
+// String implements the Stringer interface.
+func (p UnpinCodesProposal) String() string {
+ return fmt.Sprintf(`Unpin Wasm Codes Proposal:
+ Title: %s
+ Description: %s
+ Codes: %v
+`, p.Title, p.Description, p.CodeIDs)
+}
+
func validateProposalCommons(title, description string) error {
if strings.TrimSpace(title) != title {
return sdkerrors.Wrap(govtypes.ErrInvalidProposalContent, "proposal title must not start/end with white spaces")
diff --git a/x/wasm/internal/types/proposal.pb.go b/x/wasm/internal/types/proposal.pb.go
index 77abf8ef63..825380daf0 100644
--- a/x/wasm/internal/types/proposal.pb.go
+++ b/x/wasm/internal/types/proposal.pb.go
@@ -263,12 +263,98 @@ func (m *ClearAdminProposal) XXX_DiscardUnknown() {
var xxx_messageInfo_ClearAdminProposal proto.InternalMessageInfo
+// PinCodesProposal gov proposal content type to pin a set of code ids in the wasmvm cache.
+type PinCodesProposal struct {
+ // Title is a short summary
+ Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty" yaml:"title"`
+ // Description is a human readable text
+ Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" yaml:"description"`
+ // CodeIDs references the new WASM codes
+ CodeIDs []uint64 `protobuf:"varint,3,rep,packed,name=code_ids,json=codeIds,proto3" json:"code_ids,omitempty" yaml:"code_ids"`
+}
+
+func (m *PinCodesProposal) Reset() { *m = PinCodesProposal{} }
+func (*PinCodesProposal) ProtoMessage() {}
+func (*PinCodesProposal) Descriptor() ([]byte, []int) {
+ return fileDescriptor_00b43267813130fb, []int{5}
+}
+func (m *PinCodesProposal) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *PinCodesProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_PinCodesProposal.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *PinCodesProposal) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_PinCodesProposal.Merge(m, src)
+}
+func (m *PinCodesProposal) XXX_Size() int {
+ return m.Size()
+}
+func (m *PinCodesProposal) XXX_DiscardUnknown() {
+ xxx_messageInfo_PinCodesProposal.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PinCodesProposal proto.InternalMessageInfo
+
+// UnpinCodesProposal gov proposal content type to unpin a set of code ids in the wasmvm cache.
+type UnpinCodesProposal struct {
+ // Title is a short summary
+ Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty" yaml:"title"`
+ // Description is a human readable text
+ Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty" yaml:"description"`
+ // CodeIDs references the WASM codes
+ CodeIDs []uint64 `protobuf:"varint,3,rep,packed,name=code_ids,json=codeIds,proto3" json:"code_ids,omitempty" yaml:"code_ids"`
+}
+
+func (m *UnpinCodesProposal) Reset() { *m = UnpinCodesProposal{} }
+func (*UnpinCodesProposal) ProtoMessage() {}
+func (*UnpinCodesProposal) Descriptor() ([]byte, []int) {
+ return fileDescriptor_00b43267813130fb, []int{6}
+}
+func (m *UnpinCodesProposal) XXX_Unmarshal(b []byte) error {
+ return m.Unmarshal(b)
+}
+func (m *UnpinCodesProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ if deterministic {
+ return xxx_messageInfo_UnpinCodesProposal.Marshal(b, m, deterministic)
+ } else {
+ b = b[:cap(b)]
+ n, err := m.MarshalToSizedBuffer(b)
+ if err != nil {
+ return nil, err
+ }
+ return b[:n], nil
+ }
+}
+func (m *UnpinCodesProposal) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_UnpinCodesProposal.Merge(m, src)
+}
+func (m *UnpinCodesProposal) XXX_Size() int {
+ return m.Size()
+}
+func (m *UnpinCodesProposal) XXX_DiscardUnknown() {
+ xxx_messageInfo_UnpinCodesProposal.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_UnpinCodesProposal proto.InternalMessageInfo
+
func init() {
proto.RegisterType((*StoreCodeProposal)(nil), "cosmwasm.wasm.v1beta1.StoreCodeProposal")
proto.RegisterType((*InstantiateContractProposal)(nil), "cosmwasm.wasm.v1beta1.InstantiateContractProposal")
proto.RegisterType((*MigrateContractProposal)(nil), "cosmwasm.wasm.v1beta1.MigrateContractProposal")
proto.RegisterType((*UpdateAdminProposal)(nil), "cosmwasm.wasm.v1beta1.UpdateAdminProposal")
proto.RegisterType((*ClearAdminProposal)(nil), "cosmwasm.wasm.v1beta1.ClearAdminProposal")
+ proto.RegisterType((*PinCodesProposal)(nil), "cosmwasm.wasm.v1beta1.PinCodesProposal")
+ proto.RegisterType((*UnpinCodesProposal)(nil), "cosmwasm.wasm.v1beta1.UnpinCodesProposal")
}
func init() {
@@ -276,48 +362,54 @@ func init() {
}
var fileDescriptor_00b43267813130fb = []byte{
- // 654 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0x4f, 0x6f, 0xd3, 0x3e,
- 0x18, 0xc7, 0x9b, 0x6d, 0x4d, 0x3b, 0xb7, 0xfa, 0x69, 0xbf, 0xd0, 0x8d, 0x30, 0x50, 0x5a, 0x32,
- 0x0e, 0xbd, 0x90, 0x6c, 0x43, 0x02, 0x09, 0x89, 0x43, 0x53, 0x2e, 0x3b, 0x54, 0x9a, 0x32, 0xc1,
- 0xa4, 0x5d, 0x22, 0x27, 0xf1, 0x32, 0x43, 0x62, 0x47, 0xb6, 0x4b, 0xd7, 0x77, 0xc1, 0x0b, 0xe0,
- 0x05, 0x4c, 0xbc, 0x92, 0x1d, 0x77, 0x1c, 0x97, 0xc2, 0xba, 0x0b, 0x67, 0x8e, 0x9c, 0x90, 0x9d,
- 0xac, 0x74, 0xd2, 0x84, 0x26, 0xf1, 0xe7, 0x62, 0xe7, 0xc9, 0xf3, 0x7d, 0xfe, 0xf8, 0x93, 0x27,
- 0x06, 0x8f, 0x8e, 0xdd, 0x11, 0xe4, 0x99, 0x8b, 0x89, 0x40, 0x8c, 0xc0, 0xd4, 0x15, 0xe3, 0x1c,
- 0x71, 0x37, 0x67, 0x34, 0xa7, 0x1c, 0xa6, 0x4e, 0xce, 0xa8, 0xa0, 0xc6, 0x6a, 0x44, 0x79, 0x26,
- 0x75, 0x8e, 0x5a, 0xde, 0x6d, 0x85, 0x48, 0xc0, 0xad, 0xf5, 0x56, 0x42, 0x13, 0xaa, 0x14, 0xae,
- 0x7c, 0x2a, 0xc4, 0xeb, 0x96, 0x14, 0x53, 0xee, 0x86, 0x90, 0x23, 0xb7, 0x94, 0xba, 0x11, 0xc5,
- 0xa4, 0xf4, 0x3f, 0xbc, 0xb9, 0xa4, 0x5a, 0x0b, 0x89, 0x7d, 0xb2, 0x00, 0xfe, 0xdf, 0x13, 0x94,
- 0xa1, 0x3e, 0x8d, 0xd1, 0x6e, 0xd9, 0x8b, 0xd1, 0x02, 0x55, 0x81, 0x45, 0x8a, 0x4c, 0xad, 0xa3,
- 0x75, 0x97, 0xfd, 0xc2, 0x30, 0x3a, 0xa0, 0x11, 0x23, 0x1e, 0x31, 0x9c, 0x0b, 0x4c, 0x89, 0xb9,
- 0xa0, 0x7c, 0xf3, 0xaf, 0x8c, 0x55, 0xa0, 0xb3, 0x21, 0x09, 0x20, 0x37, 0x17, 0x8b, 0x40, 0x36,
- 0x24, 0x3d, 0x6e, 0x3c, 0x05, 0xff, 0xc9, 0x3e, 0x82, 0x70, 0x2c, 0x50, 0x10, 0xd1, 0x18, 0x99,
- 0x4b, 0x1d, 0xad, 0xdb, 0xf4, 0x56, 0xa6, 0x93, 0x76, 0x73, 0xbf, 0xb7, 0x37, 0xf0, 0xc6, 0x42,
- 0x35, 0xe0, 0x37, 0xa5, 0xee, 0xca, 0x32, 0xd6, 0x80, 0xce, 0xe9, 0x90, 0x45, 0xc8, 0xac, 0xaa,
- 0x74, 0xa5, 0x65, 0x98, 0xa0, 0x16, 0x0e, 0x71, 0x1a, 0x23, 0x66, 0xea, 0xca, 0x71, 0x65, 0x1a,
- 0x07, 0x60, 0x0d, 0x13, 0x2e, 0x20, 0x11, 0x18, 0x0a, 0x14, 0xe4, 0x88, 0x65, 0x98, 0x73, 0xd9,
- 0x6d, 0xad, 0xa3, 0x75, 0x1b, 0xdb, 0x1b, 0xce, 0x8d, 0x7c, 0x9d, 0x5e, 0x14, 0x21, 0xce, 0xfb,
- 0x94, 0x1c, 0xe2, 0xc4, 0x5f, 0x9d, 0x4b, 0xb1, 0x3b, 0xcb, 0x60, 0x7f, 0x5a, 0x00, 0xf7, 0x77,
- 0x7e, 0x7a, 0xfa, 0x94, 0x08, 0x06, 0x23, 0xf1, 0xb7, 0xa0, 0xb5, 0x40, 0x15, 0xc6, 0x19, 0x26,
- 0x8a, 0xd5, 0xb2, 0x5f, 0x18, 0xc6, 0x06, 0xa8, 0x49, 0x80, 0x01, 0x8e, 0x15, 0x93, 0x25, 0x0f,
- 0x4c, 0x27, 0x6d, 0x5d, 0xd2, 0xda, 0x79, 0xe9, 0xeb, 0xd2, 0xb5, 0x13, 0xcb, 0xd0, 0x14, 0x86,
- 0x28, 0x2d, 0xe9, 0x14, 0x86, 0xf1, 0x0c, 0xd4, 0x31, 0xc1, 0x22, 0xc8, 0x78, 0xa2, 0x68, 0x34,
- 0xbd, 0x07, 0xdf, 0x27, 0x6d, 0x13, 0x91, 0x88, 0xc6, 0x98, 0x24, 0xee, 0x1b, 0x4e, 0x89, 0xe3,
- 0xc3, 0xd1, 0x00, 0x71, 0x0e, 0x13, 0xe4, 0xd7, 0xa4, 0x7a, 0xc0, 0x13, 0x03, 0x82, 0xea, 0xe1,
- 0x90, 0xc4, 0xdc, 0xac, 0x77, 0x16, 0xbb, 0x8d, 0xed, 0x7b, 0x4e, 0x31, 0x76, 0x8e, 0x1c, 0xbb,
- 0x19, 0xc1, 0x3e, 0xc5, 0xc4, 0xdb, 0x3c, 0x9d, 0xb4, 0x2b, 0x1f, 0x3f, 0xb7, 0xbb, 0x09, 0x16,
- 0x47, 0xc3, 0xd0, 0x89, 0x68, 0xe6, 0x96, 0x33, 0x5a, 0x6c, 0x8f, 0x79, 0xfc, 0xb6, 0x9c, 0x3f,
- 0x19, 0xc0, 0xfd, 0x22, 0xb3, 0xfd, 0x55, 0x03, 0x77, 0x07, 0x38, 0x61, 0xff, 0x80, 0xeb, 0x3a,
- 0xa8, 0x47, 0x65, 0x89, 0x12, 0xed, 0xcc, 0xbe, 0x1d, 0xdd, 0x17, 0xa0, 0x91, 0x15, 0xad, 0x2a,
- 0x94, 0xfa, 0x2d, 0x50, 0x82, 0x32, 0x60, 0xc0, 0x13, 0xfb, 0x83, 0x06, 0xee, 0xbc, 0xca, 0x63,
- 0x28, 0x50, 0x4f, 0x7e, 0xd1, 0xdf, 0x3e, 0xe6, 0x16, 0x58, 0x26, 0x68, 0x14, 0x14, 0xb3, 0xa2,
- 0x4e, 0xea, 0xb5, 0xbe, 0x4d, 0xda, 0x2b, 0x63, 0x98, 0xa5, 0xcf, 0xed, 0x99, 0xcb, 0xf6, 0xeb,
- 0x04, 0x8d, 0x54, 0xc9, 0x5f, 0x21, 0xb0, 0x8f, 0x80, 0xd1, 0x4f, 0x11, 0x64, 0x7f, 0xa6, 0xb9,
- 0xf9, 0x4a, 0x8b, 0xd7, 0x2b, 0x79, 0xaf, 0x4f, 0x2f, 0xac, 0xca, 0xf9, 0x85, 0x55, 0x39, 0x99,
- 0x5a, 0xda, 0xe9, 0xd4, 0xd2, 0xce, 0xa6, 0x96, 0xf6, 0x65, 0x6a, 0x69, 0xef, 0x2f, 0xad, 0xca,
- 0xd9, 0xa5, 0x55, 0x39, 0xbf, 0xb4, 0x2a, 0x07, 0x9b, 0x73, 0xa3, 0xd4, 0xa7, 0x3c, 0xdb, 0x97,
- 0x17, 0x9a, 0xfc, 0x77, 0x63, 0xf7, 0xb8, 0xdc, 0xaf, 0x5f, 0x6f, 0xa1, 0xae, 0x6e, 0xb6, 0x27,
- 0x3f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xd4, 0xcb, 0x63, 0x29, 0x71, 0x05, 0x00, 0x00,
+ // 742 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0xcb, 0x6e, 0xe3, 0x36,
+ 0x14, 0xb5, 0xe2, 0xf8, 0x11, 0xda, 0x68, 0x5d, 0xd5, 0x49, 0xd5, 0xb4, 0x90, 0x5c, 0xa5, 0x28,
+ 0xbc, 0xa9, 0x94, 0xa4, 0x40, 0x5f, 0x40, 0x17, 0x96, 0xbb, 0xc9, 0xc2, 0x40, 0xa0, 0x20, 0x0d,
+ 0x90, 0x8d, 0x41, 0x4b, 0x8c, 0xc2, 0x56, 0x22, 0x05, 0x91, 0xae, 0xe3, 0xbf, 0xe8, 0x07, 0xf4,
+ 0x03, 0x82, 0x6e, 0x8a, 0xfe, 0x45, 0x96, 0x59, 0xa6, 0x1b, 0xcd, 0xc4, 0xd9, 0xcc, 0xda, 0xcb,
+ 0x59, 0x0d, 0x48, 0xca, 0x1e, 0x67, 0x10, 0x0c, 0x02, 0xcc, 0x03, 0x98, 0x8d, 0xe4, 0xcb, 0x7b,
+ 0x78, 0xcf, 0xe1, 0xb9, 0xd7, 0x22, 0xf8, 0xfa, 0xc2, 0x9d, 0x40, 0x96, 0xb8, 0x98, 0x70, 0x94,
+ 0x11, 0x18, 0xbb, 0x7c, 0x9a, 0x22, 0xe6, 0xa6, 0x19, 0x4d, 0x29, 0x83, 0xb1, 0x93, 0x66, 0x94,
+ 0x53, 0x7d, 0x33, 0xa0, 0x2c, 0x11, 0x38, 0x47, 0x3e, 0xfe, 0xdc, 0x1b, 0x21, 0x0e, 0xf7, 0xb6,
+ 0xdb, 0x11, 0x8d, 0xa8, 0x44, 0xb8, 0xe2, 0x97, 0x02, 0x6f, 0x9b, 0x02, 0x4c, 0x99, 0x3b, 0x82,
+ 0x0c, 0xb9, 0x05, 0xd4, 0x0d, 0x28, 0x26, 0x45, 0xfe, 0xab, 0x87, 0x29, 0xe5, 0x53, 0x41, 0xec,
+ 0xcb, 0x35, 0xf0, 0xc9, 0x11, 0xa7, 0x19, 0xea, 0xd3, 0x10, 0x1d, 0x16, 0x5a, 0xf4, 0x36, 0xa8,
+ 0x70, 0xcc, 0x63, 0x64, 0x68, 0x1d, 0xad, 0xbb, 0xe1, 0xab, 0x40, 0xef, 0x80, 0x46, 0x88, 0x58,
+ 0x90, 0xe1, 0x94, 0x63, 0x4a, 0x8c, 0x35, 0x99, 0x5b, 0x5d, 0xd2, 0x37, 0x41, 0x35, 0x1b, 0x93,
+ 0x21, 0x64, 0x46, 0x59, 0x6d, 0xcc, 0xc6, 0xa4, 0xc7, 0xf4, 0xef, 0xc1, 0x47, 0x42, 0xc7, 0x70,
+ 0x34, 0xe5, 0x68, 0x18, 0xd0, 0x10, 0x19, 0xeb, 0x1d, 0xad, 0xdb, 0xf4, 0x5a, 0xb3, 0xdc, 0x6a,
+ 0x9e, 0xf4, 0x8e, 0x06, 0xde, 0x94, 0x4b, 0x01, 0x7e, 0x53, 0xe0, 0x16, 0x91, 0xbe, 0x05, 0xaa,
+ 0x8c, 0x8e, 0xb3, 0x00, 0x19, 0x15, 0x59, 0xae, 0x88, 0x74, 0x03, 0xd4, 0x46, 0x63, 0x1c, 0x87,
+ 0x28, 0x33, 0xaa, 0x32, 0xb1, 0x08, 0xf5, 0x53, 0xb0, 0x85, 0x09, 0xe3, 0x90, 0x70, 0x0c, 0x39,
+ 0x1a, 0xa6, 0x28, 0x4b, 0x30, 0x63, 0x42, 0x6d, 0xad, 0xa3, 0x75, 0x1b, 0xfb, 0x3b, 0xce, 0x83,
+ 0xfe, 0x3a, 0xbd, 0x20, 0x40, 0x8c, 0xf5, 0x29, 0x39, 0xc3, 0x91, 0xbf, 0xb9, 0x52, 0xe2, 0x70,
+ 0x59, 0xc1, 0xfe, 0x7f, 0x0d, 0x7c, 0x71, 0xf0, 0x32, 0xd3, 0xa7, 0x84, 0x67, 0x30, 0xe0, 0xef,
+ 0xca, 0xb4, 0x36, 0xa8, 0xc0, 0x30, 0xc1, 0x44, 0x7a, 0xb5, 0xe1, 0xab, 0x40, 0xdf, 0x01, 0x35,
+ 0x61, 0xe0, 0x10, 0x87, 0xd2, 0x93, 0x75, 0x0f, 0xcc, 0x72, 0xab, 0x2a, 0xdc, 0x3a, 0xf8, 0xd5,
+ 0xaf, 0x8a, 0xd4, 0x41, 0x28, 0xb6, 0xc6, 0x70, 0x84, 0xe2, 0xc2, 0x1d, 0x15, 0xe8, 0x3f, 0x80,
+ 0x3a, 0x26, 0x98, 0x0f, 0x13, 0x16, 0x49, 0x37, 0x9a, 0xde, 0x97, 0xcf, 0x73, 0xcb, 0x40, 0x24,
+ 0xa0, 0x21, 0x26, 0x91, 0xfb, 0x3b, 0xa3, 0xc4, 0xf1, 0xe1, 0x64, 0x80, 0x18, 0x83, 0x11, 0xf2,
+ 0x6b, 0x02, 0x3d, 0x60, 0x91, 0x0e, 0x41, 0xe5, 0x6c, 0x4c, 0x42, 0x66, 0xd4, 0x3b, 0xe5, 0x6e,
+ 0x63, 0xff, 0x73, 0x47, 0x8d, 0x9d, 0x23, 0xc6, 0x6e, 0xe9, 0x60, 0x9f, 0x62, 0xe2, 0xed, 0x5e,
+ 0xe5, 0x56, 0xe9, 0x9f, 0x27, 0x56, 0x37, 0xc2, 0xfc, 0x7c, 0x3c, 0x72, 0x02, 0x9a, 0xb8, 0xc5,
+ 0x8c, 0xaa, 0xd7, 0xb7, 0x2c, 0xfc, 0xa3, 0x98, 0x3f, 0xb1, 0x81, 0xf9, 0xaa, 0xb2, 0xfd, 0x4c,
+ 0x03, 0x9f, 0x0d, 0x70, 0x94, 0xbd, 0x07, 0x5f, 0xb7, 0x41, 0x3d, 0x28, 0x28, 0x0a, 0x6b, 0x97,
+ 0xf1, 0xe3, 0xdc, 0xfd, 0x05, 0x34, 0x12, 0x25, 0x55, 0x5a, 0x59, 0x7d, 0x84, 0x95, 0xa0, 0xd8,
+ 0x30, 0x60, 0x91, 0xfd, 0xb7, 0x06, 0x3e, 0x3d, 0x4e, 0x43, 0xc8, 0x51, 0x4f, 0x74, 0xf4, 0x8d,
+ 0x8f, 0xb9, 0x07, 0x36, 0x08, 0x9a, 0x0c, 0xd5, 0xac, 0xc8, 0x93, 0x7a, 0xed, 0x79, 0x6e, 0xb5,
+ 0xa6, 0x30, 0x89, 0x7f, 0xb6, 0x97, 0x29, 0xdb, 0xaf, 0x13, 0x34, 0x91, 0x94, 0xaf, 0xb3, 0xc0,
+ 0x3e, 0x07, 0x7a, 0x3f, 0x46, 0x30, 0x7b, 0x3b, 0xe2, 0x56, 0x99, 0xca, 0xaf, 0x30, 0xfd, 0xab,
+ 0x81, 0xd6, 0x21, 0x26, 0xc2, 0x5d, 0xb6, 0x24, 0xfa, 0xe6, 0x1e, 0x91, 0xd7, 0x9a, 0xe7, 0x56,
+ 0x53, 0x9d, 0x44, 0x2e, 0xdb, 0x0b, 0xea, 0x1f, 0x1f, 0xa0, 0xf6, 0xb6, 0xe6, 0xb9, 0xa5, 0x2b,
+ 0xf4, 0x4a, 0xd2, 0xbe, 0x2f, 0xe9, 0x27, 0x21, 0x49, 0xf6, 0x58, 0x0c, 0x46, 0xb9, 0xbb, 0xee,
+ 0x99, 0xb3, 0xdc, 0xaa, 0xa9, 0x26, 0xb3, 0x79, 0x6e, 0x7d, 0xac, 0x2a, 0x2c, 0x40, 0xb6, 0x5f,
+ 0x53, 0x8d, 0x67, 0xf6, 0x7f, 0x1a, 0xd0, 0x8f, 0x49, 0xfa, 0x21, 0x69, 0xf6, 0x7e, 0xbb, 0xba,
+ 0x35, 0x4b, 0x37, 0xb7, 0x66, 0xe9, 0x72, 0x66, 0x6a, 0x57, 0x33, 0x53, 0xbb, 0x9e, 0x99, 0xda,
+ 0xd3, 0x99, 0xa9, 0xfd, 0x75, 0x67, 0x96, 0xae, 0xef, 0xcc, 0xd2, 0xcd, 0x9d, 0x59, 0x3a, 0xdd,
+ 0x5d, 0xf9, 0xc3, 0xf6, 0x29, 0x4b, 0x4e, 0xc4, 0xb5, 0x21, 0xbe, 0x90, 0xa1, 0x7b, 0x51, 0xbc,
+ 0xef, 0x5f, 0x22, 0xa3, 0xaa, 0xbc, 0x3f, 0xbe, 0x7b, 0x11, 0x00, 0x00, 0xff, 0xff, 0x98, 0x84,
+ 0x18, 0xe8, 0xd7, 0x06, 0x00, 0x00,
}
func (this *StoreCodeProposal) Equal(that interface{}) bool {
@@ -514,6 +606,76 @@ func (this *ClearAdminProposal) Equal(that interface{}) bool {
}
return true
}
+func (this *PinCodesProposal) Equal(that interface{}) bool {
+ if that == nil {
+ return this == nil
+ }
+
+ that1, ok := that.(*PinCodesProposal)
+ if !ok {
+ that2, ok := that.(PinCodesProposal)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ return this == nil
+ } else if this == nil {
+ return false
+ }
+ if this.Title != that1.Title {
+ return false
+ }
+ if this.Description != that1.Description {
+ return false
+ }
+ if len(this.CodeIDs) != len(that1.CodeIDs) {
+ return false
+ }
+ for i := range this.CodeIDs {
+ if this.CodeIDs[i] != that1.CodeIDs[i] {
+ return false
+ }
+ }
+ return true
+}
+func (this *UnpinCodesProposal) Equal(that interface{}) bool {
+ if that == nil {
+ return this == nil
+ }
+
+ that1, ok := that.(*UnpinCodesProposal)
+ if !ok {
+ that2, ok := that.(UnpinCodesProposal)
+ if ok {
+ that1 = &that2
+ } else {
+ return false
+ }
+ }
+ if that1 == nil {
+ return this == nil
+ } else if this == nil {
+ return false
+ }
+ if this.Title != that1.Title {
+ return false
+ }
+ if this.Description != that1.Description {
+ return false
+ }
+ if len(this.CodeIDs) != len(that1.CodeIDs) {
+ return false
+ }
+ for i := range this.CodeIDs {
+ if this.CodeIDs[i] != that1.CodeIDs[i] {
+ return false
+ }
+ }
+ return true
+}
func (m *StoreCodeProposal) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@@ -833,6 +995,116 @@ func (m *ClearAdminProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
+func (m *PinCodesProposal) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *PinCodesProposal) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *PinCodesProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.CodeIDs) > 0 {
+ dAtA3 := make([]byte, len(m.CodeIDs)*10)
+ var j2 int
+ for _, num := range m.CodeIDs {
+ for num >= 1<<7 {
+ dAtA3[j2] = uint8(uint64(num)&0x7f | 0x80)
+ num >>= 7
+ j2++
+ }
+ dAtA3[j2] = uint8(num)
+ j2++
+ }
+ i -= j2
+ copy(dAtA[i:], dAtA3[:j2])
+ i = encodeVarintProposal(dAtA, i, uint64(j2))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.Description) > 0 {
+ i -= len(m.Description)
+ copy(dAtA[i:], m.Description)
+ i = encodeVarintProposal(dAtA, i, uint64(len(m.Description)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Title) > 0 {
+ i -= len(m.Title)
+ copy(dAtA[i:], m.Title)
+ i = encodeVarintProposal(dAtA, i, uint64(len(m.Title)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
+func (m *UnpinCodesProposal) Marshal() (dAtA []byte, err error) {
+ size := m.Size()
+ dAtA = make([]byte, size)
+ n, err := m.MarshalToSizedBuffer(dAtA[:size])
+ if err != nil {
+ return nil, err
+ }
+ return dAtA[:n], nil
+}
+
+func (m *UnpinCodesProposal) MarshalTo(dAtA []byte) (int, error) {
+ size := m.Size()
+ return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *UnpinCodesProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+ i := len(dAtA)
+ _ = i
+ var l int
+ _ = l
+ if len(m.CodeIDs) > 0 {
+ dAtA5 := make([]byte, len(m.CodeIDs)*10)
+ var j4 int
+ for _, num := range m.CodeIDs {
+ for num >= 1<<7 {
+ dAtA5[j4] = uint8(uint64(num)&0x7f | 0x80)
+ num >>= 7
+ j4++
+ }
+ dAtA5[j4] = uint8(num)
+ j4++
+ }
+ i -= j4
+ copy(dAtA[i:], dAtA5[:j4])
+ i = encodeVarintProposal(dAtA, i, uint64(j4))
+ i--
+ dAtA[i] = 0x1a
+ }
+ if len(m.Description) > 0 {
+ i -= len(m.Description)
+ copy(dAtA[i:], m.Description)
+ i = encodeVarintProposal(dAtA, i, uint64(len(m.Description)))
+ i--
+ dAtA[i] = 0x12
+ }
+ if len(m.Title) > 0 {
+ i -= len(m.Title)
+ copy(dAtA[i:], m.Title)
+ i = encodeVarintProposal(dAtA, i, uint64(len(m.Title)))
+ i--
+ dAtA[i] = 0xa
+ }
+ return len(dAtA) - i, nil
+}
+
func encodeVarintProposal(dAtA []byte, offset int, v uint64) int {
offset -= sovProposal(v)
base := offset
@@ -1001,6 +1273,54 @@ func (m *ClearAdminProposal) Size() (n int) {
return n
}
+func (m *PinCodesProposal) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Title)
+ if l > 0 {
+ n += 1 + l + sovProposal(uint64(l))
+ }
+ l = len(m.Description)
+ if l > 0 {
+ n += 1 + l + sovProposal(uint64(l))
+ }
+ if len(m.CodeIDs) > 0 {
+ l = 0
+ for _, e := range m.CodeIDs {
+ l += sovProposal(uint64(e))
+ }
+ n += 1 + sovProposal(uint64(l)) + l
+ }
+ return n
+}
+
+func (m *UnpinCodesProposal) Size() (n int) {
+ if m == nil {
+ return 0
+ }
+ var l int
+ _ = l
+ l = len(m.Title)
+ if l > 0 {
+ n += 1 + l + sovProposal(uint64(l))
+ }
+ l = len(m.Description)
+ if l > 0 {
+ n += 1 + l + sovProposal(uint64(l))
+ }
+ if len(m.CodeIDs) > 0 {
+ l = 0
+ for _, e := range m.CodeIDs {
+ l += sovProposal(uint64(e))
+ }
+ n += 1 + sovProposal(uint64(l)) + l
+ }
+ return n
+}
+
func sovProposal(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
@@ -2154,6 +2474,392 @@ func (m *ClearAdminProposal) Unmarshal(dAtA []byte) error {
}
return nil
}
+func (m *PinCodesProposal) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: PinCodesProposal: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: PinCodesProposal: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthProposal
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Title = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthProposal
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Description = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType == 0 {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.CodeIDs = append(m.CodeIDs, v)
+ } else if wireType == 2 {
+ var packedLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ packedLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if packedLen < 0 {
+ return ErrInvalidLengthProposal
+ }
+ postIndex := iNdEx + packedLen
+ if postIndex < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var elementCount int
+ var count int
+ for _, integer := range dAtA[iNdEx:postIndex] {
+ if integer < 128 {
+ count++
+ }
+ }
+ elementCount = count
+ if elementCount != 0 && len(m.CodeIDs) == 0 {
+ m.CodeIDs = make([]uint64, 0, elementCount)
+ }
+ for iNdEx < postIndex {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.CodeIDs = append(m.CodeIDs, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field CodeIDs", wireType)
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipProposal(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if (iNdEx + skippy) < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+func (m *UnpinCodesProposal) Unmarshal(dAtA []byte) error {
+ l := len(dAtA)
+ iNdEx := 0
+ for iNdEx < l {
+ preIndex := iNdEx
+ var wire uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ wire |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ fieldNum := int32(wire >> 3)
+ wireType := int(wire & 0x7)
+ if wireType == 4 {
+ return fmt.Errorf("proto: UnpinCodesProposal: wiretype end group for non-group")
+ }
+ if fieldNum <= 0 {
+ return fmt.Errorf("proto: UnpinCodesProposal: illegal tag %d (wire type %d)", fieldNum, wire)
+ }
+ switch fieldNum {
+ case 1:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthProposal
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Title = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 2:
+ if wireType != 2 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType)
+ }
+ var stringLen uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ stringLen |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ intStringLen := int(stringLen)
+ if intStringLen < 0 {
+ return ErrInvalidLengthProposal
+ }
+ postIndex := iNdEx + intStringLen
+ if postIndex < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ m.Description = string(dAtA[iNdEx:postIndex])
+ iNdEx = postIndex
+ case 3:
+ if wireType == 0 {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.CodeIDs = append(m.CodeIDs, v)
+ } else if wireType == 2 {
+ var packedLen int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ packedLen |= int(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ if packedLen < 0 {
+ return ErrInvalidLengthProposal
+ }
+ postIndex := iNdEx + packedLen
+ if postIndex < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if postIndex > l {
+ return io.ErrUnexpectedEOF
+ }
+ var elementCount int
+ var count int
+ for _, integer := range dAtA[iNdEx:postIndex] {
+ if integer < 128 {
+ count++
+ }
+ }
+ elementCount = count
+ if elementCount != 0 && len(m.CodeIDs) == 0 {
+ m.CodeIDs = make([]uint64, 0, elementCount)
+ }
+ for iNdEx < postIndex {
+ var v uint64
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowProposal
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= uint64(b&0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.CodeIDs = append(m.CodeIDs, v)
+ }
+ } else {
+ return fmt.Errorf("proto: wrong wireType = %d for field CodeIDs", wireType)
+ }
+ default:
+ iNdEx = preIndex
+ skippy, err := skipProposal(dAtA[iNdEx:])
+ if err != nil {
+ return err
+ }
+ if skippy < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if (iNdEx + skippy) < 0 {
+ return ErrInvalidLengthProposal
+ }
+ if (iNdEx + skippy) > l {
+ return io.ErrUnexpectedEOF
+ }
+ iNdEx += skippy
+ }
+ }
+
+ if iNdEx > l {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
func skipProposal(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
diff --git a/x/wasm/internal/types/proposal.proto b/x/wasm/internal/types/proposal.proto
index 98bdb6fe11..e87aafbf40 100644
--- a/x/wasm/internal/types/proposal.proto
+++ b/x/wasm/internal/types/proposal.proto
@@ -85,3 +85,29 @@ message ClearAdminProposal {
// Contract is the address of the smart contract
string contract = 3;
}
+
+// PinCodesProposal gov proposal content type to pin a set of code ids in the wasmvm cache.
+message PinCodesProposal {
+ // Title is a short summary
+ string title = 1 [(gogoproto.moretags) = "yaml:\"title\""];
+ // Description is a human readable text
+ string description = 2 [(gogoproto.moretags) = "yaml:\"description\""];
+ // CodeIDs references the new WASM codes
+ repeated uint64 code_ids = 3 [
+ (gogoproto.customname) = "CodeIDs",
+ (gogoproto.moretags) = "yaml:\"code_ids\""
+ ];
+}
+
+// UnpinCodesProposal gov proposal content type to unpin a set of code ids in the wasmvm cache.
+message UnpinCodesProposal {
+ // Title is a short summary
+ string title = 1 [(gogoproto.moretags) = "yaml:\"title\""];
+ // Description is a human readable text
+ string description = 2 [(gogoproto.moretags) = "yaml:\"description\""];
+ // CodeIDs references the WASM codes
+ repeated uint64 code_ids = 3 [
+ (gogoproto.customname) = "CodeIDs",
+ (gogoproto.moretags) = "yaml:\"code_ids\""
+ ];
+}
diff --git a/x/wasm/internal/types/proposal_test.go b/x/wasm/internal/types/proposal_test.go
index c3148f6e6c..15f15592f4 100644
--- a/x/wasm/internal/types/proposal_test.go
+++ b/x/wasm/internal/types/proposal_test.go
@@ -515,6 +515,30 @@ func TestProposalStrings(t *testing.T) {
Title: Foo
Description: Bar
Contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
+`,
+ },
+ "pin codes": {
+ src: &PinCodesProposal{
+ Title: "Foo",
+ Description: "Bar",
+ CodeIDs: []uint64{1, 2, 3},
+ },
+ exp: `Pin Wasm Codes Proposal:
+ Title: Foo
+ Description: Bar
+ Codes: [1 2 3]
+`,
+ },
+ "unpin codes": {
+ src: &UnpinCodesProposal{
+ Title: "Foo",
+ Description: "Bar",
+ CodeIDs: []uint64{3, 2, 1},
+ },
+ exp: `Unpin Wasm Codes Proposal:
+ Title: Foo
+ Description: Bar
+ Codes: [3 2 1]
`,
},
}
@@ -608,6 +632,20 @@ contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
exp: `title: Foo
description: Bar
contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
+`,
+ },
+ "pin codes": {
+ src: &PinCodesProposal{
+ Title: "Foo",
+ Description: "Bar",
+ CodeIDs: []uint64{1, 2, 3},
+ },
+ exp: `title: Foo
+description: Bar
+code_ids:
+- 1
+- 2
+- 3
`,
},
}
diff --git a/x/wasm/internal/types/types.pb.go b/x/wasm/internal/types/types.pb.go
index cf7fa3aa46..35cba507cd 100644
--- a/x/wasm/internal/types/types.pb.go
+++ b/x/wasm/internal/types/types.pb.go
@@ -212,7 +212,7 @@ var xxx_messageInfo_Params proto.InternalMessageInfo
// CodeInfo is data for the uploaded contract WASM code
type CodeInfo struct {
- // CodeHash is the unique CodeID
+ // CodeHash is the unique identifier created by wasmvm
CodeHash []byte `protobuf:"bytes,1,opt,name=code_hash,json=codeHash,proto3" json:"code_hash,omitempty"`
// Creator address who initially stored the code
Creator string `protobuf:"bytes,2,opt,name=creator,proto3" json:"creator,omitempty"`
diff --git a/x/wasm/internal/types/types.proto b/x/wasm/internal/types/types.proto
index 7328436ed0..0ea99dc245 100644
--- a/x/wasm/internal/types/types.proto
+++ b/x/wasm/internal/types/types.proto
@@ -44,7 +44,7 @@ message Params {
// CodeInfo is data for the uploaded contract WASM code
message CodeInfo {
- // CodeHash is the unique CodeID
+ // CodeHash is the unique identifier created by wasmvm
bytes code_hash = 1;
// Creator address who initially stored the code
string creator = 2;
diff --git a/x/wasm/internal/types/wasmer_engine.go b/x/wasm/internal/types/wasmer_engine.go
index 8aba3fd31c..2d4b0d89e6 100644
--- a/x/wasm/internal/types/wasmer_engine.go
+++ b/x/wasm/internal/types/wasmer_engine.go
@@ -197,4 +197,15 @@ type WasmerEngine interface {
gasMeter wasmvm.GasMeter,
gasLimit uint64,
) (*wasmvmtypes.IBCBasicResponse, uint64, error)
+
+ // Pin pins a code to an in-memory cache, such that is
+ // always loaded quickly when executed.
+ // Pin is idempotent.
+ Pin(checksum wasmvm.Checksum) error
+
+ // Unpin removes the guarantee of a contract to be pinned (see Pin).
+ // After calling this, the code may or may not remain in memory depending on
+ // the implementor's choice.
+ // Unpin is idempotent.
+ Unpin(checksum wasmvm.Checksum) error
}