Add staking queries with some open TODOs

This commit is contained in:
Ethan Frey
2020-05-11 11:28:07 +02:00
parent e6dd80493b
commit 6b88cefe43
4 changed files with 109 additions and 13 deletions

View File

@@ -3,12 +3,12 @@ package keeper
import (
"encoding/json"
"fmt"
"github.com/cosmos/cosmos-sdk/x/distribution"
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"
"github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmwasm/wasmd/x/wasm/internal/types"
)

View File

@@ -2,6 +2,7 @@ package keeper
import (
"encoding/binary"
"github.com/cosmos/cosmos-sdk/x/staking"
"path/filepath"
wasm "github.com/CosmWasm/go-cosmwasm"
@@ -43,6 +44,7 @@ type Keeper struct {
// 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,
stakingKeeper staking.Keeper,
router sdk.Router, homeDir string, wasmConfig types.WasmConfig, customEncoders *MessageEncoders, customPlugins *QueryPlugins) Keeper {
wasmer, err := wasm.NewWasmer(filepath.Join(homeDir, "wasm"), wasmConfig.CacheSize)
if err != nil {
@@ -60,7 +62,7 @@ func NewKeeper(cdc *codec.Codec, storeKey sdk.StoreKey, accountKeeper auth.Accou
messenger: messenger,
queryGasLimit: wasmConfig.SmartQueryGasLimit,
}
keeper.queryPlugins = DefaultQueryPlugins(bankKeeper, keeper).Merge(customPlugins)
keeper.queryPlugins = DefaultQueryPlugins(bankKeeper, stakingKeeper, keeper).Merge(customPlugins)
return keeper
}

View File

@@ -6,6 +6,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/staking"
)
type QueryHandler struct {
@@ -31,18 +32,20 @@ func (q QueryHandler) Query(request wasmTypes.QueryRequest) ([]byte, error) {
return nil, wasmTypes.Unknown{}
}
type CustomQuerier func(ctx sdk.Context, request json.RawMessage) ([]byte, error)
type QueryPlugins struct {
Bank func(ctx sdk.Context, request *wasmTypes.BankQuery) ([]byte, error)
Custom func(ctx sdk.Context, request json.RawMessage) ([]byte, error)
Custom CustomQuerier
Staking func(ctx sdk.Context, request *wasmTypes.StakingQuery) ([]byte, error)
Wasm func(ctx sdk.Context, request *wasmTypes.WasmQuery) ([]byte, error)
}
func DefaultQueryPlugins(bank bank.ViewKeeper, wasm Keeper) QueryPlugins {
func DefaultQueryPlugins(bank bank.ViewKeeper, staking staking.Keeper, wasm Keeper) QueryPlugins {
return QueryPlugins{
Bank: BankQuerier(bank),
Custom: NoCustomQuerier,
Staking: NoStakingQuerier,
Staking: StakingQuerier(staking),
Wasm: WasmQuerier(wasm),
}
}
@@ -103,8 +106,72 @@ func NoCustomQuerier(ctx sdk.Context, request json.RawMessage) ([]byte, error) {
return nil, wasmTypes.UnsupportedRequest{"custom"}
}
func NoStakingQuerier(ctx sdk.Context, request *wasmTypes.StakingQuery) ([]byte, error) {
return nil, wasmTypes.UnsupportedRequest{"staking"}
func StakingQuerier(keeper staking.Keeper) func(ctx sdk.Context, request *wasmTypes.StakingQuery) ([]byte, error) {
return func(ctx sdk.Context, request *wasmTypes.StakingQuery) ([]byte, error) {
if request.Validators != nil {
validators := keeper.GetBondedValidatorsByPower(ctx)
wasmVals := make([]wasmTypes.Validator, len(validators))
for i, v := range validators {
wasmVals[i] = wasmTypes.Validator{
Address: v.OperatorAddress.String(),
Commission: decToWasm(v.Commission.Rate),
MaxCommission: decToWasm(v.Commission.MaxRate),
MaxChangeRate: decToWasm(v.Commission.MaxChangeRate),
}
}
res := wasmTypes.ValidatorsResponse{
Validators: wasmVals,
}
return json.Marshal(res)
}
if request.Delegations != nil {
delegator, err := sdk.AccAddressFromBech32(request.Delegations.Delegator)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, request.Delegations.Delegator)
}
var validator sdk.ValAddress
validator, err = sdk.ValAddressFromBech32(request.Delegations.Validator)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, request.Delegations.Validator)
}
// get delegations
var sdkDels []staking.Delegation
if len(validator) == 0 {
sdkDels = keeper.GetAllDelegatorDelegations(ctx, delegator)
} else {
d, found := keeper.GetDelegation(ctx, delegator, validator)
if found {
sdkDels = []staking.Delegation{d}
}
}
// convert them
delegations := make([]wasmTypes.Delegation, len(sdkDels))
for i, d := range sdkDels {
// shares to funds (amount, acc rewards)
// Validator.tokens * del.Shares / Validator.Shares ???
// Accumulated Rewards???
// can relegate? other query for redelegations?
// keeper.GetRedelegation
delegations[i] = wasmTypes.Delegation{
Delegator: d.DelegatorAddress.String(),
Validator: d.ValidatorAddress.String(),
// TODO: Amount
// TODO: AccumulatedRewards
CanRedelegate: true,
}
}
res := wasmTypes.DelegationsResponse{
Delegations: delegations,
}
return json.Marshal(res)
}
return nil, wasmTypes.UnsupportedRequest{"unknown Staking variant"}
}
}
func WasmQuerier(wasm Keeper) func(ctx sdk.Context, request *wasmTypes.WasmQuery) ([]byte, error) {
@@ -140,3 +207,15 @@ func convertSdkCoinToWasmCoin(coins []sdk.Coin) wasmTypes.Coins {
}
return converted
}
// TODO: move this into go-cosmwasm, so it stays close to the definitions
var WasmDecMultiplier int64 = 1_000_000
// Take the bigDec type and fit it into the wasm uint64 type (
func decToWasm(dec sdk.Dec) uint64 {
mul := dec.MulInt64(WasmDecMultiplier).TruncateInt64()
if mul < 0 {
panic("Try to conver negative value to uint64")
}
return uint64(mul)
}

View File

@@ -2,6 +2,8 @@ package keeper
import (
"fmt"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/supply"
"testing"
"time"
@@ -44,6 +46,8 @@ func MakeTestCodec() *codec.Codec {
func CreateTestInput(t *testing.T, isCheckTx bool, tempDir string, encoders *MessageEncoders, queriers *QueryPlugins) (sdk.Context, auth.AccountKeeper, Keeper) {
keyContract := sdk.NewKVStoreKey(types.StoreKey)
keyAcc := sdk.NewKVStoreKey(auth.StoreKey)
keyStaking := sdk.NewKVStoreKey(staking.StoreKey)
keySupply := sdk.NewKVStoreKey(supply.StoreKey)
keyParams := sdk.NewKVStoreKey(params.StoreKey)
tkeyParams := sdk.NewTransientStoreKey(params.TStoreKey)
@@ -71,22 +75,33 @@ func CreateTestInput(t *testing.T, isCheckTx bool, tempDir string, encoders *Mes
auth.ProtoBaseAccount, // prototype
)
bk := bank.NewBaseKeeper(
bankKeeper := bank.NewBaseKeeper(
accountKeeper,
pk.Subspace(bank.DefaultParamspace),
nil,
)
bk.SetSendEnabled(ctx, true)
bankKeeper.SetSendEnabled(ctx, true)
maccPerms := map[string][]string{
//mint.ModuleName: {supply.Minter},
staking.BondedPoolName: {supply.Burner, supply.Staking},
staking.NotBondedPoolName: {supply.Burner, supply.Staking},
//gov.ModuleName: {supply.Burner},
}
supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, maccPerms)
stakingKeeper := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace))
// TODO: register slashing (and more?)
router := baseapp.NewRouter()
h := bank.NewHandler(bk)
router.AddRoute(bank.RouterKey, h)
bh := bank.NewHandler(bankKeeper)
router.AddRoute(bank.RouterKey, bh)
sh := staking.NewHandler(stakingKeeper)
router.AddRoute(staking.RouterKey, sh)
// Load default wasm config
wasmConfig := wasmTypes.DefaultWasmConfig()
keeper := NewKeeper(cdc, keyContract, accountKeeper, bk, router, tempDir, wasmConfig, encoders, queriers)
keeper := NewKeeper(cdc, keyContract, accountKeeper, bankKeeper, stakingKeeper, router, tempDir, wasmConfig, encoders, queriers)
// add wasm handler so we can loop-back (contracts calling contracts)
router.AddRoute(wasmTypes.RouterKey, TestHandler(keeper))