added querier to gov module

This commit is contained in:
Sunny Aggarwal 2018-08-03 12:55:00 -07:00
parent 1d1a95656a
commit 804baa70f4
5 changed files with 230 additions and 48 deletions

View File

@ -393,10 +393,18 @@ func handleQueryP2P(app *BaseApp, path []string, req abci.RequestQuery) (res abc
func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) {
// "/custom" prefix for keeper queries // "/custom" prefix for keeper queries
queryable := app.queryrouter.Route(path[1]) querier := app.queryrouter.Route(path[1])
ctx := app.checkState.ctx ctx := app.checkState.ctx
res, err := queryable.Query(ctx, path[2:], req) resBytes, err := querier(ctx, path[2:], req)
return if err != nil {
return abci.ResponseQuery{
Code: uint32(err.ABCICode()),
}
}
return abci.ResponseQuery{
Code: uint32(sdk.ABCICodeOK),
Value: resBytes,
}
} }
// BeginBlock implements the ABCI application interface. // BeginBlock implements the ABCI application interface.

View File

@ -6,14 +6,14 @@ import (
// QueryRouter provides queryables for each query path. // QueryRouter provides queryables for each query path.
type QueryRouter interface { type QueryRouter interface {
AddRoute(r string, h sdk.CustomQueryable) (rtr QueryRouter) AddRoute(r string, h sdk.Querier) (rtr QueryRouter)
Route(path string) (h sdk.CustomQueryable) Route(path string) (h sdk.Querier)
} }
// map a transaction type to a handler and an initgenesis function // map a transaction type to a handler and an initgenesis function
type queryroute struct { type queryroute struct {
r string r string
h sdk.CustomQueryable h sdk.Querier
} }
type queryrouter struct { type queryrouter struct {
@ -30,7 +30,7 @@ func NewQueryRouter() *queryrouter {
} }
// AddRoute - TODO add description // AddRoute - TODO add description
func (rtr *queryrouter) AddRoute(r string, h sdk.CustomQueryable) QueryRouter { func (rtr *queryrouter) AddRoute(r string, h sdk.Querier) QueryRouter {
if !isAlphaNumeric(r) { if !isAlphaNumeric(r) {
panic("route expressions can only contain alphanumeric characters") panic("route expressions can only contain alphanumeric characters")
} }
@ -41,7 +41,7 @@ func (rtr *queryrouter) AddRoute(r string, h sdk.CustomQueryable) QueryRouter {
// Route - TODO add description // Route - TODO add description
// TODO handle expressive matches. // TODO handle expressive matches.
func (rtr *queryrouter) Route(path string) (h sdk.CustomQueryable) { func (rtr *queryrouter) Route(path string) (h sdk.Querier) {
for _, route := range rtr.routes { for _, route := range rtr.routes {
if route.r == path { if route.r == path {
return route.h return route.h

View File

@ -2,6 +2,5 @@ package types
import abci "github.com/tendermint/tendermint/abci/types" import abci "github.com/tendermint/tendermint/abci/types"
type CustomQueryable interface { // Type for querier functions on keepers to implement to handle custom queries
Query(ctx Context, path []string, req abci.RequestQuery) (res []byte, err Error) type Querier = func(ctx Context, path []string, req abci.RequestQuery) (res []byte, err Error)
}

View File

@ -108,6 +108,52 @@ func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposal Proposal) {
store.Delete(KeyProposal(proposal.GetProposalID())) store.Delete(KeyProposal(proposal.GetProposalID()))
} }
// nolint: gocyclo
// Get Proposal from store by ProposalID
func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositerAddr sdk.AccAddress, status ProposalStatus, numLatest int64) []Proposal {
maxProposalID, err := keeper.peekCurrentProposalID(ctx)
if err != nil {
return nil
}
matchingProposals := []Proposal{}
if numLatest <= 0 {
numLatest = maxProposalID
}
for proposalID := maxProposalID - numLatest; proposalID < maxProposalID; proposalID++ {
if voterAddr != nil && len(voterAddr) != 0 {
_, found := keeper.GetVote(ctx, proposalID, voterAddr)
if !found {
continue
}
}
if depositerAddr != nil && len(depositerAddr) != 0 {
_, found := keeper.GetDeposit(ctx, proposalID, depositerAddr)
if !found {
continue
}
}
proposal := keeper.GetProposal(ctx, proposalID)
if proposal == nil {
continue
}
if validProposalStatus(status) {
if proposal.GetStatus() != status {
continue
}
}
matchingProposals = append(matchingProposals, proposal)
}
return matchingProposals
}
func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk.Error { func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk.Error {
store := ctx.KVStore(keeper.storeKey) store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyNextProposalID) bz := store.Get(KeyNextProposalID)
@ -131,6 +177,7 @@ func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) {
return return
} }
// Gets the next available ProposalID and increments it
func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) { func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) {
store := ctx.KVStore(keeper.storeKey) store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyNextProposalID) bz := store.Get(KeyNextProposalID)
@ -143,6 +190,19 @@ func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sd
return proposalID, nil return proposalID, nil
} }
// Peeks the next available ProposalID without incrementing it
func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyNextProposalID)
if bz == nil {
return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
}
keeper.cdc.MustUnmarshalBinary(bz, &proposalID)
bz = keeper.cdc.MustMarshalBinary(proposalID + 1)
store.Set(KeyNextProposalID, bz)
return proposalID, nil
}
func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) { func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) {
proposal.SetVotingStartBlock(ctx.BlockHeight()) proposal.SetVotingStartBlock(ctx.BlockHeight())
proposal.SetStatus(StatusVotingPeriod) proposal.SetStatus(StatusVotingPeriod)

View File

@ -5,52 +5,167 @@ import (
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
) )
type Querier struct { func NewQuerier(keeper Keeper) sdk.Querier {
keeper Keeper return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
} switch path[0] {
case "proposal":
func NewQuerier(keeper Keeper) { return queryProposal(ctx, path[1:], req, keeper)
return Querier{ case "deposit":
keeper: keeper, return queryDeposit(ctx, path[1:], req, keeper)
case "vote":
return queryVote(ctx, path[1:], req, keeper)
case "deposits":
return queryDeposits(ctx, path[1:], req, keeper)
case "votes":
return queryVotes(ctx, path[1:], req, keeper)
case "proposals":
return queryProposals(ctx, path[1:], req, keeper)
case "tally":
return queryTally(ctx, path[1:], req, keeper)
default:
return nil, sdk.ErrUnknownRequest("unknown gov query endpoint")
}
} }
} }
func (keeper Keeper) Query(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { // Params for query 'custom/gov/proposal'
switch path[0] { type QueryProposalParams struct {
case "tally": ProposalID int64
return QueryTally(ctx, path[1:], req)
case "proposal":
return handleMsgSubmitProposal(ctx, keeper, msg)
case MsgVote:
return handleMsgVote(ctx, keeper, msg)
default:
errMsg := "Unrecognized gov msg type"
return sdk.ErrUnknownRequest(errMsg).Result()
}
} }
func QueryProposal(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
var proposalID int64 var params QueryProposalParams
err := keeper.cdc.UnmarshalBinary(req.Data, proposalID) err2 := keeper.cdc.UnmarshalBinary(req.Data, &params)
if err != nil { if err2 != nil {
return []byte{}, sdk.ErrUnknownRequest() return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data")
} }
proposal := keeper.GetProposal(ctx, proposalID)
proposal := keeper.GetProposal(ctx, params.ProposalID)
if proposal == nil { if proposal == nil {
return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) return []byte{}, ErrUnknownProposal(DefaultCodespace, params.ProposalID)
} }
return keeper.cdc.MustMarshalBinary(proposal), nil return keeper.cdc.MustMarshalBinary(proposal), nil
} }
func QueryTally(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { // Params for query 'custom/gov/deposit'
var proposalID int64 type QueryDepositParams struct {
err := keeper.cdc.UnmarshalBinary(req.Data, proposalID) ProposalID int64
if err != nil { Depositer sdk.AccAddress
return []byte{}, sdk.ErrUnknownRequest() }
}
proposal := keeper.GetProposal(ctx, proposalID) func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
if proposal == nil { var params QueryDepositParams
return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) err2 := keeper.cdc.UnmarshalBinary(req.Data, params)
} if err2 != nil {
passes, _ := tally(ctx, keeper, proposal) return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data")
}
deposit, _ := keeper.GetDeposit(ctx, params.ProposalID, params.Depositer)
return keeper.cdc.MustMarshalBinary(deposit), nil
}
// Params for query 'custom/gov/vote'
type QueryVoteParams struct {
ProposalID int64
Voter sdk.AccAddress
}
func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
var params QueryVoteParams
err2 := keeper.cdc.UnmarshalBinary(req.Data, &params)
if err2 != nil {
return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data")
}
vote, _ := keeper.GetVote(ctx, params.ProposalID, params.Voter)
return keeper.cdc.MustMarshalBinary(vote), nil
}
// Params for query 'custom/gov/deposits'
type QueryDepositsParams struct {
ProposalID int64
}
func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
var params QueryDepositParams
err2 := keeper.cdc.UnmarshalBinary(req.Data, &params)
if err2 != nil {
return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data")
}
var deposits []Deposit
depositsIterator := keeper.GetDeposits(ctx, params.ProposalID)
for ; depositsIterator.Valid(); depositsIterator.Next() {
deposit := Deposit{}
keeper.cdc.MustUnmarshalBinary(depositsIterator.Value(), &deposit)
deposits = append(deposits, deposit)
}
return keeper.cdc.MustMarshalBinary(deposits), nil
}
// Params for query 'custom/gov/votes'
type QueryVotesParams struct {
ProposalID int64
}
func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
var params QueryVotesParams
err2 := keeper.cdc.UnmarshalBinary(req.Data, &params)
if err2 != nil {
return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data")
}
var votes []Vote
votesIterator := keeper.GetVotes(ctx, params.ProposalID)
for ; votesIterator.Valid(); votesIterator.Next() {
vote := Vote{}
keeper.cdc.MustUnmarshalBinary(votesIterator.Value(), &vote)
votes = append(votes, vote)
}
return keeper.cdc.MustMarshalBinary(votes), nil
}
// Params for query 'custom/gov/proposals'
type QueryProposalsParams struct {
Voter sdk.AccAddress
Depositer sdk.AccAddress
ProposalStatus ProposalStatus
NumLatestProposals int64
}
func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
var params QueryProposalsParams
err2 := keeper.cdc.UnmarshalBinary(req.Data, &params)
if err2 != nil {
return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data")
}
proposals := keeper.GetProposalsFiltered(ctx, params.Voter, params.Depositer, params.ProposalStatus, params.NumLatestProposals)
bz := keeper.cdc.MustMarshalBinary(proposals)
return bz, nil
}
// Params for query 'custom/gov/tally'
type QueryTallyParams struct {
ProposalID int64
}
func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
// TODO: Dependant on #1914
// var proposalID int64
// err2 := keeper.cdc.UnmarshalBinary(req.Data, proposalID)
// if err2 != nil {
// return []byte{}, sdk.ErrUnknownRequest()
// }
// proposal := keeper.GetProposal(ctx, proposalID)
// if proposal == nil {
// return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID)
// }
// _, tallyResult, _ := tally(ctx, keeper, proposal)
return nil, nil
} }