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) {
// "/custom" prefix for keeper queries
queryable := app.queryrouter.Route(path[1])
querier := app.queryrouter.Route(path[1])
ctx := app.checkState.ctx
res, err := queryable.Query(ctx, path[2:], req)
return
resBytes, err := querier(ctx, path[2:], req)
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.

View File

@ -6,14 +6,14 @@ import (
// QueryRouter provides queryables for each query path.
type QueryRouter interface {
AddRoute(r string, h sdk.CustomQueryable) (rtr QueryRouter)
Route(path string) (h sdk.CustomQueryable)
AddRoute(r string, h sdk.Querier) (rtr QueryRouter)
Route(path string) (h sdk.Querier)
}
// map a transaction type to a handler and an initgenesis function
type queryroute struct {
r string
h sdk.CustomQueryable
h sdk.Querier
}
type queryrouter struct {
@ -30,7 +30,7 @@ func NewQueryRouter() *queryrouter {
}
// 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) {
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
// 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 {
if route.r == path {
return route.h

View File

@ -2,6 +2,5 @@ package types
import abci "github.com/tendermint/tendermint/abci/types"
type CustomQueryable interface {
Query(ctx Context, path []string, req abci.RequestQuery) (res []byte, err Error)
}
// Type for querier functions on keepers to implement to handle custom queries
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()))
}
// 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 {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyNextProposalID)
@ -131,6 +177,7 @@ func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) {
return
}
// Gets the next available ProposalID and increments it
func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyNextProposalID)
@ -143,6 +190,19 @@ func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sd
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) {
proposal.SetVotingStartBlock(ctx.BlockHeight())
proposal.SetStatus(StatusVotingPeriod)

View File

@ -5,52 +5,167 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
)
type Querier struct {
keeper Keeper
}
func NewQuerier(keeper Keeper) {
return Querier{
keeper: keeper,
}
}
func (keeper Keeper) Query(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
func NewQuerier(keeper Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
switch path[0] {
case "tally":
return QueryTally(ctx, path[1:], req)
case "proposal":
return handleMsgSubmitProposal(ctx, keeper, msg)
case MsgVote:
return handleMsgVote(ctx, keeper, msg)
return queryProposal(ctx, path[1:], req, keeper)
case "deposit":
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:
errMsg := "Unrecognized gov msg type"
return sdk.ErrUnknownRequest(errMsg).Result()
return nil, sdk.ErrUnknownRequest("unknown gov query endpoint")
}
}
}
func QueryProposal(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
var proposalID int64
err := keeper.cdc.UnmarshalBinary(req.Data, proposalID)
if err != nil {
return []byte{}, sdk.ErrUnknownRequest()
// Params for query 'custom/gov/proposal'
type QueryProposalParams struct {
ProposalID int64
}
func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
var params QueryProposalParams
err2 := keeper.cdc.UnmarshalBinary(req.Data, &params)
if err2 != nil {
return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data")
}
proposal := keeper.GetProposal(ctx, proposalID)
proposal := keeper.GetProposal(ctx, params.ProposalID)
if proposal == nil {
return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID)
return []byte{}, ErrUnknownProposal(DefaultCodespace, params.ProposalID)
}
return keeper.cdc.MustMarshalBinary(proposal), nil
}
func QueryTally(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
var proposalID int64
err := keeper.cdc.UnmarshalBinary(req.Data, proposalID)
if err != nil {
return []byte{}, sdk.ErrUnknownRequest()
}
proposal := keeper.GetProposal(ctx, proposalID)
if proposal == nil {
return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID)
}
passes, _ := tally(ctx, keeper, proposal)
// Params for query 'custom/gov/deposit'
type QueryDepositParams struct {
ProposalID int64
Depositer sdk.AccAddress
}
func queryDeposit(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")
}
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
}