Add bank querier

This commit is contained in:
Ethan Frey 2020-05-06 13:58:18 +02:00
parent f4294868d6
commit 77d1ea4c22
3 changed files with 104 additions and 24 deletions

View File

@ -37,7 +37,7 @@ type Keeper struct {
router sdk.Router
wasmer wasm.Wasmer
querier QueryHandler
queryMods QueryModules
messenger MessageHandler
// queryGasLimit is the max wasm gas that can be spent on executing a query with a contract
queryGasLimit uint64
@ -52,7 +52,11 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, accountKeeper auth.Accou
}
messenger := MessageHandler{
router: router,
router: router,
encoders: DefaultEncoders(),
}
queryMods := QueryModules{
Bank: bankKeeper,
}
return Keeper{
@ -62,7 +66,7 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, accountKeeper auth.Accou
accountKeeper: accountKeeper,
bankKeeper: bankKeeper,
messenger: messenger,
querier: QueryHandler{}, // TODO: not empty
queryMods: queryMods,
queryGasLimit: wasmConfig.SmartQueryGasLimit,
}
}
@ -131,9 +135,15 @@ func (k Keeper) Instantiate(ctx sdk.Context, codeID uint64, creator sdk.AccAddre
prefixStoreKey := types.GetContractStorePrefixKey(contractAddress)
prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), prefixStoreKey)
// prepare querier
querier := QueryHandler{
Ctx: ctx,
Modules: k.queryMods,
}
// instantiate wasm contract
gas := gasForContract(ctx)
res, err := k.wasmer.Instantiate(codeInfo.CodeHash, params, initMsg, prefixStore, cosmwasmAPI, k.querier, gas)
res, err := k.wasmer.Instantiate(codeInfo.CodeHash, params, initMsg, prefixStore, cosmwasmAPI, querier, gas)
if err != nil {
return contractAddress, sdkerrors.Wrap(types.ErrInstantiateFailed, err.Error())
// return contractAddress, sdkerrors.Wrap(err, "cosmwasm instantiate")
@ -175,8 +185,14 @@ func (k Keeper) Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller
params := types.NewParams(ctx, caller, coins, contractAccount)
// prepare querier
querier := QueryHandler{
Ctx: ctx,
Modules: k.queryMods,
}
gas := gasForContract(ctx)
res, execErr := k.wasmer.Execute(codeInfo.CodeHash, params, msg, prefixStore, cosmwasmAPI, k.querier, gas)
res, execErr := k.wasmer.Execute(codeInfo.CodeHash, params, msg, prefixStore, cosmwasmAPI, querier, gas)
if execErr != nil {
// TODO: wasmer doesn't return gas used on error. we should consume it (for error on metering failure)
return sdk.Result{}, sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error())
@ -205,7 +221,12 @@ func (k Keeper) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []b
if err != nil {
return nil, err
}
queryResult, gasUsed, qErr := k.wasmer.Query(codeInfo.CodeHash, req, prefixStore, cosmwasmAPI, k.querier, gasForContract(ctx))
// prepare querier
querier := QueryHandler{
Ctx: ctx,
Modules: k.queryMods,
}
queryResult, gasUsed, qErr := k.wasmer.Query(codeInfo.CodeHash, req, prefixStore, cosmwasmAPI, querier, gasForContract(ctx))
if qErr != nil {
return nil, sdkerrors.Wrap(types.ErrQueryFailed, qErr.Error())
}

View File

@ -224,8 +224,6 @@ func TestInstantiateWithNonExistingCodeID(t *testing.T) {
}
func TestExecute(t *testing.T) {
// TODO
t.Skip("this causes a panic in the rust code!")
tempDir, err := ioutil.TempDir("", "wasm")
require.NoError(t, err)
defer os.RemoveAll(tempDir)
@ -286,7 +284,7 @@ func TestExecute(t *testing.T) {
// make sure gas is properly deducted from ctx
gasAfter := ctx.GasMeter().GasConsumed()
require.Equal(t, uint64(31162), gasAfter-gasBefore)
require.Equal(t, uint64(32196), gasAfter-gasBefore)
// ensure bob now exists and got both payments released
bobAcct = accKeeper.GetAccount(ctx, bob)

View File

@ -1,27 +1,88 @@
package keeper
import (
"encoding/json"
wasmTypes "github.com/CosmWasm/go-cosmwasm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/bank"
)
// TODO: make this something besides failure
// Give it sub-queriers
type QueryHandler struct{}
type QueryHandler struct {
Ctx sdk.Context
Modules QueryModules
}
var _ wasmTypes.Querier = QueryHandler{}
// Fill out more modules
// Rethink interfaces
type QueryModules struct {
Bank bank.ViewKeeper
}
//type QueryPlugins struct {
// Bank func(msg *wasmTypes.BankQuery) ([]byte, error)
// Custom func(msg json.RawMessage) ([]byte, error)
// Staking func(msg *wasmTypes.StakingQuery) ([]byte, error)
// Wasm func(msg *wasmTypes.WasmQuery) ([]byte, error)
//}
func (q QueryHandler) Query(request wasmTypes.QueryRequest) ([]byte, error) {
//if request.Bank != nil {
// return q.Bank.Query(request.Bank)
//}
//if request.Custom != nil {
// return q.Custom.Query(request.Custom)
//}
//if request.Staking != nil {
// return nil, wasmTypes.UnsupportedRequest{"staking"}
//}
//if request.Wasm != nil {
// return nil, wasmTypes.UnsupportedRequest{"wasm"}
//}
if request.Bank != nil {
return q.QueryBank(request.Bank)
}
// TODO: below
if request.Custom != nil {
return nil, wasmTypes.UnsupportedRequest{"custom"}
}
if request.Staking != nil {
return nil, wasmTypes.UnsupportedRequest{"staking"}
}
if request.Wasm != nil {
return nil, wasmTypes.UnsupportedRequest{"wasm"}
}
return nil, wasmTypes.Unknown{}
}
func (q QueryHandler) QueryBank(request *wasmTypes.BankQuery) ([]byte, error) {
if request.AllBalances != nil {
addr, err := sdk.AccAddressFromBech32(request.AllBalances.Address)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, request.AllBalances.Address)
}
coins := q.Modules.Bank.GetCoins(q.Ctx, addr)
res := wasmTypes.AllBalancesResponse{
Amount: convertSdkCoinToWasmCoin(coins),
}
return json.Marshal(res)
}
if request.Balance != nil {
addr, err := sdk.AccAddressFromBech32(request.Balance.Address)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, request.Balance.Address)
}
coins := q.Modules.Bank.GetCoins(q.Ctx, addr)
amount := coins.AmountOf(request.Balance.Denom)
res := wasmTypes.BalanceResponse{
Amount: wasmTypes.Coin{
Denom: request.Balance.Denom,
Amount: amount.String(),
},
}
return json.Marshal(res)
}
return nil, wasmTypes.UnsupportedRequest{"unknown BankQuery variant"}
}
func convertSdkCoinToWasmCoin(coins []sdk.Coin) wasmTypes.Coins {
var converted wasmTypes.Coins
for _, coin := range coins {
c := wasmTypes.Coin{
Denom: coin.Denom,
Amount: coin.Amount.String(),
}
converted = append(converted, c)
}
return converted
}