github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/wasm/keeper/keeper.go (about)

     1  package keeper
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/binary"
     7  	"encoding/json"
     8  	"fmt"
     9  	"math"
    10  	"path/filepath"
    11  	"strconv"
    12  	"strings"
    13  
    14  	wasmvm "github.com/CosmWasm/wasmvm"
    15  	wasmvmtypes "github.com/CosmWasm/wasmvm/types"
    16  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    17  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/prefix"
    18  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    19  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    20  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/innertx"
    21  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported"
    22  	"github.com/fibonacci-chain/fbc/libs/tendermint/libs/log"
    23  	paramtypes "github.com/fibonacci-chain/fbc/x/params"
    24  	"github.com/fibonacci-chain/fbc/x/wasm/ioutils"
    25  	"github.com/fibonacci-chain/fbc/x/wasm/types"
    26  	"github.com/fibonacci-chain/fbc/x/wasm/watcher"
    27  	"github.com/gogo/protobuf/proto"
    28  )
    29  
    30  // contractMemoryLimit is the memory limit of each contract execution (in MiB)
    31  // constant value so all nodes run with the same limit.
    32  const contractMemoryLimit = 32
    33  const SupportedFeatures = "iterator,staking,stargate"
    34  
    35  type contextKey int
    36  
    37  const (
    38  	// private type creates an interface key for Context that cannot be accessed by any other package
    39  	contextKeyQueryStackSize contextKey = iota
    40  )
    41  
    42  // Option is an extension point to instantiate keeper with non default values
    43  type Option interface {
    44  	apply(*Keeper)
    45  }
    46  
    47  // WasmVMQueryHandler is an extension point for custom query handler implementations
    48  type WasmVMQueryHandler interface {
    49  	// HandleQuery executes the requested query
    50  	HandleQuery(ctx sdk.Context, caller sdk.AccAddress, request wasmvmtypes.QueryRequest) ([]byte, error)
    51  }
    52  
    53  type CoinTransferrer interface {
    54  	// TransferCoins sends the coin amounts from the source to the destination with rules applied.
    55  	TransferCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
    56  }
    57  
    58  // WasmVMResponseHandler is an extension point to handles the response data returned by a contract call.
    59  type WasmVMResponseHandler interface {
    60  	// Handle processes the data returned by a contract invocation.
    61  	Handle(
    62  		ctx sdk.Context,
    63  		contractAddr sdk.AccAddress,
    64  		ibcPort string,
    65  		messages []wasmvmtypes.SubMsg,
    66  		origRspData []byte,
    67  	) ([]byte, error)
    68  }
    69  
    70  // Keeper will have a reference to Wasmer with it's own data directory.
    71  type Keeper struct {
    72  	storeKey              sdk.StoreKey
    73  	cdc                   *codec.CodecProxy
    74  	accountKeeper         types.AccountKeeper
    75  	bank                  CoinTransferrer
    76  	portKeeper            types.PortKeeper
    77  	capabilityKeeper      types.CapabilityKeeper
    78  	wasmVM                types.WasmerEngine
    79  	wasmVMQueryHandler    WasmVMQueryHandler
    80  	wasmVMResponseHandler WasmVMResponseHandler
    81  	messenger             Messenger
    82  	innertxKeeper         innertx.InnerTxKeeper
    83  
    84  	// queryGasLimit is the max wasmvm gas that can be spent on executing a query with a contract
    85  	queryGasLimit     uint64
    86  	paramSpace        types.Subspace
    87  	gasRegister       GasRegister
    88  	maxQueryStackSize uint32
    89  	ada               types.DBAdapter
    90  }
    91  
    92  type defaultAdapter struct{}
    93  
    94  func (d defaultAdapter) NewStore(_ sdk.GasMeter, store sdk.KVStore, pre []byte) sdk.KVStore {
    95  	if len(pre) != 0 {
    96  		store = prefix.NewStore(store, pre)
    97  	}
    98  	return watcher.WrapWriteKVStore(store)
    99  }
   100  
   101  // NewKeeper creates a new contract Keeper instance
   102  // If customEncoders is non-nil, we can use this to override some of the message handler, especially custom
   103  func NewKeeper(
   104  	cdc *codec.CodecProxy,
   105  	storeKey sdk.StoreKey,
   106  	paramSpace paramtypes.Subspace,
   107  	accountKeeper types.AccountKeeper,
   108  	bankKeeper types.BankKeeper,
   109  	//distKeeper types.DistributionKeeper,
   110  	channelKeeper types.ChannelKeeper,
   111  	portKeeper types.PortKeeper,
   112  	capabilityKeeper types.CapabilityKeeper,
   113  	portSource types.ICS20TransferPortSource,
   114  	router MessageRouter,
   115  	queryRouter GRPCQueryRouter,
   116  	homeDir string,
   117  	wasmConfig types.WasmConfig,
   118  	supportedFeatures string,
   119  	opts ...Option,
   120  ) Keeper {
   121  	// set KeyTable if it has not already been set
   122  	if !paramSpace.HasKeyTable() {
   123  		paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
   124  	}
   125  	watcher.SetWatchDataManager()
   126  	k := newKeeper(cdc, storeKey, paramSpace, accountKeeper, bankKeeper, channelKeeper, portKeeper, capabilityKeeper, portSource, router, queryRouter, homeDir, wasmConfig, supportedFeatures, defaultAdapter{}, opts...)
   127  	accountKeeper.SetObserverKeeper(k)
   128  
   129  	return k
   130  }
   131  
   132  func NewSimulateKeeper(
   133  	cdc *codec.CodecProxy,
   134  	storeKey sdk.StoreKey,
   135  	paramSpace types.Subspace,
   136  	accountKeeper types.AccountKeeper,
   137  	bankKeeper types.BankKeeper,
   138  	channelKeeper types.ChannelKeeper,
   139  	portKeeper types.PortKeeper,
   140  	capabilityKeeper types.CapabilityKeeper,
   141  	portSource types.ICS20TransferPortSource,
   142  	router MessageRouter,
   143  	queryRouter GRPCQueryRouter,
   144  	homeDir string,
   145  	wasmConfig types.WasmConfig,
   146  	supportedFeatures string,
   147  	opts ...Option,
   148  ) Keeper {
   149  	return newKeeper(cdc, storeKey, paramSpace, accountKeeper, bankKeeper, channelKeeper, portKeeper, capabilityKeeper, portSource, router, queryRouter, homeDir, wasmConfig, supportedFeatures, watcher.Adapter{}, opts...)
   150  }
   151  
   152  func newKeeper(cdc *codec.CodecProxy,
   153  	storeKey sdk.StoreKey,
   154  	paramSpace types.Subspace,
   155  	accountKeeper types.AccountKeeper,
   156  	bankKeeper types.BankKeeper,
   157  	channelKeeper types.ChannelKeeper,
   158  	portKeeper types.PortKeeper,
   159  	capabilityKeeper types.CapabilityKeeper,
   160  	portSource types.ICS20TransferPortSource,
   161  	router MessageRouter,
   162  	queryRouter GRPCQueryRouter,
   163  	homeDir string,
   164  	wasmConfig types.WasmConfig,
   165  	supportedFeatures string,
   166  	ada types.DBAdapter,
   167  	opts ...Option,
   168  ) Keeper {
   169  	wasmer, err := wasmvm.NewVM(filepath.Join(homeDir, "wasm"), supportedFeatures, contractMemoryLimit, wasmConfig.ContractDebugMode, wasmConfig.MemoryCacheSize)
   170  	if err != nil {
   171  		panic(err)
   172  	}
   173  
   174  	keeper := &Keeper{
   175  		storeKey:          storeKey,
   176  		cdc:               cdc,
   177  		wasmVM:            wasmer,
   178  		accountKeeper:     accountKeeper,
   179  		bank:              NewBankCoinTransferrer(bankKeeper),
   180  		portKeeper:        portKeeper,
   181  		capabilityKeeper:  capabilityKeeper,
   182  		messenger:         NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, cdc.GetProtocMarshal(), portSource),
   183  		queryGasLimit:     wasmConfig.SmartQueryGasLimit,
   184  		paramSpace:        paramSpace,
   185  		gasRegister:       NewDefaultWasmGasRegister(),
   186  		ada:               ada,
   187  		maxQueryStackSize: types.DefaultMaxQueryStackSize,
   188  	}
   189  	keeper.wasmVMQueryHandler = DefaultQueryPlugins(bankKeeper, channelKeeper, queryRouter, keeper)
   190  	for _, o := range opts {
   191  		o.apply(keeper)
   192  	}
   193  	// not updateable, yet
   194  	keeper.wasmVMResponseHandler = NewDefaultWasmVMContractResponseHandler(NewMessageDispatcher(keeper.messenger, keeper))
   195  	return *keeper
   196  }
   197  
   198  func (k Keeper) GetStoreKey() sdk.StoreKey {
   199  	return k.storeKey
   200  }
   201  
   202  func (k Keeper) IsContractMethodBlocked(ctx sdk.Context, contractAddr, method string) bool {
   203  	blockedMethods := k.GetContractMethodBlockedList(ctx, contractAddr)
   204  	return blockedMethods.IsMethodBlocked(method)
   205  }
   206  
   207  func (k Keeper) GetContractMethodBlockedList(ctx sdk.Context, contractAddr string) *types.ContractMethods {
   208  	return k.getContractMethodBlockedList(ctx, contractAddr)
   209  }
   210  
   211  func (k Keeper) getAllBlockedList(ctx sdk.Context) []*types.ContractMethods {
   212  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   213  	it := sdk.KVStorePrefixIterator(store, types.GetContractMethodBlockedListPrefix(""))
   214  	defer it.Close()
   215  
   216  	var cms []*types.ContractMethods
   217  	for ; it.Valid(); it.Next() {
   218  		var method types.ContractMethods
   219  		err := proto.Unmarshal(it.Value(), &method)
   220  		if err != nil {
   221  			panic(err)
   222  		}
   223  		cms = append(cms, &method)
   224  	}
   225  	return cms
   226  }
   227  
   228  func (k Keeper) getContractMethodBlockedList(ctx sdk.Context, contractAddr string) *types.ContractMethods {
   229  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   230  	key := types.GetContractMethodBlockedListPrefix(contractAddr)
   231  	data := store.Get(key)
   232  	var blockedMethods types.ContractMethods
   233  	err := proto.Unmarshal(data, &blockedMethods)
   234  	if err != nil {
   235  		panic(err)
   236  	}
   237  	return &blockedMethods
   238  }
   239  
   240  func (k Keeper) updateContractMethodBlockedList(ctx sdk.Context, blockedMethods *types.ContractMethods, isDelete bool) error {
   241  	oldBlockedMethods := k.getContractMethodBlockedList(ctx, blockedMethods.GetContractAddr())
   242  	if isDelete {
   243  		oldBlockedMethods.DeleteMethods(blockedMethods.Methods)
   244  	} else {
   245  		oldBlockedMethods.AddMethods(blockedMethods.Methods)
   246  	}
   247  	data, err := proto.Marshal(oldBlockedMethods)
   248  	if err != nil {
   249  		return err
   250  	}
   251  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   252  	key := types.GetContractMethodBlockedListPrefix(blockedMethods.ContractAddr)
   253  	store.Set(key, data)
   254  	GetWasmParamsCache().SetNeedBlockedUpdate()
   255  	return nil
   256  }
   257  
   258  func (k Keeper) updateUploadAccessConfig(ctx sdk.Context, config types.AccessConfig) {
   259  	params := k.GetParams(ctx)
   260  	params.CodeUploadAccess = config
   261  	k.SetParams(ctx, params)
   262  }
   263  
   264  func (k Keeper) getUploadAccessConfig(ctx sdk.Context) types.AccessConfig {
   265  	//var a types.AccessConfig
   266  	//k.paramSpace.Get(ctx, types.ParamStoreKeyUploadAccess, &a)
   267  	//return a
   268  	return k.GetParams(ctx).CodeUploadAccess
   269  }
   270  
   271  func (k Keeper) getInstantiateAccessConfig(ctx sdk.Context) types.AccessType {
   272  	//var a types.AccessType
   273  	//k.paramSpace.Get(ctx, types.ParamStoreKeyInstantiateAccess, &a)
   274  	//return a
   275  	return k.GetParams(ctx).InstantiateDefaultPermission
   276  }
   277  
   278  // GetParams returns the total set of wasm parameters.
   279  func (k Keeper) GetParams(ctx sdk.Context) types.Params {
   280  	var params types.Params
   281  	k.paramSpace.GetParamSet(ctx, &params)
   282  	return params
   283  }
   284  
   285  func (k Keeper) SetParams(ctx sdk.Context, ps types.Params) {
   286  	watcher.SetParams(ps)
   287  	k.paramSpace.SetParamSet(ctx, &ps)
   288  	GetWasmParamsCache().SetNeedParamsUpdate()
   289  }
   290  
   291  func (k Keeper) OnAccountUpdated(acc exported.Account) {
   292  	watcher.DeleteAccount(acc.GetAddress())
   293  }
   294  
   295  func (k Keeper) create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, instantiateAccess *types.AccessConfig, authZ AuthorizationPolicy) (codeID uint64, err error) {
   296  	if creator == nil {
   297  		return 0, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "cannot be nil")
   298  	}
   299  
   300  	if !authZ.CanCreateCode(k.getUploadAccessConfig(ctx), creator) {
   301  		return 0, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not create code")
   302  	}
   303  	// figure out proper instantiate access
   304  	defaultAccessConfig := k.getInstantiateAccessConfig(ctx).With(creator)
   305  	if instantiateAccess == nil {
   306  		instantiateAccess = &defaultAccessConfig
   307  	} else if !instantiateAccess.IsSubset(defaultAccessConfig) {
   308  		// we enforce this must be subset of default upload access
   309  		return 0, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "instantiate access must be subset of default upload access")
   310  	}
   311  
   312  	wasmCode, err = ioutils.Uncompress(wasmCode, uint64(types.MaxWasmSize))
   313  	if err != nil {
   314  		return 0, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
   315  	}
   316  	ctx.GasMeter().ConsumeGas(k.gasRegister.CompileCosts(len(wasmCode)), "Compiling WASM Bytecode")
   317  
   318  	checksum, err := k.wasmVM.Create(wasmCode)
   319  	if err != nil {
   320  		return 0, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
   321  	}
   322  	report, err := k.wasmVM.AnalyzeCode(checksum)
   323  	if err != nil {
   324  		return 0, sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
   325  	}
   326  	codeID = k.autoIncrementID(ctx, types.KeyLastCodeID)
   327  	k.Logger(ctx).Debug("storing new contract", "features", report.RequiredFeatures, "code_id", codeID)
   328  	codeInfo := types.NewCodeInfo(checksum, creator, *instantiateAccess)
   329  	k.storeCodeInfo(ctx, codeID, codeInfo)
   330  
   331  	evt := sdk.NewEvent(
   332  		types.EventTypeStoreCode,
   333  		sdk.NewAttribute(types.AttributeKeyCodeID, strconv.FormatUint(codeID, 10)),
   334  	)
   335  	for _, f := range strings.Split(report.RequiredFeatures, ",") {
   336  		evt.AppendAttributes(sdk.NewAttribute(types.AttributeKeyFeature, strings.TrimSpace(f)))
   337  	}
   338  	ctx.EventManager().EmitEvent(evt)
   339  
   340  	return codeID, nil
   341  }
   342  
   343  func (k Keeper) storeCodeInfo(ctx sdk.Context, codeID uint64, codeInfo types.CodeInfo) {
   344  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   345  	// 0x01 | codeID (uint64) -> ContractInfo
   346  	store.Set(types.GetCodeKey(codeID), k.cdc.GetProtocMarshal().MustMarshal(&codeInfo))
   347  }
   348  
   349  func (k Keeper) importCode(ctx sdk.Context, codeID uint64, codeInfo types.CodeInfo, wasmCode []byte) error {
   350  	wasmCode, err := ioutils.Uncompress(wasmCode, uint64(types.MaxWasmSize))
   351  	if err != nil {
   352  		return sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
   353  	}
   354  	newCodeHash, err := k.wasmVM.Create(wasmCode)
   355  	if err != nil {
   356  		return sdkerrors.Wrap(types.ErrCreateFailed, err.Error())
   357  	}
   358  	if !bytes.Equal(codeInfo.CodeHash, newCodeHash) {
   359  		return sdkerrors.Wrap(types.ErrInvalid, "code hashes not same")
   360  	}
   361  
   362  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   363  
   364  	key := types.GetCodeKey(codeID)
   365  	if store.Has(key) {
   366  		return sdkerrors.Wrapf(types.ErrDuplicate, "duplicate code: %d", codeID)
   367  	}
   368  	// 0x01 | codeID (uint64) -> ContractInfo
   369  	store.Set(key, k.cdc.GetProtocMarshal().MustMarshal(&codeInfo))
   370  	return nil
   371  }
   372  
   373  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) {
   374  	//defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "instantiate")
   375  	instanceCosts := k.gasRegister.NewContractInstanceCosts(k.IsPinnedCode(ctx, codeID), len(initMsg))
   376  	ctx.GasMeter().ConsumeGas(instanceCosts, "Loading CosmWasm module: instantiate")
   377  
   378  	// create contract address
   379  	contractAddress := k.generateContractAddress(ctx, codeID)
   380  	existingAcct := k.accountKeeper.GetAccount(ctx, contractAddress)
   381  	if existingAcct != nil {
   382  		return nil, nil, sdkerrors.Wrap(types.ErrAccountExists, existingAcct.GetAddress().String())
   383  	}
   384  
   385  	// deposit initial contract funds
   386  	if !deposit.IsZero() {
   387  		if err := k.bank.TransferCoins(ctx, creator, contractAddress, deposit); err != nil {
   388  			return nil, nil, err
   389  		}
   390  	} else {
   391  		// create an empty account (so we don't have issues later)
   392  		// TODO: can we remove this?
   393  		contractAccount := k.accountKeeper.NewAccountWithAddress(ctx, contractAddress)
   394  		k.accountKeeper.SetAccount(ctx, contractAccount)
   395  	}
   396  
   397  	// get contact info
   398  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   399  	codeInfo := k.GetCodeInfo(ctx, codeID)
   400  	if codeInfo == nil {
   401  		return nil, nil, sdkerrors.Wrap(types.ErrNotFound, "code")
   402  	}
   403  
   404  	if !authZ.CanInstantiateContract(codeInfo.InstantiateConfig, creator) {
   405  		return nil, nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not instantiate")
   406  	}
   407  
   408  	// prepare params for contract instantiate call
   409  	env := types.NewEnv(ctx, contractAddress)
   410  	adapters := sdk.CoinsToCoinAdapters(deposit)
   411  	info := types.NewInfo(creator, adapters)
   412  
   413  	// create prefixed data store
   414  	// 0x03 | BuildContractAddress (sdk.AccAddress)
   415  	prefixStore := prefix.NewStore(store, types.GetContractStorePrefix(contractAddress))
   416  	prefixStoreAdapter := types.NewStoreAdapter(prefixStore)
   417  
   418  	// prepare querier
   419  	querier := k.newQueryHandler(ctx, contractAddress)
   420  
   421  	// instantiate wasm contract
   422  	gas := k.runtimeGasForContract(ctx)
   423  	res, gasUsed, err := k.wasmVM.Instantiate(codeInfo.CodeHash, env, info, initMsg, prefixStoreAdapter, cosmwasmAPI, querier, k.gasMeter(ctx), gas, costJSONDeserialization)
   424  	k.consumeRuntimeGas(ctx, gasUsed)
   425  	if !ctx.IsCheckTx() && k.innertxKeeper != nil {
   426  		k.innertxKeeper.UpdateWasmInnerTx(ctx.TxBytes(), ctx.BlockHeight(), innertx.CosmosDepth, creator, contractAddress, innertx.CosmosCallType, types.InstantiateInnertxName, sdk.Coins{}, err, k.gasRegister.FromWasmVMGas(gasUsed), string(initMsg))
   427  	}
   428  	if err != nil {
   429  		return nil, nil, sdkerrors.Wrap(types.ErrInstantiateFailed, err.Error())
   430  	}
   431  
   432  	// persist instance first
   433  	createdAt := types.NewAbsoluteTxPosition(ctx)
   434  	contractInfo := types.NewContractInfo(codeID, creator, admin, label, createdAt)
   435  
   436  	// check for IBC flag
   437  	report, err := k.wasmVM.AnalyzeCode(codeInfo.CodeHash)
   438  	if err != nil {
   439  		return nil, nil, sdkerrors.Wrap(types.ErrInstantiateFailed, err.Error())
   440  	}
   441  	if report.HasIBCEntryPoints {
   442  		// register IBC port
   443  		ibcPort, err := k.ensureIbcPort(ctx, contractAddress)
   444  		if err != nil {
   445  			return nil, nil, err
   446  		}
   447  		contractInfo.IBCPortID = ibcPort
   448  	}
   449  
   450  	// store contract before dispatch so that contract could be called back
   451  	historyEntry := contractInfo.InitialHistory(initMsg)
   452  	k.addToContractCodeSecondaryIndex(ctx, contractAddress, historyEntry)
   453  	k.appendToContractHistory(ctx, contractAddress, historyEntry)
   454  	k.storeContractInfo(ctx, contractAddress, &contractInfo)
   455  
   456  	ctx.EventManager().EmitEvent(sdk.NewEvent(
   457  		types.EventTypeInstantiate,
   458  		sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()),
   459  		sdk.NewAttribute(types.AttributeKeyCodeID, strconv.FormatUint(codeID, 10)),
   460  	))
   461  
   462  	data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events)
   463  	if err != nil {
   464  		return nil, nil, sdkerrors.Wrap(err, "dispatch")
   465  	}
   466  
   467  	return contractAddress, data, nil
   468  }
   469  
   470  // Execute executes the contract instance
   471  func (k Keeper) execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) ([]byte, error) {
   472  	//defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "execute")
   473  	contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddress)
   474  	if err != nil {
   475  		return nil, err
   476  	}
   477  
   478  	executeCosts := k.gasRegister.InstantiateContractCosts(k.IsPinnedCode(ctx, contractInfo.CodeID), len(msg))
   479  	ctx.GasMeter().ConsumeGas(executeCosts, "Loading CosmWasm module: execute")
   480  
   481  	// add more funds
   482  	if !coins.IsZero() {
   483  		if err := k.bank.TransferCoins(ctx, caller, contractAddress, coins); err != nil {
   484  			return nil, err
   485  		}
   486  	}
   487  
   488  	env := types.NewEnv(ctx, contractAddress)
   489  	adapters := sdk.CoinsToCoinAdapters(coins)
   490  	info := types.NewInfo(caller, adapters)
   491  
   492  	// prepare querier
   493  	querier := k.newQueryHandler(ctx, contractAddress)
   494  	gas := k.runtimeGasForContract(ctx)
   495  	if k.GetParams(ctx).UseContractBlockedList {
   496  		var methodsMap map[string]interface{}
   497  		err = json.Unmarshal(msg, &methodsMap)
   498  		if err != nil {
   499  			return nil, err
   500  		}
   501  		for method := range methodsMap {
   502  			if k.IsContractMethodBlocked(ctx, contractAddress.String(), method) {
   503  				return nil, sdkerrors.Wrap(types.ErrExecuteFailed, fmt.Sprintf("%s method of contract %s is not allowed", contractAddress.String(), method))
   504  			}
   505  		}
   506  	}
   507  
   508  	res, gasUsed, execErr := k.wasmVM.Execute(codeInfo.CodeHash, env, info, msg, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas, costJSONDeserialization)
   509  	k.consumeRuntimeGas(ctx, gasUsed)
   510  	if !ctx.IsCheckTx() && k.innertxKeeper != nil {
   511  		k.innertxKeeper.UpdateWasmInnerTx(ctx.TxBytes(), ctx.BlockHeight(), innertx.CosmosDepth, caller, contractAddress, innertx.CosmosCallType, types.ExecuteInnertxName, coins, err, k.gasRegister.FromWasmVMGas(gasUsed), string(msg))
   512  	}
   513  	if execErr != nil {
   514  		return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
   515  	}
   516  
   517  	ctx.EventManager().EmitEvent(sdk.NewEvent(
   518  		types.EventTypeExecute,
   519  		sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()),
   520  	))
   521  
   522  	data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events)
   523  	if err != nil {
   524  		return nil, sdkerrors.Wrap(err, "dispatch")
   525  	}
   526  
   527  	return data, nil
   528  }
   529  
   530  func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, newCodeID uint64, msg []byte, authZ AuthorizationPolicy) ([]byte, error) {
   531  	//defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "migrate")
   532  	migrateSetupCosts := k.gasRegister.InstantiateContractCosts(k.IsPinnedCode(ctx, newCodeID), len(msg))
   533  	ctx.GasMeter().ConsumeGas(migrateSetupCosts, "Loading CosmWasm module: migrate")
   534  
   535  	contractInfo := k.GetContractInfo(ctx, contractAddress)
   536  	if contractInfo == nil {
   537  		return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "unknown contract")
   538  	}
   539  	if !authZ.CanModifyContract(contractInfo.AdminAddr(), caller) {
   540  		return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not migrate")
   541  	}
   542  
   543  	newCodeInfo := k.GetCodeInfo(ctx, newCodeID)
   544  	if newCodeInfo == nil {
   545  		return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "unknown code")
   546  	}
   547  
   548  	// check for IBC flag
   549  	switch report, err := k.wasmVM.AnalyzeCode(newCodeInfo.CodeHash); {
   550  	case err != nil:
   551  		return nil, sdkerrors.Wrap(types.ErrMigrationFailed, err.Error())
   552  	case !report.HasIBCEntryPoints && contractInfo.IBCPortID != "":
   553  		// prevent update to non ibc contract
   554  		return nil, sdkerrors.Wrap(types.ErrMigrationFailed, "requires ibc callbacks")
   555  	case report.HasIBCEntryPoints && contractInfo.IBCPortID == "":
   556  		// add ibc port
   557  		ibcPort, err := k.ensureIbcPort(ctx, contractAddress)
   558  		if err != nil {
   559  			return nil, err
   560  		}
   561  		contractInfo.IBCPortID = ibcPort
   562  	}
   563  
   564  	env := types.NewEnv(ctx, contractAddress)
   565  
   566  	// prepare querier
   567  	querier := k.newQueryHandler(ctx, contractAddress)
   568  
   569  	prefixStoreKey := types.GetContractStorePrefix(contractAddress)
   570  	prefixStore := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), prefixStoreKey)
   571  	prefixAdapater := types.NewStoreAdapter(prefixStore)
   572  
   573  	gas := k.runtimeGasForContract(ctx)
   574  	res, gasUsed, err := k.wasmVM.Migrate(newCodeInfo.CodeHash, env, msg, &prefixAdapater, cosmwasmAPI, &querier, k.gasMeter(ctx), gas, costJSONDeserialization)
   575  	k.consumeRuntimeGas(ctx, gasUsed)
   576  	if !ctx.IsCheckTx() && k.innertxKeeper != nil {
   577  		k.innertxKeeper.UpdateWasmInnerTx(ctx.TxBytes(), ctx.BlockHeight(), innertx.CosmosDepth, caller, contractAddress, innertx.CosmosCallType, types.MigrateInnertxName, sdk.Coins{}, err, k.gasRegister.FromWasmVMGas(gasUsed), string(msg))
   578  	}
   579  	if err != nil {
   580  		return nil, sdkerrors.Wrap(types.ErrMigrationFailed, err.Error())
   581  	}
   582  
   583  	// delete old secondary index entry
   584  	k.removeFromContractCodeSecondaryIndex(ctx, contractAddress, k.getLastContractHistoryEntry(ctx, contractAddress))
   585  	// persist migration updates
   586  	historyEntry := contractInfo.AddMigration(ctx, newCodeID, msg)
   587  	k.appendToContractHistory(ctx, contractAddress, historyEntry)
   588  	k.addToContractCodeSecondaryIndex(ctx, contractAddress, historyEntry)
   589  	k.storeContractInfo(ctx, contractAddress, contractInfo)
   590  
   591  	ctx.EventManager().EmitEvent(sdk.NewEvent(
   592  		types.EventTypeMigrate,
   593  		sdk.NewAttribute(types.AttributeKeyCodeID, strconv.FormatUint(newCodeID, 10)),
   594  		sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()),
   595  	))
   596  
   597  	data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events)
   598  	if err != nil {
   599  		return nil, sdkerrors.Wrap(err, "dispatch")
   600  	}
   601  
   602  	return data, nil
   603  }
   604  
   605  // Sudo allows priviledged access to a contract. This can never be called by an external tx, but only by
   606  // another native Go module directly, or on-chain governance (if sudo proposals are enabled). Thus, the keeper doesn't
   607  // place any access controls on it, that is the responsibility or the app developer (who passes the wasm.Keeper in app.go)
   608  func (k Keeper) Sudo(ctx sdk.Context, contractAddress sdk.AccAddress, msg []byte) ([]byte, error) {
   609  	//defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "sudo")
   610  	contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddress)
   611  	if err != nil {
   612  		return nil, err
   613  	}
   614  
   615  	sudoSetupCosts := k.gasRegister.InstantiateContractCosts(k.IsPinnedCode(ctx, contractInfo.CodeID), len(msg))
   616  	ctx.GasMeter().ConsumeGas(sudoSetupCosts, "Loading CosmWasm module: sudo")
   617  
   618  	env := types.NewEnv(ctx, contractAddress)
   619  
   620  	// prepare querier
   621  	querier := k.newQueryHandler(ctx, contractAddress)
   622  	gas := k.runtimeGasForContract(ctx)
   623  	res, gasUsed, execErr := k.wasmVM.Sudo(codeInfo.CodeHash, env, msg, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas, costJSONDeserialization)
   624  	k.consumeRuntimeGas(ctx, gasUsed)
   625  	if execErr != nil {
   626  		return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
   627  	}
   628  
   629  	ctx.EventManager().EmitEvent(sdk.NewEvent(
   630  		types.EventTypeSudo,
   631  		sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()),
   632  	))
   633  
   634  	data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events)
   635  	if err != nil {
   636  		return nil, sdkerrors.Wrap(err, "dispatch")
   637  	}
   638  
   639  	return data, nil
   640  }
   641  
   642  // reply is only called from keeper internal functions (dispatchSubmessages) after processing the submessage
   643  func (k Keeper) reply(ctx sdk.Context, contractAddress sdk.AccAddress, reply wasmvmtypes.Reply) ([]byte, error) {
   644  	contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddress)
   645  	if err != nil {
   646  		return nil, err
   647  	}
   648  
   649  	// always consider this pinned
   650  	replyCosts := k.gasRegister.ReplyCosts(true, reply)
   651  	ctx.GasMeter().ConsumeGas(replyCosts, "Loading CosmWasm module: reply")
   652  
   653  	env := types.NewEnv(ctx, contractAddress)
   654  
   655  	// prepare querier
   656  	querier := k.newQueryHandler(ctx, contractAddress)
   657  	gas := k.runtimeGasForContract(ctx)
   658  	res, gasUsed, execErr := k.wasmVM.Reply(codeInfo.CodeHash, env, reply, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), gas, costJSONDeserialization)
   659  	k.consumeRuntimeGas(ctx, gasUsed)
   660  	if execErr != nil {
   661  		return nil, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
   662  	}
   663  
   664  	ctx.EventManager().EmitEvent(sdk.NewEvent(
   665  		types.EventTypeReply,
   666  		sdk.NewAttribute(types.AttributeKeyContractAddr, contractAddress.String()),
   667  	))
   668  
   669  	data, err := k.handleContractResponse(ctx, contractAddress, contractInfo.IBCPortID, res.Messages, res.Attributes, res.Data, res.Events)
   670  	if err != nil {
   671  		return nil, sdkerrors.Wrap(err, "dispatch")
   672  	}
   673  
   674  	return data, nil
   675  }
   676  
   677  // addToContractCodeSecondaryIndex adds element to the index for contracts-by-codeid queries
   678  func (k Keeper) addToContractCodeSecondaryIndex(ctx sdk.Context, contractAddress sdk.AccAddress, entry types.ContractCodeHistoryEntry) {
   679  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   680  	store.Set(types.GetContractByCreatedSecondaryIndexKey(contractAddress, entry), []byte{})
   681  }
   682  
   683  // removeFromContractCodeSecondaryIndex removes element to the index for contracts-by-codeid queries
   684  func (k Keeper) removeFromContractCodeSecondaryIndex(ctx sdk.Context, contractAddress sdk.AccAddress, entry types.ContractCodeHistoryEntry) {
   685  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   686  	store.Delete(types.GetContractByCreatedSecondaryIndexKey(contractAddress, entry))
   687  }
   688  
   689  // IterateContractsByCode iterates over all contracts with given codeID ASC on code update time.
   690  func (k Keeper) IterateContractsByCode(ctx sdk.Context, codeID uint64, cb func(address sdk.AccAddress) bool) {
   691  	prefixStore := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), types.GetContractByCodeIDSecondaryIndexPrefix(codeID))
   692  	iter := prefixStore.Iterator(nil, nil)
   693  	defer iter.Close()
   694  
   695  	for ; iter.Valid(); iter.Next() {
   696  		key := iter.Key()
   697  		if cb(key[types.AbsoluteTxPositionLen:]) {
   698  			return
   699  		}
   700  	}
   701  }
   702  
   703  func (k Keeper) setContractAdmin(ctx sdk.Context, contractAddress, caller, newAdmin sdk.AccAddress, authZ AuthorizationPolicy) (err error) {
   704  	gas := ctx.GasMeter().GasConsumed()
   705  	defer func() {
   706  		if !ctx.IsCheckTx() && k.innertxKeeper != nil {
   707  			k.innertxKeeper.UpdateWasmInnerTx(ctx.TxBytes(), ctx.BlockHeight(), innertx.CosmosDepth, caller, contractAddress, innertx.CosmosCallType, types.SetContractAdminInnertxName, sdk.Coins{}, err, ctx.GasMeter().GasConsumed()-gas, "")
   708  		}
   709  	}()
   710  	contractInfo := k.GetContractInfo(ctx, contractAddress)
   711  	if contractInfo == nil {
   712  		return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "unknown contract")
   713  	}
   714  	if !authZ.CanModifyContract(contractInfo.AdminAddr(), caller) {
   715  		return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not modify contract")
   716  	}
   717  	contractInfo.Admin = newAdmin.String()
   718  	k.storeContractInfo(ctx, contractAddress, contractInfo)
   719  	return nil
   720  }
   721  
   722  func (k Keeper) appendToContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress, newEntries ...types.ContractCodeHistoryEntry) {
   723  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   724  	// find last element position
   725  	var pos uint64
   726  	prefixStore := prefix.NewStore(store, types.GetContractCodeHistoryElementPrefix(contractAddr))
   727  	iter := prefixStore.ReverseIterator(nil, nil)
   728  	defer iter.Close()
   729  
   730  	if iter.Valid() {
   731  		pos = sdk.BigEndianToUint64(iter.Key())
   732  	}
   733  	// then store with incrementing position
   734  	for _, e := range newEntries {
   735  		pos++
   736  		key := types.GetContractCodeHistoryElementKey(contractAddr, pos)
   737  		store.Set(key, k.cdc.GetProtocMarshal().MustMarshal(&e)) //nolint:gosec
   738  	}
   739  }
   740  
   741  func (k Keeper) GetContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress) []types.ContractCodeHistoryEntry {
   742  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), types.GetContractCodeHistoryElementPrefix(contractAddr))
   743  
   744  	r := make([]types.ContractCodeHistoryEntry, 0)
   745  	iter := store.Iterator(nil, nil)
   746  	defer iter.Close()
   747  
   748  	for ; iter.Valid(); iter.Next() {
   749  		var e types.ContractCodeHistoryEntry
   750  		k.cdc.GetProtocMarshal().MustUnmarshal(iter.Value(), &e)
   751  		r = append(r, e)
   752  	}
   753  	return r
   754  }
   755  
   756  // getLastContractHistoryEntry returns the last element from history. To be used internally only as it panics when none exists
   757  func (k Keeper) getLastContractHistoryEntry(ctx sdk.Context, contractAddr sdk.AccAddress) types.ContractCodeHistoryEntry {
   758  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), types.GetContractCodeHistoryElementPrefix(contractAddr))
   759  	iter := store.ReverseIterator(nil, nil)
   760  	defer iter.Close()
   761  
   762  	var r types.ContractCodeHistoryEntry
   763  	if !iter.Valid() {
   764  		// all contracts have a history
   765  		panic(fmt.Sprintf("no history for %s", contractAddr.String()))
   766  	}
   767  	k.cdc.GetProtocMarshal().MustUnmarshal(iter.Value(), &r)
   768  	return r
   769  }
   770  
   771  // QuerySmart queries the smart contract itself.
   772  func (k Keeper) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) {
   773  	//defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "query-smart")
   774  
   775  	// checks and increase query stack size
   776  	ctx, err := checkAndIncreaseQueryStackSize(ctx, k.maxQueryStackSize)
   777  	if err != nil {
   778  		return nil, err
   779  	}
   780  
   781  	contractInfo, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr)
   782  	if err != nil {
   783  		return nil, err
   784  	}
   785  
   786  	smartQuerySetupCosts := k.gasRegister.InstantiateContractCosts(k.IsPinnedCode(ctx, contractInfo.CodeID), len(req))
   787  	ctx.GasMeter().ConsumeGas(smartQuerySetupCosts, "Loading CosmWasm module: query")
   788  
   789  	// prepare querier
   790  	querier := k.newQueryHandler(ctx, contractAddr)
   791  
   792  	env := types.NewEnv(ctx, contractAddr)
   793  	queryResult, gasUsed, qErr := k.wasmVM.Query(codeInfo.CodeHash, env, req, prefixStore, cosmwasmAPI, querier, k.gasMeter(ctx), k.runtimeGasForContract(ctx), costJSONDeserialization)
   794  	k.consumeRuntimeGas(ctx, gasUsed)
   795  	if qErr != nil {
   796  		return nil, sdkerrors.Wrap(types.ErrQueryFailed, qErr.Error())
   797  	}
   798  	return queryResult, nil
   799  }
   800  
   801  func checkAndIncreaseQueryStackSize(ctx sdk.Context, maxQueryStackSize uint32) (sdk.Context, error) {
   802  	var queryStackSize uint32
   803  
   804  	// read current value
   805  	if size := ctx.Context().Value(contextKeyQueryStackSize); size != nil {
   806  		queryStackSize = size.(uint32)
   807  	} else {
   808  		queryStackSize = 0
   809  	}
   810  
   811  	// increase
   812  	queryStackSize++
   813  
   814  	// did we go too far?
   815  	if queryStackSize > maxQueryStackSize {
   816  		return ctx, types.ErrExceedMaxQueryStackSize
   817  	}
   818  
   819  	// set updated stack size
   820  	contextCtx := context.WithValue(ctx.Context(), contextKeyQueryStackSize, queryStackSize)
   821  	ctx.SetContext(contextCtx)
   822  
   823  	return ctx, nil
   824  }
   825  
   826  // QueryRaw returns the contract's state for give key. Returns `nil` when key is `nil`.
   827  func (k Keeper) QueryRaw(ctx sdk.Context, contractAddress sdk.AccAddress, key []byte) []byte {
   828  	//defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "query-raw")
   829  	if key == nil {
   830  		return nil
   831  	}
   832  	prefixStoreKey := types.GetContractStorePrefix(contractAddress)
   833  	prefixStore := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), prefixStoreKey)
   834  	return prefixStore.Get(key)
   835  }
   836  
   837  func (k Keeper) contractInstance(ctx sdk.Context, contractAddress sdk.AccAddress) (types.ContractInfo, types.CodeInfo, types.StoreAdapter, error) {
   838  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   839  	contractBz := store.Get(types.GetContractAddressKey(contractAddress))
   840  	if contractBz == nil {
   841  		return types.ContractInfo{}, types.CodeInfo{}, types.StoreAdapter{}, sdkerrors.Wrap(types.ErrNotFound, "contract")
   842  	}
   843  	var contractInfo types.ContractInfo
   844  	k.cdc.GetProtocMarshal().MustUnmarshal(contractBz, &contractInfo)
   845  
   846  	codeInfoBz := store.Get(types.GetCodeKey(contractInfo.CodeID))
   847  	if codeInfoBz == nil {
   848  		return contractInfo, types.CodeInfo{}, types.StoreAdapter{}, sdkerrors.Wrap(types.ErrNotFound, "code info")
   849  	}
   850  	var codeInfo types.CodeInfo
   851  	k.cdc.GetProtocMarshal().MustUnmarshal(codeInfoBz, &codeInfo)
   852  	prefixStoreKey := types.GetContractStorePrefix(contractAddress)
   853  	prefixStore := prefix.NewStore(store, prefixStoreKey)
   854  	return contractInfo, codeInfo, types.NewStoreAdapter(prefixStore), nil
   855  }
   856  
   857  func (k Keeper) GetContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress) *types.ContractInfo {
   858  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   859  	var contract types.ContractInfo
   860  	contractBz := store.Get(types.GetContractAddressKey(contractAddress))
   861  	if contractBz == nil {
   862  		return nil
   863  	}
   864  	k.cdc.GetProtocMarshal().MustUnmarshal(contractBz, &contract)
   865  	return &contract
   866  }
   867  
   868  func (k Keeper) HasContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress) bool {
   869  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   870  	return store.Has(types.GetContractAddressKey(contractAddress))
   871  }
   872  
   873  // storeContractInfo persists the ContractInfo. No secondary index updated here.
   874  func (k Keeper) storeContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress, contract *types.ContractInfo) {
   875  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   876  	store.Set(types.GetContractAddressKey(contractAddress), k.cdc.GetProtocMarshal().MustMarshal(contract))
   877  }
   878  
   879  func (k Keeper) IterateContractInfo(ctx sdk.Context, cb func(sdk.AccAddress, types.ContractInfo) bool) {
   880  	prefixStore := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), types.ContractKeyPrefix)
   881  	iter := prefixStore.Iterator(nil, nil)
   882  	defer iter.Close()
   883  
   884  	for ; iter.Valid(); iter.Next() {
   885  		var contract types.ContractInfo
   886  		k.cdc.GetProtocMarshal().MustUnmarshal(iter.Value(), &contract)
   887  		// cb returns true to stop early
   888  		if cb(iter.Key(), contract) {
   889  			break
   890  		}
   891  	}
   892  }
   893  
   894  // IterateContractState iterates through all elements of the key value store for the given contract address and passes
   895  // them to the provided callback function. The callback method can return true to abort early.
   896  func (k Keeper) IterateContractState(ctx sdk.Context, contractAddress sdk.AccAddress, cb func(key, value []byte) bool) {
   897  	prefixStoreKey := types.GetContractStorePrefix(contractAddress)
   898  	prefixStore := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), prefixStoreKey)
   899  
   900  	iter := prefixStore.Iterator(nil, nil)
   901  	defer iter.Close()
   902  
   903  	for ; iter.Valid(); iter.Next() {
   904  		if cb(iter.Key(), iter.Value()) {
   905  			break
   906  		}
   907  	}
   908  }
   909  
   910  func (k Keeper) importContractState(ctx sdk.Context, contractAddress sdk.AccAddress, models []types.Model) error {
   911  	prefixStoreKey := types.GetContractStorePrefix(contractAddress)
   912  	prefixStore := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), prefixStoreKey)
   913  	for _, model := range models {
   914  		if model.Value == nil {
   915  			model.Value = []byte{}
   916  		}
   917  		if prefixStore.Has(model.Key) {
   918  			return sdkerrors.Wrapf(types.ErrDuplicate, "duplicate key: %x", model.Key)
   919  		}
   920  		prefixStore.Set(model.Key, model.Value)
   921  	}
   922  	return nil
   923  }
   924  
   925  func (k Keeper) GetCodeInfo(ctx sdk.Context, codeID uint64) *types.CodeInfo {
   926  
   927  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   928  	var codeInfo types.CodeInfo
   929  	codeInfoBz := store.Get(types.GetCodeKey(codeID))
   930  	if codeInfoBz == nil {
   931  		return nil
   932  	}
   933  	k.cdc.GetProtocMarshal().MustUnmarshal(codeInfoBz, &codeInfo)
   934  	return &codeInfo
   935  }
   936  
   937  func (k Keeper) containsCodeInfo(ctx sdk.Context, codeID uint64) bool {
   938  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   939  	return store.Has(types.GetCodeKey(codeID))
   940  }
   941  
   942  func (k Keeper) IterateCodeInfos(ctx sdk.Context, cb func(uint64, types.CodeInfo) bool) {
   943  	prefixStore := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), types.CodeKeyPrefix)
   944  
   945  	iter := prefixStore.Iterator(nil, nil)
   946  	defer iter.Close()
   947  
   948  	for ; iter.Valid(); iter.Next() {
   949  		var c types.CodeInfo
   950  		k.cdc.GetProtocMarshal().MustUnmarshal(iter.Value(), &c)
   951  		// cb returns true to stop early
   952  		if cb(binary.BigEndian.Uint64(iter.Key()), c) {
   953  			return
   954  		}
   955  	}
   956  }
   957  
   958  func (k Keeper) GetByteCode(ctx sdk.Context, codeID uint64) ([]byte, error) {
   959  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   960  
   961  	var codeInfo types.CodeInfo
   962  	codeInfoBz := store.Get(types.GetCodeKey(codeID))
   963  	if codeInfoBz == nil {
   964  		return nil, nil
   965  	}
   966  	k.cdc.GetProtocMarshal().MustUnmarshal(codeInfoBz, &codeInfo)
   967  	return k.wasmVM.GetCode(codeInfo.CodeHash)
   968  }
   969  
   970  // PinCode pins the wasm contract in wasmvm cache
   971  func (k Keeper) pinCode(ctx sdk.Context, codeID uint64) error {
   972  	codeInfo := k.GetCodeInfo(ctx, codeID)
   973  	if codeInfo == nil {
   974  		return sdkerrors.Wrap(types.ErrNotFound, "code info")
   975  	}
   976  
   977  	if err := k.wasmVM.Pin(codeInfo.CodeHash); err != nil {
   978  		return sdkerrors.Wrap(types.ErrPinContractFailed, err.Error())
   979  	}
   980  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
   981  
   982  	// store 1 byte to not run into `nil` debugging issues
   983  	store.Set(types.GetPinnedCodeIndexPrefix(codeID), []byte{1})
   984  
   985  	ctx.EventManager().EmitEvent(sdk.NewEvent(
   986  		types.EventTypePinCode,
   987  		sdk.NewAttribute(types.AttributeKeyCodeID, strconv.FormatUint(codeID, 10)),
   988  	))
   989  	return nil
   990  }
   991  
   992  // UnpinCode removes the wasm contract from wasmvm cache
   993  func (k Keeper) unpinCode(ctx sdk.Context, codeID uint64) error {
   994  	codeInfo := k.GetCodeInfo(ctx, codeID)
   995  	if codeInfo == nil {
   996  		return sdkerrors.Wrap(types.ErrNotFound, "code info")
   997  	}
   998  	if err := k.wasmVM.Unpin(codeInfo.CodeHash); err != nil {
   999  		return sdkerrors.Wrap(types.ErrUnpinContractFailed, err.Error())
  1000  	}
  1001  
  1002  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
  1003  
  1004  	store.Delete(types.GetPinnedCodeIndexPrefix(codeID))
  1005  
  1006  	ctx.EventManager().EmitEvent(sdk.NewEvent(
  1007  		types.EventTypeUnpinCode,
  1008  		sdk.NewAttribute(types.AttributeKeyCodeID, strconv.FormatUint(codeID, 10)),
  1009  	))
  1010  	return nil
  1011  }
  1012  
  1013  // IsPinnedCode returns true when codeID is pinned in wasmvm cache
  1014  func (k Keeper) IsPinnedCode(ctx sdk.Context, codeID uint64) bool {
  1015  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
  1016  	return store.Has(types.GetPinnedCodeIndexPrefix(codeID))
  1017  }
  1018  
  1019  // InitializePinnedCodes updates wasmvm to pin to cache all contracts marked as pinned
  1020  func (k Keeper) InitializePinnedCodes(ctx sdk.Context) error {
  1021  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), types.PinnedCodeIndexPrefix)
  1022  
  1023  	iter := store.Iterator(nil, nil)
  1024  	defer iter.Close()
  1025  
  1026  	for ; iter.Valid(); iter.Next() {
  1027  		codeInfo := k.GetCodeInfo(ctx, types.ParsePinnedCodeIndex(iter.Key()))
  1028  		if codeInfo == nil {
  1029  			return sdkerrors.Wrap(types.ErrNotFound, "code info")
  1030  		}
  1031  		if err := k.wasmVM.Pin(codeInfo.CodeHash); err != nil {
  1032  			return sdkerrors.Wrap(types.ErrPinContractFailed, err.Error())
  1033  		}
  1034  	}
  1035  	return nil
  1036  }
  1037  
  1038  // setContractInfoExtension updates the extension point data that is stored with the contract info
  1039  func (k Keeper) setContractInfoExtension(ctx sdk.Context, contractAddr sdk.AccAddress, ext types.ContractInfoExtension) error {
  1040  	info := k.GetContractInfo(ctx, contractAddr)
  1041  	if info == nil {
  1042  		return sdkerrors.Wrap(types.ErrNotFound, "contract info")
  1043  	}
  1044  	if err := info.SetExtension(ext); err != nil {
  1045  		return err
  1046  	}
  1047  	k.storeContractInfo(ctx, contractAddr, info)
  1048  	return nil
  1049  }
  1050  
  1051  // setAccessConfig updates the access config of a code id.
  1052  func (k Keeper) setAccessConfig(ctx sdk.Context, codeID uint64, config types.AccessConfig) error {
  1053  	info := k.GetCodeInfo(ctx, codeID)
  1054  	if info == nil {
  1055  		return sdkerrors.Wrap(types.ErrNotFound, "code info")
  1056  	}
  1057  	info.InstantiateConfig = config
  1058  	k.storeCodeInfo(ctx, codeID, *info)
  1059  	return nil
  1060  }
  1061  
  1062  // handleContractResponse processes the contract response data by emitting events and sending sub-/messages.
  1063  func (k *Keeper) handleContractResponse(
  1064  	ctx sdk.Context,
  1065  	contractAddr sdk.AccAddress,
  1066  	ibcPort string,
  1067  	msgs []wasmvmtypes.SubMsg,
  1068  	attrs []wasmvmtypes.EventAttribute,
  1069  	data []byte,
  1070  	evts wasmvmtypes.Events,
  1071  ) ([]byte, error) {
  1072  	attributeGasCost := k.gasRegister.EventCosts(attrs, evts)
  1073  	ctx.GasMeter().ConsumeGas(attributeGasCost, "Custom contract event attributes")
  1074  	// emit all events from this contract itself
  1075  	if len(attrs) != 0 {
  1076  		wasmEvents, err := newWasmModuleEvent(attrs, contractAddr)
  1077  		if err != nil {
  1078  			return nil, err
  1079  		}
  1080  		ctx.EventManager().EmitEvents(wasmEvents)
  1081  	}
  1082  	if len(evts) > 0 {
  1083  		customEvents, err := newCustomEvents(evts, contractAddr)
  1084  		if err != nil {
  1085  			return nil, err
  1086  		}
  1087  		ctx.EventManager().EmitEvents(customEvents)
  1088  	}
  1089  	return k.wasmVMResponseHandler.Handle(ctx, contractAddr, ibcPort, msgs, data)
  1090  }
  1091  
  1092  func (k Keeper) runtimeGasForContract(ctx sdk.Context) uint64 {
  1093  	meter := ctx.GasMeter()
  1094  	if meter.IsOutOfGas() {
  1095  		return 0
  1096  	}
  1097  	if meter.Limit() == 0 { // infinite gas meter with limit=0 and not out of gas
  1098  		return math.MaxUint64
  1099  	}
  1100  	return k.gasRegister.ToWasmVMGas(meter.Limit() - meter.GasConsumedToLimit())
  1101  }
  1102  
  1103  func (k Keeper) consumeRuntimeGas(ctx sdk.Context, gas uint64) {
  1104  	consumed := k.gasRegister.FromWasmVMGas(gas)
  1105  	ctx.GasMeter().ConsumeGas(consumed, "wasm contract")
  1106  	// throw OutOfGas error if we ran out (got exactly to zero due to better limit enforcing)
  1107  	if ctx.GasMeter().IsOutOfGas() {
  1108  		panic(sdk.ErrorOutOfGas{Descriptor: "Wasmer function execution"})
  1109  	}
  1110  }
  1111  
  1112  // generates a contract address from codeID + instanceID
  1113  func (k Keeper) generateContractAddress(ctx sdk.Context, codeID uint64) sdk.AccAddress {
  1114  	instanceID := k.autoIncrementID(ctx, types.KeyLastInstanceID)
  1115  	return BuildContractAddress(codeID, instanceID)
  1116  }
  1117  
  1118  // BuildContractAddress builds an sdk account address for a contract.
  1119  func BuildContractAddress(codeID, instanceID uint64) sdk.AccAddress {
  1120  	contractID := make([]byte, 16)
  1121  	binary.BigEndian.PutUint64(contractID[:8], codeID)
  1122  	binary.BigEndian.PutUint64(contractID[8:], instanceID)
  1123  	return types.Module(types.ModuleName, contractID)[:types.ContractAddrLen]
  1124  }
  1125  
  1126  func (k Keeper) autoIncrementID(ctx sdk.Context, lastIDKey []byte) uint64 {
  1127  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
  1128  
  1129  	bz := store.Get(lastIDKey)
  1130  	id := uint64(1)
  1131  	if bz != nil {
  1132  		id = binary.BigEndian.Uint64(bz)
  1133  	}
  1134  	bz = sdk.Uint64ToBigEndian(id + 1)
  1135  	store.Set(lastIDKey, bz)
  1136  	return id
  1137  }
  1138  
  1139  // PeekAutoIncrementID reads the current value without incrementing it.
  1140  func (k Keeper) PeekAutoIncrementID(ctx sdk.Context, lastIDKey []byte) uint64 {
  1141  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
  1142  	bz := store.Get(lastIDKey)
  1143  	id := uint64(1)
  1144  	if bz != nil {
  1145  		id = binary.BigEndian.Uint64(bz)
  1146  	}
  1147  	return id
  1148  }
  1149  
  1150  func (k Keeper) importAutoIncrementID(ctx sdk.Context, lastIDKey []byte, val uint64) error {
  1151  	store := k.ada.NewStore(ctx.GasMeter(), ctx.KVStore(k.storeKey), nil)
  1152  
  1153  	if store.Has(lastIDKey) {
  1154  		return sdkerrors.Wrapf(types.ErrDuplicate, "autoincrement id: %s", string(lastIDKey))
  1155  	}
  1156  	bz := sdk.Uint64ToBigEndian(val)
  1157  	store.Set(lastIDKey, bz)
  1158  	return nil
  1159  }
  1160  
  1161  func (k Keeper) importContract(ctx sdk.Context, contractAddr sdk.AccAddress, c *types.ContractInfo, state []types.Model) error {
  1162  	if !k.containsCodeInfo(ctx, c.CodeID) {
  1163  		return sdkerrors.Wrapf(types.ErrNotFound, "code id: %d", c.CodeID)
  1164  	}
  1165  	if k.HasContractInfo(ctx, contractAddr) {
  1166  		return sdkerrors.Wrapf(types.ErrDuplicate, "contract: %s", contractAddr)
  1167  	}
  1168  
  1169  	historyEntry := c.ResetFromGenesis(ctx)
  1170  	k.appendToContractHistory(ctx, contractAddr, historyEntry)
  1171  	k.storeContractInfo(ctx, contractAddr, c)
  1172  	k.addToContractCodeSecondaryIndex(ctx, contractAddr, historyEntry)
  1173  	return k.importContractState(ctx, contractAddr, state)
  1174  }
  1175  
  1176  func (k Keeper) newQueryHandler(ctx sdk.Context, contractAddress sdk.AccAddress) QueryHandler {
  1177  	return NewQueryHandler(ctx, k.wasmVMQueryHandler, contractAddress, k.gasRegister)
  1178  }
  1179  
  1180  // MultipliedGasMeter wraps the GasMeter from context and multiplies all reads by out defined multiplier
  1181  type MultipliedGasMeter struct {
  1182  	originalMeter sdk.GasMeter
  1183  	GasRegister   GasRegister
  1184  }
  1185  
  1186  func NewMultipliedGasMeter(originalMeter sdk.GasMeter, gr GasRegister) MultipliedGasMeter {
  1187  	return MultipliedGasMeter{originalMeter: originalMeter, GasRegister: gr}
  1188  }
  1189  
  1190  var _ wasmvm.GasMeter = MultipliedGasMeter{}
  1191  
  1192  func (m MultipliedGasMeter) GasConsumed() sdk.Gas {
  1193  	return m.GasRegister.ToWasmVMGas(m.originalMeter.GasConsumed())
  1194  }
  1195  
  1196  func (k Keeper) gasMeter(ctx sdk.Context) MultipliedGasMeter {
  1197  	return NewMultipliedGasMeter(ctx.GasMeter(), k.gasRegister)
  1198  }
  1199  
  1200  // Logger returns a module-specific logger.
  1201  func (k Keeper) Logger(ctx sdk.Context) log.Logger {
  1202  	return moduleLogger(ctx)
  1203  }
  1204  
  1205  func (k *Keeper) SetInnerTxKeeper(innertxKeeper innertx.InnerTxKeeper) {
  1206  	k.innertxKeeper = innertxKeeper
  1207  }
  1208  
  1209  func moduleLogger(ctx sdk.Context) log.Logger {
  1210  	return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
  1211  }
  1212  
  1213  // Querier creates a new grpc querier instance
  1214  func Querier(k *Keeper) *grpcQuerier {
  1215  	return NewGrpcQuerier(*k.cdc, k.storeKey, k, k.queryGasLimit)
  1216  }
  1217  
  1218  // QueryGasLimit returns the gas limit for smart queries.
  1219  func (k Keeper) QueryGasLimit() sdk.Gas {
  1220  	return k.queryGasLimit
  1221  }
  1222  
  1223  // BankCoinTransferrer replicates the cosmos-sdk behaviour as in
  1224  // https://github.com/fibonacci-chain/fbc/libs/cosmos-sdk/blob/v0.41.4/x/bank/keeper/msg_server.go#L26
  1225  type BankCoinTransferrer struct {
  1226  	keeper types.BankKeeper
  1227  }
  1228  
  1229  func NewBankCoinTransferrer(keeper types.BankKeeper) BankCoinTransferrer {
  1230  	return BankCoinTransferrer{
  1231  		keeper: keeper,
  1232  	}
  1233  }
  1234  
  1235  // TransferCoins transfers coins from source to destination account when coin send was enabled for them and the recipient
  1236  // is not in the blocked address list.
  1237  func (c BankCoinTransferrer) TransferCoins(parentCtx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amount sdk.Coins) error {
  1238  	em := sdk.NewEventManager()
  1239  	ctx := *parentCtx.SetEventManager(em)
  1240  	if err := c.keeper.IsSendEnabledCoins(ctx, amount...); err != nil {
  1241  		return err
  1242  	}
  1243  	if c.keeper.BlockedAddr(toAddr) {
  1244  		return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", toAddr.String())
  1245  	}
  1246  
  1247  	sdkerr := c.keeper.SendCoins(ctx, fromAddr, toAddr, amount)
  1248  	if sdkerr != nil {
  1249  		return sdkerr
  1250  	}
  1251  	for _, e := range em.Events() {
  1252  		if e.Type == sdk.EventTypeMessage { // skip messages as we talk to the keeper directly
  1253  			continue
  1254  		}
  1255  		parentCtx.EventManager().EmitEvent(e)
  1256  	}
  1257  	return nil
  1258  }
  1259  
  1260  type msgDispatcher interface {
  1261  	DispatchSubmessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error)
  1262  }
  1263  
  1264  // DefaultWasmVMContractResponseHandler default implementation that first dispatches submessage then normal messages.
  1265  // The Submessage execution may include an success/failure response handling by the contract that can overwrite the
  1266  // original
  1267  type DefaultWasmVMContractResponseHandler struct {
  1268  	md msgDispatcher
  1269  }
  1270  
  1271  func NewDefaultWasmVMContractResponseHandler(md msgDispatcher) *DefaultWasmVMContractResponseHandler {
  1272  	return &DefaultWasmVMContractResponseHandler{md: md}
  1273  }
  1274  
  1275  // Handle processes the data returned by a contract invocation.
  1276  func (h DefaultWasmVMContractResponseHandler) Handle(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, messages []wasmvmtypes.SubMsg, origRspData []byte) ([]byte, error) {
  1277  	result := origRspData
  1278  	switch rsp, err := h.md.DispatchSubmessages(ctx, contractAddr, ibcPort, messages); {
  1279  	case err != nil:
  1280  		return nil, sdkerrors.Wrap(err, "submessages")
  1281  	case rsp != nil:
  1282  		result = rsp
  1283  	}
  1284  	return result, nil
  1285  }