Skip to content

Commit

Permalink
Merge PR cosmos#1168: Governance MVP
Browse files Browse the repository at this point in the history
  • Loading branch information
sunnya97 authored and cwgoes committed Jun 22, 2018
1 parent d08b916 commit dc2c8f9
Show file tree
Hide file tree
Showing 32 changed files with 3,396 additions and 25 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,9 @@ profile.out
*.log
vagrant

# IDE
.idea/
*.iml

# Graphviz
dependency-graph.png
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ FEATURES
* [gaiacli] You can now attach a simple text-only memo to any transaction, with the `--memo` flag
* [lcd] Queried TXs now include the tx hash to identify each tx
* [mockapp] CompleteSetup() no longer takes a testing parameter
* [governance] Implemented MVP
* Supported proposal types: just binary (pass/fail) TextProposals for now
* Proposals need deposits to be votable; deposits are burned if proposal fails
* Delegators delegate votes to validator by default but can override (for their stake)

FIXES
* \#1259 - fix bug where certain tests that could have a nil pointer in defer
Expand Down
217 changes: 217 additions & 0 deletions client/lcd/lcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
tests "github.com/cosmos/cosmos-sdk/tests"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/stake"
stakerest "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
)
Expand Down Expand Up @@ -423,6 +424,96 @@ func TestBonding(t *testing.T) {

}

func TestSubmitProposal(t *testing.T) {
name, password := "test", "1234567890"
addr, seed := CreateAddr(t, "test", password, GetKB(t))
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.Address{addr})
defer cleanup()

// create SubmitProposal TX
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
tests.WaitForHeight(resultTx.Height+1, port)

// check if tx was commited
assert.Equal(t, uint32(0), resultTx.CheckTx.Code)
assert.Equal(t, uint32(0), resultTx.DeliverTx.Code)

var proposalID int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID)

// query proposal
proposal := getProposal(t, port, proposalID)
assert.Equal(t, "Test", proposal.Title)
}

func TestDeposit(t *testing.T) {
name, password := "test", "1234567890"
addr, seed := CreateAddr(t, "test", password, GetKB(t))
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.Address{addr})
defer cleanup()

// create SubmitProposal TX
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
tests.WaitForHeight(resultTx.Height+1, port)

// check if tx was commited
assert.Equal(t, uint32(0), resultTx.CheckTx.Code)
assert.Equal(t, uint32(0), resultTx.DeliverTx.Code)

var proposalID int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID)

// query proposal
proposal := getProposal(t, port, proposalID)
assert.Equal(t, "Test", proposal.Title)

// create SubmitProposal TX
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID)
tests.WaitForHeight(resultTx.Height+1, port)

// query proposal
proposal = getProposal(t, port, proposalID)
assert.True(t, proposal.TotalDeposit.IsEqual(sdk.Coins{sdk.NewCoin("steak", 10)}))
}

func TestVote(t *testing.T) {
name, password := "test", "1234567890"
addr, seed := CreateAddr(t, "test", password, GetKB(t))
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.Address{addr})
defer cleanup()

// create SubmitProposal TX
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
tests.WaitForHeight(resultTx.Height+1, port)

// check if tx was commited
assert.Equal(t, uint32(0), resultTx.CheckTx.Code)
assert.Equal(t, uint32(0), resultTx.DeliverTx.Code)

var proposalID int64
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID)

// query proposal
proposal := getProposal(t, port, proposalID)
assert.Equal(t, "Test", proposal.Title)

// create SubmitProposal TX
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID)
tests.WaitForHeight(resultTx.Height+1, port)

// query proposal
proposal = getProposal(t, port, proposalID)
assert.Equal(t, gov.StatusToString(gov.StatusVotingPeriod), proposal.Status)

// create SubmitProposal TX
resultTx = doVote(t, port, seed, name, password, addr, proposalID)
tests.WaitForHeight(resultTx.Height+1, port)

vote := getVote(t, port, proposalID, addr)
assert.Equal(t, proposalID, vote.ProposalID)
assert.Equal(t, gov.VoteOptionToString(gov.OptionYes), vote.Option)
}

//_____________________________________________________________________________
// get the account to get the sequence
func getAccount(t *testing.T, port string, addr sdk.Address) auth.Account {
Expand Down Expand Up @@ -602,3 +693,129 @@ func getValidators(t *testing.T, port string) []stakerest.StakeValidatorOutput {
require.Nil(t, err)
return validators
}

func getProposal(t *testing.T, port string, proposalID int64) gov.ProposalRest {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d", proposalID), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var proposal gov.ProposalRest
err := cdc.UnmarshalJSON([]byte(body), &proposal)
require.Nil(t, err)
return proposal
}

func getVote(t *testing.T, port string, proposalID int64, voterAddr sdk.Address) gov.VoteRest {
bechVoterAddr := sdk.MustBech32ifyAcc(voterAddr)
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/votes/%d/%s", proposalID, bechVoterAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var vote gov.VoteRest
err := cdc.UnmarshalJSON([]byte(body), &vote)
require.Nil(t, err)
return vote
}

func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.Address) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence
acc := getAccount(t, port, proposerAddr)
accnum := acc.GetAccountNumber()
sequence := acc.GetSequence()

chainID := viper.GetString(client.FlagChainID)

bechProposerAddr := sdk.MustBech32ifyAcc(proposerAddr)

// submitproposal
jsonStr := []byte(fmt.Sprintf(`{
"title": "Test",
"description": "test",
"proposal_type": "Text",
"proposer": "%s",
"initial_deposit": [{ "denom": "steak", "amount": 5 }],
"base_req": {
"name": "%s",
"password": "%s",
"chain_id": "%s",
"account_number": %d,
"sequence": %d,
"gas": 100000
}
}`, bechProposerAddr, name, password, chainID, accnum, sequence))
res, body := Request(t, port, "POST", "/gov/submitproposal", jsonStr)
fmt.Println(res)
require.Equal(t, http.StatusOK, res.StatusCode, body)

var results ctypes.ResultBroadcastTxCommit
err := cdc.UnmarshalJSON([]byte(body), &results)
require.Nil(t, err)

return results
}

func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.Address, proposalID int64) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence
acc := getAccount(t, port, proposerAddr)
accnum := acc.GetAccountNumber()
sequence := acc.GetSequence()

chainID := viper.GetString(client.FlagChainID)

bechProposerAddr := sdk.MustBech32ifyAcc(proposerAddr)

// deposit on proposal
jsonStr := []byte(fmt.Sprintf(`{
"depositer": "%s",
"proposalID": %d,
"amount": [{ "denom": "steak", "amount": 5 }],
"base_req": {
"name": "%s",
"password": "%s",
"chain_id": "%s",
"account_number": %d,
"sequence": %d,
"gas": 100000
}
}`, bechProposerAddr, proposalID, name, password, chainID, accnum, sequence))
res, body := Request(t, port, "POST", "/gov/deposit", jsonStr)
fmt.Println(res)
require.Equal(t, http.StatusOK, res.StatusCode, body)

var results ctypes.ResultBroadcastTxCommit
err := cdc.UnmarshalJSON([]byte(body), &results)
require.Nil(t, err)

return results
}

func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.Address, proposalID int64) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence
acc := getAccount(t, port, proposerAddr)
accnum := acc.GetAccountNumber()
sequence := acc.GetSequence()

chainID := viper.GetString(client.FlagChainID)

bechProposerAddr := sdk.MustBech32ifyAcc(proposerAddr)

// vote on proposal
jsonStr := []byte(fmt.Sprintf(`{
"voter": "%s",
"proposalID": %d,
"option": "Yes",
"base_req": {
"name": "%s",
"password": "%s",
"chain_id": "%s",
"account_number": %d,
"sequence": %d,
"gas": 100000
}
}`, bechProposerAddr, proposalID, name, password, chainID, accnum, sequence))
res, body := Request(t, port, "POST", "/gov/vote", jsonStr)
fmt.Println(res)
require.Equal(t, http.StatusOK, res.StatusCode, body)

var results ctypes.ResultBroadcastTxCommit
err := cdc.UnmarshalJSON([]byte(body), &results)
require.Nil(t, err)

return results
}
2 changes: 2 additions & 0 deletions client/lcd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/cosmos/cosmos-sdk/wire"
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
gov "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
ibc "github.com/cosmos/cosmos-sdk/x/ibc/client/rest"
stake "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
)
Expand Down Expand Up @@ -80,5 +81,6 @@ func createHandler(cdc *wire.Codec) http.Handler {
bank.RegisterRoutes(ctx, r, cdc, kb)
ibc.RegisterRoutes(ctx, r, cdc, kb)
stake.RegisterRoutes(ctx, r, cdc, kb)
gov.RegisterRoutes(ctx, r, cdc, kb)
return r
}
16 changes: 14 additions & 2 deletions cmd/gaia/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/ibc"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/stake"
Expand All @@ -41,6 +42,7 @@ type GaiaApp struct {
keyIBC *sdk.KVStoreKey
keyStake *sdk.KVStoreKey
keySlashing *sdk.KVStoreKey
keyGov *sdk.KVStoreKey

// Manage getting and setting accounts
accountMapper auth.AccountMapper
Expand All @@ -49,6 +51,7 @@ type GaiaApp struct {
ibcMapper ibc.Mapper
stakeKeeper stake.Keeper
slashingKeeper slashing.Keeper
govKeeper gov.Keeper
}

func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
Expand All @@ -63,6 +66,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
keyIBC: sdk.NewKVStoreKey("ibc"),
keyStake: sdk.NewKVStoreKey("stake"),
keySlashing: sdk.NewKVStoreKey("slashing"),
keyGov: sdk.NewKVStoreKey("gov"),
}

// define the accountMapper
Expand All @@ -77,20 +81,22 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.RegisterCodespace(slashing.DefaultCodespace))
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))

// register message routes
app.Router().
AddRoute("bank", bank.NewHandler(app.coinKeeper)).
AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)).
AddRoute("stake", stake.NewHandler(app.stakeKeeper)).
AddRoute("slashing", slashing.NewHandler(app.slashingKeeper))
AddRoute("slashing", slashing.NewHandler(app.slashingKeeper)).
AddRoute("gov", gov.NewHandler(app.govKeeper))

// initialize BaseApp
app.SetInitChainer(app.initChainer)
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing)
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing, app.keyGov)
err := app.LoadLatestVersion(app.keyMain)
if err != nil {
cmn.Exit(err.Error())
Expand All @@ -106,6 +112,7 @@ func MakeCodec() *wire.Codec {
bank.RegisterWire(cdc)
stake.RegisterWire(cdc)
slashing.RegisterWire(cdc)
gov.RegisterWire(cdc)
auth.RegisterWire(cdc)
sdk.RegisterWire(cdc)
wire.RegisterCrypto(cdc)
Expand All @@ -125,8 +132,11 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab
func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)

tags, _ := gov.EndBlocker(ctx, app.govKeeper)

return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
Tags: tags,
}
}

Expand All @@ -152,6 +162,8 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
// load the initial stake information
stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)

gov.InitGenesis(ctx, app.govKeeper, gov.DefaultGenesisState())

return abci.ResponseInitChain{}
}

Expand Down
Loading

0 comments on commit dc2c8f9

Please sign in to comment.