Skip to content

Commit

Permalink
Merge pull request #471 from CosmWasm/extendable_keeper
Browse files Browse the repository at this point in the history
Introduce new interfaces for extendability
  • Loading branch information
ethanfrey authored Mar 29, 2021
2 parents 2abf3f5 + 48df71f commit d9ca5d8
Show file tree
Hide file tree
Showing 32 changed files with 492 additions and 348 deletions.
2 changes: 1 addition & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b
if len(enabledProposals) != 0 {
govRouter.AddRoute(wasm.RouterKey, wasm.NewWasmProposalHandler(app.wasmKeeper, enabledProposals))
}
ibcRouter.AddRoute(wasm.ModuleName, wasm.NewIBCHandler(app.wasmKeeper))
ibcRouter.AddRoute(wasm.ModuleName, wasm.NewIBCHandler(app.wasmKeeper, app.ibcKeeper.ChannelKeeper))
app.ibcKeeper.SetRouter(ibcRouter)

app.govKeeper = govkeeper.NewKeeper(
Expand Down
6 changes: 3 additions & 3 deletions x/wasm/alias.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// nolint
// autogenerated code using github.com/rigelrozanski/multitool
// aliases generated for the following subdirectories:
// ALIASGEN: github.com/cosmwasm/wasmd/x/wasm/types
// ALIASGEN: github.com/cosmwasm/wasmd/x/wasm/keeper
// ALIASGEN: github.com/Cosmwasm/wasmd/x/wasm/types
// ALIASGEN: github.com/CosmWasm/wasmd/x/wasm/keeper
package wasm

import (
Expand Down Expand Up @@ -76,7 +76,7 @@ var (
CreateTestInput = keeper.CreateTestInput
TestHandler = keeper.TestHandler
NewWasmProposalHandler = keeper.NewWasmProposalHandler
NewQuerier = keeper.NewQuerier
NewQuerier = keeper.Querier
ContractFromPortID = keeper.ContractFromPortID
WithWasmEngine = keeper.WithWasmEngine

Expand Down
4 changes: 2 additions & 2 deletions x/wasm/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

// NewHandler returns a handler for "bank" type messages.
func NewHandler(k *Keeper) sdk.Handler {
// NewHandler returns a handler for "wasm" type messages.
func NewHandler(k types.ContractOpsKeeper) sdk.Handler {
msgServer := keeper.NewMsgServerImpl(k)

return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
Expand Down
12 changes: 6 additions & 6 deletions x/wasm/ibc.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package wasm

import (
wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types"
types "github.com/CosmWasm/wasmd/x/wasm/types"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand All @@ -15,12 +15,12 @@ import (
var _ porttypes.IBCModule = IBCHandler{}

type IBCHandler struct {
keeper Keeper
channelKeeper wasmTypes.ChannelKeeper
keeper types.IBCContractKeeper
channelKeeper types.ChannelKeeper
}

func NewIBCHandler(keeper Keeper) IBCHandler {
return IBCHandler{keeper: keeper, channelKeeper: keeper.ChannelKeeper}
func NewIBCHandler(k types.IBCContractKeeper, ck types.ChannelKeeper) IBCHandler {
return IBCHandler{keeper: k, channelKeeper: ck}
}

// OnChanOpenInit implements the IBCModule interface
Expand Down Expand Up @@ -265,7 +265,7 @@ func ValidateChannelParams(channelID string) error {
return err
}
if channelSequence > math.MaxUint32 {
return sdkerrors.Wrapf(wasmTypes.ErrMaxIBCChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, math.MaxUint32)
return sdkerrors.Wrapf(types.ErrMaxIBCChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, math.MaxUint32)
}
return nil
}
2 changes: 1 addition & 1 deletion x/wasm/keeper/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func BenchmarkExecution(b *testing.B) {
ctx, keepers := createTestInput(b, false, SupportedFeatures, wasmConfig, spec.db())
example := InstantiateHackatomExampleContract(b, ctx, keepers)
if spec.pinned {
require.NoError(b, keepers.WasmKeeper.PinCode(ctx, example.CodeID))
require.NoError(b, keepers.ContractKeeper.PinCode(ctx, example.CodeID))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
Expand Down
68 changes: 68 additions & 0 deletions x/wasm/keeper/contract_keeper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package keeper

import (
"github.com/CosmWasm/wasmd/x/wasm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

var _ types.ContractOpsKeeper = PermissionedKeeper{}

// decoratedKeeper contains a subset of the wasm keeper that are already or can be guarded by an authorization policy in the future
type decoratedKeeper 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
execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) (*sdk.Result, error)
}

type PermissionedKeeper struct {
authZPolicy AuthorizationPolicy
nested decoratedKeeper
}

func NewPermissionedKeeper(nested decoratedKeeper, authZPolicy AuthorizationPolicy) *PermissionedKeeper {
return &PermissionedKeeper{authZPolicy: authZPolicy, nested: nested}
}

func NewGovPermissionKeeper(nested decoratedKeeper) *PermissionedKeeper {
return NewPermissionedKeeper(nested, GovAuthorizationPolicy{})
}

func NewDefaultPermissionKeeper(nested decoratedKeeper) *PermissionedKeeper {
return NewPermissionedKeeper(nested, DefaultAuthorizationPolicy{})
}

func (p PermissionedKeeper) Create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, source string, builder string, instantiateAccess *types.AccessConfig) (codeID uint64, err error) {
return p.nested.create(ctx, creator, wasmCode, source, builder, instantiateAccess, p.authZPolicy)
}

func (p PermissionedKeeper) Instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.AccAddress, initMsg []byte, label string, deposit sdk.Coins) (sdk.AccAddress, []byte, error) {
return p.nested.instantiate(ctx, codeID, creator, admin, initMsg, label, deposit, p.authZPolicy)
}

func (p PermissionedKeeper) Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) (*sdk.Result, error) {
return p.nested.execute(ctx, contractAddress, caller, msg, coins)
}

func (p PermissionedKeeper) Migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newCodeID uint64, msg []byte) (*sdk.Result, error) {
return p.nested.migrate(ctx, contractAddress, caller, newCodeID, msg, p.authZPolicy)
}

func (p PermissionedKeeper) UpdateContractAdmin(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newAdmin sdk.AccAddress) error {
return p.nested.setContractAdmin(ctx, contractAddress, caller, newAdmin, p.authZPolicy)
}

func (p PermissionedKeeper) ClearContractAdmin(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress) error {
return p.nested.setContractAdmin(ctx, contractAddress, caller, nil, p.authZPolicy)
}

func (p PermissionedKeeper) PinCode(ctx sdk.Context, codeID uint64) error {
return p.nested.pinCode(ctx, codeID)
}

func (p PermissionedKeeper) UnpinCode(ctx sdk.Context, codeID uint64) error {
return p.nested.unpinCode(ctx, codeID)
}
4 changes: 2 additions & 2 deletions x/wasm/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ type ValidatorSetSource interface {
//
// CONTRACT: all types of accounts must have been already initialized/created
func InitGenesis(ctx sdk.Context, keeper *Keeper, data types.GenesisState, stakingKeeper ValidatorSetSource, msgHandler sdk.Handler) ([]abci.ValidatorUpdate, error) {
contractKeeper := NewGovPermissionKeeper(keeper)
keeper.setParams(ctx, data.Params)

var maxCodeID uint64
for i, code := range data.Codes {
err := keeper.importCode(ctx, code.CodeID, code.CodeInfo, code.CodeBytes)
Expand All @@ -28,7 +28,7 @@ func InitGenesis(ctx sdk.Context, keeper *Keeper, data types.GenesisState, staki
maxCodeID = code.CodeID
}
if code.Pinned {
if err := keeper.PinCode(ctx, code.CodeID); err != nil {
if err := contractKeeper.PinCode(ctx, code.CodeID); err != nil {
return nil, sdkerrors.Wrapf(err, "contract number %d", i)
}
}
Expand Down
34 changes: 18 additions & 16 deletions x/wasm/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,16 @@ import (
const firstCodeID = 1

func TestGenesisExportImport(t *testing.T) {
srcKeeper, srcCtx, srcStoreKeys := setupKeeper(t)
wasmKeeper, srcCtx, srcStoreKeys := setupKeeper(t)
contractKeeper := NewGovPermissionKeeper(wasmKeeper)

wasmCode, err := ioutil.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)

// store some test data
f := fuzz.New().Funcs(ModelFuzzers...)

srcKeeper.setParams(srcCtx, types.DefaultParams())
wasmKeeper.setParams(srcCtx, types.DefaultParams())

for i := 0; i < 25; i++ {
var (
Expand All @@ -60,24 +61,24 @@ func TestGenesisExportImport(t *testing.T) {
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)
codeID, err := contractKeeper.Create(srcCtx, creatorAddr, wasmCode, codeInfo.Source, codeInfo.Builder, &codeInfo.InstantiateConfig)
require.NoError(t, err)
if pinned {
srcKeeper.PinCode(srcCtx, codeID)
contractKeeper.PinCode(srcCtx, codeID)
}

contract.CodeID = codeID
contractAddr := srcKeeper.generateContractAddress(srcCtx, codeID)
srcKeeper.storeContractInfo(srcCtx, contractAddr, &contract)
srcKeeper.appendToContractHistory(srcCtx, contractAddr, history...)
srcKeeper.importContractState(srcCtx, contractAddr, stateModels)
contractAddr := wasmKeeper.generateContractAddress(srcCtx, codeID)
wasmKeeper.storeContractInfo(srcCtx, contractAddr, &contract)
wasmKeeper.appendToContractHistory(srcCtx, contractAddr, history...)
wasmKeeper.importContractState(srcCtx, contractAddr, stateModels)
}
var wasmParams types.Params
f.NilChance(0).Fuzz(&wasmParams)
srcKeeper.setParams(srcCtx, wasmParams)
wasmKeeper.setParams(srcCtx, wasmParams)

// export
exportedState := ExportGenesis(srcCtx, srcKeeper)
exportedState := ExportGenesis(srcCtx, wasmKeeper)
// order should not matter
rand.Shuffle(len(exportedState.Codes), func(i, j int) {
exportedState.Codes[i], exportedState.Codes[j] = exportedState.Codes[j], exportedState.Codes[i]
Expand All @@ -92,10 +93,10 @@ func TestGenesisExportImport(t *testing.T) {
require.NoError(t, err)

// reset ContractInfo in source DB for comparison with dest DB
srcKeeper.IterateContractInfo(srcCtx, func(address sdk.AccAddress, info wasmTypes.ContractInfo) bool {
srcKeeper.deleteContractSecondIndex(srcCtx, address, &info)
wasmKeeper.IterateContractInfo(srcCtx, func(address sdk.AccAddress, info wasmTypes.ContractInfo) bool {
wasmKeeper.deleteContractSecondIndex(srcCtx, address, &info)
info.ResetFromGenesis(srcCtx)
srcKeeper.storeContractInfo(srcCtx, address, &info)
wasmKeeper.storeContractInfo(srcCtx, address, &info)
return false
})

Expand All @@ -105,7 +106,7 @@ func TestGenesisExportImport(t *testing.T) {
var importState wasmTypes.GenesisState
err = json.Unmarshal(exportedGenesis, &importState)
require.NoError(t, err)
InitGenesis(dstCtx, dstKeeper, importState, &StakingKeeperMock{}, TestHandler(dstKeeper))
InitGenesis(dstCtx, dstKeeper, importState, &StakingKeeperMock{}, TestHandler(contractKeeper))

// compare whole DB
for j := range srcStoreKeys {
Expand Down Expand Up @@ -479,6 +480,7 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) {
]
}`
keeper, ctx, _ := setupKeeper(t)
contractKeeper := NewGovPermissionKeeper(keeper)

wasmCode, err := ioutil.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
Expand All @@ -497,7 +499,7 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) {
ctx = ctx.WithBlockHeight(0).WithGasMeter(sdk.NewInfiniteGasMeter())

// when
_, err = InitGenesis(ctx, keeper, importState, &StakingKeeperMock{}, TestHandler(keeper))
_, err = InitGenesis(ctx, keeper, importState, &StakingKeeperMock{}, TestHandler(contractKeeper))
require.NoError(t, err)

// verify wasm code
Expand Down Expand Up @@ -597,7 +599,7 @@ func TestSupportedGenMsgTypes(t *testing.T) {
ctx = ctx.WithBlockHeight(0).WithGasMeter(sdk.NewInfiniteGasMeter())
fundAccounts(t, ctx, keepers.AccountKeeper, keepers.BankKeeper, myAddress, sdk.NewCoins(sdk.NewCoin(denom, sdk.NewInt(100))))
// when
_, err = InitGenesis(ctx, keeper, importState, &StakingKeeperMock{}, TestHandler(keeper))
_, err = InitGenesis(ctx, keeper, importState, &StakingKeeperMock{}, TestHandler(keepers.ContractKeeper))
require.NoError(t, err)

// verify code stored
Expand Down
8 changes: 4 additions & 4 deletions x/wasm/keeper/handler_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type SDKMessageHandler struct {
encoders msgEncoder
}

func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource, customEncoders ...*MessageEncoders) messenger {
func NewDefaultMessageHandler(router sdk.Router, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource, customEncoders ...*MessageEncoders) Messenger {
encoders := DefaultEncoders(unpacker, portSource)
for _, e := range customEncoders {
encoders = encoders.Merge(e)
Expand Down Expand Up @@ -89,11 +89,11 @@ func (h SDKMessageHandler) handleSdkMessage(ctx sdk.Context, contractAddr sdk.Ad

// MessageHandlerChain defines a chain of handlers that are called one by one until it can be handled.
type MessageHandlerChain struct {
handlers []messenger
handlers []Messenger
}

func NewMessageHandlerChain(first messenger, others ...messenger) *MessageHandlerChain {
r := &MessageHandlerChain{handlers: append([]messenger{first}, others...)}
func NewMessageHandlerChain(first Messenger, others ...Messenger) *MessageHandlerChain {
r := &MessageHandlerChain{handlers: append([]Messenger{first}, others...)}
for i := range r.handlers {
if r.handlers[i] == nil {
panic(fmt.Sprintf("handler must not be nil at position : %d", i))
Expand Down
14 changes: 7 additions & 7 deletions x/wasm/keeper/handler_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,28 @@ func TestMessageHandlerChainDispatch(t *testing.T) {

myMsg := wasmvmtypes.CosmosMsg{Custom: []byte(`{}`)}
specs := map[string]struct {
handlers []messenger
handlers []Messenger
expErr *sdkerrors.Error
expEvents []sdk.Event
}{
"single handler": {
handlers: []messenger{capturingHandler},
handlers: []Messenger{capturingHandler},
},
"passed to next handler": {
handlers: []messenger{alwaysUnknownMsgHandler, capturingHandler},
handlers: []Messenger{alwaysUnknownMsgHandler, capturingHandler},
},
"stops iteration when handled": {
handlers: []messenger{capturingHandler, assertNotCalledHandler},
handlers: []Messenger{capturingHandler, assertNotCalledHandler},
},
"stops iteration on handler error": {
handlers: []messenger{&wasmtesting.MockMessageHandler{
handlers: []Messenger{&wasmtesting.MockMessageHandler{
DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
return nil, nil, types.ErrInvalidMsg
}}, assertNotCalledHandler},
expErr: types.ErrInvalidMsg,
},
"return events when handle": {
handlers: []messenger{&wasmtesting.MockMessageHandler{
handlers: []Messenger{&wasmtesting.MockMessageHandler{
DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
_, data, _ = capturingHandler.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg)
return []sdk.Event{sdk.NewEvent("myEvent", sdk.NewAttribute("foo", "bar"))}, data, nil
Expand All @@ -63,7 +63,7 @@ func TestMessageHandlerChainDispatch(t *testing.T) {
expEvents: []sdk.Event{sdk.NewEvent("myEvent", sdk.NewAttribute("foo", "bar"))},
},
"return error when none can handle": {
handlers: []messenger{alwaysUnknownMsgHandler},
handlers: []Messenger{alwaysUnknownMsgHandler},
expErr: types.ErrUnknownMsg,
},
}
Expand Down
2 changes: 1 addition & 1 deletion x/wasm/keeper/ibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestBindingPortForIBCContractOnInstantiate(t *testing.T) {

// create a second contract should give yet another portID (and different address)
creator := RandomAccountAddress(t)
addr, _, err := keepers.WasmKeeper.Instantiate(ctx, example.CodeID, creator, nil, initMsgBz, "ibc-reflect-2", nil)
addr, _, err := keepers.ContractKeeper.Instantiate(ctx, example.CodeID, creator, nil, initMsgBz, "ibc-reflect-2", nil)
require.NoError(t, err)
require.NotEqual(t, example.Contract, addr)

Expand Down
Loading

0 comments on commit d9ca5d8

Please sign in to comment.