Merge branch 'develop' into joon/2490-copy-godocs
This commit is contained in:
commit
047c3d1456
|
@ -69,7 +69,8 @@ BREAKING CHANGES
|
||||||
* [x/staking] \#2244 staking now holds a consensus-address-index instead of a consensus-pubkey-index
|
* [x/staking] \#2244 staking now holds a consensus-address-index instead of a consensus-pubkey-index
|
||||||
* [x/staking] \#2236 more distribution hooks for distribution
|
* [x/staking] \#2236 more distribution hooks for distribution
|
||||||
* [x/stake] \#2394 Split up UpdateValidator into distinct state transitions applied only in EndBlock
|
* [x/stake] \#2394 Split up UpdateValidator into distinct state transitions applied only in EndBlock
|
||||||
* [x/stake] Global Paramstore refactored
|
* [x/stake] \#2412 Added an unbonding validator queue to EndBlock to automatically update validator.Status when finished Unbonding
|
||||||
|
* [x/params] Global Paramstore refactored
|
||||||
|
|
||||||
* Tendermint
|
* Tendermint
|
||||||
* Update tendermint version from v0.23.0 to v0.25.0, notable changes
|
* Update tendermint version from v0.23.0 to v0.25.0, notable changes
|
||||||
|
@ -92,6 +93,7 @@ FEATURES
|
||||||
* [gaia-lite] [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) Add /sign endpoint to sign transactions generated with `generate_only=true`.
|
* [gaia-lite] [\#1953](https://github.com/cosmos/cosmos-sdk/issues/1953) Add /sign endpoint to sign transactions generated with `generate_only=true`.
|
||||||
* [gaia-lite] [\#1954](https://github.com/cosmos/cosmos-sdk/issues/1954) Add /broadcast endpoint to broadcast transactions signed by the /sign endpoint.
|
* [gaia-lite] [\#1954](https://github.com/cosmos/cosmos-sdk/issues/1954) Add /broadcast endpoint to broadcast transactions signed by the /sign endpoint.
|
||||||
* [gaia-lite] [\#2113](https://github.com/cosmos/cosmos-sdk/issues/2113) Rename `/accounts/{address}/send` to `/bank/accounts/{address}/transfers`, rename `/accounts/{address}` to `/auth/accounts/{address}`
|
* [gaia-lite] [\#2113](https://github.com/cosmos/cosmos-sdk/issues/2113) Rename `/accounts/{address}/send` to `/bank/accounts/{address}/transfers`, rename `/accounts/{address}` to `/auth/accounts/{address}`
|
||||||
|
* [gaia-lite] [\#2478](https://github.com/cosmos/cosmos-sdk/issues/2478) Add query gov proposal's deposits endpoint
|
||||||
|
|
||||||
* Gaia CLI (`gaiacli`)
|
* Gaia CLI (`gaiacli`)
|
||||||
* [cli] Cmds to query staking pool and params
|
* [cli] Cmds to query staking pool and params
|
||||||
|
|
|
@ -10,19 +10,19 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/rpc"
|
||||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||||
|
p2p "github.com/tendermint/tendermint/p2p"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
cryptoKeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
cryptoKeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||||
p2p "github.com/tendermint/tendermint/p2p"
|
|
||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
|
|
||||||
client "github.com/cosmos/cosmos-sdk/client"
|
client "github.com/cosmos/cosmos-sdk/client"
|
||||||
keys "github.com/cosmos/cosmos-sdk/client/keys"
|
keys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||||
rpc "github.com/cosmos/cosmos-sdk/client/rpc"
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
tests "github.com/cosmos/cosmos-sdk/tests"
|
tests "github.com/cosmos/cosmos-sdk/tests"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
@ -613,7 +613,7 @@ func TestSubmitProposal(t *testing.T) {
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
// create SubmitProposal TX
|
// create SubmitProposal TX
|
||||||
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
|
resultTx := doSubmitProposal(t, port, seed, name, password, addr, 5)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
// check if tx was committed
|
// check if tx was committed
|
||||||
|
@ -635,7 +635,7 @@ func TestDeposit(t *testing.T) {
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
// create SubmitProposal TX
|
// create SubmitProposal TX
|
||||||
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
|
resultTx := doSubmitProposal(t, port, seed, name, password, addr, 5)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
// check if tx was committed
|
// check if tx was committed
|
||||||
|
@ -650,7 +650,7 @@ func TestDeposit(t *testing.T) {
|
||||||
require.Equal(t, "Test", proposal.GetTitle())
|
require.Equal(t, "Test", proposal.GetTitle())
|
||||||
|
|
||||||
// create SubmitProposal TX
|
// create SubmitProposal TX
|
||||||
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID)
|
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID, 5)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
// query proposal
|
// query proposal
|
||||||
|
@ -669,7 +669,7 @@ func TestVote(t *testing.T) {
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
// create SubmitProposal TX
|
// create SubmitProposal TX
|
||||||
resultTx := doSubmitProposal(t, port, seed, name, password, addr)
|
resultTx := doSubmitProposal(t, port, seed, name, password, addr, 5)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
// check if tx was committed
|
// check if tx was committed
|
||||||
|
@ -684,7 +684,7 @@ func TestVote(t *testing.T) {
|
||||||
require.Equal(t, "Test", proposal.GetTitle())
|
require.Equal(t, "Test", proposal.GetTitle())
|
||||||
|
|
||||||
// create SubmitProposal TX
|
// create SubmitProposal TX
|
||||||
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID)
|
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID, 5)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
// query proposal
|
// query proposal
|
||||||
|
@ -725,27 +725,52 @@ func TestProposalsQuery(t *testing.T) {
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
// Addr1 proposes (and deposits) proposals #1 and #2
|
// Addr1 proposes (and deposits) proposals #1 and #2
|
||||||
resultTx := doSubmitProposal(t, port, seed, name, password1, addr)
|
resultTx := doSubmitProposal(t, port, seed, name, password1, addr, 5)
|
||||||
var proposalID1 int64
|
var proposalID1 int64
|
||||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID1)
|
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID1)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
resultTx = doSubmitProposal(t, port, seed, name, password1, addr)
|
resultTx = doSubmitProposal(t, port, seed, name, password1, addr, 5)
|
||||||
var proposalID2 int64
|
var proposalID2 int64
|
||||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID2)
|
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID2)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
// Addr2 proposes (and deposits) proposals #3
|
// Addr2 proposes (and deposits) proposals #3
|
||||||
resultTx = doSubmitProposal(t, port, seed2, name2, password2, addr2)
|
resultTx = doSubmitProposal(t, port, seed2, name2, password2, addr2, 5)
|
||||||
var proposalID3 int64
|
var proposalID3 int64
|
||||||
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID3)
|
cdc.UnmarshalBinaryBare(resultTx.DeliverTx.GetData(), &proposalID3)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
// Addr2 deposits on proposals #2 & #3
|
// Addr2 deposits on proposals #2 & #3
|
||||||
resultTx = doDeposit(t, port, seed2, name2, password2, addr2, proposalID2)
|
resultTx = doDeposit(t, port, seed2, name2, password2, addr2, proposalID2, 5)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
resultTx = doDeposit(t, port, seed2, name2, password2, addr2, proposalID3)
|
resultTx = doDeposit(t, port, seed2, name2, password2, addr2, proposalID3, 5)
|
||||||
tests.WaitForHeight(resultTx.Height+1, port)
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
|
// check deposits match proposal and individual deposits
|
||||||
|
deposits := getDeposits(t, port, proposalID1)
|
||||||
|
require.Len(t, deposits, 1)
|
||||||
|
deposit := getDeposit(t, port, proposalID1, addr)
|
||||||
|
require.Equal(t, deposit, deposits[0])
|
||||||
|
|
||||||
|
deposits = getDeposits(t, port, proposalID2)
|
||||||
|
require.Len(t, deposits, 2)
|
||||||
|
deposit = getDeposit(t, port, proposalID2, addr)
|
||||||
|
require.Equal(t, deposit, deposits[0])
|
||||||
|
deposit = getDeposit(t, port, proposalID2, addr2)
|
||||||
|
require.Equal(t, deposit, deposits[1])
|
||||||
|
|
||||||
|
deposits = getDeposits(t, port, proposalID3)
|
||||||
|
require.Len(t, deposits, 1)
|
||||||
|
deposit = getDeposit(t, port, proposalID3, addr2)
|
||||||
|
require.Equal(t, deposit, deposits[0])
|
||||||
|
|
||||||
|
// increasing the amount of the deposit should update the existing one
|
||||||
|
resultTx = doDeposit(t, port, seed, name, password1, addr, proposalID1, 1)
|
||||||
|
tests.WaitForHeight(resultTx.Height+1, port)
|
||||||
|
|
||||||
|
deposits = getDeposits(t, port, proposalID1)
|
||||||
|
require.Len(t, deposits, 1)
|
||||||
|
|
||||||
// Only proposals #1 should be in Deposit Period
|
// Only proposals #1 should be in Deposit Period
|
||||||
proposals := getProposalsFilterStatus(t, port, gov.StatusDepositPeriod)
|
proposals := getProposalsFilterStatus(t, port, gov.StatusDepositPeriod)
|
||||||
require.Len(t, proposals, 1)
|
require.Len(t, proposals, 1)
|
||||||
|
@ -1168,6 +1193,15 @@ func getProposal(t *testing.T, port string, proposalID int64) gov.Proposal {
|
||||||
return proposal
|
return proposal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDeposits(t *testing.T, port string, proposalID int64) []gov.Deposit {
|
||||||
|
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), nil)
|
||||||
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
var deposits []gov.Deposit
|
||||||
|
err := cdc.UnmarshalJSON([]byte(body), &deposits)
|
||||||
|
require.Nil(t, err)
|
||||||
|
return deposits
|
||||||
|
}
|
||||||
|
|
||||||
func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.AccAddress) gov.Deposit {
|
func getDeposit(t *testing.T, port string, proposalID int64, depositerAddr sdk.AccAddress) gov.Deposit {
|
||||||
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, depositerAddr), nil)
|
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, depositerAddr), nil)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
@ -1245,7 +1279,7 @@ func getProposalsFilterStatus(t *testing.T, port string, status gov.ProposalStat
|
||||||
return proposals
|
return proposals
|
||||||
}
|
}
|
||||||
|
|
||||||
func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
|
func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||||
|
|
||||||
acc := getAccount(t, port, proposerAddr)
|
acc := getAccount(t, port, proposerAddr)
|
||||||
accnum := acc.GetAccountNumber()
|
accnum := acc.GetAccountNumber()
|
||||||
|
@ -1259,7 +1293,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
|
||||||
"description": "test",
|
"description": "test",
|
||||||
"proposal_type": "Text",
|
"proposal_type": "Text",
|
||||||
"proposer": "%s",
|
"proposer": "%s",
|
||||||
"initial_deposit": [{ "denom": "steak", "amount": "5" }],
|
"initial_deposit": [{ "denom": "steak", "amount": "%d" }],
|
||||||
"base_req": {
|
"base_req": {
|
||||||
"name": "%s",
|
"name": "%s",
|
||||||
"password": "%s",
|
"password": "%s",
|
||||||
|
@ -1267,7 +1301,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
|
||||||
"account_number":"%d",
|
"account_number":"%d",
|
||||||
"sequence":"%d"
|
"sequence":"%d"
|
||||||
}
|
}
|
||||||
}`, proposerAddr, name, password, chainID, accnum, sequence))
|
}`, proposerAddr, amount, name, password, chainID, accnum, sequence))
|
||||||
res, body := Request(t, port, "POST", "/gov/proposals", jsonStr)
|
res, body := Request(t, port, "POST", "/gov/proposals", jsonStr)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
|
||||||
|
@ -1278,7 +1312,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID int64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID int64, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||||
|
|
||||||
acc := getAccount(t, port, proposerAddr)
|
acc := getAccount(t, port, proposerAddr)
|
||||||
accnum := acc.GetAccountNumber()
|
accnum := acc.GetAccountNumber()
|
||||||
|
@ -1289,7 +1323,7 @@ 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",
|
||||||
"amount": [{ "denom": "steak", "amount": "5" }],
|
"amount": [{ "denom": "steak", "amount": "%d" }],
|
||||||
"base_req": {
|
"base_req": {
|
||||||
"name": "%s",
|
"name": "%s",
|
||||||
"password": "%s",
|
"password": "%s",
|
||||||
|
@ -1297,7 +1331,7 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
|
||||||
"account_number":"%d",
|
"account_number":"%d",
|
||||||
"sequence": "%d"
|
"sequence": "%d"
|
||||||
}
|
}
|
||||||
}`, proposerAddr, name, password, chainID, accnum, sequence))
|
}`, proposerAddr, amount, name, password, chainID, accnum, sequence))
|
||||||
res, body := Request(t, port, "POST", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), jsonStr)
|
res, body := Request(t, port, "POST", fmt.Sprintf("/gov/proposals/%d/deposits", proposalID), jsonStr)
|
||||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,20 @@
|
||||||
# End-Block
|
# End-Block
|
||||||
|
|
||||||
|
## Unbonding Validator Queue
|
||||||
|
|
||||||
|
For all unbonding validators that have finished their unbonding period, this switches their validator.Status
|
||||||
|
from sdk.Unbonding to sdk.Unbonded
|
||||||
|
|
||||||
|
```golang
|
||||||
|
validatorQueue(currTime time.Time):
|
||||||
|
// unbonding validators are in ordered queue from oldest to newest
|
||||||
|
for all unbondingValidators whose CompleteTime < currTime:
|
||||||
|
validator = GetValidator(unbondingValidator.ValidatorAddr)
|
||||||
|
validator.Status = sdk.Bonded
|
||||||
|
SetValidator(unbondingValidator)
|
||||||
|
return
|
||||||
|
```
|
||||||
|
|
||||||
## Validator Set Changes
|
## Validator Set Changes
|
||||||
|
|
||||||
The Tendermint validator set may be updated by state transitions that run at
|
The Tendermint validator set may be updated by state transitions that run at
|
||||||
|
|
|
@ -188,7 +188,9 @@ func (c Context) WithBlockTime(newTime time.Time) Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Context) WithBlockHeight(height int64) Context {
|
func (c Context) WithBlockHeight(height int64) Context {
|
||||||
return c.withValue(contextKeyBlockHeight, height)
|
newHeader := c.BlockHeader()
|
||||||
|
newHeader.Height = height
|
||||||
|
return c.withValue(contextKeyBlockHeight, height).withValue(contextKeyBlockHeader, newHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context {
|
func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context {
|
||||||
|
|
|
@ -164,15 +164,16 @@ func TestContextWithCustom(t *testing.T) {
|
||||||
meter := types.NewGasMeter(10000)
|
meter := types.NewGasMeter(10000)
|
||||||
minFees := types.Coins{types.NewInt64Coin("feeCoin", 1)}
|
minFees := types.Coins{types.NewInt64Coin("feeCoin", 1)}
|
||||||
|
|
||||||
ctx = types.NewContext(nil, header, ischeck, logger).
|
ctx = types.NewContext(nil, header, ischeck, logger)
|
||||||
|
require.Equal(t, header, ctx.BlockHeader())
|
||||||
|
|
||||||
|
ctx = ctx.
|
||||||
WithBlockHeight(height).
|
WithBlockHeight(height).
|
||||||
WithChainID(chainid).
|
WithChainID(chainid).
|
||||||
WithTxBytes(txbytes).
|
WithTxBytes(txbytes).
|
||||||
WithVoteInfos(voteinfos).
|
WithVoteInfos(voteinfos).
|
||||||
WithGasMeter(meter).
|
WithGasMeter(meter).
|
||||||
WithMinimumFees(minFees)
|
WithMinimumFees(minFees)
|
||||||
|
|
||||||
require.Equal(t, header, ctx.BlockHeader())
|
|
||||||
require.Equal(t, height, ctx.BlockHeight())
|
require.Equal(t, height, ctx.BlockHeight())
|
||||||
require.Equal(t, chainid, ctx.ChainID())
|
require.Equal(t, chainid, ctx.ChainID())
|
||||||
require.Equal(t, ischeck, ctx.IsCheckTx())
|
require.Equal(t, ischeck, ctx.IsCheckTx())
|
||||||
|
|
|
@ -31,13 +31,12 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec)
|
||||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), depositHandlerFn(cdc, cliCtx)).Methods("POST")
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), depositHandlerFn(cdc, cliCtx)).Methods("POST")
|
||||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), voteHandlerFn(cdc, cliCtx)).Methods("POST")
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), voteHandlerFn(cdc, cliCtx)).Methods("POST")
|
||||||
|
|
||||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}", RestProposalID), queryProposalHandlerFn(cdc)).Methods("GET")
|
r.HandleFunc("/gov/proposals", queryProposalsWithParameterFn(cdc, cliCtx)).Methods("GET")
|
||||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits/{%s}", RestProposalID, RestDepositer), queryDepositHandlerFn(cdc)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}", RestProposalID), queryProposalHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes/{%s}", RestProposalID, RestVoter), queryVoteHandlerFn(cdc)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), queryDepositsHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||||
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits/{%s}", RestProposalID, RestDepositer), queryDepositHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||||
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), queryVotesOnProposalHandlerFn(cdc)).Methods("GET")
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), queryVotesOnProposalHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||||
|
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes/{%s}", RestProposalID, RestVoter), queryVoteHandlerFn(cdc, cliCtx)).Methods("GET")
|
||||||
r.HandleFunc("/gov/proposals", queryProposalsWithParameterFn(cdc)).Methods("GET")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type postProposalReq struct {
|
type postProposalReq struct {
|
||||||
|
@ -164,7 +163,7 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func queryProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
func queryProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) 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[RestProposalID]
|
strProposalID := vars[RestProposalID]
|
||||||
|
@ -180,8 +179,6 @@ func queryProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
|
||||||
|
|
||||||
params := gov.QueryProposalParams{
|
params := gov.QueryProposalParams{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
}
|
}
|
||||||
|
@ -198,11 +195,41 @@ func queryProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Write(res)
|
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func queryDepositHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
func queryDepositsHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
strProposalID := vars[RestProposalID]
|
||||||
|
|
||||||
|
proposalID, ok := utils.ParseInt64OrReturnBadRequest(w, strProposalID)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params := gov.QueryDepositsParams{
|
||||||
|
ProposalID: proposalID,
|
||||||
|
}
|
||||||
|
|
||||||
|
bz, err := cdc.MarshalJSON(params)
|
||||||
|
if err != nil {
|
||||||
|
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := cliCtx.QueryWithData("custom/gov/deposits", bz)
|
||||||
|
if err != nil {
|
||||||
|
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) 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[RestProposalID]
|
strProposalID := vars[RestProposalID]
|
||||||
|
@ -232,8 +259,6 @@ func queryDepositHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
|
||||||
|
|
||||||
params := gov.QueryDepositParams{
|
params := gov.QueryDepositParams{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
Depositer: depositerAddr,
|
Depositer: depositerAddr,
|
||||||
|
@ -265,11 +290,11 @@ func queryDepositHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Write(res)
|
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func queryVoteHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
func queryVoteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) 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[RestProposalID]
|
strProposalID := vars[RestProposalID]
|
||||||
|
@ -299,8 +324,6 @@ func queryVoteHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
|
||||||
|
|
||||||
params := gov.QueryVoteParams{
|
params := gov.QueryVoteParams{
|
||||||
Voter: voterAddr,
|
Voter: voterAddr,
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
|
@ -335,12 +358,12 @@ func queryVoteHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Write(res)
|
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: Split this functionality into helper functions to remove the above
|
// todo: Split this functionality into helper functions to remove the above
|
||||||
func queryVotesOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
func queryVotesOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) 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[RestProposalID]
|
strProposalID := vars[RestProposalID]
|
||||||
|
@ -356,8 +379,6 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
|
||||||
|
|
||||||
params := gov.QueryVotesParams{
|
params := gov.QueryVotesParams{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
}
|
}
|
||||||
|
@ -373,12 +394,12 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Write(res)
|
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: Split this functionality into helper functions to remove the above
|
// todo: Split this functionality into helper functions to remove the above
|
||||||
func queryProposalsWithParameterFn(cdc *codec.Codec) http.HandlerFunc {
|
func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
bechVoterAddr := r.URL.Query().Get(RestVoter)
|
bechVoterAddr := r.URL.Query().Get(RestVoter)
|
||||||
bechDepositerAddr := r.URL.Query().Get(RestDepositer)
|
bechDepositerAddr := r.URL.Query().Get(RestDepositer)
|
||||||
|
@ -430,20 +451,18 @@ func queryProposalsWithParameterFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
|
||||||
|
|
||||||
res, err := cliCtx.QueryWithData("custom/gov/proposals", bz)
|
res, err := cliCtx.QueryWithData("custom/gov/proposals", bz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Write(res)
|
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: Split this functionality into helper functions to remove the above
|
// todo: Split this functionality into helper functions to remove the above
|
||||||
func queryTallyOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
func queryTallyOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) 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[RestProposalID]
|
strProposalID := vars[RestProposalID]
|
||||||
|
@ -461,8 +480,6 @@ func queryTallyOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cliCtx := context.NewCLIContext().WithCodec(cdc)
|
|
||||||
|
|
||||||
params := gov.QueryTallyParams{
|
params := gov.QueryTallyParams{
|
||||||
ProposalID: proposalID,
|
ProposalID: proposalID,
|
||||||
}
|
}
|
||||||
|
@ -480,6 +497,6 @@ func queryTallyOnProposalHandlerFn(cdc *codec.Codec) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Write(res)
|
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ type QueryDepositsParams struct {
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
|
func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
|
||||||
var params QueryDepositParams
|
var params QueryDepositsParams
|
||||||
err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error()))
|
return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error()))
|
||||||
|
|
|
@ -35,6 +35,8 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
|
||||||
func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.ValidatorUpdate) {
|
func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.ValidatorUpdate) {
|
||||||
endBlockerTags := sdk.EmptyTags()
|
endBlockerTags := sdk.EmptyTags()
|
||||||
|
|
||||||
|
k.UnbondAllMatureValidatorQueue(ctx)
|
||||||
|
|
||||||
matureUnbonds := k.DequeueAllMatureUnbondingQueue(ctx, ctx.BlockHeader().Time)
|
matureUnbonds := k.DequeueAllMatureUnbondingQueue(ctx, ctx.BlockHeader().Time)
|
||||||
for _, dvPair := range matureUnbonds {
|
for _, dvPair := range matureUnbonds {
|
||||||
err := k.CompleteUnbonding(ctx, dvPair.DelegatorAddr, dvPair.ValidatorAddr)
|
err := k.CompleteUnbonding(ctx, dvPair.DelegatorAddr, dvPair.ValidatorAddr)
|
||||||
|
|
|
@ -629,6 +629,56 @@ func TestJailValidator(t *testing.T) {
|
||||||
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidatorQueue(t *testing.T) {
|
||||||
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||||
|
validatorAddr, delegatorAddr := sdk.ValAddress(keep.Addrs[0]), keep.Addrs[1]
|
||||||
|
|
||||||
|
// set the unbonding time
|
||||||
|
params := keeper.GetParams(ctx)
|
||||||
|
params.UnbondingTime = 7 * time.Second
|
||||||
|
keeper.SetParams(ctx, params)
|
||||||
|
|
||||||
|
// create the validator
|
||||||
|
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10)
|
||||||
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||||
|
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
|
||||||
|
|
||||||
|
// bond a delegator
|
||||||
|
msgDelegate := newTestMsgDelegate(delegatorAddr, validatorAddr, 10)
|
||||||
|
got = handleMsgDelegate(ctx, msgDelegate, keeper)
|
||||||
|
require.True(t, got.IsOK(), "expected ok, got %v", got)
|
||||||
|
|
||||||
|
EndBlocker(ctx, keeper)
|
||||||
|
|
||||||
|
// unbond the all self-delegation to put validator in unbonding state
|
||||||
|
msgBeginUnbondingValidator := NewMsgBeginUnbonding(sdk.AccAddress(validatorAddr), validatorAddr, sdk.NewDec(10))
|
||||||
|
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper)
|
||||||
|
require.True(t, got.IsOK(), "expected no error: %v", got)
|
||||||
|
var finishTime time.Time
|
||||||
|
types.MsgCdc.MustUnmarshalBinary(got.Data, &finishTime)
|
||||||
|
ctx = ctx.WithBlockTime(finishTime)
|
||||||
|
EndBlocker(ctx, keeper)
|
||||||
|
origHeader := ctx.BlockHeader()
|
||||||
|
|
||||||
|
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
||||||
|
require.True(t, found)
|
||||||
|
require.True(t, validator.GetStatus() == sdk.Unbonding, "%v", validator)
|
||||||
|
|
||||||
|
// should still be unbonding at time 6 seconds later
|
||||||
|
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 6))
|
||||||
|
EndBlocker(ctx, keeper)
|
||||||
|
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||||
|
require.True(t, found)
|
||||||
|
require.True(t, validator.GetStatus() == sdk.Unbonding, "%v", validator)
|
||||||
|
|
||||||
|
// should be in unbonded state at time 7 seconds later
|
||||||
|
ctx = ctx.WithBlockTime(origHeader.Time.Add(time.Second * 7))
|
||||||
|
EndBlocker(ctx, keeper)
|
||||||
|
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||||
|
require.True(t, found)
|
||||||
|
require.True(t, validator.GetStatus() == sdk.Unbonded, "%v", validator)
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnbondingPeriod(t *testing.T) {
|
func TestUnbondingPeriod(t *testing.T) {
|
||||||
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||||
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
||||||
|
|
|
@ -447,10 +447,10 @@ func (k Keeper) getBeginInfo(ctx sdk.Context, valSrcAddr sdk.ValAddress) (
|
||||||
|
|
||||||
// the longest wait - just unbonding period from now
|
// the longest wait - just unbonding period from now
|
||||||
minTime = ctx.BlockHeader().Time.Add(k.UnbondingTime(ctx))
|
minTime = ctx.BlockHeader().Time.Add(k.UnbondingTime(ctx))
|
||||||
height = ctx.BlockHeader().Height
|
height = ctx.BlockHeight()
|
||||||
return minTime, height, false
|
return minTime, height, false
|
||||||
|
|
||||||
case validator.IsUnbonded(ctx):
|
case validator.Status == sdk.Unbonded:
|
||||||
return minTime, height, true
|
return minTime, height, true
|
||||||
|
|
||||||
case validator.Status == sdk.Unbonding:
|
case validator.Status == sdk.Unbonding:
|
||||||
|
|
|
@ -374,12 +374,8 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
|
||||||
}
|
}
|
||||||
keeper.SetDelegation(ctx, delegation)
|
keeper.SetDelegation(ctx, delegation)
|
||||||
|
|
||||||
header := ctx.BlockHeader()
|
ctx = ctx.WithBlockHeight(10)
|
||||||
blockHeight := int64(10)
|
ctx = ctx.WithBlockTime(time.Unix(333, 0))
|
||||||
header.Height = blockHeight
|
|
||||||
blockTime := time.Unix(333, 0)
|
|
||||||
header.Time = blockTime
|
|
||||||
ctx = ctx.WithBlockHeader(header)
|
|
||||||
|
|
||||||
// unbond the all self-delegation to put validator in unbonding state
|
// unbond the all self-delegation to put validator in unbonding state
|
||||||
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDec(10))
|
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDec(10))
|
||||||
|
@ -391,17 +387,12 @@ func TestUndelegateFromUnbondedValidator(t *testing.T) {
|
||||||
|
|
||||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, blockHeight, validator.UnbondingHeight)
|
require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight)
|
||||||
params := keeper.GetParams(ctx)
|
params := keeper.GetParams(ctx)
|
||||||
require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingMinTime))
|
require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingMinTime))
|
||||||
|
|
||||||
// change the context to one which makes the validator considered unbonded
|
// unbond the validator
|
||||||
header = ctx.BlockHeader()
|
keeper.unbondingToUnbonded(ctx, validator)
|
||||||
blockHeight2 := int64(20)
|
|
||||||
header.Height = blockHeight2
|
|
||||||
blockTime2 := time.Unix(444, 0).Add(params.UnbondingTime)
|
|
||||||
header.Time = blockTime2
|
|
||||||
ctx = ctx.WithBlockHeader(header)
|
|
||||||
|
|
||||||
// unbond some of the other delegation's shares
|
// unbond some of the other delegation's shares
|
||||||
_, err = keeper.BeginUnbonding(ctx, addrDels[0], addrVals[0], sdk.NewDec(6))
|
_, err = keeper.BeginUnbonding(ctx, addrDels[0], addrVals[0], sdk.NewDec(6))
|
||||||
|
@ -696,12 +687,8 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) {
|
||||||
validator2 = testingUpdateValidator(keeper, ctx, validator2)
|
validator2 = testingUpdateValidator(keeper, ctx, validator2)
|
||||||
require.Equal(t, sdk.Bonded, validator2.Status)
|
require.Equal(t, sdk.Bonded, validator2.Status)
|
||||||
|
|
||||||
header := ctx.BlockHeader()
|
ctx = ctx.WithBlockHeight(10)
|
||||||
blockHeight := int64(10)
|
ctx = ctx.WithBlockTime(time.Unix(333, 0))
|
||||||
header.Height = blockHeight
|
|
||||||
blockTime := time.Unix(333, 0)
|
|
||||||
header.Time = blockTime
|
|
||||||
ctx = ctx.WithBlockHeader(header)
|
|
||||||
|
|
||||||
// unbond the all self-delegation to put validator in unbonding state
|
// unbond the all self-delegation to put validator in unbonding state
|
||||||
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDec(10))
|
_, err := keeper.BeginUnbonding(ctx, val0AccAddr, addrVals[0], sdk.NewDec(10))
|
||||||
|
@ -713,23 +700,18 @@ func TestRedelegateFromUnbondedValidator(t *testing.T) {
|
||||||
|
|
||||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, blockHeight, validator.UnbondingHeight)
|
require.Equal(t, ctx.BlockHeight(), validator.UnbondingHeight)
|
||||||
params := keeper.GetParams(ctx)
|
params := keeper.GetParams(ctx)
|
||||||
require.True(t, blockTime.Add(params.UnbondingTime).Equal(validator.UnbondingMinTime))
|
require.True(t, ctx.BlockHeader().Time.Add(params.UnbondingTime).Equal(validator.UnbondingMinTime))
|
||||||
|
|
||||||
// change the context to one which makes the validator considered unbonded
|
// unbond the validator
|
||||||
header = ctx.BlockHeader()
|
keeper.unbondingToUnbonded(ctx, validator)
|
||||||
blockHeight2 := int64(20)
|
|
||||||
header.Height = blockHeight2
|
|
||||||
blockTime2 := time.Unix(444, 0).Add(params.UnbondingTime)
|
|
||||||
header.Time = blockTime2
|
|
||||||
ctx = ctx.WithBlockHeader(header)
|
|
||||||
|
|
||||||
// unbond some of the other delegation's shares
|
// redelegate some of the delegation's shares
|
||||||
_, err = keeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], sdk.NewDec(6))
|
_, err = keeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], sdk.NewDec(6))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// no ubd should have been found, coins should have been returned direcly to account
|
// no red should have been found
|
||||||
ubd, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
red, found := keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
require.False(t, found, "%v", ubd)
|
require.False(t, found, "%v", red)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ var (
|
||||||
RedelegationByValDstIndexKey = []byte{0x0C} // prefix for each key for an redelegation, by destination validator operator
|
RedelegationByValDstIndexKey = []byte{0x0C} // prefix for each key for an redelegation, by destination validator operator
|
||||||
UnbondingQueueKey = []byte{0x0D} // prefix for the timestamps in unbonding queue
|
UnbondingQueueKey = []byte{0x0D} // prefix for the timestamps in unbonding queue
|
||||||
RedelegationQueueKey = []byte{0x0E} // prefix for the timestamps in redelegations queue
|
RedelegationQueueKey = []byte{0x0E} // prefix for the timestamps in redelegations queue
|
||||||
|
ValidatorQueueKey = []byte{0x0F} // prefix for the timestamps in validator queue
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch
|
const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch
|
||||||
|
@ -86,6 +87,12 @@ func getValidatorPowerRank(validator types.Validator) []byte {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gets the prefix for all unbonding delegations from a delegator
|
||||||
|
func GetValidatorQueueTimeKey(timestamp time.Time) []byte {
|
||||||
|
bz := types.MsgCdc.MustMarshalBinary(timestamp)
|
||||||
|
return append(ValidatorQueueKey, bz...)
|
||||||
|
}
|
||||||
|
|
||||||
//______________________________________________________________________________
|
//______________________________________________________________________________
|
||||||
|
|
||||||
// gets the key for delegator bond with validator
|
// gets the key for delegator bond with validator
|
||||||
|
|
|
@ -46,7 +46,7 @@ func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeigh
|
||||||
}
|
}
|
||||||
|
|
||||||
// should not be slashing unbonded
|
// should not be slashing unbonded
|
||||||
if validator.IsUnbonded(ctx) {
|
if validator.Status == sdk.Unbonded {
|
||||||
panic(fmt.Sprintf("should not be slashing unbonded validator: %s", validator.GetOperator()))
|
panic(fmt.Sprintf("should not be slashing unbonded validator: %s", validator.GetOperator()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,8 +131,9 @@ func (k Keeper) unbondedToBonded(ctx sdk.Context, validator types.Validator) typ
|
||||||
return k.bondValidator(ctx, validator)
|
return k.bondValidator(ctx, validator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// switches a validator from unbonding state to unbonded state
|
||||||
func (k Keeper) unbondingToUnbonded(ctx sdk.Context, validator types.Validator) types.Validator {
|
func (k Keeper) unbondingToUnbonded(ctx sdk.Context, validator types.Validator) types.Validator {
|
||||||
if validator.Status != sdk.Unbonded {
|
if validator.Status != sdk.Unbonding {
|
||||||
panic(fmt.Sprintf("bad state transition unbondingToBonded, validator: %v\n", validator))
|
panic(fmt.Sprintf("bad state transition unbondingToBonded, validator: %v\n", validator))
|
||||||
}
|
}
|
||||||
return k.completeUnbondingValidator(ctx, validator)
|
return k.completeUnbondingValidator(ctx, validator)
|
||||||
|
@ -213,6 +214,9 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
|
||||||
|
|
||||||
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
k.SetValidatorByPowerIndex(ctx, validator, pool)
|
||||||
|
|
||||||
|
// Adds to unbonding validator queue
|
||||||
|
k.InsertValidatorQueue(ctx, validator)
|
||||||
|
|
||||||
// call the unbond hook if present
|
// call the unbond hook if present
|
||||||
if k.hooks != nil {
|
if k.hooks != nil {
|
||||||
k.hooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress())
|
k.hooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress())
|
||||||
|
|
|
@ -3,6 +3,7 @@ package keeper
|
||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
|
@ -281,3 +282,69 @@ func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator {
|
||||||
}
|
}
|
||||||
return validators[:i] // trim
|
return validators[:i] // trim
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gets a specific validator queue timeslice. A timeslice is a slice of ValAddresses corresponding to unbonding validators
|
||||||
|
// that expire at a certain time.
|
||||||
|
func (k Keeper) GetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time) (valAddrs []sdk.ValAddress) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
bz := store.Get(GetValidatorQueueTimeKey(timestamp))
|
||||||
|
if bz == nil {
|
||||||
|
return []sdk.ValAddress{}
|
||||||
|
}
|
||||||
|
k.cdc.MustUnmarshalBinary(bz, &valAddrs)
|
||||||
|
return valAddrs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets a specific validator queue timeslice.
|
||||||
|
func (k Keeper) SetValidatorQueueTimeSlice(ctx sdk.Context, timestamp time.Time, keys []sdk.ValAddress) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
bz := k.cdc.MustMarshalBinary(keys)
|
||||||
|
store.Set(GetValidatorQueueTimeKey(timestamp), bz)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert an validator address to the appropriate timeslice in the validator queue
|
||||||
|
func (k Keeper) InsertValidatorQueue(ctx sdk.Context, val types.Validator) {
|
||||||
|
timeSlice := k.GetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime)
|
||||||
|
if len(timeSlice) == 0 {
|
||||||
|
k.SetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime, []sdk.ValAddress{val.OperatorAddr})
|
||||||
|
} else {
|
||||||
|
timeSlice = append(timeSlice, val.OperatorAddr)
|
||||||
|
k.SetValidatorQueueTimeSlice(ctx, val.UnbondingMinTime, timeSlice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns all the validator queue timeslices from time 0 until endTime
|
||||||
|
func (k Keeper) ValidatorQueueIterator(ctx sdk.Context, endTime time.Time) sdk.Iterator {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
return store.Iterator(ValidatorQueueKey, sdk.InclusiveEndBytes(GetValidatorQueueTimeKey(endTime)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a concatenated list of all the timeslices before currTime, and deletes the timeslices from the queue
|
||||||
|
func (k Keeper) GetAllMatureValidatorQueue(ctx sdk.Context, currTime time.Time) (matureValsAddrs []sdk.ValAddress) {
|
||||||
|
// gets an iterator for all timeslices from time 0 until the current Blockheader time
|
||||||
|
validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
|
for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
|
||||||
|
timeslice := []sdk.ValAddress{}
|
||||||
|
k.cdc.MustUnmarshalBinary(validatorTimesliceIterator.Value(), ×lice)
|
||||||
|
matureValsAddrs = append(matureValsAddrs, timeslice...)
|
||||||
|
}
|
||||||
|
return matureValsAddrs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unbonds all the unbonding validators that have finished their unbonding period
|
||||||
|
func (k Keeper) UnbondAllMatureValidatorQueue(ctx sdk.Context) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
validatorTimesliceIterator := k.ValidatorQueueIterator(ctx, ctx.BlockHeader().Time)
|
||||||
|
for ; validatorTimesliceIterator.Valid(); validatorTimesliceIterator.Next() {
|
||||||
|
timeslice := []sdk.ValAddress{}
|
||||||
|
k.cdc.MustUnmarshalBinary(validatorTimesliceIterator.Value(), ×lice)
|
||||||
|
for _, valAddr := range timeslice {
|
||||||
|
val, found := k.GetValidator(ctx, valAddr)
|
||||||
|
if !found || val.GetStatus() != sdk.Unbonding {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
k.unbondingToUnbonded(ctx, val)
|
||||||
|
}
|
||||||
|
store.Delete(validatorTimesliceIterator.Key())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -435,21 +435,6 @@ func (v Validator) BondedTokens() sdk.Dec {
|
||||||
return sdk.ZeroDec()
|
return sdk.ZeroDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove this once the validator queue logic is implemented
|
|
||||||
// Returns if the validator should be considered unbonded
|
|
||||||
func (v Validator) IsUnbonded(ctx sdk.Context) bool {
|
|
||||||
switch v.Status {
|
|
||||||
case sdk.Unbonded:
|
|
||||||
return true
|
|
||||||
case sdk.Unbonding:
|
|
||||||
ctxTime := ctx.BlockHeader().Time
|
|
||||||
if ctxTime.After(v.UnbondingMinTime) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
//______________________________________________________________________
|
//______________________________________________________________________
|
||||||
|
|
||||||
// ensure fulfills the sdk validator types
|
// ensure fulfills the sdk validator types
|
||||||
|
|
Loading…
Reference in New Issue