mirror of https://github.com/certusone/wasmd.git
Merge pull request #179 from CosmWasm/gov_restrict_upload
Restrict code upload
This commit is contained in:
commit
f5d4622266
|
@ -37,6 +37,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
## [Unreleased]
|
||||
|
||||
### Features
|
||||
* (wasmd) [\#164](https://github.com/CosmWasm/wasmd/issues/164) Control who can upload code
|
||||
* (wasmd) [\#173](https://github.com/CosmWasm/wasmd/issues/173) Gov proposal types and handler
|
||||
* (wasmd) [\#122](https://github.com/CosmWasm/wasmd/pull/122]) Migrate contract backend functionality with go-cosmwasm stub impl
|
||||
* (wasmd)[\#2](https://github.com/cosmwasm/wasmd/pull/22) Improve wasm contract queries (all, raw, smart)
|
||||
* (wasmd) [\#119](https://github.com/cosmwasm/wasmd/pull/119) Add support for the `--inter-block-cache` CLI
|
||||
|
|
|
@ -179,6 +179,7 @@ func NewWasmApp(
|
|||
app.subspaces[gov.ModuleName] = app.paramsKeeper.Subspace(gov.DefaultParamspace).WithKeyTable(gov.ParamKeyTable())
|
||||
app.subspaces[crisis.ModuleName] = app.paramsKeeper.Subspace(crisis.DefaultParamspace)
|
||||
app.subspaces[evidence.ModuleName] = app.paramsKeeper.Subspace(evidence.DefaultParamspace)
|
||||
app.subspaces[wasm.ModuleName] = app.paramsKeeper.Subspace(wasm.DefaultParamspace)
|
||||
|
||||
// add keepers
|
||||
app.accountKeeper = auth.NewAccountKeeper(
|
||||
|
@ -249,7 +250,7 @@ func NewWasmApp(
|
|||
// The last arguments can contain custom message handlers, and custom query handlers,
|
||||
// if we want to allow any custom callbacks
|
||||
supportedFeatures := "staking"
|
||||
app.wasmKeeper = wasm.NewKeeper(app.cdc, keys[wasm.StoreKey], app.accountKeeper, app.bankKeeper, app.stakingKeeper, wasmRouter, wasmDir, wasmConfig, supportedFeatures, nil, nil)
|
||||
app.wasmKeeper = wasm.NewKeeper(app.cdc, keys[wasm.StoreKey], app.subspaces[wasm.ModuleName], app.accountKeeper, app.bankKeeper, app.stakingKeeper, wasmRouter, wasmDir, wasmConfig, supportedFeatures, nil, nil)
|
||||
|
||||
if len(wasm.DefaultEnabledProposals) != 0 {
|
||||
govRouter.AddRoute(wasm.RouterKey, wasm.NewWasmProposalHandler(app.wasmKeeper, wasm.DefaultEnabledProposals))
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/CosmWasm/wasmd/x/wasm"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
db "github.com/tendermint/tm-db"
|
||||
|
@ -38,6 +39,7 @@ func TestBlackListedAddrs(t *testing.T) {
|
|||
|
||||
func setGenesis(gapp *WasmApp) error {
|
||||
genesisState := simapp.NewDefaultGenesisState()
|
||||
genesisState[wasm.ModuleName] = wasm.AppModuleBasic{}.DefaultGenesis()
|
||||
stateBytes, err := codec.MarshalJSONIndent(gapp.Codec(), genesisState)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
1
go.mod
1
go.mod
|
@ -28,6 +28,7 @@ require (
|
|||
go.etcd.io/bbolt v1.3.4 // indirect
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
)
|
||||
|
||||
replace github.com/keybase/go-keychain => github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
DefaultParamspace = types.DefaultParamspace
|
||||
ModuleName = types.ModuleName
|
||||
StoreKey = types.StoreKey
|
||||
TStoreKey = types.TStoreKey
|
||||
|
@ -48,6 +49,7 @@ var (
|
|||
NewWasmCoins = types.NewWasmCoins
|
||||
ParseEvents = types.ParseEvents
|
||||
DefaultWasmConfig = types.DefaultWasmConfig
|
||||
DefaultParams = types.DefaultParams
|
||||
InitGenesis = keeper.InitGenesis
|
||||
ExportGenesis = keeper.ExportGenesis
|
||||
NewMessageHandler = keeper.NewMessageHandler
|
||||
|
|
|
@ -75,7 +75,7 @@ func handleStoreCode(ctx sdk.Context, k Keeper, msg *MsgStoreCode) (*sdk.Result,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
codeID, err := k.Create(ctx, msg.Sender, msg.WASMByteCode, msg.Source, msg.Builder)
|
||||
codeID, err := k.Create(ctx, msg.Sender, msg.WASMByteCode, msg.Source, msg.Builder, msg.InstantiatePermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error
|
|||
if keeper.peekAutoIncrementID(ctx, types.KeyLastInstanceID) <= uint64(maxContractID) {
|
||||
return sdkerrors.Wrapf(types.ErrInvalid, "seq %s must be greater %d ", string(types.KeyLastInstanceID), maxContractID)
|
||||
}
|
||||
keeper.setParams(ctx, data.Params)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -54,6 +55,8 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error
|
|||
func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
|
||||
var genState types.GenesisState
|
||||
|
||||
genState.Params = keeper.GetParams(ctx)
|
||||
|
||||
maxCodeID := keeper.GetNextCodeID(ctx)
|
||||
for i := uint64(1); i < maxCodeID; i++ {
|
||||
if !keeper.containsCodeInfo(ctx, i) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
fuzz "github.com/google/gofuzz"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -22,13 +23,13 @@ import (
|
|||
)
|
||||
|
||||
func TestGenesisExportImport(t *testing.T) {
|
||||
srcKeeper, srcCtx, srcCleanup := setupKeeper(t)
|
||||
srcKeeper, srcCtx, srcStoreKeys, srcCleanup := setupKeeper(t)
|
||||
defer srcCleanup()
|
||||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
// store some test data
|
||||
f := fuzz.New().Funcs(FuzzAddr, FuzzAbsoluteTxPosition, FuzzContractInfo, FuzzStateModel)
|
||||
f := fuzz.New().Funcs(FuzzAddr, FuzzAbsoluteTxPosition, FuzzContractInfo, FuzzStateModel, FuzzAccessType, FuzzAccessConfig)
|
||||
for i := 0; i < 25; i++ {
|
||||
var (
|
||||
codeInfo types.CodeInfo
|
||||
|
@ -39,13 +40,16 @@ func TestGenesisExportImport(t *testing.T) {
|
|||
f.Fuzz(&contract)
|
||||
f.Fuzz(&stateModels)
|
||||
|
||||
codeID, err := srcKeeper.Create(srcCtx, codeInfo.Creator, wasmCode, codeInfo.Source, codeInfo.Builder)
|
||||
codeID, err := srcKeeper.Create(srcCtx, codeInfo.Creator, wasmCode, codeInfo.Source, codeInfo.Builder, &codeInfo.InstantiateConfig)
|
||||
require.NoError(t, err)
|
||||
contract.CodeID = codeID
|
||||
contractAddr := srcKeeper.generateContractAddress(srcCtx, codeID)
|
||||
srcKeeper.setContractInfo(srcCtx, contractAddr, &contract)
|
||||
srcKeeper.importContractState(srcCtx, contractAddr, stateModels)
|
||||
}
|
||||
var wasmParams types.Params
|
||||
f.Fuzz(&wasmParams)
|
||||
srcKeeper.setParams(srcCtx, wasmParams)
|
||||
|
||||
// export
|
||||
genesisState := ExportGenesis(srcCtx, srcKeeper)
|
||||
|
@ -62,23 +66,25 @@ func TestGenesisExportImport(t *testing.T) {
|
|||
})
|
||||
|
||||
// re-import
|
||||
dstKeeper, dstCtx, dstCleanup := setupKeeper(t)
|
||||
dstKeeper, dstCtx, dstStoreKeys, dstCleanup := setupKeeper(t)
|
||||
defer dstCleanup()
|
||||
|
||||
InitGenesis(dstCtx, dstKeeper, genesisState)
|
||||
|
||||
// compare whole DB
|
||||
srcIT := srcCtx.KVStore(srcKeeper.storeKey).Iterator(nil, nil)
|
||||
dstIT := dstCtx.KVStore(dstKeeper.storeKey).Iterator(nil, nil)
|
||||
for j := range srcStoreKeys {
|
||||
srcIT := srcCtx.KVStore(srcStoreKeys[j]).Iterator(nil, nil)
|
||||
dstIT := dstCtx.KVStore(dstStoreKeys[j]).Iterator(nil, nil)
|
||||
|
||||
for i := 0; srcIT.Valid(); i++ {
|
||||
require.True(t, dstIT.Valid(), "destination DB has less elements than source. Missing: %q", srcIT.Key())
|
||||
require.Equal(t, srcIT.Key(), dstIT.Key(), i)
|
||||
require.Equal(t, srcIT.Value(), dstIT.Value(), "element (%d): %s", i, srcIT.Key())
|
||||
srcIT.Next()
|
||||
dstIT.Next()
|
||||
for i := 0; srcIT.Valid(); i++ {
|
||||
require.True(t, dstIT.Valid(), "destination DB has less elements than source. Missing: %q", srcIT.Key())
|
||||
require.Equal(t, srcIT.Key(), dstIT.Key(), i)
|
||||
require.Equal(t, srcIT.Value(), dstIT.Value(), "[%s] element (%d): %s", srcStoreKeys[j].Name(), i, srcIT.Key())
|
||||
srcIT.Next()
|
||||
dstIT.Next()
|
||||
}
|
||||
require.False(t, dstIT.Valid())
|
||||
}
|
||||
require.False(t, dstIT.Valid())
|
||||
}
|
||||
|
||||
func TestFailFastImport(t *testing.T) {
|
||||
|
@ -101,11 +107,11 @@ func TestFailFastImport(t *testing.T) {
|
|||
},
|
||||
CodesBytes: wasmCode,
|
||||
}},
|
||||
Contracts: nil,
|
||||
Sequences: []types.Sequence{
|
||||
{IDKey: types.KeyLastCodeID, Value: 2},
|
||||
{IDKey: types.KeyLastInstanceID, Value: 1},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
expSuccess: true,
|
||||
},
|
||||
|
@ -126,11 +132,11 @@ func TestFailFastImport(t *testing.T) {
|
|||
},
|
||||
CodesBytes: wasmCode,
|
||||
}},
|
||||
Contracts: nil,
|
||||
Sequences: []types.Sequence{
|
||||
{IDKey: types.KeyLastCodeID, Value: 10},
|
||||
{IDKey: types.KeyLastInstanceID, Value: 1},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
expSuccess: true,
|
||||
},
|
||||
|
@ -156,6 +162,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
{IDKey: types.KeyLastCodeID, Value: 3},
|
||||
{IDKey: types.KeyLastInstanceID, Value: 1},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
expSuccess: true,
|
||||
},
|
||||
|
@ -168,7 +175,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
},
|
||||
CodesBytes: wasmCode,
|
||||
}},
|
||||
Contracts: nil,
|
||||
Params: types.DefaultParams(),
|
||||
}},
|
||||
"prevent duplicate codeIDs": {src: types.GenesisState{
|
||||
Codes: []types.Code{
|
||||
|
@ -189,6 +196,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
CodesBytes: wasmCode,
|
||||
},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
}},
|
||||
"happy path: code id in info and contract do match": {
|
||||
src: types.GenesisState{
|
||||
|
@ -210,6 +218,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
{IDKey: types.KeyLastCodeID, Value: 2},
|
||||
{IDKey: types.KeyLastInstanceID, Value: 2},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
expSuccess: true,
|
||||
},
|
||||
|
@ -236,6 +245,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
{IDKey: types.KeyLastCodeID, Value: 2},
|
||||
{IDKey: types.KeyLastInstanceID, Value: 3},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
expSuccess: true,
|
||||
},
|
||||
|
@ -247,6 +257,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }),
|
||||
},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
},
|
||||
"prevent duplicate contract address": {
|
||||
|
@ -268,6 +279,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
ContractInfo: types.ContractInfoFixture(func(c *wasmTypes.ContractInfo) { c.CodeID = 1 }),
|
||||
},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
},
|
||||
"prevent duplicate contract model keys": {
|
||||
|
@ -296,6 +308,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
},
|
||||
"prevent duplicate sequences": {
|
||||
|
@ -304,6 +317,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
{IDKey: []byte("foo"), Value: 1},
|
||||
{IDKey: []byte("foo"), Value: 9999},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
},
|
||||
"prevent code id seq init value == max codeID used": {
|
||||
|
@ -319,6 +333,7 @@ func TestFailFastImport(t *testing.T) {
|
|||
Sequences: []types.Sequence{
|
||||
{IDKey: types.KeyLastCodeID, Value: 1},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
},
|
||||
"prevent contract id seq init value == count contracts": {
|
||||
|
@ -341,13 +356,14 @@ func TestFailFastImport(t *testing.T) {
|
|||
{IDKey: types.KeyLastCodeID, Value: 2},
|
||||
{IDKey: types.KeyLastInstanceID, Value: 1},
|
||||
},
|
||||
Params: types.DefaultParams(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for msg, spec := range specs {
|
||||
t.Run(msg, func(t *testing.T) {
|
||||
keeper, ctx, cleanup := setupKeeper(t)
|
||||
keeper, ctx, _, cleanup := setupKeeper(t)
|
||||
defer cleanup()
|
||||
|
||||
require.NoError(t, types.ValidateGenesis(spec.src))
|
||||
|
@ -361,26 +377,34 @@ func TestFailFastImport(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func setupKeeper(t *testing.T) (Keeper, sdk.Context, func()) {
|
||||
func setupKeeper(t *testing.T) (Keeper, sdk.Context, []sdk.StoreKey, func()) {
|
||||
t.Helper()
|
||||
tempDir, err := ioutil.TempDir("", "wasm")
|
||||
require.NoError(t, err)
|
||||
cleanup := func() { os.RemoveAll(tempDir) }
|
||||
//t.Cleanup(cleanup) todo: add with Go 1.14
|
||||
var (
|
||||
keyParams = sdk.NewKVStoreKey(params.StoreKey)
|
||||
tkeyParams = sdk.NewTransientStoreKey(params.TStoreKey)
|
||||
keyWasm = sdk.NewKVStoreKey(wasmTypes.StoreKey)
|
||||
)
|
||||
|
||||
keyContract := sdk.NewKVStoreKey(wasmTypes.StoreKey)
|
||||
db := dbm.NewMemDB()
|
||||
ms := store.NewCommitMultiStore(db)
|
||||
ms.MountStoreWithDB(keyContract, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keyWasm, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
|
||||
ms.MountStoreWithDB(tkeyParams, sdk.StoreTypeTransient, db)
|
||||
require.NoError(t, ms.LoadLatestVersion())
|
||||
|
||||
ctx := sdk.NewContext(ms, abci.Header{
|
||||
Height: 1234567,
|
||||
Time: time.Date(2020, time.April, 22, 12, 0, 0, 0, time.UTC),
|
||||
}, false, log.NewNopLogger())
|
||||
|
||||
cdc := MakeTestCodec()
|
||||
pk := params.NewKeeper(cdc, keyParams, tkeyParams)
|
||||
wasmConfig := wasmTypes.DefaultWasmConfig()
|
||||
srcKeeper := NewKeeper(cdc, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), auth.AccountKeeper{}, nil, staking.Keeper{}, nil, tempDir, wasmConfig, "", nil, nil)
|
||||
srcKeeper.setParams(ctx, wasmTypes.DefaultParams())
|
||||
|
||||
srcKeeper := NewKeeper(cdc, keyContract, auth.AccountKeeper{}, nil, staking.Keeper{}, nil, tempDir, wasmConfig, "", nil, nil)
|
||||
return srcKeeper, ctx, cleanup
|
||||
return srcKeeper, ctx, []sdk.StoreKey{keyWasm, keyParams}, cleanup
|
||||
}
|
||||
|
|
|
@ -5,20 +5,21 @@ import (
|
|||
"encoding/binary"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/params/subspace"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
wasm "github.com/CosmWasm/go-cosmwasm"
|
||||
wasmTypes "github.com/CosmWasm/go-cosmwasm/types"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
|
||||
)
|
||||
|
||||
// GasMultiplier is how many cosmwasm gas points = 1 sdk gas point
|
||||
|
@ -50,11 +51,12 @@ type Keeper struct {
|
|||
// queryGasLimit is the max wasm gas that can be spent on executing a query with a contract
|
||||
queryGasLimit uint64
|
||||
authZPolicy AuthorizationPolicy
|
||||
paramSpace subspace.Subspace
|
||||
}
|
||||
|
||||
// NewKeeper creates a new contract Keeper instance
|
||||
// If customEncoders is non-nil, we can use this to override some of the message handler, especially custom
|
||||
func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper,
|
||||
func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace, accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper,
|
||||
stakingKeeper staking.Keeper,
|
||||
router sdk.Router, homeDir string, wasmConfig types.WasmConfig, supportedFeatures string, customEncoders *MessageEncoders, customPlugins *QueryPlugins) Keeper {
|
||||
wasmer, err := wasm.NewWasmer(filepath.Join(homeDir, "wasm"), supportedFeatures, wasmConfig.CacheSize)
|
||||
|
@ -62,7 +64,10 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, accountKeeper auth.Accou
|
|||
panic(err)
|
||||
}
|
||||
|
||||
messenger := NewMessageHandler(router, customEncoders)
|
||||
// set KeyTable if it has not already been set
|
||||
if !paramSpace.HasKeyTable() {
|
||||
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
|
||||
}
|
||||
|
||||
keeper := Keeper{
|
||||
storeKey: storeKey,
|
||||
|
@ -70,16 +75,47 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, accountKeeper auth.Accou
|
|||
wasmer: *wasmer,
|
||||
accountKeeper: accountKeeper,
|
||||
bankKeeper: bankKeeper,
|
||||
messenger: messenger,
|
||||
messenger: NewMessageHandler(router, customEncoders),
|
||||
queryGasLimit: wasmConfig.SmartQueryGasLimit,
|
||||
authZPolicy: DefaultAuthorizationPolicy{},
|
||||
paramSpace: paramSpace,
|
||||
}
|
||||
keeper.queryPlugins = DefaultQueryPlugins(bankKeeper, stakingKeeper, keeper).Merge(customPlugins)
|
||||
return keeper
|
||||
}
|
||||
|
||||
func (k Keeper) getUploadAccessConfig(ctx sdk.Context) types.AccessConfig {
|
||||
var a types.AccessConfig
|
||||
k.paramSpace.Get(ctx, types.ParamStoreKeyUploadAccess, &a)
|
||||
return a
|
||||
}
|
||||
|
||||
func (k Keeper) getInstantiateAccessConfig(ctx sdk.Context) types.AccessType {
|
||||
var a types.AccessType
|
||||
k.paramSpace.Get(ctx, types.ParamStoreKeyInstantiateAccess, &a)
|
||||
return a
|
||||
}
|
||||
|
||||
// GetParams returns the total set of wasm parameters.
|
||||
func (k Keeper) GetParams(ctx sdk.Context) types.Params {
|
||||
var params types.Params
|
||||
k.paramSpace.GetParamSet(ctx, ¶ms)
|
||||
return params
|
||||
}
|
||||
|
||||
func (k Keeper) setParams(ctx sdk.Context, ps types.Params) {
|
||||
k.paramSpace.SetParamSet(ctx, &ps)
|
||||
}
|
||||
|
||||
// Create uploads and compiles a WASM contract, returning a short identifier for the contract
|
||||
func (k Keeper) Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, source string, builder string) (codeID uint64, err error) {
|
||||
func (k Keeper) Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, source string, builder string, instantiateAccess *types.AccessConfig) (codeID uint64, err error) {
|
||||
return k.create(ctx, creator, wasmCode, source, builder, instantiateAccess, k.authZPolicy)
|
||||
}
|
||||
|
||||
func (k Keeper) create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, source string, builder string, instantiateAccess *types.AccessConfig, authZ AuthorizationPolicy) (codeID uint64, err error) {
|
||||
if !authZ.CanCreateCode(k.getUploadAccessConfig(ctx), creator) {
|
||||
return 0, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not create code")
|
||||
}
|
||||
wasmCode, err = uncompress(wasmCode)
|
||||
if err != nil {
|
||||
return 0, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
|
||||
|
@ -93,7 +129,11 @@ func (k Keeper) Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte,
|
|||
}
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
codeID = k.autoIncrementID(ctx, types.KeyLastCodeID)
|
||||
codeInfo := types.NewCodeInfo(codeHash, creator, source, builder)
|
||||
if instantiateAccess == nil {
|
||||
defaultAccessConfig := k.getInstantiateAccessConfig(ctx).With(creator)
|
||||
instantiateAccess = &defaultAccessConfig
|
||||
}
|
||||
codeInfo := types.NewCodeInfo(codeHash, creator, source, builder, *instantiateAccess)
|
||||
// 0x01 | codeID (uint64) -> ContractInfo
|
||||
store.Set(types.GetCodeKey(codeID), k.cdc.MustMarshalBinaryBare(codeInfo))
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestCreate(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "cosmwasm-opt:0.5.2")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "cosmwasm-opt:0.5.2", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), contractID)
|
||||
// and verify content
|
||||
|
@ -53,6 +53,56 @@ func TestCreate(t *testing.T) {
|
|||
require.Equal(t, wasmCode, storedCode)
|
||||
}
|
||||
|
||||
func TestCreateWithParamPermissions(t *testing.T) {
|
||||
tempDir, err := ioutil.TempDir("", "wasm")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tempDir)
|
||||
ctx, keepers := CreateTestInput(t, false, tempDir, SupportedFeatures, nil, nil)
|
||||
accKeeper, keeper := keepers.AccountKeeper, keepers.WasmKeeper
|
||||
|
||||
deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
|
||||
creator := createFakeFundedAccount(ctx, accKeeper, deposit)
|
||||
otherAddr := createFakeFundedAccount(ctx, accKeeper, deposit)
|
||||
|
||||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
specs := map[string]struct {
|
||||
srcPermission types.AccessConfig
|
||||
expError *sdkerrors.Error
|
||||
}{
|
||||
"default": {
|
||||
srcPermission: types.DefaultUploadAccess,
|
||||
},
|
||||
"everybody": {
|
||||
srcPermission: types.AllowEverybody,
|
||||
},
|
||||
"nobody": {
|
||||
srcPermission: types.AllowNobody,
|
||||
expError: sdkerrors.ErrUnauthorized,
|
||||
},
|
||||
"onlyAddress with matching address": {
|
||||
srcPermission: types.OnlyAddress.With(creator),
|
||||
},
|
||||
"onlyAddress with non matching address": {
|
||||
srcPermission: types.OnlyAddress.With(otherAddr),
|
||||
expError: sdkerrors.ErrUnauthorized,
|
||||
},
|
||||
}
|
||||
for msg, spec := range specs {
|
||||
t.Run(msg, func(t *testing.T) {
|
||||
params := types.DefaultParams()
|
||||
params.UploadAccess = spec.srcPermission
|
||||
keeper.setParams(ctx, params)
|
||||
_, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "cosmwasm-opt:0.5.2", nil)
|
||||
require.True(t, spec.expError.Is(err), err)
|
||||
if spec.expError != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateDuplicate(t *testing.T) {
|
||||
tempDir, err := ioutil.TempDir("", "wasm")
|
||||
require.NoError(t, err)
|
||||
|
@ -67,12 +117,12 @@ func TestCreateDuplicate(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// create one copy
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "cosmwasm-opt:0.5.2")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "cosmwasm-opt:0.5.2", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), contractID)
|
||||
|
||||
// create second copy
|
||||
duplicateID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "cosmwasm-opt:0.5.2")
|
||||
duplicateID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "cosmwasm-opt:0.5.2", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(2), duplicateID)
|
||||
|
||||
|
@ -102,14 +152,14 @@ func TestCreateWithSimulation(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// create this once in simulation mode
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "confio/cosmwasm-opt:0.57.2")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "confio/cosmwasm-opt:0.57.2", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), contractID)
|
||||
|
||||
// then try to create it in non-simulation mode (should not fail)
|
||||
ctx, keepers = CreateTestInput(t, false, tempDir, SupportedFeatures, nil, nil)
|
||||
accKeeper, keeper = keepers.AccountKeeper, keepers.WasmKeeper
|
||||
contractID, err = keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "confio/cosmwasm-opt:0.7.2")
|
||||
contractID, err = keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "confio/cosmwasm-opt:0.7.2", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), contractID)
|
||||
|
||||
|
@ -157,7 +207,7 @@ func TestCreateWithGzippedPayload(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm.gzip")
|
||||
require.NoError(t, err)
|
||||
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), contractID)
|
||||
// and verify content
|
||||
|
@ -181,7 +231,7 @@ func TestInstantiate(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "https://github.com/CosmWasm/wasmd/blob/master/x/wasm/testdata/escrow.wasm", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, bob := keyPubAddr()
|
||||
|
@ -202,7 +252,7 @@ func TestInstantiate(t *testing.T) {
|
|||
require.Equal(t, "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", addr.String())
|
||||
|
||||
gasAfter := ctx.GasMeter().GasConsumed()
|
||||
require.Equal(t, uint64(0x11536), gasAfter-gasBefore)
|
||||
require.Equal(t, uint64(0x11542), gasAfter-gasBefore)
|
||||
|
||||
// ensure it is stored properly
|
||||
info := keeper.GetContractInfo(ctx, addr)
|
||||
|
@ -250,7 +300,7 @@ func TestExecute(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, bob := keyPubAddr()
|
||||
|
@ -297,7 +347,7 @@ func TestExecute(t *testing.T) {
|
|||
|
||||
// make sure gas is properly deducted from ctx
|
||||
gasAfter := ctx.GasMeter().GasConsumed()
|
||||
require.Equal(t, uint64(0x11bef), gasAfter-gasBefore)
|
||||
require.Equal(t, uint64(0x11bfb), gasAfter-gasBefore)
|
||||
|
||||
// ensure bob now exists and got both payments released
|
||||
bobAcct = accKeeper.GetAccount(ctx, bob)
|
||||
|
@ -344,7 +394,7 @@ func TestExecuteWithPanic(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, bob := keyPubAddr()
|
||||
|
@ -378,7 +428,7 @@ func TestExecuteWithCpuLoop(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, bob := keyPubAddr()
|
||||
|
@ -419,7 +469,7 @@ func TestExecuteWithStorageLoop(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, bob := keyPubAddr()
|
||||
|
@ -466,9 +516,9 @@ func TestMigrate(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
newContractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
newContractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, originalContractID, newContractID)
|
||||
|
||||
|
@ -601,9 +651,9 @@ func TestMigrateWithDispatchedMessage(t *testing.T) {
|
|||
burnerCode, err := ioutil.ReadFile("./testdata/burner.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
burnerContractID, err := keeper.Create(ctx, creator, burnerCode, "", "")
|
||||
burnerContractID, err := keeper.Create(ctx, creator, burnerCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, originalContractID, burnerContractID)
|
||||
|
||||
|
@ -712,7 +762,7 @@ func TestUpdateContractAdmin(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, anyAddr := keyPubAddr()
|
||||
|
@ -787,7 +837,7 @@ func TestClearContractAdmin(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
originalContractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, anyAddr := keyPubAddr()
|
||||
|
|
|
@ -26,16 +26,16 @@ func NewWasmProposalHandler(k Keeper, enabledTypes map[string]struct{}) govtypes
|
|||
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unsupported wasm proposal content type: %q", content.ProposalType())
|
||||
}
|
||||
switch c := content.(type) {
|
||||
case *types.StoreCodeProposal:
|
||||
return handleStoreCodeProposal(ctx, k, *c)
|
||||
case *types.InstantiateContractProposal:
|
||||
return handleInstantiateProposal(ctx, k, *c)
|
||||
case *types.MigrateContractProposal:
|
||||
return handleMigrateProposal(ctx, k, *c)
|
||||
case *types.UpdateAdminProposal:
|
||||
return handleUpdateAdminProposal(ctx, k, *c)
|
||||
case *types.ClearAdminProposal:
|
||||
return handleClearAdminProposal(ctx, k, *c)
|
||||
case types.StoreCodeProposal:
|
||||
return handleStoreCodeProposal(ctx, k, c)
|
||||
case types.InstantiateContractProposal:
|
||||
return handleInstantiateProposal(ctx, k, c)
|
||||
case types.MigrateContractProposal:
|
||||
return handleMigrateProposal(ctx, k, c)
|
||||
case types.UpdateAdminProposal:
|
||||
return handleUpdateAdminProposal(ctx, k, c)
|
||||
case types.ClearAdminProposal:
|
||||
return handleClearAdminProposal(ctx, k, c)
|
||||
default:
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized wasm proposal content type: %T", c)
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ func handleStoreCodeProposal(ctx sdk.Context, k Keeper, p types.StoreCodeProposa
|
|||
return err
|
||||
}
|
||||
|
||||
codeID, err := k.Create(ctx, p.Creator, p.WASMByteCode, p.Source, p.Builder)
|
||||
codeID, err := k.create(ctx, p.Creator, p.WASMByteCode, p.Source, p.Builder, p.InstantiatePermission, GovAuthorizationPolicy{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/CosmWasm/wasmd/x/wasm/internal/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -36,7 +37,7 @@ func TestStoreCodeProposal(t *testing.T) {
|
|||
})
|
||||
|
||||
// when stored
|
||||
storedProposal, err := govKeeper.SubmitProposal(ctx, &src)
|
||||
storedProposal, err := govKeeper.SubmitProposal(ctx, src)
|
||||
require.NoError(t, err)
|
||||
|
||||
// and proposal execute
|
||||
|
@ -84,7 +85,7 @@ func TestInstantiateProposal(t *testing.T) {
|
|||
})
|
||||
|
||||
// when stored
|
||||
storedProposal, err := govKeeper.SubmitProposal(ctx, &src)
|
||||
storedProposal, err := govKeeper.SubmitProposal(ctx, src)
|
||||
require.NoError(t, err)
|
||||
|
||||
// and proposal execute
|
||||
|
@ -153,7 +154,7 @@ func TestMigrateProposal(t *testing.T) {
|
|||
}
|
||||
|
||||
// when stored
|
||||
storedProposal, err := govKeeper.SubmitProposal(ctx, &src)
|
||||
storedProposal, err := govKeeper.SubmitProposal(ctx, src)
|
||||
require.NoError(t, err)
|
||||
|
||||
// and proposal execute
|
||||
|
@ -187,7 +188,7 @@ func TestAdminProposals(t *testing.T) {
|
|||
}{
|
||||
"update with different admin": {
|
||||
state: types.ContractInfoFixture(),
|
||||
srcProposal: &types.UpdateAdminProposal{
|
||||
srcProposal: types.UpdateAdminProposal{
|
||||
WasmProposal: types.WasmProposal{
|
||||
Title: "Foo",
|
||||
Description: "Bar",
|
||||
|
@ -202,7 +203,7 @@ func TestAdminProposals(t *testing.T) {
|
|||
state: types.ContractInfoFixture(func(info *types.ContractInfo) {
|
||||
info.Admin = nil
|
||||
}),
|
||||
srcProposal: &types.UpdateAdminProposal{
|
||||
srcProposal: types.UpdateAdminProposal{
|
||||
WasmProposal: types.WasmProposal{
|
||||
Title: "Foo",
|
||||
Description: "Bar",
|
||||
|
@ -215,7 +216,7 @@ func TestAdminProposals(t *testing.T) {
|
|||
},
|
||||
"clear admin": {
|
||||
state: types.ContractInfoFixture(),
|
||||
srcProposal: &types.ClearAdminProposal{
|
||||
srcProposal: types.ClearAdminProposal{
|
||||
WasmProposal: types.WasmProposal{
|
||||
Title: "Foo",
|
||||
Description: "Bar",
|
||||
|
@ -229,7 +230,7 @@ func TestAdminProposals(t *testing.T) {
|
|||
state: types.ContractInfoFixture(func(info *types.ContractInfo) {
|
||||
info.Admin = nil
|
||||
}),
|
||||
srcProposal: &types.ClearAdminProposal{
|
||||
srcProposal: types.ClearAdminProposal{
|
||||
WasmProposal: types.WasmProposal{
|
||||
Title: "Foo",
|
||||
Description: "Bar",
|
||||
|
@ -268,3 +269,77 @@ func TestAdminProposals(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateParamsProposal(t *testing.T) {
|
||||
tempDir, err := ioutil.TempDir("", "wasm")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
ctx, keepers := CreateTestInput(t, false, tempDir, "staking", nil, nil)
|
||||
govKeeper, wasmKeeper := keepers.GovKeeper, keepers.WasmKeeper
|
||||
|
||||
var (
|
||||
cdc = keepers.WasmKeeper.cdc
|
||||
myAddress sdk.AccAddress = make([]byte, sdk.AddrLen)
|
||||
oneAddressAccessConfig = types.OnlyAddress.With(myAddress)
|
||||
)
|
||||
|
||||
specs := map[string]struct {
|
||||
src params.ParamChange
|
||||
expUploadConfig types.AccessConfig
|
||||
expInstantiateType types.AccessType
|
||||
}{
|
||||
"update upload permission param": {
|
||||
src: params.ParamChange{
|
||||
Subspace: types.DefaultParamspace,
|
||||
Key: string(types.ParamStoreKeyUploadAccess),
|
||||
Value: string(cdc.MustMarshalJSON(&types.AllowNobody)),
|
||||
},
|
||||
expUploadConfig: types.AllowNobody,
|
||||
expInstantiateType: types.Everybody,
|
||||
},
|
||||
"update upload permission param with address": {
|
||||
src: params.ParamChange{
|
||||
Subspace: types.DefaultParamspace,
|
||||
Key: string(types.ParamStoreKeyUploadAccess),
|
||||
Value: string(cdc.MustMarshalJSON(&oneAddressAccessConfig)),
|
||||
},
|
||||
expUploadConfig: oneAddressAccessConfig,
|
||||
expInstantiateType: types.Everybody,
|
||||
},
|
||||
"update instantiate param": {
|
||||
src: params.ParamChange{
|
||||
Subspace: types.DefaultParamspace,
|
||||
Key: string(types.ParamStoreKeyInstantiateAccess),
|
||||
Value: string(cdc.MustMarshalJSON(types.Nobody)),
|
||||
},
|
||||
expUploadConfig: types.AllowEverybody,
|
||||
expInstantiateType: types.Nobody,
|
||||
},
|
||||
}
|
||||
for msg, spec := range specs {
|
||||
t.Run(msg, func(t *testing.T) {
|
||||
wasmKeeper.setParams(ctx, types.DefaultParams())
|
||||
|
||||
proposal := params.ParameterChangeProposal{
|
||||
Title: "Foo",
|
||||
Description: "Bar",
|
||||
Changes: []params.ParamChange{spec.src},
|
||||
}
|
||||
|
||||
// when stored
|
||||
storedProposal, err := govKeeper.SubmitProposal(ctx, proposal)
|
||||
require.NoError(t, err)
|
||||
|
||||
// and proposal execute
|
||||
handler := govKeeper.Router().GetRoute(storedProposal.ProposalRoute())
|
||||
err = handler(ctx, storedProposal.Content)
|
||||
require.NoError(t, err)
|
||||
|
||||
// then
|
||||
assert.True(t, spec.expUploadConfig.Equals(wasmKeeper.getUploadAccessConfig(ctx)),
|
||||
"got %#v not %#v", wasmKeeper.getUploadAccessConfig(ctx), spec.expUploadConfig)
|
||||
assert.Equal(t, spec.expInstantiateType, wasmKeeper.getInstantiateAccessConfig(ctx))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ func TestQueryContractState(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
contractID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, bob := keyPubAddr()
|
||||
|
@ -159,7 +159,7 @@ func TestListContractByCodeOrdering(t *testing.T) {
|
|||
wasmCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
codeID, err := keeper.Create(ctx, creator, wasmCode, "", "")
|
||||
codeID, err := keeper.Create(ctx, creator, wasmCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, bob := keyPubAddr()
|
||||
|
|
|
@ -65,14 +65,14 @@ func TestMaskReflectContractSend(t *testing.T) {
|
|||
// upload mask code
|
||||
maskCode, err := ioutil.ReadFile("./testdata/reflect.wasm")
|
||||
require.NoError(t, err)
|
||||
maskID, err := keeper.Create(ctx, creator, maskCode, "", "")
|
||||
maskID, err := keeper.Create(ctx, creator, maskCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), maskID)
|
||||
|
||||
// upload hackatom escrow code
|
||||
escrowCode, err := ioutil.ReadFile("./testdata/contract.wasm")
|
||||
require.NoError(t, err)
|
||||
escrowID, err := keeper.Create(ctx, creator, escrowCode, "", "")
|
||||
escrowID, err := keeper.Create(ctx, creator, escrowCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(2), escrowID)
|
||||
|
||||
|
@ -150,7 +150,7 @@ func TestMaskReflectCustomMsg(t *testing.T) {
|
|||
// upload code
|
||||
maskCode, err := ioutil.ReadFile("./testdata/reflect.wasm")
|
||||
require.NoError(t, err)
|
||||
codeID, err := keeper.Create(ctx, creator, maskCode, "", "")
|
||||
codeID, err := keeper.Create(ctx, creator, maskCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), codeID)
|
||||
|
||||
|
@ -244,7 +244,7 @@ func TestMaskReflectCustomQuery(t *testing.T) {
|
|||
// upload code
|
||||
maskCode, err := ioutil.ReadFile("./testdata/reflect.wasm")
|
||||
require.NoError(t, err)
|
||||
codeID, err := keeper.Create(ctx, creator, maskCode, "", "")
|
||||
codeID, err := keeper.Create(ctx, creator, maskCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), codeID)
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ func TestInitializeStaking(t *testing.T) {
|
|||
// upload staking derivates code
|
||||
stakingCode, err := ioutil.ReadFile("./testdata/staking.wasm")
|
||||
require.NoError(t, err)
|
||||
stakingID, err := keeper.Create(ctx, creator, stakingCode, "", "")
|
||||
stakingID, err := keeper.Create(ctx, creator, stakingCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), stakingID)
|
||||
|
||||
|
@ -187,7 +187,7 @@ func initializeStaking(t *testing.T) initInfo {
|
|||
// upload staking derivates code
|
||||
stakingCode, err := ioutil.ReadFile("./testdata/staking.wasm")
|
||||
require.NoError(t, err)
|
||||
stakingID, err := keeper.Create(ctx, creator, stakingCode, "", "")
|
||||
stakingID, err := keeper.Create(ctx, creator, stakingCode, "", "", nil)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1), stakingID)
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
"github.com/cosmos/cosmos-sdk/x/supply"
|
||||
|
||||
wasmTypes "github.com/CosmWasm/wasmd/x/wasm/internal/types"
|
||||
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/internal/types"
|
||||
)
|
||||
|
||||
const flagLRUCacheSize = "lru_size"
|
||||
|
@ -43,10 +43,10 @@ func MakeTestCodec() *codec.Codec {
|
|||
staking.AppModuleBasic{}.RegisterCodec(cdc)
|
||||
distribution.AppModuleBasic{}.RegisterCodec(cdc)
|
||||
gov.RegisterCodec(cdc)
|
||||
wasmTypes.RegisterCodec(cdc)
|
||||
wasmtypes.RegisterCodec(cdc)
|
||||
sdk.RegisterCodec(cdc)
|
||||
codec.RegisterCrypto(cdc)
|
||||
|
||||
params.RegisterCodec(cdc)
|
||||
return cdc
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ type TestKeepers struct {
|
|||
|
||||
// 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, tempDir string, supportedFeatures string, encoders *MessageEncoders, queriers *QueryPlugins) (sdk.Context, TestKeepers) {
|
||||
keyContract := sdk.NewKVStoreKey(wasmTypes.StoreKey)
|
||||
keyContract := sdk.NewKVStoreKey(wasmtypes.StoreKey)
|
||||
keyAcc := sdk.NewKVStoreKey(auth.StoreKey)
|
||||
keyStaking := sdk.NewKVStoreKey(staking.StoreKey)
|
||||
keySupply := sdk.NewKVStoreKey(supply.StoreKey)
|
||||
|
@ -98,18 +98,18 @@ func CreateTestInput(t *testing.T, isCheckTx bool, tempDir string, supportedFeat
|
|||
}, isCheckTx, log.NewNopLogger())
|
||||
cdc := MakeTestCodec()
|
||||
|
||||
pk := params.NewKeeper(cdc, keyParams, tkeyParams)
|
||||
paramsKeeper := params.NewKeeper(cdc, keyParams, tkeyParams)
|
||||
|
||||
accountKeeper := auth.NewAccountKeeper(
|
||||
cdc, // amino codec
|
||||
keyAcc, // target store
|
||||
pk.Subspace(auth.DefaultParamspace),
|
||||
paramsKeeper.Subspace(auth.DefaultParamspace),
|
||||
auth.ProtoBaseAccount, // prototype
|
||||
)
|
||||
|
||||
bankKeeper := bank.NewBaseKeeper(
|
||||
accountKeeper,
|
||||
pk.Subspace(bank.DefaultParamspace),
|
||||
paramsKeeper.Subspace(bank.DefaultParamspace),
|
||||
nil,
|
||||
)
|
||||
bankKeeper.SetSendEnabled(ctx, true)
|
||||
|
@ -125,10 +125,10 @@ func CreateTestInput(t *testing.T, isCheckTx bool, tempDir string, supportedFeat
|
|||
}
|
||||
|
||||
supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, maccPerms)
|
||||
stakingKeeper := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace))
|
||||
stakingKeeper := staking.NewKeeper(cdc, keyStaking, supplyKeeper, paramsKeeper.Subspace(staking.DefaultParamspace))
|
||||
stakingKeeper.SetParams(ctx, TestingStakeParams)
|
||||
|
||||
distKeeper := distribution.NewKeeper(cdc, keyDistro, pk.Subspace(distribution.DefaultParamspace), stakingKeeper, supplyKeeper, auth.FeeCollectorName, nil)
|
||||
distKeeper := distribution.NewKeeper(cdc, keyDistro, paramsKeeper.Subspace(distribution.DefaultParamspace), stakingKeeper, supplyKeeper, auth.FeeCollectorName, nil)
|
||||
distKeeper.SetParams(ctx, distribution.DefaultParams())
|
||||
stakingKeeper.SetHooks(distKeeper.Hooks())
|
||||
|
||||
|
@ -166,18 +166,22 @@ func CreateTestInput(t *testing.T, isCheckTx bool, tempDir string, supportedFeat
|
|||
router.AddRoute(distribution.RouterKey, dh)
|
||||
|
||||
// Load default wasm config
|
||||
wasmConfig := wasmTypes.DefaultWasmConfig()
|
||||
|
||||
keeper := NewKeeper(cdc, keyContract, accountKeeper, bankKeeper, stakingKeeper, router, tempDir, wasmConfig, supportedFeatures, encoders, queriers)
|
||||
wasmConfig := wasmtypes.DefaultWasmConfig()
|
||||
keeper := NewKeeper(cdc, keyContract, paramsKeeper.Subspace(wasmtypes.DefaultParamspace),
|
||||
accountKeeper, bankKeeper, stakingKeeper, router, tempDir, wasmConfig,
|
||||
supportedFeatures, encoders, queriers,
|
||||
)
|
||||
keeper.setParams(ctx, wasmtypes.DefaultParams())
|
||||
// add wasm handler so we can loop-back (contracts calling contracts)
|
||||
router.AddRoute(wasmTypes.RouterKey, TestHandler(keeper))
|
||||
router.AddRoute(wasmtypes.RouterKey, TestHandler(keeper))
|
||||
|
||||
govRouter := gov.NewRouter().
|
||||
AddRoute(params.RouterKey, params.NewParamChangeProposalHandler(paramsKeeper)).
|
||||
AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
|
||||
AddRoute(wasmTypes.RouterKey, NewWasmProposalHandler(keeper, wasmTypes.DefaultEnabledProposals))
|
||||
AddRoute(wasmtypes.RouterKey, NewWasmProposalHandler(keeper, wasmtypes.DefaultEnabledProposals))
|
||||
|
||||
govKeeper := gov.NewKeeper(
|
||||
cdc, keyGov, pk.Subspace(govtypes.DefaultParamspace).WithKeyTable(gov.ParamKeyTable()), supplyKeeper, stakingKeeper, govRouter,
|
||||
cdc, keyGov, paramsKeeper.Subspace(govtypes.DefaultParamspace).WithKeyTable(gov.ParamKeyTable()), supplyKeeper, stakingKeeper, govRouter,
|
||||
)
|
||||
|
||||
govKeeper.SetProposalID(ctx, govtypes.DefaultStartingProposalID)
|
||||
|
@ -203,14 +207,14 @@ func TestHandler(k Keeper) sdk.Handler {
|
|||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case wasmTypes.MsgInstantiateContract:
|
||||
case wasmtypes.MsgInstantiateContract:
|
||||
return handleInstantiate(ctx, k, &msg)
|
||||
case *wasmTypes.MsgInstantiateContract:
|
||||
case *wasmtypes.MsgInstantiateContract:
|
||||
return handleInstantiate(ctx, k, msg)
|
||||
|
||||
case wasmTypes.MsgExecuteContract:
|
||||
case wasmtypes.MsgExecuteContract:
|
||||
return handleExecute(ctx, k, &msg)
|
||||
case *wasmTypes.MsgExecuteContract:
|
||||
case *wasmtypes.MsgExecuteContract:
|
||||
return handleExecute(ctx, k, msg)
|
||||
|
||||
default:
|
||||
|
@ -220,7 +224,7 @@ func TestHandler(k Keeper) sdk.Handler {
|
|||
}
|
||||
}
|
||||
|
||||
func handleInstantiate(ctx sdk.Context, k Keeper, msg *wasmTypes.MsgInstantiateContract) (*sdk.Result, error) {
|
||||
func handleInstantiate(ctx sdk.Context, k Keeper, msg *wasmtypes.MsgInstantiateContract) (*sdk.Result, error) {
|
||||
contractAddr, err := k.Instantiate(ctx, msg.Code, msg.Sender, msg.Admin, msg.InitMsg, msg.Label, msg.InitFunds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -232,7 +236,7 @@ func handleInstantiate(ctx sdk.Context, k Keeper, msg *wasmTypes.MsgInstantiateC
|
|||
}, nil
|
||||
}
|
||||
|
||||
func handleExecute(ctx sdk.Context, k Keeper, msg *wasmTypes.MsgExecuteContract) (*sdk.Result, error) {
|
||||
func handleExecute(ctx sdk.Context, k Keeper, msg *wasmtypes.MsgExecuteContract) (*sdk.Result, error) {
|
||||
res, err := k.Execute(ctx, msg.Contract, msg.Sender, msg.Msg, msg.SentFunds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -11,6 +11,7 @@ func FuzzAddr(m *sdk.AccAddress, c fuzz.Continue) {
|
|||
*m = make([]byte, 20)
|
||||
c.Read(*m)
|
||||
}
|
||||
|
||||
func FuzzAbsoluteTxPosition(m *types.AbsoluteTxPosition, c fuzz.Continue) {
|
||||
m.BlockHeight = int64(c.RandUint64()) // can't be negative
|
||||
m.TxIndex = c.RandUint64()
|
||||
|
@ -28,7 +29,18 @@ func FuzzContractInfo(m *types.ContractInfo, c fuzz.Continue) {
|
|||
c.Fuzz(&m.LastUpdated)
|
||||
m.PreviousCodeID = c.RandUint64()
|
||||
}
|
||||
|
||||
func FuzzStateModel(m *types.Model, c fuzz.Continue) {
|
||||
m.Key = tmBytes.HexBytes(c.RandString())
|
||||
c.Fuzz(&m.Value)
|
||||
}
|
||||
|
||||
func FuzzAccessType(m *types.AccessType, c fuzz.Continue) {
|
||||
*m = types.AllAccessTypes[c.Int()%len(types.AllAccessTypes)]
|
||||
}
|
||||
func FuzzAccessConfig(m *types.AccessConfig, c fuzz.Continue) {
|
||||
FuzzAccessType(&m.Type, c)
|
||||
var add sdk.AccAddress
|
||||
FuzzAddr(&add, c)
|
||||
*m = m.Type.With(add)
|
||||
}
|
||||
|
|
|
@ -20,12 +20,16 @@ func (s Sequence) ValidateBasic() error {
|
|||
|
||||
// GenesisState is the struct representation of the export genesis
|
||||
type GenesisState struct {
|
||||
Params Params `json:"params"`
|
||||
Codes []Code `json:"codes"`
|
||||
Contracts []Contract `json:"contracts"`
|
||||
Sequences []Sequence `json:"sequences"`
|
||||
}
|
||||
|
||||
func (s GenesisState) ValidateBasic() error {
|
||||
if err := s.Params.ValidateBasic(); err != nil {
|
||||
return sdkerrors.Wrap(err, "params")
|
||||
}
|
||||
for i := range s.Codes {
|
||||
if err := s.Codes[i].ValidateBasic(); err != nil {
|
||||
return sdkerrors.Wrapf(err, "code: %d", i)
|
||||
|
|
|
@ -15,6 +15,12 @@ func TestValidateGenesisState(t *testing.T) {
|
|||
"all good": {
|
||||
srcMutator: func(s *GenesisState) {},
|
||||
},
|
||||
"params invalid": {
|
||||
srcMutator: func(s *GenesisState) {
|
||||
s.Params = Params{}
|
||||
},
|
||||
expError: true,
|
||||
},
|
||||
"codeinfo invalid": {
|
||||
srcMutator: func(s *GenesisState) {
|
||||
s.Codes[0].CodeInfo.CodeHash = nil
|
||||
|
|
|
@ -15,6 +15,8 @@ type MsgStoreCode struct {
|
|||
Source string `json:"source" yaml:"source"`
|
||||
// Builder is a valid docker image name with tag, optional
|
||||
Builder string `json:"builder" yaml:"builder"`
|
||||
// InstantiatePermission to apply on contract creation, optional
|
||||
InstantiatePermission *AccessConfig `json:"instantiate_permission" yaml:"instantiate_permission"`
|
||||
}
|
||||
|
||||
func (msg MsgStoreCode) Route() string {
|
||||
|
@ -41,6 +43,11 @@ func (msg MsgStoreCode) ValidateBasic() error {
|
|||
if err := validateBuilder(msg.Builder); err != nil {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "builder %s", err.Error())
|
||||
}
|
||||
if msg.InstantiatePermission != nil {
|
||||
if err := msg.InstantiatePermission.ValidateBasic(); err != nil {
|
||||
return sdkerrors.Wrap(err, "instantiate permission")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,14 @@ func TestStoreCodeValidation(t *testing.T) {
|
|||
},
|
||||
valid: false,
|
||||
},
|
||||
"invalid InstantiatePermission": {
|
||||
msg: MsgStoreCode{
|
||||
Sender: goodAddress,
|
||||
WASMByteCode: []byte("foo"),
|
||||
InstantiatePermission: &AccessConfig{Type: OnlyAddress, Address: badAddress},
|
||||
},
|
||||
valid: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
|
@ -119,7 +127,6 @@ func TestStoreCodeValidation(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestInstantiateContractValidation(t *testing.T) {
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -25,6 +27,8 @@ const (
|
|||
Everybody AccessType = 3
|
||||
)
|
||||
|
||||
var AllAccessTypes = []AccessType{Nobody, OnlyAddress, Everybody}
|
||||
|
||||
func (a AccessType) With(addr sdk.AccAddress) AccessConfig {
|
||||
switch a {
|
||||
case Nobody:
|
||||
|
@ -41,8 +45,12 @@ func (a AccessType) With(addr sdk.AccAddress) AccessConfig {
|
|||
}
|
||||
|
||||
type AccessConfig struct {
|
||||
Type AccessType `json:"type"`
|
||||
Address sdk.AccAddress `json:"address"`
|
||||
Type AccessType `json:"type" yaml:"type"`
|
||||
Address sdk.AccAddress `json:"address" yaml:"address"`
|
||||
}
|
||||
|
||||
func (a AccessConfig) Equals(o AccessConfig) bool {
|
||||
return a.Type == o.Type && a.Address.Equals(o.Address)
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -51,12 +59,47 @@ var (
|
|||
AllowNobody = AccessConfig{Type: Nobody}
|
||||
)
|
||||
|
||||
// ParamKeyTable type declaration for parameters
|
||||
// Params defines the set of wasm parameters.
|
||||
type Params struct {
|
||||
UploadAccess AccessConfig `json:"upload_access" yaml:"upload_access"`
|
||||
InstantiateDefaultPermission AccessType `json:"instantiate_default_permission" yaml:"instantiate_default_permission"`
|
||||
}
|
||||
|
||||
// ParamKeyTable returns the parameter key table.
|
||||
func ParamKeyTable() params.KeyTable {
|
||||
return params.NewKeyTable(
|
||||
params.NewParamSetPair(ParamStoreKeyUploadAccess, AllowEverybody, validateAccessConfig),
|
||||
params.NewParamSetPair(ParamStoreKeyInstantiateAccess, Everybody, validateAccessType),
|
||||
)
|
||||
return params.NewKeyTable().RegisterParamSet(&Params{})
|
||||
}
|
||||
|
||||
// DefaultParams returns default wasm parameters
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
UploadAccess: AllowEverybody,
|
||||
InstantiateDefaultPermission: Everybody,
|
||||
}
|
||||
}
|
||||
|
||||
func (p Params) String() string {
|
||||
out, _ := yaml.Marshal(p)
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// ParamSetPairs returns the parameter set pairs.
|
||||
func (p *Params) ParamSetPairs() params.ParamSetPairs {
|
||||
return params.ParamSetPairs{
|
||||
params.NewParamSetPair(ParamStoreKeyUploadAccess, &p.UploadAccess, validateAccessConfig),
|
||||
params.NewParamSetPair(ParamStoreKeyInstantiateAccess, &p.InstantiateDefaultPermission, validateAccessType),
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateBasic performs basic validation on wasm parameters
|
||||
func (p Params) ValidateBasic() error {
|
||||
if err := validateAccessType(p.InstantiateDefaultPermission); err != nil {
|
||||
return errors.Wrap(err, "instantiate default permission")
|
||||
}
|
||||
if err := validateAccessConfig(p.UploadAccess); err != nil {
|
||||
return errors.Wrap(err, "upload access")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAccessConfig(i interface{}) error {
|
||||
|
@ -75,8 +118,12 @@ func validateAccessType(i interface{}) error {
|
|||
if v == Undefined {
|
||||
return sdkerrors.Wrap(ErrEmpty, "type")
|
||||
}
|
||||
// TODO: should we prevent Nobody here?
|
||||
return nil
|
||||
for i := range AllAccessTypes {
|
||||
if AllAccessTypes[i] == v {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return sdkerrors.Wrapf(ErrInvalid, "unknown type: %d", v)
|
||||
}
|
||||
|
||||
func (v AccessConfig) ValidateBasic() error {
|
||||
|
@ -87,10 +134,11 @@ func (v AccessConfig) ValidateBasic() error {
|
|||
if len(v.Address) != 0 {
|
||||
return sdkerrors.Wrap(ErrInvalid, "address not allowed for this type")
|
||||
}
|
||||
return nil
|
||||
case OnlyAddress:
|
||||
return sdk.VerifyAddressFormat(v.Address)
|
||||
}
|
||||
return sdkerrors.Wrap(ErrInvalid, "unknown type")
|
||||
return sdkerrors.Wrapf(ErrInvalid, "unknown type: %d", v.Type)
|
||||
}
|
||||
|
||||
func (v AccessConfig) Allowed(actor sdk.AccAddress) bool {
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestValidateParams(t *testing.T) {
|
||||
var (
|
||||
anyAddress = make([]byte, sdk.AddrLen)
|
||||
invalidAddress = make([]byte, sdk.AddrLen-1)
|
||||
)
|
||||
|
||||
specs := map[string]struct {
|
||||
src Params
|
||||
expErr bool
|
||||
}{
|
||||
"all good with defaults": {
|
||||
src: DefaultParams(),
|
||||
},
|
||||
"all good with nobody": {
|
||||
src: Params{
|
||||
UploadAccess: AllowNobody,
|
||||
InstantiateDefaultPermission: Nobody,
|
||||
},
|
||||
},
|
||||
"all good with everybody": {
|
||||
src: Params{
|
||||
UploadAccess: AllowEverybody,
|
||||
InstantiateDefaultPermission: Everybody,
|
||||
},
|
||||
},
|
||||
"all good with only address": {
|
||||
src: Params{
|
||||
UploadAccess: OnlyAddress.With(anyAddress),
|
||||
InstantiateDefaultPermission: OnlyAddress,
|
||||
},
|
||||
},
|
||||
"reject empty type in instantiate permission": {
|
||||
src: Params{
|
||||
UploadAccess: AllowNobody,
|
||||
InstantiateDefaultPermission: 0,
|
||||
},
|
||||
expErr: true,
|
||||
},
|
||||
"reject unknown type in instantiate": {
|
||||
src: Params{
|
||||
UploadAccess: AllowNobody,
|
||||
InstantiateDefaultPermission: 4,
|
||||
},
|
||||
expErr: true,
|
||||
},
|
||||
"reject invalid address in only address": {
|
||||
src: Params{
|
||||
UploadAccess: AccessConfig{Type: OnlyAddress, Address: invalidAddress},
|
||||
InstantiateDefaultPermission: OnlyAddress,
|
||||
},
|
||||
expErr: true,
|
||||
},
|
||||
"reject AccessConfig Everybody with obsolete address": {
|
||||
src: Params{
|
||||
UploadAccess: AccessConfig{Type: Everybody, Address: anyAddress},
|
||||
InstantiateDefaultPermission: OnlyAddress,
|
||||
},
|
||||
expErr: true,
|
||||
},
|
||||
"reject AccessConfig Nobody with obsolete address": {
|
||||
src: Params{
|
||||
UploadAccess: AccessConfig{Type: Nobody, Address: anyAddress},
|
||||
InstantiateDefaultPermission: OnlyAddress,
|
||||
},
|
||||
expErr: true,
|
||||
},
|
||||
}
|
||||
for msg, spec := range specs {
|
||||
t.Run(msg, func(t *testing.T) {
|
||||
err := spec.src.ValidateBasic()
|
||||
if spec.expErr {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
|
@ -73,6 +73,8 @@ type StoreCodeProposal struct {
|
|||
Source string `json:"source" yaml:"source"`
|
||||
// Builder is a valid docker image name with tag, optional
|
||||
Builder string `json:"builder" yaml:"builder"`
|
||||
// InstantiatePermission to apply on contract creation, optional
|
||||
InstantiatePermission *AccessConfig `json:"instantiate_permission" yaml:"instantiate_permission"`
|
||||
}
|
||||
|
||||
// ProposalType returns the type
|
||||
|
@ -98,7 +100,11 @@ func (p StoreCodeProposal) ValidateBasic() error {
|
|||
if err := validateBuilder(p.Builder); err != nil {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "builder %s", err.Error())
|
||||
}
|
||||
|
||||
if p.InstantiatePermission != nil {
|
||||
if err := p.InstantiatePermission.ValidateBasic(); err != nil {
|
||||
return sdkerrors.Wrap(err, "instantiate permission")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ func TestValidateWasmProposal(t *testing.T) {
|
|||
|
||||
func TestValidateStoreCodeProposal(t *testing.T) {
|
||||
var (
|
||||
anyAddress sdk.AccAddress = bytes.Repeat([]byte{0x0}, sdk.AddrLen)
|
||||
invalidAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, sdk.AddrLen-1)
|
||||
)
|
||||
|
||||
|
@ -100,6 +101,13 @@ func TestValidateStoreCodeProposal(t *testing.T) {
|
|||
"all good": {
|
||||
src: StoreCodeProposalFixture(),
|
||||
},
|
||||
"with instantiate permission": {
|
||||
src: StoreCodeProposalFixture(func(p *StoreCodeProposal) {
|
||||
accessConfig := OnlyAddress.With(anyAddress)
|
||||
p.InstantiatePermission = &accessConfig
|
||||
}),
|
||||
},
|
||||
|
||||
"without source": {
|
||||
src: StoreCodeProposalFixture(func(p *StoreCodeProposal) {
|
||||
p.Source = ""
|
||||
|
@ -147,6 +155,12 @@ func TestValidateStoreCodeProposal(t *testing.T) {
|
|||
}),
|
||||
expErr: true,
|
||||
},
|
||||
"with invalid instantiate permission": {
|
||||
src: StoreCodeProposalFixture(func(p *StoreCodeProposal) {
|
||||
p.InstantiatePermission = &AccessConfig{}
|
||||
}),
|
||||
expErr: true,
|
||||
},
|
||||
}
|
||||
for msg, spec := range specs {
|
||||
t.Run(msg, func(t *testing.T) {
|
||||
|
|
|
@ -17,6 +17,7 @@ func GenesisFixture(mutators ...func(*GenesisState)) GenesisState {
|
|||
)
|
||||
|
||||
fixture := GenesisState{
|
||||
Params: DefaultParams(),
|
||||
Codes: make([]Code, numCodes),
|
||||
Contracts: make([]Contract, numContracts),
|
||||
Sequences: make([]Sequence, numSequences),
|
||||
|
|
|
@ -30,10 +30,11 @@ func (m Model) ValidateBasic() error {
|
|||
|
||||
// CodeInfo is data for the uploaded contract WASM code
|
||||
type CodeInfo struct {
|
||||
CodeHash []byte `json:"code_hash"`
|
||||
Creator sdk.AccAddress `json:"creator"`
|
||||
Source string `json:"source"`
|
||||
Builder string `json:"builder"`
|
||||
CodeHash []byte `json:"code_hash"`
|
||||
Creator sdk.AccAddress `json:"creator"`
|
||||
Source string `json:"source"`
|
||||
Builder string `json:"builder"`
|
||||
InstantiateConfig AccessConfig `json:"instantiate_config"`
|
||||
}
|
||||
|
||||
func (c CodeInfo) ValidateBasic() error {
|
||||
|
@ -53,12 +54,13 @@ func (c CodeInfo) ValidateBasic() error {
|
|||
}
|
||||
|
||||
// NewCodeInfo fills a new Contract struct
|
||||
func NewCodeInfo(codeHash []byte, creator sdk.AccAddress, source string, builder string) CodeInfo {
|
||||
func NewCodeInfo(codeHash []byte, creator sdk.AccAddress, source string, builder string, instantiatePermission AccessConfig) CodeInfo {
|
||||
return CodeInfo{
|
||||
CodeHash: codeHash,
|
||||
Creator: creator,
|
||||
Source: source,
|
||||
Builder: builder,
|
||||
CodeHash: codeHash,
|
||||
Creator: creator,
|
||||
Source: source,
|
||||
Builder: builder,
|
||||
InstantiateConfig: instantiatePermission,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,9 @@ func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
|
|||
// DefaultGenesis returns default genesis state as raw bytes for the wasm
|
||||
// module.
|
||||
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
|
||||
return ModuleCdc.MustMarshalJSON(&GenesisState{})
|
||||
return ModuleCdc.MustMarshalJSON(&GenesisState{
|
||||
Params: DefaultParams(),
|
||||
})
|
||||
}
|
||||
|
||||
// ValidateGenesis performs genesis state validation for the wasm module.
|
||||
|
|
Loading…
Reference in New Issue