Merge branch 'develop' into bucky/gaiadebug-bech32

This commit is contained in:
Rigel 2018-06-27 20:28:48 -04:00 committed by GitHub
commit 36e8c27786
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 380 additions and 42 deletions

View File

@ -119,7 +119,7 @@ jobs:
for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | circleci tests split --split-by=timings); do for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | circleci tests split --split-by=timings); do
id=$(basename "$pkg") id=$(basename "$pkg")
go test -timeout 5m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic "$pkg" go test -timeout 8m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic "$pkg"
done done
- persist_to_workspace: - persist_to_workspace:
root: /tmp/workspace root: /tmp/workspace

View File

@ -12,6 +12,7 @@ BREAKING CHANGES
* Removed MsgChangePubKey from auth * Removed MsgChangePubKey from auth
* Removed setPubKey from account mapper * Removed setPubKey from account mapper
* Removed GetMemo from Tx (it is still on StdTx) * Removed GetMemo from Tx (it is still on StdTx)
* Gov module REST endpoints changed to be more RESTful
* [cli] rearranged commands under subcommands * [cli] rearranged commands under subcommands
* [stake] remove Tick and add EndBlocker * [stake] remove Tick and add EndBlocker
* [stake] introduce concept of unbonding for delegations and validators * [stake] introduce concept of unbonding for delegations and validators

View File

@ -475,6 +475,10 @@ func TestDeposit(t *testing.T) {
// query proposal // query proposal
proposal = getProposal(t, port, proposalID) proposal = getProposal(t, port, proposalID)
assert.True(t, proposal.TotalDeposit.IsEqual(sdk.Coins{sdk.NewCoin("steak", 10)})) assert.True(t, proposal.TotalDeposit.IsEqual(sdk.Coins{sdk.NewCoin("steak", 10)}))
// query deposit
deposit := getDeposit(t, port, proposalID, addr)
assert.True(t, deposit.Amount.IsEqual(sdk.Coins{sdk.NewCoin("steak", 10)}))
} }
func TestVote(t *testing.T) { func TestVote(t *testing.T) {
@ -515,6 +519,75 @@ func TestVote(t *testing.T) {
assert.Equal(t, gov.VoteOptionToString(gov.OptionYes), vote.Option) assert.Equal(t, gov.VoteOptionToString(gov.OptionYes), vote.Option)
} }
func TestProposalsQuery(t *testing.T) {
name, password := "test", "1234567890"
name2, password := "test2", "1234567890"
addr, seed := CreateAddr(t, "test", password, GetKB(t))
addr2, seed2 := CreateAddr(t, "test2", password, GetKB(t))
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.Address{addr, addr2})
defer cleanup()
// Addr1 proposes (and deposits) proposals #1 and #2
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
var proposalID1 int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID1)
tests.WaitForHeight(resultTx.Height+1, port)
resultTx = doSubmitProposal(t, port, seed, name, password, addr)
var proposalID2 int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID2)
tests.WaitForHeight(resultTx.Height+1, port)
// Addr2 proposes (and deposits) proposals #3
resultTx = doSubmitProposal(t, port, seed2, name2, password, addr2)
var proposalID3 int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID3)
tests.WaitForHeight(resultTx.Height+1, port)
// Addr2 deposits on proposals #2 & #3
resultTx = doDeposit(t, port, seed2, name2, password, addr2, proposalID2)
tests.WaitForHeight(resultTx.Height+1, port)
resultTx = doDeposit(t, port, seed2, name2, password, addr2, proposalID3)
tests.WaitForHeight(resultTx.Height+1, port)
// Addr1 votes on proposals #2 & #3
resultTx = doVote(t, port, seed, name, password, addr, proposalID2)
tests.WaitForHeight(resultTx.Height+1, port)
resultTx = doVote(t, port, seed, name, password, addr, proposalID3)
tests.WaitForHeight(resultTx.Height+1, port)
// Addr2 votes on proposal #3
resultTx = doVote(t, port, seed2, name2, password, addr2, proposalID3)
tests.WaitForHeight(resultTx.Height+1, port)
// Test query all proposals
proposals := getProposalsAll(t, port)
assert.Equal(t, proposalID1, (proposals[0]).ProposalID)
assert.Equal(t, proposalID2, (proposals[1]).ProposalID)
assert.Equal(t, proposalID3, (proposals[2]).ProposalID)
// Test query deposited by addr1
proposals = getProposalsFilterDepositer(t, port, addr)
assert.Equal(t, proposalID1, (proposals[0]).ProposalID)
// Test query deposited by addr2
proposals = getProposalsFilterDepositer(t, port, addr2)
assert.Equal(t, proposalID2, (proposals[0]).ProposalID)
assert.Equal(t, proposalID3, (proposals[1]).ProposalID)
// Test query voted by addr1
proposals = getProposalsFilterVoter(t, port, addr)
assert.Equal(t, proposalID2, (proposals[0]).ProposalID)
assert.Equal(t, proposalID3, (proposals[1]).ProposalID)
// Test query voted by addr2
proposals = getProposalsFilterVoter(t, port, addr2)
assert.Equal(t, proposalID3, (proposals[0]).ProposalID)
// Test query voted and deposited by addr1
proposals = getProposalsFilterVoterDepositer(t, port, addr, addr)
assert.Equal(t, proposalID2, (proposals[0]).ProposalID)
}
//_____________________________________________________________________________ //_____________________________________________________________________________
// get the account to get the sequence // get the account to get the sequence
func getAccount(t *testing.T, port string, addr sdk.Address) auth.Account { func getAccount(t *testing.T, port string, addr sdk.Address) auth.Account {
@ -766,9 +839,19 @@ func getProposal(t *testing.T, port string, proposalID int64) gov.ProposalRest {
return proposal return proposal
} }
func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.Address) gov.DepositRest {
bechDepositerAddr := sdk.MustBech32ifyAcc(depositerAddr)
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, bechDepositerAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var deposit gov.DepositRest
err := cdc.UnmarshalJSON([]byte(body), &deposit)
require.Nil(t, err)
return deposit
}
func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.Address) gov.VoteRest { func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.Address) gov.VoteRest {
bechVoterAddr := sdk.MustBech32ifyAcc(voterAddr) bechVoterAddr := sdk.MustBech32ifyAcc(voterAddr)
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/votes/%d/%s", proposalID, bechVoterAddr), nil) res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/votes/%s", proposalID, bechVoterAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
var vote gov.VoteRest var vote gov.VoteRest
err := cdc.UnmarshalJSON([]byte(body), &vote) err := cdc.UnmarshalJSON([]byte(body), &vote)
@ -776,6 +859,53 @@ func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.Address)
return vote return vote
} }
func getProposalsAll(t *testing.T, port string) []gov.ProposalRest {
res, body := Request(t, port, "GET", "/gov/proposals", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var proposals []gov.ProposalRest
err := cdc.UnmarshalJSON([]byte(body), &proposals)
require.Nil(t, err)
return proposals
}
func getProposalsFilterDepositer(t *testing.T, port string, depositerAddr sdk.Address) []gov.ProposalRest {
bechDepositerAddr := sdk.MustBech32ifyAcc(depositerAddr)
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?depositer=%s", bechDepositerAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var proposals []gov.ProposalRest
err := cdc.UnmarshalJSON([]byte(body), &proposals)
require.Nil(t, err)
return proposals
}
func getProposalsFilterVoter(t *testing.T, port string, voterAddr sdk.Address) []gov.ProposalRest {
bechVoterAddr := sdk.MustBech32ifyAcc(voterAddr)
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?voter=%s", bechVoterAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var proposals []gov.ProposalRest
err := cdc.UnmarshalJSON([]byte(body), &proposals)
require.Nil(t, err)
return proposals
}
func getProposalsFilterVoterDepositer(t *testing.T, port string, voterAddr sdk.Address, depositerAddr sdk.Address) []gov.ProposalRest {
bechVoterAddr := sdk.MustBech32ifyAcc(voterAddr)
bechDepositerAddr := sdk.MustBech32ifyAcc(depositerAddr)
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?depositer=%s&voter=%s", bechDepositerAddr, bechVoterAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var proposals []gov.ProposalRest
err := cdc.UnmarshalJSON([]byte(body), &proposals)
require.Nil(t, err)
return proposals
}
func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.Address) (resultTx ctypes.ResultBroadcastTxCommit) { func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.Address) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence // get the account to get the sequence
acc := getAccount(t, port, proposerAddr) acc := getAccount(t, port, proposerAddr)
@ -802,7 +932,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
"gas": 100000 "gas": 100000
} }
}`, bechProposerAddr, name, password, chainID, accnum, sequence)) }`, bechProposerAddr, name, password, chainID, accnum, sequence))
res, body := Request(t, port, "POST", "/gov/submitproposal", jsonStr) res, body := Request(t, port, "POST", "/gov/proposals", jsonStr)
fmt.Println(res) fmt.Println(res)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
@ -826,7 +956,6 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
// deposit on proposal // deposit on proposal
jsonStr := []byte(fmt.Sprintf(`{ jsonStr := []byte(fmt.Sprintf(`{
"depositer": "%s", "depositer": "%s",
"proposalID": %d,
"amount": [{ "denom": "steak", "amount": 5 }], "amount": [{ "denom": "steak", "amount": 5 }],
"base_req": { "base_req": {
"name": "%s", "name": "%s",
@ -836,8 +965,8 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
"sequence": %d, "sequence": %d,
"gas": 100000 "gas": 100000
} }
}`, bechProposerAddr, proposalID, name, password, chainID, accnum, sequence)) }`, bechProposerAddr, name, password, chainID, accnum, sequence))
res, body := Request(t, port, "POST", "/gov/deposit", jsonStr) res, body := Request(t, port, "POST", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), jsonStr)
fmt.Println(res) fmt.Println(res)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)
@ -861,7 +990,6 @@ func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.Ad
// vote on proposal // vote on proposal
jsonStr := []byte(fmt.Sprintf(`{ jsonStr := []byte(fmt.Sprintf(`{
"voter": "%s", "voter": "%s",
"proposalID": %d,
"option": "Yes", "option": "Yes",
"base_req": { "base_req": {
"name": "%s", "name": "%s",
@ -871,8 +999,8 @@ func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.Ad
"sequence": %d, "sequence": %d,
"gas": 100000 "gas": 100000
} }
}`, bechProposerAddr, proposalID, name, password, chainID, accnum, sequence)) }`, bechProposerAddr, name, password, chainID, accnum, sequence))
res, body := Request(t, port, "POST", "/gov/vote", jsonStr) res, body := Request(t, port, "POST", fmt.Sprintf("/gov/proposals/%d/votes", proposalID), jsonStr)
fmt.Println(res) fmt.Println(res)
require.Equal(t, http.StatusOK, res.StatusCode, body) require.Equal(t, http.StatusOK, res.StatusCode, body)

View File

@ -17,17 +17,22 @@ import (
// REST Variable names // REST Variable names
// nolint // nolint
const ( const (
ProposalRestID = "proposalID" RestProposalID = "proposalID"
RestVoter = "voterAddress" RestDepositer = "depositer"
RestVoter = "voter"
) )
// RegisterRoutes - Central function to define routes that get registered by the main application // RegisterRoutes - Central function to define routes that get registered by the main application
func RegisterRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec, kb keys.Keybase) { func RegisterRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec, kb keys.Keybase) {
r.HandleFunc("/gov/submitproposal", postProposalHandlerFn(cdc, kb, ctx)).Methods("POST") r.HandleFunc("/gov/proposals", postProposalHandlerFn(cdc, kb, ctx)).Methods("POST")
r.HandleFunc("/gov/deposit", depositHandlerFn(cdc, kb, ctx)).Methods("POST") r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), depositHandlerFn(cdc, kb, ctx)).Methods("POST")
r.HandleFunc("/gov/vote", voteHandlerFn(cdc, kb, ctx)).Methods("POST") r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), voteHandlerFn(cdc, kb, ctx)).Methods("POST")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}", ProposalRestID), queryProposalHandlerFn("gov", cdc, kb, ctx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/votes/{%s}/{%s}", ProposalRestID, RestVoter), queryVoteHandlerFn("gov", cdc, kb, ctx)).Methods("GET") r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}", RestProposalID), queryProposalHandlerFn("gov", cdc, kb, ctx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits/{%s}", RestProposalID, RestDepositer), queryDepositHandlerFn("gov", cdc, kb, ctx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes/{%s}", RestProposalID, RestVoter), queryVoteHandlerFn("gov", cdc, kb, ctx)).Methods("GET")
r.HandleFunc("/gov/proposals", queryProposalsWithParameterFn("gov", cdc, kb, ctx)).Methods("GET")
} }
type postProposalReq struct { type postProposalReq struct {
@ -41,7 +46,6 @@ type postProposalReq struct {
type depositReq struct { type depositReq struct {
BaseReq baseReq `json:"base_req"` BaseReq baseReq `json:"base_req"`
ProposalID int64 `json:"proposalID"` // ID of the proposal
Depositer string `json:"depositer"` // Address of the depositer Depositer string `json:"depositer"` // Address of the depositer
Amount sdk.Coins `json:"amount"` // Coins to add to the proposal's deposit Amount sdk.Coins `json:"amount"` // Coins to add to the proposal's deposit
} }
@ -49,7 +53,6 @@ type depositReq struct {
type voteReq struct { type voteReq struct {
BaseReq baseReq `json:"base_req"` BaseReq baseReq `json:"base_req"`
Voter string `json:"voter"` // address of the voter Voter string `json:"voter"` // address of the voter
ProposalID int64 `json:"proposalID"` // proposalID of the proposal
Option string `json:"option"` // option from OptionSet chosen by the voter Option string `json:"option"` // option from OptionSet chosen by the voter
} }
@ -92,8 +95,25 @@ func postProposalHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreCon
func depositHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc { func depositHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
strProposalID := vars[RestProposalID]
if len(strProposalID) == 0 {
w.WriteHeader(http.StatusBadRequest)
err := errors.New("proposalId required but not specified")
w.Write([]byte(err.Error()))
return
}
proposalID, err := strconv.ParseInt(strProposalID, 10, 64)
if err != nil {
err := errors.Errorf("proposalID [%d] is not positive", proposalID)
w.Write([]byte(err.Error()))
return
}
var req depositReq var req depositReq
err := buildReq(w, r, &req) err = buildReq(w, r, &req)
if err != nil { if err != nil {
return return
} }
@ -109,7 +129,7 @@ func depositHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext)
} }
// create the message // create the message
msg := gov.NewMsgDeposit(depositer, req.ProposalID, req.Amount) msg := gov.NewMsgDeposit(depositer, proposalID, req.Amount)
err = msg.ValidateBasic() err = msg.ValidateBasic()
if err != nil { if err != nil {
writeErr(&w, http.StatusBadRequest, err.Error()) writeErr(&w, http.StatusBadRequest, err.Error())
@ -123,8 +143,25 @@ func depositHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext)
func voteHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc { func voteHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
strProposalID := vars[RestProposalID]
if len(strProposalID) == 0 {
w.WriteHeader(http.StatusBadRequest)
err := errors.New("proposalId required but not specified")
w.Write([]byte(err.Error()))
return
}
proposalID, err := strconv.ParseInt(strProposalID, 10, 64)
if err != nil {
err := errors.Errorf("proposalID [%d] is not positive", proposalID)
w.Write([]byte(err.Error()))
return
}
var req voteReq var req voteReq
err := buildReq(w, r, &req) err = buildReq(w, r, &req)
if err != nil { if err != nil {
return return
} }
@ -146,7 +183,7 @@ func voteHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) ht
} }
// create the message // create the message
msg := gov.NewMsgVote(voter, req.ProposalID, voteOptionByte) msg := gov.NewMsgVote(voter, proposalID, voteOptionByte)
err = msg.ValidateBasic() err = msg.ValidateBasic()
if err != nil { if err != nil {
writeErr(&w, http.StatusBadRequest, err.Error()) writeErr(&w, http.StatusBadRequest, err.Error())
@ -161,7 +198,7 @@ func voteHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) ht
func queryProposalHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc { func queryProposalHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
strProposalID := vars[ProposalRestID] strProposalID := vars[RestProposalID]
if len(strProposalID) == 0 { if len(strProposalID) == 0 {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -180,7 +217,7 @@ func queryProposalHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase,
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper()
res, err := ctx.QueryStore(gov.KeyProposal(proposalID), storeName) res, err := ctx.QueryStore(gov.KeyProposal(proposalID), storeName)
if len(res) == 0 || err != nil { if err != nil || len(res) == 0 {
err := errors.Errorf("proposalID [%d] does not exist", proposalID) err := errors.Errorf("proposalID [%d] does not exist", proposalID)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
@ -199,10 +236,76 @@ func queryProposalHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase,
} }
} }
func queryDepositHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
strProposalID := vars[RestProposalID]
bechDepositerAddr := vars[RestDepositer]
if len(strProposalID) == 0 {
w.WriteHeader(http.StatusBadRequest)
err := errors.New("proposalId required but not specified")
w.Write([]byte(err.Error()))
return
}
proposalID, err := strconv.ParseInt(strProposalID, 10, 64)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
err := errors.Errorf("proposalID [%d] is not positive", proposalID)
w.Write([]byte(err.Error()))
return
}
if len(bechDepositerAddr) == 0 {
w.WriteHeader(http.StatusBadRequest)
err := errors.New("depositer address required but not specified")
w.Write([]byte(err.Error()))
return
}
depositerAddr, err := sdk.GetAccAddressBech32(bechDepositerAddr)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
err := errors.Errorf("'%s' needs to be bech32 encoded", RestDepositer)
w.Write([]byte(err.Error()))
return
}
ctx := context.NewCoreContextFromViper()
res, err := ctx.QueryStore(gov.KeyDeposit(proposalID, depositerAddr), storeName)
if err != nil || len(res) == 0 {
res, err := ctx.QueryStore(gov.KeyProposal(proposalID), storeName)
if err != nil || len(res) == 0 {
w.WriteHeader(http.StatusNotFound)
err := errors.Errorf("proposalID [%d] does not exist", proposalID)
w.Write([]byte(err.Error()))
return
}
w.WriteHeader(http.StatusNotFound)
err = errors.Errorf("depositer [%s] did not deposit on proposalID [%d]", bechDepositerAddr, proposalID)
w.Write([]byte(err.Error()))
return
}
var deposit gov.Deposit
cdc.MustUnmarshalBinary(res, &deposit)
depositRest := gov.DepositToRest(deposit)
output, err := wire.MarshalJSONIndent(cdc, depositRest)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
}
}
func queryVoteHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc { func queryVoteHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
strProposalID := vars[ProposalRestID] strProposalID := vars[RestProposalID]
bechVoterAddr := vars[RestVoter] bechVoterAddr := vars[RestVoter]
if len(strProposalID) == 0 { if len(strProposalID) == 0 {
@ -214,11 +317,19 @@ func queryVoteHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase, ctx
proposalID, err := strconv.ParseInt(strProposalID, 10, 64) proposalID, err := strconv.ParseInt(strProposalID, 10, 64)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest)
err := errors.Errorf("proposalID [%s] is not positive", proposalID) err := errors.Errorf("proposalID [%s] is not positive", proposalID)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
if len(bechVoterAddr) == 0 {
w.WriteHeader(http.StatusBadRequest)
err := errors.New("voter address required but not specified")
w.Write([]byte(err.Error()))
return
}
voterAddr, err := sdk.GetAccAddressBech32(bechVoterAddr) voterAddr, err := sdk.GetAccAddressBech32(bechVoterAddr)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -229,16 +340,17 @@ func queryVoteHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase, ctx
ctx := context.NewCoreContextFromViper() ctx := context.NewCoreContextFromViper()
key := []byte(gov.KeyVote(proposalID, voterAddr)) res, err := ctx.QueryStore(gov.KeyVote(proposalID, voterAddr), storeName)
res, err := ctx.QueryStore(key, storeName) if err != nil || len(res) == 0 {
if len(res) == 0 || err != nil {
res, err := ctx.QueryStore(gov.KeyProposal(proposalID), storeName) res, err := ctx.QueryStore(gov.KeyProposal(proposalID), storeName)
if len(res) == 0 || err != nil { if err != nil || len(res) == 0 {
w.WriteHeader(http.StatusNotFound)
err := errors.Errorf("proposalID [%d] does not exist", proposalID) err := errors.Errorf("proposalID [%d] does not exist", proposalID)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
} }
w.WriteHeader(http.StatusNotFound)
err = errors.Errorf("voter [%s] did not vote on proposalID [%d]", bechVoterAddr, proposalID) err = errors.Errorf("voter [%s] did not vote on proposalID [%d]", bechVoterAddr, proposalID)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return return
@ -256,3 +368,80 @@ func queryVoteHandlerFn(storeName string, cdc *wire.Codec, kb keys.Keybase, ctx
w.Write(output) w.Write(output)
} }
} }
func queryProposalsWithParameterFn(storeName string, cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
bechVoterAddr := r.URL.Query().Get(RestVoter)
bechDepositerAddr := r.URL.Query().Get(RestDepositer)
var err error
var voterAddr sdk.Address
var depositerAddr sdk.Address
if len(bechVoterAddr) != 0 {
voterAddr, err = sdk.GetAccAddressBech32(bechVoterAddr)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
err := errors.Errorf("'%s' needs to be bech32 encoded", RestVoter)
w.Write([]byte(err.Error()))
return
}
}
if len(bechDepositerAddr) != 0 {
depositerAddr, err = sdk.GetAccAddressBech32(bechDepositerAddr)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
err := errors.Errorf("'%s' needs to be bech32 encoded", RestDepositer)
w.Write([]byte(err.Error()))
return
}
}
ctx := context.NewCoreContextFromViper()
res, err := ctx.QueryStore(gov.KeyNextProposalID, storeName)
if err != nil {
err = errors.New("no proposals exist yet and proposalID has not been set")
w.Write([]byte(err.Error()))
return
}
var maxProposalID int64
cdc.MustUnmarshalBinary(res, &maxProposalID)
matchingProposals := []gov.ProposalRest{}
for proposalID := int64(0); proposalID < maxProposalID; proposalID++ {
if voterAddr != nil {
res, err = ctx.QueryStore(gov.KeyVote(proposalID, voterAddr), storeName)
if err != nil || len(res) == 0 {
continue
}
}
if depositerAddr != nil {
res, err = ctx.QueryStore(gov.KeyDeposit(proposalID, depositerAddr), storeName)
if err != nil || len(res) == 0 {
continue
}
}
res, err = ctx.QueryStore(gov.KeyProposal(proposalID), storeName)
if err != nil || len(res) == 0 {
continue
}
var proposal gov.Proposal
cdc.MustUnmarshalBinary(res, &proposal)
matchingProposals = append(matchingProposals, gov.ProposalToRest(proposal))
}
output, err := wire.MarshalJSONIndent(cdc, matchingProposals)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
}
}

View File

@ -26,6 +26,7 @@ type Vote struct {
// Deposit // Deposit
type Deposit struct { type Deposit struct {
Depositer sdk.Address `json:"depositer"` // Address of the depositer Depositer sdk.Address `json:"depositer"` // Address of the depositer
ProposalID int64 `json:"proposal_id"` // proposalID of the proposal
Amount sdk.Coins `json:"amount"` // Deposit amount Amount sdk.Coins `json:"amount"` // Deposit amount
} }
@ -72,6 +73,25 @@ func StringToVoteOption(str string) (VoteOption, sdk.Error) {
} }
//----------------------------------------------------------- //-----------------------------------------------------------
// REST
// Rest Deposits
type DepositRest struct {
Depositer string `json:"voter"` // address of the voter
ProposalID int64 `json:"proposal_id"` // proposalID of the proposal
Amount sdk.Coins `json:"option"`
}
// Turn any Deposit to a DepositRest
func DepositToRest(deposit Deposit) DepositRest {
bechAddr := sdk.MustBech32ifyAcc(deposit.Depositer)
return DepositRest{
Depositer: bechAddr,
ProposalID: deposit.ProposalID,
Amount: deposit.Amount,
}
}
// Rest Votes // Rest Votes
type VoteRest struct { type VoteRest struct {
Voter string `json:"voter"` // address of the voter Voter string `json:"voter"` // address of the voter
@ -79,7 +99,7 @@ type VoteRest struct {
Option string `json:"option"` Option string `json:"option"`
} }
// Turn any Vote to a ProposalRest // Turn any Vote to a VoteRest
func VoteToRest(vote Vote) VoteRest { func VoteToRest(vote Vote) VoteRest {
bechAddr, _ := sdk.Bech32ifyAcc(vote.Voter) bechAddr, _ := sdk.Bech32ifyAcc(vote.Voter)
return VoteRest{ return VoteRest{

View File

@ -101,7 +101,7 @@ func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk
if bz != nil { if bz != nil {
return ErrInvalidGenesis(keeper.codespace, "Initial ProposalID already set") return ErrInvalidGenesis(keeper.codespace, "Initial ProposalID already set")
} }
bz = keeper.cdc.MustMarshalBinary(proposalID) // TODO: switch to MarshalBinaryBare when new go-amino gets added bz = keeper.cdc.MustMarshalBinary(proposalID)
store.Set(KeyNextProposalID, bz) store.Set(KeyNextProposalID, bz)
return nil return nil
} }
@ -112,8 +112,8 @@ func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sd
if bz == nil { if bz == nil {
return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set") return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set")
} }
keeper.cdc.MustUnmarshalBinary(bz, &proposalID) // TODO: switch to UnmarshalBinaryBare when new go-amino gets added keeper.cdc.MustUnmarshalBinary(bz, &proposalID)
bz = keeper.cdc.MustMarshalBinary(proposalID + 1) // TODO: switch to MarshalBinaryBare when new go-amino gets added bz = keeper.cdc.MustMarshalBinary(proposalID + 1)
store.Set(KeyNextProposalID, bz) store.Set(KeyNextProposalID, bz)
return proposalID, nil return proposalID, nil
} }
@ -264,7 +264,7 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID int64, depositerAddr
// Add or update deposit object // Add or update deposit object
currDeposit, found := keeper.GetDeposit(ctx, proposalID, depositerAddr) currDeposit, found := keeper.GetDeposit(ctx, proposalID, depositerAddr)
if !found { if !found {
newDeposit := Deposit{depositerAddr, depositAmount} newDeposit := Deposit{depositerAddr, proposalID, depositAmount}
keeper.setDeposit(ctx, proposalID, depositerAddr, newDeposit) keeper.setDeposit(ctx, proposalID, depositerAddr, newDeposit)
} else { } else {
currDeposit.Amount = currDeposit.Amount.Plus(depositAmount) currDeposit.Amount = currDeposit.Amount.Plus(depositAmount)