Merge branch 'develop' into bucky/merge-master

This commit is contained in:
Ethan Buchman 2018-08-19 16:24:45 -04:00
commit af73b885e7
86 changed files with 1776 additions and 1640 deletions

View File

@ -1,2 +0,0 @@
* @jaekwon
* @ebuchman

6
Gopkg.lock generated
View File

@ -538,14 +538,14 @@
[[projects]]
branch = "master"
digest = "1:a989b95f72fce8876213e8e20492525b4cf69a9e7fee7f1d9897983ee0d547e9"
digest = "1:4bd75b1a219bc590b05c976bbebf47f4e993314ebb5c7cbf2efe05a09a184d54"
name = "golang.org/x/sys"
packages = [
"cpu",
"unix",
]
pruneopts = "UT"
revision = "1c9583448a9c3aa0f9a6a5241bf73c0bd8aafded"
revision = "4e1fef5609515ec7a2cee7b5de30ba6d9b438cbf"
[[projects]]
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
@ -576,7 +576,7 @@
name = "google.golang.org/genproto"
packages = ["googleapis/rpc/status"]
pruneopts = "UT"
revision = "d0a8f471bba2dbb160885b0000d814ee5d559bad"
revision = "383e8b2c3b9e36c4076b235b32537292176bae20"
[[projects]]
digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74"

View File

@ -5,6 +5,7 @@ BUILD_TAGS = netgo ledger
BUILD_FLAGS = -tags "${BUILD_TAGS}" -ldflags "-X github.com/cosmos/cosmos-sdk/version.GitCommit=${COMMIT_HASH}"
GCC := $(shell command -v gcc 2> /dev/null)
LEDGER_ENABLED ?= true
UNAME_S := $(shell uname -s)
all: get_tools get_vendor_deps install install_examples install_cosmos-sdk-cli test_lint test
########################################
@ -17,12 +18,18 @@ ci: get_tools get_vendor_deps install test_cover test_lint test
check-ledger:
ifeq ($(LEDGER_ENABLED),true)
ifndef GCC
$(error "gcc not installed for ledger support, please install")
endif
ifeq ($(UNAME_S),OpenBSD)
$(info "OpenBSD detected, disabling ledger support (https://github.com/cosmos/cosmos-sdk/issues/1988)")
TMP_BUILD_TAGS := $(BUILD_TAGS)
BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS))
else
ifndef GCC
$(error "gcc not installed for ledger support, please install or set LEDGER_ENABLED to false in the Makefile")
endif
endif
else
TMP_BUILD_TAGS := $(BUILD_TAGS)
BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS))
TMP_BUILD_TAGS := $(BUILD_TAGS)
BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS))
endif
build: check-ledger
@ -100,6 +107,7 @@ get_dev_tools:
get_vendor_deps:
@echo "--> Running dep ensure"
@rm -rf .vendor-new
@dep ensure -v
draw_deps:

View File

@ -3,17 +3,24 @@
BREAKING CHANGES
* Gaia REST API (`gaiacli advanced rest-server`)
* [x/stake] Validator.Owner renamed to Validator.Operator
* Gaia CLI (`gaiacli`)
* [x/stake] Validator.Owner renamed to Validator.Operator
* [cli] unsafe_reset_all, show_validator, and show_node_id have been renamed to unsafe-reset-all, show-validator, and show-node-id
* Gaia
* Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013)
* [x/stake] \#1901 Validator type's Owner field renamed to Operator; Validator's GetOwner() renamed accordingly to comply with the SDK's Validator interface.
* SDK
* [core] \#1807 Switch from use of rational to decimal
* [types] \#1901 Validator interface's GetOwner() renamed to GetOperator()
* Tendermint
FEATURES
* Gaia REST API (`gaiacli advanced rest-server`)
@ -30,12 +37,15 @@ FEATURES
IMPROVEMENTS
* Gaia REST API (`gaiacli advanced rest-server`)
* [x/stake] \#2000 Added tests for new staking endpoints
* Gaia CLI (`gaiacli`)
* Gaia
* [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check.
* SDK
* [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present.
* Tendermint
@ -45,9 +55,12 @@ BUG FIXES
* Gaia REST API (`gaiacli advanced rest-server`)
* Gaia CLI (`gaiacli`)
* [cli] \#1997 Handle panics gracefully when `gaiacli stake {delegation,unbond}` fail to unmarshal delegation.
* Gaia
* SDK
* \#1988 Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988)
* Tendermint

View File

@ -361,13 +361,13 @@ func TestValidatorsQuery(t *testing.T) {
validators := getValidators(t, port)
require.Equal(t, len(validators), 1)
// make sure all the validators were found (order unknown because sorted by owner addr)
// make sure all the validators were found (order unknown because sorted by operator addr)
foundVal := false
pkBech := sdk.MustBech32ifyValPub(pks[0])
if validators[0].PubKey == pkBech {
foundVal = true
}
require.True(t, foundVal, "pkBech %v, owner %v", pkBech, validators[0].Owner)
require.True(t, foundVal, "pkBech %v, operator %v", pkBech, validators[0].Operator)
}
func TestValidatorQuery(t *testing.T) {
@ -375,74 +375,80 @@ func TestValidatorQuery(t *testing.T) {
defer cleanup()
require.Equal(t, 1, len(pks))
validator1Owner := sdk.AccAddress(pks[0].Address())
validator := getValidator(t, port, validator1Owner)
bech32ValAddress, err := sdk.Bech32ifyValPub(pks[0])
require.NoError(t, err)
assert.Equal(t, validator.PubKey, bech32ValAddress, "The returned validator does not hold the correct data")
validator1Operator := sdk.AccAddress(pks[0].Address())
validator := getValidator(t, port, validator1Operator)
assert.Equal(t, validator.Operator, validator1Operator, "The returned validator does not hold the correct data")
}
func TestBonding(t *testing.T) {
name, password, denom := "test", "1234567890", "steak"
addr, seed := CreateAddr(t, "test", password, GetKeyBase(t))
addr, seed := CreateAddr(t, name, password, GetKeyBase(t))
cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
defer cleanup()
validator1Owner := sdk.AccAddress(pks[0].Address())
validator1Operator := sdk.AccAddress(pks[0].Address())
validator := getValidator(t, port, validator1Operator)
// create bond TX
resultTx := doDelegate(t, port, seed, name, password, addr, validator1Owner)
resultTx := doDelegate(t, port, seed, name, password, addr, validator1Operator, 60)
tests.WaitForHeight(resultTx.Height+1, port)
// check if tx was committed
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
// query sender
acc := getAccount(t, port, addr)
coins := acc.GetCoins()
require.Equal(t, int64(40), coins.AmountOf(denom).Int64())
// query validator
bond := getDelegation(t, port, addr, validator1Owner)
bond := getDelegation(t, port, addr, validator1Operator)
require.Equal(t, "60.0000000000", bond.Shares)
summary := getDelegationSummary(t, port, addr)
require.Len(t, summary.Delegations, 1, "Delegation summary holds all delegations")
require.Equal(t, "60.0000000000", summary.Delegations[0].Shares)
require.Len(t, summary.UnbondingDelegations, 0, "Delegation summary holds all unbonding-delegations")
bondedValidators := getDelegatorValidators(t, port, addr)
require.Len(t, bondedValidators, 1)
require.Equal(t, validator1Operator, bondedValidators[0].Operator)
require.Equal(t, validator.DelegatorShares.Add(sdk.NewDec(60)).String(), bondedValidators[0].DelegatorShares.String())
bondedValidator := getDelegatorValidator(t, port, addr, validator1Operator)
require.Equal(t, validator1Operator, bondedValidator.Operator)
//////////////////////
// testing unbonding
// create unbond TX
resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Owner)
resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Operator, 60)
tests.WaitForHeight(resultTx.Height+1, port)
// query validator
bond = getDelegation(t, port, addr, validator1Owner)
require.Equal(t, "30.0000000000", bond.Shares)
// check if tx was committed
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
// should the sender should have not received any coins as the unbonding has only just begun
// query sender
// sender should have not received any coins as the unbonding has only just begun
acc = getAccount(t, port, addr)
coins = acc.GetCoins()
require.Equal(t, int64(40), coins.AmountOf("steak").Int64())
// query unbonding delegation
validatorAddr := sdk.AccAddress(pks[0].Address())
unbondings := getUndelegations(t, port, addr, validatorAddr)
assert.Len(t, unbondings, 1, "Unbondings holds all unbonding-delegations")
assert.Equal(t, "30", unbondings[0].Balance.Amount.String())
unbondings := getUndelegations(t, port, addr, validator1Operator)
require.Len(t, unbondings, 1, "Unbondings holds all unbonding-delegations")
require.Equal(t, "60", unbondings[0].Balance.Amount.String())
// query summary
summary := getDelegationSummary(t, port, addr)
summary = getDelegationSummary(t, port, addr)
assert.Len(t, summary.Delegations, 1, "Delegation summary holds all delegations")
assert.Equal(t, "30.0000000000", summary.Delegations[0].Shares)
assert.Len(t, summary.UnbondingDelegations, 1, "Delegation summary holds all unbonding-delegations")
assert.Equal(t, "30", summary.UnbondingDelegations[0].Balance.Amount.String())
require.Len(t, summary.Delegations, 0, "Delegation summary holds all delegations")
require.Len(t, summary.UnbondingDelegations, 1, "Delegation summary holds all unbonding-delegations")
require.Equal(t, "60", summary.UnbondingDelegations[0].Balance.Amount.String())
bondedValidators = getDelegatorValidators(t, port, addr)
require.Len(t, bondedValidators, 0, "There's no delegation as the user withdraw all funds")
// TODO Undonding status not currently implemented
// require.Equal(t, sdk.Unbonding, bondedValidators[0].Status)
// TODO add redelegation, need more complex capabilities such to mock context and
// TODO check summary for redelegation
@ -757,64 +763,89 @@ func getSigningInfo(t *testing.T, port string, validatorPubKey string) slashing.
// ============= Stake Module ================
func getDelegation(t *testing.T, port string, delegatorAddr, validatorAddr sdk.AccAddress) rest.DelegationWithoutRat {
// get the account to get the sequence
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/delegations/%s", delegatorAddr, validatorAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var bond rest.DelegationWithoutRat
err := cdc.UnmarshalJSON([]byte(body), &bond)
require.Nil(t, err)
return bond
}
func getUndelegations(t *testing.T, port string, delegatorAddr, validatorAddr sdk.AccAddress) []stake.UnbondingDelegation {
// get the account to get the sequence
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/unbonding_delegations/%s", delegatorAddr, validatorAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var unbondings []stake.UnbondingDelegation
err := cdc.UnmarshalJSON([]byte(body), &unbondings)
require.Nil(t, err)
return unbondings
}
func getDelegationSummary(t *testing.T, port string, delegatorAddr sdk.AccAddress) rest.DelegationSummary {
// get the account to get the sequence
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s", delegatorAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var summary rest.DelegationSummary
err := cdc.UnmarshalJSON([]byte(body), &summary)
require.Nil(t, err)
return summary
}
func getBondingTxs(t *testing.T, port string, delegatorAddr sdk.AccAddress, query string) []tx.Info {
// get the account to get the sequence
var res *http.Response
var body string
if len(query) > 0 {
res, body = Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/txs?type=%s", delegatorAddr, query), nil)
} else {
res, body = Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/txs", delegatorAddr), nil)
}
require.Equal(t, http.StatusOK, res.StatusCode, body)
var txs []tx.Info
err := cdc.UnmarshalJSON([]byte(body), &txs)
require.Nil(t, err)
return txs
}
func doDelegate(t *testing.T, port, seed, name, password string, delegatorAddr, validatorAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence
func getDelegatorValidators(t *testing.T, port string, delegatorAddr sdk.AccAddress) []stake.BechValidator {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/validators", delegatorAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var bondedValidators []stake.BechValidator
err := cdc.UnmarshalJSON([]byte(body), &bondedValidators)
require.Nil(t, err)
return bondedValidators
}
func getDelegatorValidator(t *testing.T, port string, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) stake.BechValidator {
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/validators/%s", delegatorAddr, validatorAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var bondedValidator stake.BechValidator
err := cdc.UnmarshalJSON([]byte(body), &bondedValidator)
require.Nil(t, err)
return bondedValidator
}
func doDelegate(t *testing.T, port, seed, name, password string, delegatorAddr, validatorAddr sdk.AccAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
acc := getAccount(t, port, delegatorAddr)
accnum := acc.GetAccountNumber()
sequence := acc.GetSequence()
chainID := viper.GetString(client.FlagChainID)
// send
jsonStr := []byte(fmt.Sprintf(`{
"name": "%s",
"password": "%s",
@ -826,14 +857,15 @@ func doDelegate(t *testing.T, port, seed, name, password string, delegatorAddr,
{
"delegator_addr": "%s",
"validator_addr": "%s",
"delegation": { "denom": "%s", "amount": "60" }
"delegation": { "denom": "%s", "amount": "%d" }
}
],
"begin_unbondings": [],
"complete_unbondings": [],
"begin_redelegates": [],
"complete_redelegates": []
}`, name, password, accnum, sequence, chainID, delegatorAddr, validatorAddr, "steak"))
}`, name, password, accnum, sequence, chainID, delegatorAddr, validatorAddr, "steak", amount))
res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), jsonStr)
require.Equal(t, http.StatusOK, res.StatusCode, body)
@ -845,16 +877,13 @@ func doDelegate(t *testing.T, port, seed, name, password string, delegatorAddr,
}
func doBeginUnbonding(t *testing.T, port, seed, name, password string,
delegatorAddr, validatorAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
delegatorAddr, validatorAddr sdk.AccAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence
acc := getAccount(t, port, delegatorAddr)
accnum := acc.GetAccountNumber()
sequence := acc.GetSequence()
chainID := viper.GetString(client.FlagChainID)
// send
jsonStr := []byte(fmt.Sprintf(`{
"name": "%s",
"password": "%s",
@ -867,13 +896,14 @@ func doBeginUnbonding(t *testing.T, port, seed, name, password string,
{
"delegator_addr": "%s",
"validator_addr": "%s",
"shares": "30"
"shares": "%d"
}
],
"complete_unbondings": [],
"begin_redelegates": [],
"complete_redelegates": []
}`, name, password, accnum, sequence, chainID, delegatorAddr, validatorAddr))
}`, name, password, accnum, sequence, chainID, delegatorAddr, validatorAddr, amount))
res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), jsonStr)
require.Equal(t, http.StatusOK, res.StatusCode, body)
@ -887,14 +917,12 @@ func doBeginUnbonding(t *testing.T, port, seed, name, password string,
func doBeginRedelegation(t *testing.T, port, seed, name, password string,
delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence
acc := getAccount(t, port, delegatorAddr)
accnum := acc.GetAccountNumber()
sequence := acc.GetSequence()
chainID := viper.GetString(client.FlagChainID)
// send
jsonStr := []byte(fmt.Sprintf(`{
"name": "%s",
"password": "%s",
@ -915,6 +943,7 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string,
],
"complete_redelegates": []
}`, name, password, accnum, sequence, chainID, delegatorAddr, validatorSrcAddr, validatorDstAddr))
res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), jsonStr)
require.Equal(t, http.StatusOK, res.StatusCode, body)
@ -926,7 +955,6 @@ func doBeginRedelegation(t *testing.T, port, seed, name, password string,
}
func getValidators(t *testing.T, port string) []stake.BechValidator {
// get the account to get the sequence
res, body := Request(t, port, "GET", "/stake/validators", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var validators []stake.BechValidator
@ -936,7 +964,6 @@ func getValidators(t *testing.T, port string) []stake.BechValidator {
}
func getValidator(t *testing.T, port string, validatorAddr sdk.AccAddress) stake.BechValidator {
// get the account to get the sequence
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/validators/%s", validatorAddr.String()), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var validator stake.BechValidator
@ -1034,7 +1061,7 @@ func getProposalsFilterStatus(t *testing.T, port string, status gov.ProposalStat
}
func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence
acc := getAccount(t, port, proposerAddr)
accnum := acc.GetAccountNumber()
sequence := acc.GetSequence()
@ -1068,7 +1095,7 @@ func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerA
}
func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID int64) (resultTx ctypes.ResultBroadcastTxCommit) {
// get the account to get the sequence
acc := getAccount(t, port, proposerAddr)
accnum := acc.GetAccountNumber()
sequence := acc.GetSequence()

View File

@ -173,7 +173,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 100)}
acc := gapp.NewGenesisAccount(&accAuth)
genesisState.Accounts = append(genesisState.Accounts, acc)
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewRat(100))
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewDec(100))
}
appState, err := wire.MarshalJSONIndent(cdc, genesisState)

View File

@ -185,7 +185,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
}
acc := NewGenesisAccount(&accAuth)
genaccs[i] = acc
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionsAcc)) // increase the supply
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionsAcc)) // increase the supply
// add the validator
if len(genTx.Name) > 0 {
@ -193,17 +193,17 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState
validator := stake.NewValidator(genTx.Address,
sdk.MustGetAccPubKeyBech32(genTx.PubKey), desc)
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionVal)) // increase the supply
stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionVal)) // increase the supply
// add some new shares to the validator
var issuedDelShares sdk.Rat
var issuedDelShares sdk.Dec
validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, freeFermionVal)
stakeData.Validators = append(stakeData.Validators, validator)
// create the self-delegation from the issuedDelShares
delegation := stake.Delegation{
DelegatorAddr: validator.Owner,
ValidatorAddr: validator.Owner,
DelegatorAddr: validator.Operator,
ValidatorAddr: validator.Operator,
Shares: issuedDelShares,
Height: 0,
}

View File

@ -34,7 +34,7 @@ func init() {
}
func TestGaiaCLISend(t *testing.T) {
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome), "")
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "")
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass)
@ -87,7 +87,7 @@ func TestGaiaCLISend(t *testing.T) {
}
func TestGaiaCLICreateValidator(t *testing.T) {
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome), "")
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "")
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass)
chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome))
@ -131,13 +131,13 @@ func TestGaiaCLICreateValidator(t *testing.T) {
require.Equal(t, int64(8), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc)
validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
require.Equal(t, validator.Owner, barAddr)
require.True(sdk.RatEq(t, sdk.NewRat(2), validator.Tokens))
require.Equal(t, validator.Operator, barAddr)
require.True(sdk.DecEq(t, sdk.NewDec(2), validator.Tokens))
// unbond a single share
unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags)
unbondStr += fmt.Sprintf(" --from=%s", "bar")
unbondStr += fmt.Sprintf(" --address-validator=%s", barAddr)
unbondStr += fmt.Sprintf(" --validator=%s", barAddr)
unbondStr += fmt.Sprintf(" --shares-amount=%v", "1")
success := executeWrite(t, unbondStr, app.DefaultKeyPass)
@ -149,11 +149,11 @@ func TestGaiaCLICreateValidator(t *testing.T) {
require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc)
*/
validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags))
require.Equal(t, "1/1", validator.Tokens.String())
require.Equal(t, "1.0000000000", validator.Tokens.String())
}
func TestGaiaCLISubmitProposal(t *testing.T) {
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe_reset_all", gaiadHome), "")
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "")
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass)
chainID := executeInit(t, fmt.Sprintf("gaiad init -o --name=foo --home=%s --home-client=%s", gaiadHome, gaiacliHome))

View File

@ -493,6 +493,49 @@ paths:
500:
description: Internal Server Error
/stake/delegators/{delegatorAddr}/validators:
parameters:
- in: path
name: delegatorAddr
description: Bech32 AccAddress of Delegator
required: true
type: string
get:
summary: Query all validators that a delegator is bonded to
tags:
- stake
produces:
- application/json
responses:
200:
description: OK
404:
description: Not Found
/stake/delegators/{delegatorAddr}/validators/{validatorAddr}:
parameters:
- in: path
name: delegatorAddr
description: Bech32 AccAddress of Delegator
required: true
type: string
- in: path
name: validatorAddr
description: Bech32 ValAddress of Delegator
required: true
type: string
get:
summary: Query a validator that a delegator is bonded to
tags:
- stake
produces:
- application/json
responses:
200:
description: OK
404:
description: Not Found
/stake/delegators/{delegatorAddr}/txs:
parameters:
- in: path

View File

@ -41,7 +41,7 @@ First, remove the outdated files and reset the data.
```bash
rm $HOME/.gaiad/config/addrbook.json $HOME/.gaiad/config/genesis.json
gaiad unsafe_reset_all
gaiad unsafe-reset-all
```
Your node is now in a pristine state while keeping the original `priv_validator.json` and `config.toml`. If you had any sentry nodes or full nodes setup before,

View File

@ -1,59 +0,0 @@
# Install
The fastest and easiest way to install the Cosmos SDK binaries
is to run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_ubuntu.sh) on a fresh Ubuntu instance. Similarly, you can run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_bsd.sh) on a fresh FreeBSD instance. Read the scripts before running them to ensure no untrusted connection is being made, for example we're making curl requests to download golang. Also read the comments / instructions carefully (i.e., reset your terminal after running the script).
Cosmos SDK can be installed to
`$GOPATH/src/github.com/cosmos/cosmos-sdk` like a normal Go program:
```
go get github.com/cosmos/cosmos-sdk
```
If the dependencies have been updated with breaking changes, or if
another branch is required, `dep` is used for dependency management.
Thus, assuming you've already run `go get` or otherwise cloned the repo,
the correct way to install is:
```
cd $GOPATH/src/github.com/cosmos/cosmos-sdk
make get_tools
make get_vendor_deps
make install
make install_examples
```
This will install `gaiad` and `gaiacli` and four example binaries:
`basecoind`, `basecli`, `democoind`, and `democli`.
Verify that everything is OK by running:
```
gaiad version
```
you should see:
```
0.17.3-a5a78eb
```
then with:
```
gaiacli version
```
you should see the same version (or a later one for both).
## Update
Get latest code (you can also `git fetch` only the version desired),
ensure the dependencies are up to date, then recompile.
```
cd $GOPATH/src/github.com/cosmos/cosmos-sdk
git fetch -a origin
git checkout VERSION
make get_vendor_deps
make install
```

View File

@ -479,6 +479,62 @@ Returns on error:
}
```
### /stake/delegators/{delegatorAddr}/validators - GET
url: /stake/delegators/{delegatorAddr}/validators
Functionality: Query all validators that a delegator is bonded to.
Returns on success:
```json
{
"rest api":"2.0",
"code":200,
"error":"",
"result":{}
}
```
Returns on failure:
```json
{
"rest api":"2.0",
"code":500,
"error":"TODO",
"result":{}
}
```
### /stake/delegators/{delegatorAddr}/validators/{validatorAddr} - GET
url: /stake/delegators/{delegatorAddr}/validators/{validatorAddr}
Functionality: Query a validator that a delegator is bonded to
Returns on success:
```json
{
"rest api":"2.0",
"code":200,
"error":"",
"result":{}
}
```
Returns on failure:
```json
{
"rest api":"2.0",
"code":500,
"error":"TODO",
"result":{}
}
```
### /stake/delegators/{delegatorAddr}/txs - GET
url: /stake/delegators/{delegatorAddr}/txs

View File

@ -323,6 +323,14 @@ return KeyOutput{
TODO
### [/stake/delegators/{delegatorAddr}/validators](api.md#stakedelegatorsdelegatorAddrvalidators---get)
TODO
### [/stake/delegators/{delegatorAddr}/validators/{validatorAddr}](api.md#stakedelegatorsdelegatorAddrvalidatorsvalidatorAddr---get)
TODO
### [/stake/delegators/{delegatorAddr}/txs](api.md#stakedelegatorsdelegatorAddrtxs---get)
TODO

View File

@ -27,7 +27,7 @@ There are three types of key representations that are used:
- e.g. `cosmosaccpub1zcjduc3q7fu03jnlu2xpl75s2nkt7krm6grh4cc5aqth73v0zwmea25wj2hsqhlqzm`
- `cosmosvalpub`
- Generated when the node is created with `gaiad init`.
- Get this value with `gaiad tendermint show_validator`
- Get this value with `gaiad tendermint show-validator`
- e.g. `cosmosvalpub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c`
#### Generate Keys
@ -57,7 +57,7 @@ gaiacli keys list
View the validator pubkey for your node by typing:
```bash
gaiad tendermint show_validator
gaiad tendermint show-validator
```
::: danger Warning
@ -141,7 +141,7 @@ On the testnet, we delegate `steak` instead of `atom`. Here's how you can bond t
```bash
gaiacli stake delegate \
--amount=10steak \
--address-validator=$(gaiad tendermint show_validator) \
--validator=$(gaiad tendermint show-validator) \
--name=<key_name> \
--chain-id=<chain_id>
```

View File

@ -25,9 +25,9 @@ type VotingProcedure struct {
```go
type TallyingProcedure struct {
Threshold rational.Rational // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto rational.Rational // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Rat // Penalty if validator does not vote
Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Dec // Penalty if validator does not vote
GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
}
```
@ -81,7 +81,7 @@ This type is used in a temp map when tallying
```go
type ValidatorGovInfo struct {
Minus sdk.Rat
Minus sdk.Dec
Vote Vote
}
```
@ -103,17 +103,17 @@ type Proposal struct {
VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
CurrentStatus ProposalStatus // Current status of the proposal
YesVotes sdk.Rat
NoVotes sdk.Rat
NoWithVetoVotes sdk.Rat
AbstainVotes sdk.Rat
YesVotes sdk.Dec
NoVotes sdk.Dec
NoWithVetoVotes sdk.Dec
AbstainVotes sdk.Dec
}
```
We also mention a method to update the tally for a given proposal:
```go
func (proposal Proposal) updateTally(vote byte, amount sdk.Rat)
func (proposal Proposal) updateTally(vote byte, amount sdk.Dec)
```
### Stores

View File

@ -7,7 +7,7 @@
The current annual inflation rate.
```golang
type Inflation sdk.Rat
type Inflation sdk.Dec
```
### InflationLastTime

View File

@ -16,4 +16,3 @@ EndBlock() ValidatorSetChanges
ClearTendermintUpdates()
return vsc
```

View File

@ -13,7 +13,7 @@ type Pool struct {
LooseTokens int64 // tokens not associated with any bonded validator
BondedTokens int64 // reserve of bonded tokens
InflationLastTime int64 // block which the last inflation was processed // TODO make time
Inflation sdk.Rat // current annual inflation rate
Inflation sdk.Dec // current annual inflation rate
DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily)
}
@ -28,10 +28,10 @@ overall functioning of the stake module.
```golang
type Params struct {
InflationRateChange sdk.Rat // maximum annual change in inflation rate
InflationMax sdk.Rat // maximum inflation rate
InflationMin sdk.Rat // minimum inflation rate
GoalBonded sdk.Rat // Goal of percent bonded atoms
InflationRateChange sdk.Dec // maximum annual change in inflation rate
InflationMax sdk.Dec // maximum inflation rate
InflationMin sdk.Dec // minimum inflation rate
GoalBonded sdk.Dec // Goal of percent bonded atoms
MaxValidators uint16 // maximum number of validators
BondDenom string // bondable coin denomination
@ -74,9 +74,9 @@ type Validator struct {
Revoked bool // has the validator been revoked?
Status sdk.BondStatus // validator status (bonded/unbonding/unbonded)
Tokens sdk.Rat // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Rat // total shares issued to a validator's delegators
SlashRatio sdk.Rat // increases each time the validator is slashed
Tokens sdk.Dec // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Dec // total shares issued to a validator's delegators
SlashRatio sdk.Dec // increases each time the validator is slashed
Description Description // description terms for the validator
@ -88,10 +88,10 @@ type Validator struct {
}
type CommissionInfo struct {
Rate sdk.Rat // the commission rate of fees charged to any delegators
Max sdk.Rat // maximum commission rate which this validator can ever charge
ChangeRate sdk.Rat // maximum daily increase of the validator commission
ChangeToday sdk.Rat // commission rate change today, reset each day (UTC time)
Rate sdk.Dec // the commission rate of fees charged to any delegators
Max sdk.Dec // maximum commission rate which this validator can ever charge
ChangeRate sdk.Dec // maximum daily increase of the validator commission
ChangeToday sdk.Dec // commission rate change today, reset each day (UTC time)
LastChange int64 // unix timestamp of last commission change
}
@ -117,7 +117,7 @@ the transaction is the owner of the bond.
```golang
type Delegation struct {
Shares sdk.Rat // delegation shares recieved
Shares sdk.Dec // delegation shares recieved
Height int64 // last height bond updated
}
```
@ -178,8 +178,8 @@ the original redelegation has been completed.
```golang
type Redelegation struct {
SourceShares sdk.Rat // amount of source shares redelegating
DestinationShares sdk.Rat // amount of destination shares created at redelegation
SourceShares sdk.Dec // amount of source shares redelegating
DestinationShares sdk.Dec // amount of destination shares created at redelegation
CompleteTime int64 // unix time to complete redelegation
}
```

View File

@ -1,7 +1,7 @@
## Transaction Overview
In this section we describe the processing of the transactions and the
corresponding updates to the state. Transactions:
corresponding updates to the state. Transactions:
- TxCreateValidator
- TxEditValidator
- TxDelegation
@ -18,8 +18,8 @@ Other notes:
- `sender` denotes the address of the sender of the transaction
- `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and
modify objects from the store
- `sdk.Rat` refers to a rational numeric type specified by the SDK.
- `sdk.Dec` refers to a decimal type specified by the SDK.
### TxCreateValidator
- triggers: `distribution.CreateValidatorDistribution`
@ -28,74 +28,74 @@ A validator is created using the `TxCreateValidator` transaction.
```golang
type TxCreateValidator struct {
OwnerAddr sdk.Address
Operator sdk.Address
ConsensusPubKey crypto.PubKey
GovernancePubKey crypto.PubKey
SelfDelegation coin.Coin
SelfDelegation coin.Coin
Description Description
Commission sdk.Rat
CommissionMax sdk.Rat
CommissionMaxChange sdk.Rat
Commission sdk.Dec
CommissionMax sdk.Dec
CommissionMaxChange sdk.Dec
}
createValidator(tx TxCreateValidator):
validator = getValidator(tx.OwnerAddr)
validator = getValidator(tx.Operator)
if validator != nil return // only one validator per address
validator = NewValidator(OwnerAddr, ConsensusPubKey, GovernancePubKey, Description)
validator = NewValidator(operatorAddr, ConsensusPubKey, GovernancePubKey, Description)
init validator poolShares, delegatorShares set to 0
init validator commision fields from tx
validator.PoolShares = 0
setValidator(validator)
txDelegate = TxDelegate(tx.OwnerAddr, tx.OwnerAddr, tx.SelfDelegation)
txDelegate = TxDelegate(tx.Operator, tx.Operator, tx.SelfDelegation)
delegate(txDelegate, validator) // see delegate function in [TxDelegate](TxDelegate)
return
```
```
### TxEditValidator
If either the `Description` (excluding `DateBonded` which is constant),
`Commission`, or the `GovernancePubKey` need to be updated, the
`TxEditCandidacy` transaction should be sent from the owner account:
`TxEditCandidacy` transaction should be sent from the operator account:
```golang
type TxEditCandidacy struct {
GovernancePubKey crypto.PubKey
Commission sdk.Rat
Commission sdk.Dec
Description Description
}
editCandidacy(tx TxEditCandidacy):
validator = getValidator(tx.ValidatorAddr)
if tx.Commission > CommissionMax || tx.Commission < 0 then fail
if tx.Commission > CommissionMax || tx.Commission < 0 then fail
if rateChange(tx.Commission) > CommissionMaxChange then fail
validator.Commission = tx.Commission
if tx.GovernancePubKey != nil validator.GovernancePubKey = tx.GovernancePubKey
if tx.Description != nil validator.Description = tx.Description
setValidator(store, validator)
return
```
### TxDelegate
- triggers: `distribution.CreateOrModDelegationDistribution`
Within this transaction the delegator provides coins, and in return receives
some amount of their validator's delegator-shares that are assigned to
`Delegation.Shares`.
`Delegation.Shares`.
```golang
type TxDelegate struct {
DelegatorAddr sdk.Address
ValidatorAddr sdk.Address
Amount sdk.Coin
DelegatorAddr sdk.Address
ValidatorAddr sdk.Address
Amount sdk.Coin
}
delegate(tx TxDelegate):
@ -104,14 +104,14 @@ delegate(tx TxDelegate):
delegation = getDelegatorBond(DelegatorAddr, ValidatorAddr)
if delegation == nil then delegation = NewDelegation(DelegatorAddr, ValidatorAddr)
validator, pool, issuedDelegatorShares = validator.addTokensFromDel(tx.Amount, pool)
delegation.Shares += issuedDelegatorShares
setDelegation(delegation)
updateValidator(validator)
setPool(pool)
return
return
```
### TxStartUnbonding
@ -120,28 +120,28 @@ Delegator unbonding is defined with the following transaction:
```golang
type TxStartUnbonding struct {
DelegatorAddr sdk.Address
ValidatorAddr sdk.Address
Shares string
DelegatorAddr sdk.Address
ValidatorAddr sdk.Address
Shares string
}
startUnbonding(tx TxStartUnbonding):
startUnbonding(tx TxStartUnbonding):
delegation, found = getDelegatorBond(store, sender, tx.PubKey)
if !found == nil return
if !found == nil return
if bond.Shares < tx.Shares
return ErrNotEnoughBondShares
validator, found = GetValidator(tx.ValidatorAddr)
if !found {
return err
return err
bond.Shares -= tx.Shares
revokeCandidacy = false
if bond.Shares.IsZero() {
if bond.DelegatorAddr == validator.Owner && validator.Revoked == false
if bond.DelegatorAddr == validator.Operator && validator.Revoked == false
revokeCandidacy = true
removeDelegation( bond)
@ -162,7 +162,7 @@ startUnbonding(tx TxStartUnbonding):
validator = updateValidator(validator)
if validator.DelegatorShares == 0 {
removeValidator(validator.Owner)
removeValidator(validator.Operator)
return
```
@ -185,7 +185,7 @@ redelegationComplete(tx TxRedelegate):
returnTokens = ExpectedTokens * tx.startSlashRatio/validator.SlashRatio
AddCoins(unbonding.DelegatorAddr, returnTokens)
removeUnbondingDelegation(unbonding)
return
return
```
### TxRedelegation
@ -199,27 +199,27 @@ type TxRedelegate struct {
DelegatorAddr Address
ValidatorFrom Validator
ValidatorTo Validator
Shares sdk.Rat
Shares sdk.Dec
CompletedTime int64
}
redelegate(tx TxRedelegate):
pool = getPool()
delegation = getDelegatorBond(tx.DelegatorAddr, tx.ValidatorFrom.Owner)
delegation = getDelegatorBond(tx.DelegatorAddr, tx.ValidatorFrom.Operator)
if delegation == nil
return
if delegation.Shares < tx.Shares
return
return
if delegation.Shares < tx.Shares
return
delegation.shares -= Tx.Shares
validator, pool, createdCoins = validator.RemoveShares(pool, tx.Shares)
setPool(pool)
redelegation = newRedelegation(tx.DelegatorAddr, tx.validatorFrom,
redelegation = newRedelegation(tx.DelegatorAddr, tx.validatorFrom,
tx.validatorTo, tx.Shares, createdCoins, tx.CompletedTime)
setRedelegation(redelegation)
return
return
```
### TxCompleteRedelegation
@ -239,7 +239,7 @@ redelegationComplete(tx TxRedelegate):
redelegation = getRedelegation(tx.DelegatorAddr, tx.validatorFrom, tx.validatorTo)
if redelegation.CompleteTime >= CurrentBlockTime && redelegation.CompleteHeight >= CurrentBlockHeight
removeRedelegation(redelegation)
return
return
```
### Update Validators
@ -273,11 +273,11 @@ updateBondedValidators(newValidator Validator) (updatedVal Validator)
// use the validator provided because it has not yet been updated
// in the main validator store
ownerAddr = iterator.Value()
if bytes.Equal(ownerAddr, newValidator.Owner) {
operatorAddr = iterator.Value()
if bytes.Equal(operatorAddr, newValidator.Operator) {
validator = newValidator
else
validator = getValidator(ownerAddr)
validator = getValidator(operatorAddr)
// if not previously a validator (and unrevoked),
// kick the cliff validator / bond this new validator
@ -285,7 +285,7 @@ updateBondedValidators(newValidator Validator) (updatedVal Validator)
kickCliffValidator = true
validator = bondValidator(ctx, store, validator)
if bytes.Equal(ownerAddr, newValidator.Owner) {
if bytes.Equal(operatorAddr, newValidator.Operator) {
updatedVal = validator
bondedValidatorsCount++
@ -316,7 +316,7 @@ unbondValidator(ctx Context, store KVStore, validator Validator)
}
// perform all the store operations for when a validator status becomes bonded
bondValidator(ctx Context, store KVStore, validator Validator) Validator
bondValidator(ctx Context, store KVStore, validator Validator) Validator
pool = GetPool(ctx)
// set the status

View File

@ -19,7 +19,7 @@ If you want to become a validator for the Hub's `mainnet`, you should [research
Your `cosmosvalpub` can be used to create a new validator by staking tokens. You can find your validator pubkey by running:
```bash
gaiad tendermint show_validator
gaiad tendermint show-validator
```
Next, craft your `gaiacli stake create-validator` command:
@ -31,7 +31,7 @@ Don't use more `steak` thank you have! You can always get more by using the [Fau
```bash
gaiacli stake create-validator \
--amount=5steak \
--pubkey=$(gaiad tendermint show_validator) \
--pubkey=$(gaiad tendermint show-validator) \
--address-validator=<account_cosmosaccaddr>
--moniker="choose a moniker" \
--chain-id=<chain_id> \
@ -46,7 +46,7 @@ The `--identity` can be used as to verify identity with systems like Keybase or
```bash
gaiacli stake edit-validator
--address-validator=<account_cosmosaccaddr>
--validator=<account_cosmosaccaddr>
--moniker="choose a moniker" \
--website="https://cosmos.network" \
--identity=6A0D65E29A4CBC8E
@ -60,9 +60,7 @@ gaiacli stake edit-validator
View the validator's information with this command:
```bash
gaiacli stake validator \
--address-validator=<account_cosmosaccaddr> \
--chain-id=<chain_id>
gaiacli stake validator <account_cosmosaccaddr>
```
### Track Validator Signing Information
@ -82,6 +80,8 @@ When a validator is `Revoked` for downtime, you must submit an `Unrevoke` transa
gaiacli stake unrevoke \
--from=<key_name> \
--chain-id=<chain_id>
--validator=<account_cosmosaccaddr> \
--chain-id=gaia-6002
```
### Confirm Your Validator is Running
@ -89,7 +89,7 @@ gaiacli stake unrevoke \
Your validator is active if the following command returns anything:
```bash
gaiacli advanced tendermint validator-set | grep "$(gaiad tendermint show_validator)"
gaiacli advanced tendermint validator-set | grep "$(gaiad tendermint show-validator)"
```
You should also be able to see your validator on the [Explorer](https://explorecosmos.network/validators). You are looking for the `bech32` encoded `address` in the `~/.gaiad/config/priv_validator.json` file.

View File

@ -104,9 +104,9 @@ You should now see alice, bob and charlie's account all show up.
```
NAME: ADDRESS: PUBKEY:
alice 90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD 1624DE62201D47E63694448665F5D0217EA8458177728C91C373047A42BD3C0FB78BD0BFA7
bob 29D721F054537C91F618A0FDBF770DA51EF8C48D 1624DE6220F54B2A2CA9EB4EE30DE23A73D15902E087C09CC5616456DDDD3814769E2E0A16
charlie 2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E 1624DE6220F8C9FB8B07855FD94126F88A155BD6EB973509AE5595EFDE1AF05B4964836A53
alice cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f cosmosaccpub1addwnpepq0w037u5g7y7lvdvsred2dehg90j84k0weyss5ynysf0nnnax74agrsxns6
bob cosmosaccaddr18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz cosmosaccpub1addwnpepqwe97n8lryxrzvamrvjfj24jys3uzf8wndfvqa2l7mh5nsv4jrvdznvyeg6
charlie cosmosaccaddr13wq5mklhn03ljpd4dkph5rflk5a3ssma2ag07q cosmosaccpub1addwnpepqdmtxv35rrmv2dvcr3yhfyxj7dzrd4z4rnhmclksq4g55a4wpl54clvx33l
```
@ -115,15 +115,15 @@ charlie 2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E 1624DE6220F8C9FB8B07855FD94126F
Lets send bob and charlie some tokens. First, lets query alice's account so we can see what kind of tokens she has:
```
basecli account 90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD
basecli account cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f
```
Where `90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD` is alice's address we got from running `basecli keys list`. You should see a large amount of "mycoin" there. If you search for bob's or charlie's address, the command will fail, because they haven't been added into the blockchain database yet since they have no coins. We need to send them some!
Where `cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f` is alice's address we got from running `basecli keys list`. You should see a large amount of "mycoin" there. If you search for bob's or charlie's address, the command will fail, because they haven't been added into the blockchain database yet since they have no coins. We need to send them some!
The following command will send coins from alice, to bob:
```
basecli send --from=alice --amount=10000mycoin --to=29D721F054537C91F618A0FDBF770DA51EF8C48D
basecli send --from=alice --amount=10000mycoin --to=cosmosaccaddr18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz
--sequence=0 --chain-id=test-chain-AE4XQo
```
@ -136,13 +136,13 @@ Flag Descriptions:
Now if we check bobs account, it should have `10000 mycoin`. You can do so by running :
```
basecli account 29D721F054537C91F618A0FDBF770DA51EF8C48D
basecli account cosmosaccaddr18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz
```
Now lets send some from bob to charlie. Make sure you send less than bob has, otherwise the transaction will fail:
```
basecli send --from=bob --amount=5000mycoin --to=2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E
basecli send --from=bob --amount=5000mycoin --to=cosmosaccaddr13wq5mklhn03ljpd4dkph5rflk5a3ssma2ag07q
--sequence=0 --chain-id=test-chain-AE4XQo
```
@ -151,7 +151,7 @@ Note how we use the ``--from`` flag to select a different account to send from.
Lets now try to send from bob back to alice:
```
basecli send --from=bob --amount=3000mycoin --to=90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD
basecli send --from=bob --amount=3000mycoin --to=cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f
--sequence=1 --chain-id=test-chain-AE4XQo
```
@ -179,7 +179,7 @@ starting this tutorial again or trying something new), the following
commands are run:
```
basecoind unsafe_reset_all
basecoind unsafe-reset-all
rm -rf ~/.basecoind
rm -rf ~/.basecli
```

View File

@ -10,7 +10,7 @@ var _ auth.Account = (*AppAccount)(nil)
// AppAccount is a custom extension for this application. It is an example of
// extending auth.BaseAccount with custom fields. It is compatible with the
// stock auth.AccountStore, since auth.AccountStore uses the flexible go-amino
// stock auth.AccountMapper, since auth.AccountMapper uses the flexible go-amino
// library.
type AppAccount struct {
auth.BaseAccount

View File

@ -10,7 +10,7 @@ import (
// Validator implements sdk.Validator
type Validator struct {
Address sdk.AccAddress
Power sdk.Rat
Power sdk.Dec
}
// Implements sdk.Validator
@ -19,7 +19,7 @@ func (v Validator) GetStatus() sdk.BondStatus {
}
// Implements sdk.Validator
func (v Validator) GetOwner() sdk.AccAddress {
func (v Validator) GetOperator() sdk.AccAddress {
return v.Address
}
@ -29,18 +29,18 @@ func (v Validator) GetPubKey() crypto.PubKey {
}
// Implements sdk.Validator
func (v Validator) GetTokens() sdk.Rat {
return sdk.ZeroRat()
func (v Validator) GetTokens() sdk.Dec {
return sdk.ZeroDec()
}
// Implements sdk.Validator
func (v Validator) GetPower() sdk.Rat {
func (v Validator) GetPower() sdk.Dec {
return v.Power
}
// Implements sdk.Validator
func (v Validator) GetDelegatorShares() sdk.Rat {
return sdk.ZeroRat()
func (v Validator) GetDelegatorShares() sdk.Dec {
return sdk.ZeroDec()
}
// Implements sdk.Validator
@ -93,8 +93,8 @@ func (vs *ValidatorSet) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey)
}
// TotalPower implements sdk.ValidatorSet
func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Rat {
res := sdk.ZeroRat()
func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Dec {
res := sdk.ZeroDec()
for _, val := range vs.Validators {
res = res.Add(val.Power)
}
@ -122,7 +122,7 @@ func (vs *ValidatorSet) RemoveValidator(addr sdk.AccAddress) {
}
// Implements sdk.ValidatorSet
func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Rat) {
func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Dec) {
panic("not implemented")
}

View File

@ -32,8 +32,8 @@ func TestValidatorSet(t *testing.T) {
addr2 := []byte("addr2")
base := &mock.ValidatorSet{[]mock.Validator{
{addr1, sdk.NewRat(1)},
{addr2, sdk.NewRat(2)},
{addr1, sdk.NewDec(1)},
{addr2, sdk.NewDec(2)},
}}
valset := NewValidatorSet(wire.NewCodec(), ctx.KVStore(key).Prefix([]byte("assoc")), base, 1, 5)

View File

@ -38,7 +38,7 @@ func NewHandler(keeper Keeper) sdk.Handler {
In the previous example, the keeper has an `oracle.Keeper`. `oracle.Keeper`s are generated by `NewKeeper`.
```go
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper {
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Dec, timeout int64) Keeper {
return Keeper {
cdc: cdc,
key: key,

View File

@ -23,7 +23,7 @@ func (keeper Keeper) update(ctx sdk.Context, val sdk.Validator, valset sdk.Valid
// and recalculate voted power
hash := ctx.BlockHeader().ValidatorsHash
if !bytes.Equal(hash, info.Hash) {
info.Power = sdk.ZeroRat()
info.Power = sdk.ZeroDec()
info.Hash = hash
prefix := GetSignPrefix(p, keeper.cdc)
store := ctx.KVStore(keeper.key)

View File

@ -13,12 +13,12 @@ type Keeper struct {
valset sdk.ValidatorSet
supermaj sdk.Rat
supermaj sdk.Dec
timeout int64
}
// NewKeeper constructs a new keeper
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper {
func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Dec, timeout int64) Keeper {
if timeout < 0 {
panic("Timeout should not be negative")
}
@ -46,7 +46,7 @@ const (
// Info for each payload
type Info struct {
Power sdk.Rat
Power sdk.Dec
Hash []byte
LastSigned int64
Status InfoStatus
@ -55,7 +55,7 @@ type Info struct {
// EmptyInfo construct an empty Info
func EmptyInfo(ctx sdk.Context) Info {
return Info{
Power: sdk.ZeroRat(),
Power: sdk.ZeroDec(),
Hash: ctx.BlockHeader().ValidatorsHash,
LastSigned: ctx.BlockHeight(),
Status: Pending,

View File

@ -107,9 +107,9 @@ func TestOracle(t *testing.T) {
addr3 := []byte("addr3")
addr4 := []byte("addr4")
valset := &mock.ValidatorSet{[]mock.Validator{
{addr1, sdk.NewRat(7)},
{addr2, sdk.NewRat(7)},
{addr3, sdk.NewRat(1)},
{addr1, sdk.NewDec(7)},
{addr2, sdk.NewDec(7)},
{addr3, sdk.NewDec(1)},
}}
key := sdk.NewKVStoreKey("testkey")
@ -119,7 +119,7 @@ func TestOracle(t *testing.T) {
require.Nil(t, err)
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})
ork := NewKeeper(key, cdc, valset, sdk.NewRat(2, 3), 100)
ork := NewKeeper(key, cdc, valset, sdk.NewDecWithPrec(667, 3), 100) // 66.7%
h := seqHandler(ork, key, sdk.CodespaceRoot)
// Nonmock.Validator signed, transaction failed
@ -171,7 +171,7 @@ func TestOracle(t *testing.T) {
require.Equal(t, 1, getSequence(ctx, key))
// Should handle mock.Validator set change
valset.AddValidator(mock.Validator{addr4, sdk.NewRat(12)})
valset.AddValidator(mock.Validator{addr4, sdk.NewDec(12)})
bz, err = json.Marshal(valset)
require.Nil(t, err)
ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz})

View File

@ -24,6 +24,6 @@
- name: Reset network
when: UNSAFE_RESET_ALL | default(false) | bool
command: "sudo -u gaiad gaiad unsafe_reset_all"
command: "sudo -u gaiad gaiad unsafe-reset-all"
notify: restart gaiad

View File

@ -16,7 +16,7 @@ import (
// ShowNodeIDCmd - ported from Tendermint, dump node ID to stdout
func ShowNodeIDCmd(ctx *Context) *cobra.Command {
return &cobra.Command{
Use: "show_node_id",
Use: "show-node-id",
Short: "Show this node's ID",
RunE: func(cmd *cobra.Command, args []string) error {
cfg := ctx.Config
@ -34,7 +34,7 @@ func ShowNodeIDCmd(ctx *Context) *cobra.Command {
func ShowValidatorCmd(ctx *Context) *cobra.Command {
flagJSON := "json"
cmd := cobra.Command{
Use: "show_validator",
Use: "show-validator",
Short: "Show this node's tendermint validator info",
RunE: func(cmd *cobra.Command, args []string) error {
@ -68,7 +68,7 @@ func ShowValidatorCmd(ctx *Context) *cobra.Command {
// UnsafeResetAllCmd - extension of the tendermint command, resets initialization
func UnsafeResetAllCmd(ctx *Context) *cobra.Command {
return &cobra.Command{
Use: "unsafe_reset_all",
Use: "unsafe-reset-all",
Short: "Reset blockchain database, priv_validator.json file, and the logger",
RunE: func(cmd *cobra.Command, args []string) error {
cfg := ctx.Config

421
types/decimal.go Normal file
View File

@ -0,0 +1,421 @@
package types
import (
"encoding/json"
"fmt"
"math/big"
"strconv"
"strings"
"testing"
)
// NOTE: never use new(Dec) or else we will panic unmarshalling into the
// nil embedded big.Int
type Dec struct {
*big.Int `json:"int"`
}
// number of decimal places
const (
Precision = 10
// bytes required to represent the above precision
// ceil(log2(9999999999))
DecimalPrecisionBits = 34
)
var (
precisionReuse = new(big.Int).Exp(big.NewInt(10), big.NewInt(Precision), nil)
fivePrecision = new(big.Int).Quo(precisionReuse, big.NewInt(2))
precisionMultipliers []*big.Int
zeroInt = big.NewInt(0)
oneInt = big.NewInt(1)
tenInt = big.NewInt(10)
)
// Set precision multipliers
func init() {
precisionMultipliers = make([]*big.Int, Precision+1)
for i := 0; i <= Precision; i++ {
precisionMultipliers[i] = calcPrecisionMultiplier(int64(i))
}
}
func precisionInt() *big.Int {
return new(big.Int).Set(precisionReuse)
}
// nolint - common values
func ZeroDec() Dec { return Dec{new(big.Int).Set(zeroInt)} }
func OneDec() Dec { return Dec{precisionInt()} }
// calculate the precision multiplier
func calcPrecisionMultiplier(prec int64) *big.Int {
if prec > Precision {
panic(fmt.Sprintf("too much precision, maximum %v, provided %v", Precision, prec))
}
zerosToAdd := Precision - prec
multiplier := new(big.Int).Exp(tenInt, big.NewInt(zerosToAdd), nil)
return multiplier
}
// get the precision multiplier, do not mutate result
func precisionMultiplier(prec int64) *big.Int {
if prec > Precision {
panic(fmt.Sprintf("too much precision, maximum %v, provided %v", Precision, prec))
}
return precisionMultipliers[prec]
}
//______________________________________________________________________________________________
// create a new Dec from integer assuming whole number
func NewDec(i int64) Dec {
return NewDecWithPrec(i, 0)
}
// create a new Dec from integer with decimal place at prec
// CONTRACT: prec <= Precision
func NewDecWithPrec(i, prec int64) Dec {
return Dec{
new(big.Int).Mul(big.NewInt(i), precisionMultiplier(prec)),
}
}
// create a new Dec from big integer assuming whole numbers
// CONTRACT: prec <= Precision
func NewDecFromBigInt(i *big.Int) Dec {
return NewDecFromBigIntWithPrec(i, 0)
}
// create a new Dec from big integer assuming whole numbers
// CONTRACT: prec <= Precision
func NewDecFromBigIntWithPrec(i *big.Int, prec int64) Dec {
return Dec{
new(big.Int).Mul(i, precisionMultiplier(prec)),
}
}
// create a new Dec from big integer assuming whole numbers
// CONTRACT: prec <= Precision
func NewDecFromInt(i Int) Dec {
return NewDecFromIntWithPrec(i, 0)
}
// create a new Dec from big integer with decimal place at prec
// CONTRACT: prec <= Precision
func NewDecFromIntWithPrec(i Int, prec int64) Dec {
return Dec{
new(big.Int).Mul(i.BigInt(), precisionMultiplier(prec)),
}
}
// create a decimal from an input decimal string.
// valid must come in the form:
// (-) whole integers (.) decimal integers
// examples of acceptable input include:
// -123.456
// 456.7890
// 345
// -456789
//
// NOTE - An error will return if more decimal places
// are provided in the string than the constant Precision.
//
// CONTRACT - This function does not mutate the input str.
func NewDecFromStr(str string) (d Dec, err Error) {
if len(str) == 0 {
return d, ErrUnknownRequest("decimal string is empty")
}
// first extract any negative symbol
neg := false
if str[0] == '-' {
neg = true
str = str[1:]
}
if len(str) == 0 {
return d, ErrUnknownRequest("decimal string is empty")
}
strs := strings.Split(str, ".")
lenDecs := 0
combinedStr := strs[0]
if len(strs) == 2 {
lenDecs = len(strs[1])
if lenDecs == 0 || len(combinedStr) == 0 {
return d, ErrUnknownRequest("bad decimal length")
}
combinedStr = combinedStr + strs[1]
} else if len(strs) > 2 {
return d, ErrUnknownRequest("too many periods to be a decimal string")
}
if lenDecs > Precision {
return d, ErrUnknownRequest(
fmt.Sprintf("too much precision, maximum %v, len decimal %v", Precision, lenDecs))
}
// add some extra zero's to correct to the Precision factor
zerosToAdd := Precision - lenDecs
zeros := fmt.Sprintf(`%0`+strconv.Itoa(zerosToAdd)+`s`, "")
combinedStr = combinedStr + zeros
combined, ok := new(big.Int).SetString(combinedStr, 10)
if !ok {
return d, ErrUnknownRequest(fmt.Sprintf("bad string to integer conversion, combinedStr: %v", combinedStr))
}
if neg {
combined = new(big.Int).Neg(combined)
}
return Dec{combined}, nil
}
//______________________________________________________________________________________________
//nolint
func (d Dec) IsZero() bool { return (d.Int).Sign() == 0 } // Is equal to zero
func (d Dec) Equal(d2 Dec) bool { return (d.Int).Cmp(d2.Int) == 0 }
func (d Dec) GT(d2 Dec) bool { return (d.Int).Cmp(d2.Int) > 0 } // greater than
func (d Dec) GTE(d2 Dec) bool { return (d.Int).Cmp(d2.Int) >= 0 } // greater than or equal
func (d Dec) LT(d2 Dec) bool { return (d.Int).Cmp(d2.Int) < 0 } // less than
func (d Dec) LTE(d2 Dec) bool { return (d.Int).Cmp(d2.Int) <= 0 } // less than or equal
func (d Dec) Neg() Dec { return Dec{new(big.Int).Neg(d.Int)} } // reverse the decimal sign
// addition
func (d Dec) Add(d2 Dec) Dec {
res := new(big.Int).Add(d.Int, d2.Int)
if res.BitLen() > 255+DecimalPrecisionBits {
panic("Int overflow")
}
return Dec{res}
}
// subtraction
func (d Dec) Sub(d2 Dec) Dec {
res := new(big.Int).Sub(d.Int, d2.Int)
if res.BitLen() > 255+DecimalPrecisionBits {
panic("Int overflow")
}
return Dec{res}
}
// multiplication
func (d Dec) Mul(d2 Dec) Dec {
mul := new(big.Int).Mul(d.Int, d2.Int)
chopped := chopPrecisionAndRound(mul)
if chopped.BitLen() > 255+DecimalPrecisionBits {
panic("Int overflow")
}
return Dec{chopped}
}
// quotient
func (d Dec) Quo(d2 Dec) Dec {
// multiply precision twice
mul := new(big.Int).Mul(d.Int, precisionReuse)
mul.Mul(mul, precisionReuse)
quo := new(big.Int).Quo(mul, d2.Int)
chopped := chopPrecisionAndRound(quo)
if chopped.BitLen() > 255+DecimalPrecisionBits {
panic("Int overflow")
}
return Dec{chopped}
}
func (d Dec) String() string {
str := d.ToLeftPaddedWithDecimals(Precision)
placement := len(str) - Precision
if placement < 0 {
panic("too few decimal digits")
}
return str[:placement] + "." + str[placement:]
}
// TODO panic if negative or if totalDigits < len(initStr)???
// evaluate as an integer and return left padded string
func (d Dec) ToLeftPaddedWithDecimals(totalDigits int8) string {
intStr := d.Int.String()
fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s`
return fmt.Sprintf(fcode, intStr)
}
// TODO panic if negative or if totalDigits < len(initStr)???
// evaluate as an integer and return left padded string
func (d Dec) ToLeftPadded(totalDigits int8) string {
chopped := chopPrecisionAndRoundNonMutative(d.Int)
intStr := chopped.String()
fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s`
return fmt.Sprintf(fcode, intStr)
}
// ____
// __| |__ "chop 'em
// ` \ round!"
// ___|| ~ _ -bankers
// | | __
// | | | __|__|__
// |_____: / | $$$ |
// |________|
// nolint - go-cyclo
// Remove a Precision amount of rightmost digits and perform bankers rounding
// on the remainder (gaussian rounding) on the digits which have been removed.
//
// Mutates the input. Use the non-mutative version if that is undesired
func chopPrecisionAndRound(d *big.Int) *big.Int {
// remove the negative and add it back when returning
if d.Sign() == -1 {
// make d positive, compute chopped value, and then un-mutate d
d = d.Neg(d)
d = chopPrecisionAndRound(d)
d = d.Neg(d)
return d
}
// get the trucated quotient and remainder
quo, rem := d, big.NewInt(0)
quo, rem = quo.QuoRem(d, precisionReuse, rem)
if rem.Sign() == 0 { // remainder is zero
return quo
}
switch rem.Cmp(fivePrecision) {
case -1:
return quo
case 1:
return quo.Add(quo, oneInt)
default: // bankers rounding must take place
// always round to an even number
if quo.Bit(0) == 0 {
return quo
}
return quo.Add(quo, oneInt)
}
}
func chopPrecisionAndRoundNonMutative(d *big.Int) *big.Int {
tmp := new(big.Int).Set(d)
return chopPrecisionAndRound(tmp)
}
// RoundInt64 rounds the decimal using bankers rounding
func (d Dec) RoundInt64() int64 {
chopped := chopPrecisionAndRoundNonMutative(d.Int)
if !chopped.IsInt64() {
panic("Int64() out of bound")
}
return chopped.Int64()
}
// RoundInt round the decimal using bankers rounding
func (d Dec) RoundInt() Int {
return NewIntFromBigInt(chopPrecisionAndRoundNonMutative(d.Int))
}
//___________________________________________________________________________________
// reuse nil values
var (
nilAmino string
nilJSON []byte
)
func init() {
empty := new(big.Int)
bz, err := empty.MarshalText()
if err != nil {
panic("bad nil amino init")
}
nilAmino = string(bz)
nilJSON, err = json.Marshal(string(bz))
if err != nil {
panic("bad nil json init")
}
}
// wraps d.MarshalText()
func (d Dec) MarshalAmino() (string, error) {
if d.Int == nil {
return nilAmino, nil
}
bz, err := d.Int.MarshalText()
return string(bz), err
}
// requires a valid JSON string - strings quotes and calls UnmarshalText
func (d *Dec) UnmarshalAmino(text string) (err error) {
tempInt := new(big.Int)
err = tempInt.UnmarshalText([]byte(text))
if err != nil {
return err
}
d.Int = tempInt
return nil
}
// MarshalJSON defines custom encoding scheme
func (d Dec) MarshalJSON() ([]byte, error) {
if d.Int == nil {
return nilJSON, nil
}
bz, err := d.Int.MarshalText()
if err != nil {
return nil, err
}
return json.Marshal(string(bz))
}
// UnmarshalJSON defines custom decoding scheme
func (d *Dec) UnmarshalJSON(bz []byte) error {
if d.Int == nil {
d.Int = new(big.Int)
}
var text string
err := json.Unmarshal(bz, &text)
if err != nil {
return err
}
return d.Int.UnmarshalText([]byte(text))
}
//___________________________________________________________________________________
// helpers
// test if two decimal arrays are equal
func DecsEqual(d1s, d2s []Dec) bool {
if len(d1s) != len(d2s) {
return false
}
for i, d1 := range d1s {
if !d1.Equal(d2s[i]) {
return false
}
}
return true
}
// minimum decimal between two
func MinDec(d1, d2 Dec) Dec {
if d1.LT(d2) {
return d1
}
return d2
}
// intended to be used with require/assert: require.True(DecEq(...))
func DecEq(t *testing.T, exp, got Dec) (*testing.T, bool, string, Dec, Dec) {
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp, got
}

301
types/decimal_test.go Normal file
View File

@ -0,0 +1,301 @@
package types
import (
"math/big"
"testing"
wire "github.com/cosmos/cosmos-sdk/wire"
"github.com/stretchr/testify/require"
)
// create a decimal from a decimal string (ex. "1234.5678")
func mustNewDecFromStr(t *testing.T, str string) (d Dec) {
d, err := NewDecFromStr(str)
require.NoError(t, err)
return d
}
//_______________________________________
func TestPrecisionMultiplier(t *testing.T) {
res := precisionMultiplier(5)
exp := big.NewInt(100000)
require.Equal(t, 0, res.Cmp(exp), "equality was incorrect, res %v, exp %v", res, exp)
}
func TestNewDecFromStr(t *testing.T) {
largeBigInt, success := new(big.Int).SetString("3144605511029693144278234343371835", 10)
require.True(t, success)
tests := []struct {
decimalStr string
expErr bool
exp Dec
}{
{"", true, Dec{}},
{"0.-75", true, Dec{}},
{"0", false, NewDec(0)},
{"1", false, NewDec(1)},
{"1.1", false, NewDecWithPrec(11, 1)},
{"0.75", false, NewDecWithPrec(75, 2)},
{"0.8", false, NewDecWithPrec(8, 1)},
{"0.11111", false, NewDecWithPrec(11111, 5)},
{"314460551102969.3144278234343371835", true, NewDec(3141203149163817869)},
{"314460551102969314427823434337.1835718092488231350",
true, NewDecFromBigIntWithPrec(largeBigInt, 4)},
{"314460551102969314427823434337.1835",
false, NewDecFromBigIntWithPrec(largeBigInt, 4)},
{".", true, Dec{}},
{".0", true, NewDec(0)},
{"1.", true, NewDec(1)},
{"foobar", true, Dec{}},
{"0.foobar", true, Dec{}},
{"0.foobar.", true, Dec{}},
}
for tcIndex, tc := range tests {
res, err := NewDecFromStr(tc.decimalStr)
if tc.expErr {
require.NotNil(t, err, "error expected, decimalStr %v, tc %v", tc.decimalStr, tcIndex)
} else {
require.Nil(t, err, "unexpected error, decimalStr %v, tc %v", tc.decimalStr, tcIndex)
require.True(t, res.Equal(tc.exp), "equality was incorrect, res %v, exp %v, tc %v", res, tc.exp, tcIndex)
}
// negative tc
res, err = NewDecFromStr("-" + tc.decimalStr)
if tc.expErr {
require.NotNil(t, err, "error expected, decimalStr %v, tc %v", tc.decimalStr, tcIndex)
} else {
require.Nil(t, err, "unexpected error, decimalStr %v, tc %v", tc.decimalStr, tcIndex)
exp := tc.exp.Mul(NewDec(-1))
require.True(t, res.Equal(exp), "equality was incorrect, res %v, exp %v, tc %v", res, exp, tcIndex)
}
}
}
func TestEqualities(t *testing.T) {
tests := []struct {
d1, d2 Dec
gt, lt, eq bool
}{
{NewDec(0), NewDec(0), false, false, true},
{NewDecWithPrec(0, 2), NewDecWithPrec(0, 4), false, false, true},
{NewDecWithPrec(100, 0), NewDecWithPrec(100, 0), false, false, true},
{NewDecWithPrec(-100, 0), NewDecWithPrec(-100, 0), false, false, true},
{NewDecWithPrec(-1, 1), NewDecWithPrec(-1, 1), false, false, true},
{NewDecWithPrec(3333, 3), NewDecWithPrec(3333, 3), false, false, true},
{NewDecWithPrec(0, 0), NewDecWithPrec(3333, 3), false, true, false},
{NewDecWithPrec(0, 0), NewDecWithPrec(100, 0), false, true, false},
{NewDecWithPrec(-1, 0), NewDecWithPrec(3333, 3), false, true, false},
{NewDecWithPrec(-1, 0), NewDecWithPrec(100, 0), false, true, false},
{NewDecWithPrec(1111, 3), NewDecWithPrec(100, 0), false, true, false},
{NewDecWithPrec(1111, 3), NewDecWithPrec(3333, 3), false, true, false},
{NewDecWithPrec(-3333, 3), NewDecWithPrec(-1111, 3), false, true, false},
{NewDecWithPrec(3333, 3), NewDecWithPrec(0, 0), true, false, false},
{NewDecWithPrec(100, 0), NewDecWithPrec(0, 0), true, false, false},
{NewDecWithPrec(3333, 3), NewDecWithPrec(-1, 0), true, false, false},
{NewDecWithPrec(100, 0), NewDecWithPrec(-1, 0), true, false, false},
{NewDecWithPrec(100, 0), NewDecWithPrec(1111, 3), true, false, false},
{NewDecWithPrec(3333, 3), NewDecWithPrec(1111, 3), true, false, false},
{NewDecWithPrec(-1111, 3), NewDecWithPrec(-3333, 3), true, false, false},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.gt, tc.d1.GT(tc.d2), "GT result is incorrect, tc %d", tcIndex)
require.Equal(t, tc.lt, tc.d1.LT(tc.d2), "LT result is incorrect, tc %d", tcIndex)
require.Equal(t, tc.eq, tc.d1.Equal(tc.d2), "equality result is incorrect, tc %d", tcIndex)
}
}
func TestDecsEqual(t *testing.T) {
tests := []struct {
d1s, d2s []Dec
eq bool
}{
{[]Dec{NewDec(0)}, []Dec{NewDec(0)}, true},
{[]Dec{NewDec(0)}, []Dec{NewDec(1)}, false},
{[]Dec{NewDec(0)}, []Dec{}, false},
{[]Dec{NewDec(0), NewDec(1)}, []Dec{NewDec(0), NewDec(1)}, true},
{[]Dec{NewDec(1), NewDec(0)}, []Dec{NewDec(1), NewDec(0)}, true},
{[]Dec{NewDec(1), NewDec(0)}, []Dec{NewDec(0), NewDec(1)}, false},
{[]Dec{NewDec(1), NewDec(0)}, []Dec{NewDec(1)}, false},
{[]Dec{NewDec(1), NewDec(2)}, []Dec{NewDec(2), NewDec(4)}, false},
{[]Dec{NewDec(3), NewDec(18)}, []Dec{NewDec(1), NewDec(6)}, false},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.eq, DecsEqual(tc.d1s, tc.d2s), "equality of decional arrays is incorrect, tc %d", tcIndex)
require.Equal(t, tc.eq, DecsEqual(tc.d2s, tc.d1s), "equality of decional arrays is incorrect (converse), tc %d", tcIndex)
}
}
func TestArithmetic(t *testing.T) {
tests := []struct {
d1, d2 Dec
expMul, expDiv, expAdd, expSub Dec
}{
// d1 d2 MUL DIV ADD SUB
{NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0)},
{NewDec(1), NewDec(0), NewDec(0), NewDec(0), NewDec(1), NewDec(1)},
{NewDec(0), NewDec(1), NewDec(0), NewDec(0), NewDec(1), NewDec(-1)},
{NewDec(0), NewDec(-1), NewDec(0), NewDec(0), NewDec(-1), NewDec(1)},
{NewDec(-1), NewDec(0), NewDec(0), NewDec(0), NewDec(-1), NewDec(-1)},
{NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(2), NewDec(0)},
{NewDec(-1), NewDec(-1), NewDec(1), NewDec(1), NewDec(-2), NewDec(0)},
{NewDec(1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(2)},
{NewDec(-1), NewDec(1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(-2)},
{NewDec(3), NewDec(7), NewDec(21), NewDecWithPrec(4285714286, 10), NewDec(10), NewDec(-4)},
{NewDec(2), NewDec(4), NewDec(8), NewDecWithPrec(5, 1), NewDec(6), NewDec(-2)},
{NewDec(100), NewDec(100), NewDec(10000), NewDec(1), NewDec(200), NewDec(0)},
{NewDecWithPrec(15, 1), NewDecWithPrec(15, 1), NewDecWithPrec(225, 2),
NewDec(1), NewDec(3), NewDec(0)},
{NewDecWithPrec(3333, 4), NewDecWithPrec(333, 4), NewDecWithPrec(1109889, 8),
NewDecWithPrec(10009009009, 9), NewDecWithPrec(3666, 4), NewDecWithPrec(3, 1)},
}
for tcIndex, tc := range tests {
resAdd := tc.d1.Add(tc.d2)
resSub := tc.d1.Sub(tc.d2)
resMul := tc.d1.Mul(tc.d2)
require.True(t, tc.expAdd.Equal(resAdd), "exp %v, res %v, tc %d", tc.expAdd, resAdd, tcIndex)
require.True(t, tc.expSub.Equal(resSub), "exp %v, res %v, tc %d", tc.expSub, resSub, tcIndex)
require.True(t, tc.expMul.Equal(resMul), "exp %v, res %v, tc %d", tc.expMul, resMul, tcIndex)
if tc.d2.IsZero() { // panic for divide by zero
require.Panics(t, func() { tc.d1.Quo(tc.d2) })
} else {
resDiv := tc.d1.Quo(tc.d2)
require.True(t, tc.expDiv.Equal(resDiv), "exp %v, res %v, tc %d", tc.expDiv.String(), resDiv.String(), tcIndex)
}
}
}
func TestBankerRoundChop(t *testing.T) {
tests := []struct {
d1 Dec
exp int64
}{
{mustNewDecFromStr(t, "0.25"), 0},
{mustNewDecFromStr(t, "0"), 0},
{mustNewDecFromStr(t, "1"), 1},
{mustNewDecFromStr(t, "0.75"), 1},
{mustNewDecFromStr(t, "0.5"), 0},
{mustNewDecFromStr(t, "7.5"), 8},
{mustNewDecFromStr(t, "1.5"), 2},
{mustNewDecFromStr(t, "2.5"), 2},
{mustNewDecFromStr(t, "0.545"), 1}, // 0.545-> 1 even though 5 is first decimal and 1 not even
{mustNewDecFromStr(t, "1.545"), 2},
}
for tcIndex, tc := range tests {
resNeg := tc.d1.Neg().RoundInt64()
require.Equal(t, -1*tc.exp, resNeg, "negative tc %d", tcIndex)
resPos := tc.d1.RoundInt64()
require.Equal(t, tc.exp, resPos, "positive tc %d", tcIndex)
}
}
func TestToLeftPadded(t *testing.T) {
tests := []struct {
dec Dec
digits int8
exp string
}{
{mustNewDecFromStr(t, "33.3"), 8, "00000033"},
{mustNewDecFromStr(t, "50"), 8, "00000050"},
{mustNewDecFromStr(t, "333"), 8, "00000333"},
{mustNewDecFromStr(t, "333"), 12, "000000000333"},
{mustNewDecFromStr(t, "0.3333"), 8, "00000000"},
}
for tcIndex, tc := range tests {
res := tc.dec.ToLeftPadded(tc.digits)
require.Equal(t, tc.exp, res, "incorrect left padding, tc %d", tcIndex)
}
}
var cdc = wire.NewCodec()
func TestZeroDeserializationJSON(t *testing.T) {
d := Dec{new(big.Int)}
err := cdc.UnmarshalJSON([]byte(`"0"`), &d)
require.Nil(t, err)
err = cdc.UnmarshalJSON([]byte(`"{}"`), &d)
require.NotNil(t, err)
}
func TestSerializationText(t *testing.T) {
d := mustNewDecFromStr(t, "0.333")
bz, err := d.MarshalText()
require.NoError(t, err)
d2 := Dec{new(big.Int)}
err = d2.UnmarshalText(bz)
require.NoError(t, err)
require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2)
}
func TestSerializationGoWireJSON(t *testing.T) {
d := mustNewDecFromStr(t, "0.333")
bz, err := cdc.MarshalJSON(d)
require.NoError(t, err)
d2 := Dec{new(big.Int)}
err = cdc.UnmarshalJSON(bz, &d2)
require.NoError(t, err)
require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2)
}
func TestSerializationGoWireBinary(t *testing.T) {
d := mustNewDecFromStr(t, "0.333")
bz, err := cdc.MarshalBinary(d)
require.NoError(t, err)
var d2 Dec
err = cdc.UnmarshalBinary(bz, &d2)
require.NoError(t, err)
require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2)
}
type testDEmbedStruct struct {
Field1 string `json:"f1"`
Field2 int `json:"f2"`
Field3 Dec `json:"f3"`
}
// TODO make work for UnmarshalJSON
func TestEmbeddedStructSerializationGoWire(t *testing.T) {
obj := testDEmbedStruct{"foo", 10, NewDecWithPrec(1, 3)}
bz, err := cdc.MarshalBinary(obj)
require.Nil(t, err)
var obj2 testDEmbedStruct
err = cdc.UnmarshalBinary(bz, &obj2)
require.Nil(t, err)
require.Equal(t, obj.Field1, obj2.Field1)
require.Equal(t, obj.Field2, obj2.Field2)
require.True(t, obj.Field3.Equal(obj2.Field3), "original: %v, unmarshalled: %v", obj, obj2)
}
func TestStringOverflow(t *testing.T) {
// two random 64 bit primes
dec1, err := NewDecFromStr("51643150036226787134389711697696177267")
require.NoError(t, err)
dec2, err := NewDecFromStr("-31798496660535729618459429845579852627")
require.NoError(t, err)
dec3 := dec1.Add(dec2)
require.Equal(t,
"19844653375691057515930281852116324640.0000000000",
dec3.String(),
)
}

View File

@ -1,262 +0,0 @@
package types
import (
"fmt"
"math/big"
"strconv"
"strings"
"testing"
)
// "that's one big rat!"
// ______
// / / /\ \____oo
// __ /___...._____ _\o
// __| |_ |_
// NOTE: never use new(Rat) or else
// we will panic unmarshalling into the
// nil embedded big.Rat
type Rat struct {
*big.Rat `json:"rat"`
}
// nolint - common values
func ZeroRat() Rat { return Rat{big.NewRat(0, 1)} }
func OneRat() Rat { return Rat{big.NewRat(1, 1)} }
// New - create a new Rat from integers
func NewRat(Numerator int64, Denominator ...int64) Rat {
switch len(Denominator) {
case 0:
return Rat{big.NewRat(Numerator, 1)}
case 1:
return Rat{big.NewRat(Numerator, Denominator[0])}
default:
panic("improper use of New, can only have one denominator")
}
}
func getNumeratorDenominator(str []string, prec int) (numerator string, denom int64, err Error) {
switch len(str) {
case 1:
if len(str[0]) == 0 {
return "", 0, ErrUnknownRequest("not a decimal string")
}
numerator = str[0]
return numerator, 1, nil
case 2:
if len(str[0]) == 0 || len(str[1]) == 0 {
return "", 0, ErrUnknownRequest("not a decimal string")
}
if len(str[1]) > prec {
return "", 0, ErrUnknownRequest("string has too many decimals")
}
numerator = str[0] + str[1]
len := int64(len(str[1]))
denom = new(big.Int).Exp(big.NewInt(10), big.NewInt(len), nil).Int64()
return numerator, denom, nil
default:
return "", 0, ErrUnknownRequest("not a decimal string")
}
}
// create a rational from decimal string or integer string
// precision is the number of values after the decimal point which should be read
func NewRatFromDecimal(decimalStr string, prec int) (f Rat, err Error) {
// first extract any negative symbol
if len(decimalStr) == 0 {
return f, ErrUnknownRequest("decimal string is empty")
}
neg := false
if string(decimalStr[0]) == "-" {
neg = true
decimalStr = decimalStr[1:]
}
str := strings.Split(decimalStr, ".")
numStr, denom, err := getNumeratorDenominator(str, prec)
if err != nil {
return f, err
}
num, errConv := strconv.Atoi(numStr)
if errConv != nil && strings.HasSuffix(errConv.Error(), "value out of range") {
// resort to big int, don't make this default option for efficiency
numBig, success := new(big.Int).SetString(numStr, 10)
if success != true {
return f, ErrUnknownRequest("not a decimal string")
}
if neg {
numBig.Neg(numBig)
}
return NewRatFromBigInt(numBig, big.NewInt(denom)), nil
} else if errConv != nil {
return f, ErrUnknownRequest("not a decimal string")
}
if neg {
num *= -1
}
return NewRat(int64(num), denom), nil
}
// NewRatFromBigInt constructs Rat from big.Int
func NewRatFromBigInt(num *big.Int, denom ...*big.Int) Rat {
switch len(denom) {
case 0:
return Rat{new(big.Rat).SetInt(num)}
case 1:
return Rat{new(big.Rat).SetFrac(num, denom[0])}
default:
panic("improper use of NewRatFromBigInt, can only have one denominator")
}
}
// NewRatFromInt constructs Rat from Int
func NewRatFromInt(num Int, denom ...Int) Rat {
switch len(denom) {
case 0:
return Rat{new(big.Rat).SetInt(num.BigInt())}
case 1:
return Rat{new(big.Rat).SetFrac(num.BigInt(), denom[0].BigInt())}
default:
panic("improper use of NewRatFromBigInt, can only have one denominator")
}
}
//nolint
func (r Rat) Num() Int { return Int{r.Rat.Num()} } // Num - return the numerator
func (r Rat) Denom() Int { return Int{r.Rat.Denom()} } // Denom - return the denominator
func (r Rat) IsZero() bool { return r.Num().IsZero() } // IsZero - Is the Rat equal to zero
func (r Rat) Equal(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == 0 }
func (r Rat) GT(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == 1 } // greater than
func (r Rat) GTE(r2 Rat) bool { return !r.LT(r2) } // greater than or equal
func (r Rat) LT(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == -1 } // less than
func (r Rat) LTE(r2 Rat) bool { return !r.GT(r2) } // less than or equal
func (r Rat) Mul(r2 Rat) Rat { return Rat{new(big.Rat).Mul(r.Rat, r2.Rat)} } // Mul - multiplication
func (r Rat) Quo(r2 Rat) Rat { return Rat{new(big.Rat).Quo(r.Rat, r2.Rat)} } // Quo - quotient
func (r Rat) Add(r2 Rat) Rat { return Rat{new(big.Rat).Add(r.Rat, r2.Rat)} } // Add - addition
func (r Rat) Sub(r2 Rat) Rat { return Rat{new(big.Rat).Sub(r.Rat, r2.Rat)} } // Sub - subtraction
func (r Rat) String() string { return r.Rat.String() }
func (r Rat) FloatString() string { return r.Rat.FloatString(10) } // a human-friendly string format. The last digit is rounded to nearest, with halves rounded away from zero.
var (
zero = big.NewInt(0)
one = big.NewInt(1)
two = big.NewInt(2)
five = big.NewInt(5)
nFive = big.NewInt(-5)
ten = big.NewInt(10)
)
// evaluate the rational using bankers rounding
func (r Rat) EvaluateBig() *big.Int {
num := r.Rat.Num()
denom := r.Rat.Denom()
d, rem := new(big.Int), new(big.Int)
d.QuoRem(num, denom, rem)
if rem.Cmp(zero) == 0 { // is the remainder zero
return d
}
// evaluate the remainder using bankers rounding
tenNum := new(big.Int).Mul(num, ten)
tenD := new(big.Int).Mul(d, ten)
remainderDigit := new(big.Int).Sub(new(big.Int).Quo(tenNum, denom), tenD) // get the first remainder digit
isFinalDigit := (new(big.Int).Rem(tenNum, denom).Cmp(zero) == 0) // is this the final digit in the remainder?
switch {
case isFinalDigit && (remainderDigit.Cmp(five) == 0 || remainderDigit.Cmp(nFive) == 0):
dRem2 := new(big.Int).Rem(d, two)
return new(big.Int).Add(d, dRem2) // always rounds to the even number
case remainderDigit.Cmp(five) != -1: //remainderDigit >= 5:
d.Add(d, one)
case remainderDigit.Cmp(nFive) != 1: //remainderDigit <= -5:
d.Sub(d, one)
}
return d
}
// RoundInt64 rounds the rational using bankers rounding
func (r Rat) RoundInt64() int64 {
return r.EvaluateBig().Int64()
}
// RoundInt round the rational using bankers rounding
func (r Rat) RoundInt() Int {
return NewIntFromBigInt(r.EvaluateBig())
}
// round Rat with the provided precisionFactor
func (r Rat) Round(precisionFactor int64) Rat {
rTen := Rat{new(big.Rat).Mul(r.Rat, big.NewRat(precisionFactor, 1))}
return Rat{big.NewRat(rTen.RoundInt64(), precisionFactor)}
}
// TODO panic if negative or if totalDigits < len(initStr)???
// evaluate as an integer and return left padded string
func (r Rat) ToLeftPadded(totalDigits int8) string {
intStr := r.EvaluateBig().String()
fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s`
return fmt.Sprintf(fcode, intStr)
}
//___________________________________________________________________________________
//Wraps r.MarshalText().
func (r Rat) MarshalAmino() (string, error) {
if r.Rat == nil {
r.Rat = new(big.Rat)
}
bz, err := r.Rat.MarshalText()
return string(bz), err
}
// Requires a valid JSON string - strings quotes and calls UnmarshalText
func (r *Rat) UnmarshalAmino(text string) (err error) {
tempRat := big.NewRat(0, 1)
err = tempRat.UnmarshalText([]byte(text))
if err != nil {
return err
}
r.Rat = tempRat
return nil
}
//___________________________________________________________________________________
// helpers
// test if two rat arrays are equal
func RatsEqual(r1s, r2s []Rat) bool {
if len(r1s) != len(r2s) {
return false
}
for i, r1 := range r1s {
if !r1.Equal(r2s[i]) {
return false
}
}
return true
}
// intended to be used with require/assert: require.True(RatEq(...))
func RatEq(t *testing.T, exp, got Rat) (*testing.T, bool, string, Rat, Rat) {
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp, got
}
// minimum rational between two
func MinRat(r1, r2 Rat) Rat {
if r1.LT(r2) {
return r1
}
return r2
}

View File

@ -1,402 +0,0 @@
package types
import (
"math/big"
"math/rand"
"testing"
wire "github.com/cosmos/cosmos-sdk/wire"
"github.com/stretchr/testify/require"
)
func TestNew(t *testing.T) {
require.Equal(t, NewRat(1), NewRat(1, 1))
require.Equal(t, NewRat(100), NewRat(100, 1))
require.Equal(t, NewRat(-1), NewRat(-1, 1))
require.Equal(t, NewRat(-100), NewRat(-100, 1))
require.Equal(t, NewRat(0), NewRat(0, 1))
// do not allow for more than 2 variables
require.Panics(t, func() { NewRat(1, 1, 1) })
}
func TestNewFromDecimal(t *testing.T) {
largeBigInt, success := new(big.Int).SetString("3109736052979742687701388262607869", 10)
require.True(t, success)
tests := []struct {
decimalStr string
expErr bool
exp Rat
}{
{"", true, Rat{}},
{"0", false, NewRat(0)},
{"1", false, NewRat(1)},
{"1.1", false, NewRat(11, 10)},
{"0.75", false, NewRat(3, 4)},
{"0.8", false, NewRat(4, 5)},
{"0.11111", true, NewRat(1111, 10000)},
{"628240629832763.5738930323617075341", true, NewRat(3141203149163817869, 5000)},
{"621947210595948537540277652521.5738930323617075341",
true, NewRatFromBigInt(largeBigInt, big.NewInt(5000))},
{"628240629832763.5738", false, NewRat(3141203149163817869, 5000)},
{"621947210595948537540277652521.5738",
false, NewRatFromBigInt(largeBigInt, big.NewInt(5000))},
{".", true, Rat{}},
{".0", true, Rat{}},
{"1.", true, Rat{}},
{"foobar", true, Rat{}},
{"0.foobar", true, Rat{}},
{"0.foobar.", true, Rat{}},
}
for tcIndex, tc := range tests {
res, err := NewRatFromDecimal(tc.decimalStr, 4)
if tc.expErr {
require.NotNil(t, err, tc.decimalStr, "error expected, tc #%d", tcIndex)
} else {
require.Nil(t, err, tc.decimalStr, "unexpected error, tc #%d", tcIndex)
require.True(t, res.Equal(tc.exp), tc.decimalStr, "equality was incorrect, tc #%d", tcIndex)
}
// negative tc
res, err = NewRatFromDecimal("-"+tc.decimalStr, 4)
if tc.expErr {
require.NotNil(t, err, tc.decimalStr, "error expected (negative case), tc #%d", tcIndex)
} else {
require.Nil(t, err, tc.decimalStr, "unexpected error (negative case), tc #%d", tcIndex)
require.True(t, res.Equal(tc.exp.Mul(NewRat(-1))), tc.decimalStr, "equality was incorrect (negative case), tc #%d", tcIndex)
}
}
}
func TestEqualities(t *testing.T) {
tests := []struct {
r1, r2 Rat
gt, lt, eq bool
}{
{NewRat(0), NewRat(0), false, false, true},
{NewRat(0, 100), NewRat(0, 10000), false, false, true},
{NewRat(100), NewRat(100), false, false, true},
{NewRat(-100), NewRat(-100), false, false, true},
{NewRat(-100, -1), NewRat(100), false, false, true},
{NewRat(-1, 1), NewRat(1, -1), false, false, true},
{NewRat(1, -1), NewRat(-1, 1), false, false, true},
{NewRat(3, 7), NewRat(3, 7), false, false, true},
{NewRat(0), NewRat(3, 7), false, true, false},
{NewRat(0), NewRat(100), false, true, false},
{NewRat(-1), NewRat(3, 7), false, true, false},
{NewRat(-1), NewRat(100), false, true, false},
{NewRat(1, 7), NewRat(100), false, true, false},
{NewRat(1, 7), NewRat(3, 7), false, true, false},
{NewRat(-3, 7), NewRat(-1, 7), false, true, false},
{NewRat(3, 7), NewRat(0), true, false, false},
{NewRat(100), NewRat(0), true, false, false},
{NewRat(3, 7), NewRat(-1), true, false, false},
{NewRat(100), NewRat(-1), true, false, false},
{NewRat(100), NewRat(1, 7), true, false, false},
{NewRat(3, 7), NewRat(1, 7), true, false, false},
{NewRat(-1, 7), NewRat(-3, 7), true, false, false},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.gt, tc.r1.GT(tc.r2), "GT result is incorrect, tc #%d", tcIndex)
require.Equal(t, tc.lt, tc.r1.LT(tc.r2), "LT result is incorrect, tc #%d", tcIndex)
require.Equal(t, tc.eq, tc.r1.Equal(tc.r2), "equality result is incorrect, tc #%d", tcIndex)
}
}
func TestArithmetic(t *testing.T) {
tests := []struct {
r1, r2 Rat
resMul, resDiv, resAdd, resSub Rat
}{
// r1 r2 MUL DIV ADD SUB
{NewRat(0), NewRat(0), NewRat(0), NewRat(0), NewRat(0), NewRat(0)},
{NewRat(1), NewRat(0), NewRat(0), NewRat(0), NewRat(1), NewRat(1)},
{NewRat(0), NewRat(1), NewRat(0), NewRat(0), NewRat(1), NewRat(-1)},
{NewRat(0), NewRat(-1), NewRat(0), NewRat(0), NewRat(-1), NewRat(1)},
{NewRat(-1), NewRat(0), NewRat(0), NewRat(0), NewRat(-1), NewRat(-1)},
{NewRat(1), NewRat(1), NewRat(1), NewRat(1), NewRat(2), NewRat(0)},
{NewRat(-1), NewRat(-1), NewRat(1), NewRat(1), NewRat(-2), NewRat(0)},
{NewRat(1), NewRat(-1), NewRat(-1), NewRat(-1), NewRat(0), NewRat(2)},
{NewRat(-1), NewRat(1), NewRat(-1), NewRat(-1), NewRat(0), NewRat(-2)},
{NewRat(3), NewRat(7), NewRat(21), NewRat(3, 7), NewRat(10), NewRat(-4)},
{NewRat(2), NewRat(4), NewRat(8), NewRat(1, 2), NewRat(6), NewRat(-2)},
{NewRat(100), NewRat(100), NewRat(10000), NewRat(1), NewRat(200), NewRat(0)},
{NewRat(3, 2), NewRat(3, 2), NewRat(9, 4), NewRat(1), NewRat(3), NewRat(0)},
{NewRat(3, 7), NewRat(7, 3), NewRat(1), NewRat(9, 49), NewRat(58, 21), NewRat(-40, 21)},
{NewRat(1, 21), NewRat(11, 5), NewRat(11, 105), NewRat(5, 231), NewRat(236, 105), NewRat(-226, 105)},
{NewRat(-21), NewRat(3, 7), NewRat(-9), NewRat(-49), NewRat(-144, 7), NewRat(-150, 7)},
{NewRat(100), NewRat(1, 7), NewRat(100, 7), NewRat(700), NewRat(701, 7), NewRat(699, 7)},
}
for tcIndex, tc := range tests {
require.True(t, tc.resMul.Equal(tc.r1.Mul(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex)
require.True(t, tc.resAdd.Equal(tc.r1.Add(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex)
require.True(t, tc.resSub.Equal(tc.r1.Sub(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex)
if tc.r2.Num().IsZero() { // panic for divide by zero
require.Panics(t, func() { tc.r1.Quo(tc.r2) })
} else {
require.True(t, tc.resDiv.Equal(tc.r1.Quo(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex)
}
}
}
func TestEvaluate(t *testing.T) {
tests := []struct {
r1 Rat
res int64
}{
{NewRat(0), 0},
{NewRat(1), 1},
{NewRat(1, 4), 0},
{NewRat(1, 2), 0},
{NewRat(3, 4), 1},
{NewRat(5, 6), 1},
{NewRat(3, 2), 2},
{NewRat(5, 2), 2},
{NewRat(6, 11), 1}, // 0.545-> 1 even though 5 is first decimal and 1 not even
{NewRat(17, 11), 2}, // 1.545
{NewRat(5, 11), 0},
{NewRat(16, 11), 1},
{NewRat(113, 12), 9},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.res, tc.r1.RoundInt64(), "%v. tc #%d", tc.r1, tcIndex)
require.Equal(t, tc.res*-1, tc.r1.Mul(NewRat(-1)).RoundInt64(), "%v. tc #%d", tc.r1.Mul(NewRat(-1)), tcIndex)
}
}
func TestRound(t *testing.T) {
many3 := "333333333333333333333333333333333333333333333"
many7 := "777777777777777777777777777777777777777777777"
big3, worked := new(big.Int).SetString(many3, 10)
require.True(t, worked)
big7, worked := new(big.Int).SetString(many7, 10)
require.True(t, worked)
tests := []struct {
r, res Rat
precFactor int64
}{
{NewRat(333, 777), NewRat(429, 1000), 1000},
{Rat{new(big.Rat).SetFrac(big3, big7)}, NewRat(429, 1000), 1000},
{Rat{new(big.Rat).SetFrac(big3, big7)}, Rat{big.NewRat(4285714286, 10000000000)}, 10000000000},
{NewRat(1, 2), NewRat(1, 2), 1000},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.res, tc.r.Round(tc.precFactor), "%v", tc.r, "incorrect rounding, tc #%d", tcIndex)
negR1, negRes := tc.r.Mul(NewRat(-1)), tc.res.Mul(NewRat(-1))
require.Equal(t, negRes, negR1.Round(tc.precFactor), "%v", negR1, "incorrect rounding (negative case), tc #%d", tcIndex)
}
}
func TestToLeftPadded(t *testing.T) {
tests := []struct {
rat Rat
digits int8
res string
}{
{NewRat(100, 3), 8, "00000033"},
{NewRat(1, 3), 8, "00000000"},
{NewRat(100, 2), 8, "00000050"},
{NewRat(1000, 3), 8, "00000333"},
{NewRat(1000, 3), 12, "000000000333"},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.res, tc.rat.ToLeftPadded(tc.digits), "incorrect left padding, tc #%d", tcIndex)
}
}
var cdc = wire.NewCodec() //var jsonCdc JSONCodec // TODO wire.Codec
func TestZeroSerializationJSON(t *testing.T) {
r := NewRat(0, 1)
err := cdc.UnmarshalJSON([]byte(`"0/1"`), &r)
require.Nil(t, err)
err = cdc.UnmarshalJSON([]byte(`"0/0"`), &r)
require.NotNil(t, err)
err = cdc.UnmarshalJSON([]byte(`"1/0"`), &r)
require.NotNil(t, err)
err = cdc.UnmarshalJSON([]byte(`"{}"`), &r)
require.NotNil(t, err)
}
func TestSerializationText(t *testing.T) {
r := NewRat(1, 3)
bz, err := r.MarshalText()
require.NoError(t, err)
var r2 = Rat{new(big.Rat)}
err = r2.UnmarshalText(bz)
require.NoError(t, err)
require.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
}
func TestSerializationGoWireJSON(t *testing.T) {
r := NewRat(1, 3)
bz, err := cdc.MarshalJSON(r)
require.NoError(t, err)
var r2 Rat
err = cdc.UnmarshalJSON(bz, &r2)
require.NoError(t, err)
require.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
}
func TestSerializationGoWireBinary(t *testing.T) {
r := NewRat(1, 3)
bz, err := cdc.MarshalBinary(r)
require.NoError(t, err)
var r2 Rat
err = cdc.UnmarshalBinary(bz, &r2)
require.NoError(t, err)
require.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2)
}
type testEmbedStruct struct {
Field1 string `json:"f1"`
Field2 int `json:"f2"`
Field3 Rat `json:"f3"`
}
func TestEmbeddedStructSerializationGoWire(t *testing.T) {
obj := testEmbedStruct{"foo", 10, NewRat(1, 3)}
bz, err := cdc.MarshalJSON(obj)
require.Nil(t, err)
var obj2 testEmbedStruct
err = cdc.UnmarshalJSON(bz, &obj2)
require.Nil(t, err)
require.Equal(t, obj.Field1, obj2.Field1)
require.Equal(t, obj.Field2, obj2.Field2)
require.True(t, obj.Field3.Equal(obj2.Field3), "original: %v, unmarshalled: %v", obj, obj2)
}
func TestRatsEqual(t *testing.T) {
tests := []struct {
r1s, r2s []Rat
eq bool
}{
{[]Rat{NewRat(0)}, []Rat{NewRat(0)}, true},
{[]Rat{NewRat(0)}, []Rat{NewRat(1)}, false},
{[]Rat{NewRat(0)}, []Rat{}, false},
{[]Rat{NewRat(0), NewRat(1)}, []Rat{NewRat(0), NewRat(1)}, true},
{[]Rat{NewRat(1), NewRat(0)}, []Rat{NewRat(1), NewRat(0)}, true},
{[]Rat{NewRat(1), NewRat(0)}, []Rat{NewRat(0), NewRat(1)}, false},
{[]Rat{NewRat(1), NewRat(0)}, []Rat{NewRat(1)}, false},
{[]Rat{NewRat(1), NewRat(2)}, []Rat{NewRat(2), NewRat(4)}, false},
{[]Rat{NewRat(3), NewRat(18)}, []Rat{NewRat(1), NewRat(6)}, false},
}
for tcIndex, tc := range tests {
require.Equal(t, tc.eq, RatsEqual(tc.r1s, tc.r2s), "equality of rational arrays is incorrect, tc #%d", tcIndex)
require.Equal(t, tc.eq, RatsEqual(tc.r2s, tc.r1s), "equality of rational arrays is incorrect (converse), tc #%d", tcIndex)
}
}
func TestStringOverflow(t *testing.T) {
// two random 64 bit primes
rat1 := NewRat(5164315003622678713, 4389711697696177267)
rat2 := NewRat(-3179849666053572961, 8459429845579852627)
rat3 := rat1.Add(rat2)
require.Equal(t,
"29728537197630860939575850336935951464/37134458148982045574552091851127630409",
rat3.String(),
)
}
// Tests below uses randomness
// Since we are using *big.Rat as underlying value
// and (U/)Int is immutable value(see TestImmutability(U/)Int)
// it is safe to use randomness in the tests
func TestArithRat(t *testing.T) {
for i := 0; i < 20; i++ {
n1 := NewInt(int64(rand.Int31()))
d1 := NewInt(int64(rand.Int31()))
rat1 := NewRatFromInt(n1, d1)
n2 := NewInt(int64(rand.Int31()))
d2 := NewInt(int64(rand.Int31()))
rat2 := NewRatFromInt(n2, d2)
n1d2 := n1.Mul(d2)
n2d1 := n2.Mul(d1)
cases := []struct {
nres Int
dres Int
rres Rat
}{
{n1d2.Add(n2d1), d1.Mul(d2), rat1.Add(rat2)},
{n1d2.Sub(n2d1), d1.Mul(d2), rat1.Sub(rat2)},
{n1.Mul(n2), d1.Mul(d2), rat1.Mul(rat2)},
{n1d2, n2d1, rat1.Quo(rat2)},
}
for _, tc := range cases {
require.Equal(t, NewRatFromInt(tc.nres, tc.dres), tc.rres)
}
}
}
func TestCompRat(t *testing.T) {
for i := 0; i < 20; i++ {
n1 := NewInt(int64(rand.Int31()))
d1 := NewInt(int64(rand.Int31()))
rat1 := NewRatFromInt(n1, d1)
n2 := NewInt(int64(rand.Int31()))
d2 := NewInt(int64(rand.Int31()))
rat2 := NewRatFromInt(n2, d2)
n1d2 := n1.Mul(d2)
n2d1 := n2.Mul(d1)
cases := []struct {
ires bool
rres bool
}{
{n1d2.Equal(n2d1), rat1.Equal(rat2)},
{n1d2.GT(n2d1), rat1.GT(rat2)},
{n1d2.LT(n2d1), rat1.LT(rat2)},
{n1d2.GT(n2d1) || n1d2.Equal(n2d1), rat1.GTE(rat2)},
{n1d2.LT(n2d1) || n1d2.Equal(n2d1), rat1.LTE(rat2)},
}
for _, tc := range cases {
require.Equal(t, tc.ires, tc.rres)
}
}
}
func TestImmutabilityRat(t *testing.T) {
for i := 0; i < 20; i++ {
n := int64(rand.Int31())
r := NewRat(n)
z := ZeroRat()
o := OneRat()
r.Add(z)
r.Sub(z)
r.Mul(o)
r.Quo(o)
require.Equal(t, n, r.RoundInt64())
require.True(t, NewRat(n).Equal(r))
}
}

View File

@ -40,11 +40,11 @@ type Validator interface {
GetRevoked() bool // whether the validator is revoked
GetMoniker() string // moniker of the validator
GetStatus() BondStatus // status of the validator
GetOwner() AccAddress // owner AccAddress to receive/return validators coins
GetOperator() AccAddress // owner AccAddress to receive/return validators coins
GetPubKey() crypto.PubKey // validation pubkey
GetPower() Rat // validation power
GetTokens() Rat // validation tokens
GetDelegatorShares() Rat // Total out standing delegator shares
GetPower() Dec // validation power
GetTokens() Dec // validation tokens
GetDelegatorShares() Dec // Total out standing delegator shares
GetBondHeight() int64 // height in which the validator became active
}
@ -69,10 +69,10 @@ type ValidatorSet interface {
Validator(Context, AccAddress) Validator // get a particular validator by owner AccAddress
ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by signing PubKey
TotalPower(Context) Rat // total power of the validator set
TotalPower(Context) Dec // total power of the validator set
// slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction
Slash(Context, crypto.PubKey, int64, int64, Rat)
Slash(Context, crypto.PubKey, int64, int64, Dec)
Revoke(Context, crypto.PubKey) // revoke a validator
Unrevoke(Context, crypto.PubKey) // unrevoke a validator
}
@ -83,7 +83,7 @@ type ValidatorSet interface {
type Delegation interface {
GetDelegator() AccAddress // delegator AccAddress for the bond
GetValidator() AccAddress // validator owner AccAddress for the bond
GetBondShares() Rat // amount of validator's shares
GetBondShares() Dec // amount of validator's shares
}
// properties for the set of all delegations for a particular

View File

@ -23,13 +23,13 @@ package stake
////_________________________________________________________________________
//// cummulative power of the non-absent prevotes
//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Rat {
//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Dec {
//store := ctx.KVStore(k.storeKey)
//// get absent prevote indexes
//absents := ctx.AbsentValidators()
//TotalPower := sdk.ZeroRat()
//TotalPower := sdk.ZeroDec()
//i := int32(0)
//iterator := store.SubspaceIterator(ValidatorsBondedKey)
//for ; iterator.Valid(); iterator.Next() {

View File

@ -8,8 +8,8 @@ package stake
//var candidatesIn [5]Candidate
//for i, amt := range amts {
//candidatesIn[i] = NewCandidate(addrVals[i], pks[i], Description{})
//candidatesIn[i].BondedShares = sdk.NewRat(amt)
//candidatesIn[i].DelegatorShares = sdk.NewRat(amt)
//candidatesIn[i].BondedShares = sdk.NewDec(amt)
//candidatesIn[i].DelegatorShares = sdk.NewDec(amt)
//keeper.setCandidate(ctx, candidatesIn[i])
//}
@ -18,7 +18,7 @@ package stake
//require.Equal(t, 5, len(gotValidators))
//totPow := keeper.GetTotalPrecommitVotingPower(ctx)
//exp := sdk.NewRat(11111)
//exp := sdk.NewDec(11111)
//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow)
//// set absent gotValidators to be the 1st and 3rd record sorted by pubKey address
@ -26,6 +26,6 @@ package stake
//totPow = keeper.GetTotalPrecommitVotingPower(ctx)
//// XXX verify that this order should infact exclude these two records
//exp = sdk.NewRat(11100)
//exp = sdk.NewDec(11100)
//require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow)
//}

View File

@ -17,7 +17,7 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
//// calculate the proposer reward
//precommitPower := k.GetTotalPrecommitVotingPower(ctx)
//toProposer := coinsMulRat(collectedFees, (sdk.NewRat(1, 100).Add(sdk.NewRat(4, 100).Mul(precommitPower).Quo(pool.BondedShares))))
//toProposer := coinsMulRat(collectedFees, (sdk.NewDec(1, 100).Add(sdk.NewDec(4, 100).Mul(precommitPower).Quo(pool.BondedShares))))
//candidate.ProposerRewardPool = candidate.ProposerRewardPool.Plus(toProposer)
//toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee)
@ -34,10 +34,10 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
//k.setPool(ctx, pool)
//}
//func coinsMulRat(coins sdk.Coins, rat sdk.Rat) sdk.Coins {
//func coinsMulRat(coins sdk.Coins, rat sdk.Dec) sdk.Coins {
//var res sdk.Coins
//for _, coin := range coins {
//coinMulAmt := rat.Mul(sdk.NewRat(coin.Amount)).Evaluate()
//coinMulAmt := rat.Mul(sdk.NewDec(coin.Amount)).Evaluate()
//coinMul := sdk.Coins{{coin.Denom, coinMulAmt}}
//res = res.Plus(coinMul)
//}
@ -49,14 +49,14 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {}
//// calculate adjustment changes for a candidate at a height
//func CalculateAdjustmentChange(candidate Candidate, pool Pool, denoms []string, height int64) (Candidate, Pool) {
//heightRat := sdk.NewRat(height)
//lastHeightRat := sdk.NewRat(height - 1)
//heightRat := sdk.NewDec(height)
//lastHeightRat := sdk.NewDec(height - 1)
//candidateFeeCount := candidate.BondedShares.Mul(heightRat)
//poolFeeCount := pool.BondedShares.Mul(heightRat)
//for i, denom := range denoms {
//poolFeeSumReceived := sdk.NewRat(pool.FeeSumReceived.AmountOf(denom))
//poolFeeRecent := sdk.NewRat(pool.FeeRecent.AmountOf(denom))
//poolFeeSumReceived := sdk.NewDec(pool.FeeSumReceived.AmountOf(denom))
//poolFeeRecent := sdk.NewDec(pool.FeeRecent.AmountOf(denom))
//// calculate simple and projected pools
//simplePool := candidateFeeCount.Quo(poolFeeCount).Mul(poolFeeSumReceived)
//calc1 := candidate.PrevBondedShares.Mul(lastHeightRat).Quo(pool.PrevBondedShares.Mul(lastHeightRat)).Mul(poolFeeRecent)

View File

@ -23,8 +23,8 @@ package stake
//// fee information for a validator
//type Validator struct {
//Adjustments []sdk.Rat `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
//PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // total shares of a global hold pools
//Adjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // total shares of a global hold pools
//}
////_________________________________________________________________________
@ -32,7 +32,7 @@ package stake
//// Params defines the high level settings for staking
//type Params struct {
//FeeDenoms []string `json:"fee_denoms"` // accepted fee denoms
//ReservePoolFee sdk.Rat `json:"reserve_pool_fee"` // percent of fees which go to reserve pool
//ReservePoolFee sdk.Dec `json:"reserve_pool_fee"` // percent of fees which go to reserve pool
//}
//func (p Params) equal(p2 Params) bool {
@ -43,7 +43,7 @@ package stake
//func defaultParams() Params {
//return Params{
//FeeDenoms: []string{"steak"},
//ReservePoolFee: sdk.NewRat(5, 100),
//ReservePoolFee: sdk.NewDec(5, 100),
//}
//}
@ -55,8 +55,8 @@ package stake
//FeePool sdk.Coins `json:"fee_pool"` // XXX fee pool for all the fee shares which have already been distributed
//FeeSumReceived sdk.Coins `json:"fee_sum_received"` // XXX sum of all fees received, post reserve pool `json:"fee_sum_received"`
//FeeRecent sdk.Coins `json:"fee_recent"` // XXX most recent fee collected
//FeeAdjustments []sdk.Rat `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
//PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // XXX last recorded bonded shares
//FeeAdjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms
//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // XXX last recorded bonded shares
//}
//func (p Pool) equal(p2 Pool) bool {
@ -64,7 +64,7 @@ package stake
//p.FeePool.IsEqual(p2.FeePool) &&
//p.FeeSumReceived.IsEqual(p2.FeeSumReceived) &&
//p.FeeRecent.IsEqual(p2.FeeRecent) &&
//sdk.RatsEqual(p.FeeAdjustments, p2.FeeAdjustments) &&
//sdk.DecsEqual(p.FeeAdjustments, p2.FeeAdjustments) &&
//p.PrevBondedShares.Equal(p2.PrevBondedShares)
//}
@ -75,8 +75,8 @@ package stake
//FeePool: sdk.Coins(nil),
//FeeSumReceived: sdk.Coins(nil),
//FeeRecent: sdk.Coins(nil),
//FeeAdjustments: []sdk.Rat{sdk.ZeroRat()},
//PrevBondedShares: sdk.ZeroRat(),
//FeeAdjustments: []sdk.Dec{sdk.ZeroDec()},
//PrevBondedShares: sdk.ZeroDec(),
//}
//}
@ -85,8 +85,8 @@ package stake
//// Used in calculation of fee shares, added to a queue for each block where a power change occures
//type PowerChange struct {
//Height int64 `json:"height"` // block height at change
//Power sdk.Rat `json:"power"` // total power at change
//PrevPower sdk.Rat `json:"prev_power"` // total power at previous height-1
//Power sdk.Dec `json:"power"` // total power at change
//PrevPower sdk.Dec `json:"prev_power"` // total power at previous height-1
//FeesIn sdk.Coins `json:"fees_in"` // fees in at block height
//PrevFeePool sdk.Coins `json:"prev_fee_pool"` // total fees in at previous block height
//}

View File

@ -33,9 +33,9 @@ func DefaultGenesisState() GenesisState {
VotingPeriod: 200,
},
TallyingProcedure: TallyingProcedure{
Threshold: sdk.NewRat(1, 2),
Veto: sdk.NewRat(1, 3),
GovernancePenalty: sdk.NewRat(1, 100),
Threshold: sdk.NewDecWithPrec(5, 1),
Veto: sdk.NewDecWithPrec(334, 3),
GovernancePenalty: sdk.NewDecWithPrec(1, 2),
},
}
}

View File

@ -155,7 +155,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
keeper.GetTallyingProcedure(ctx).GovernancePenalty)
logger.Info(fmt.Sprintf("Validator %s failed to vote on proposal %d, slashing",
val.GetOwner(), activeProposal.GetProposalID()))
val.GetOperator(), activeProposal.GetProposalID()))
}
resTags.AppendTag(tags.Action, action)

View File

@ -12,9 +12,9 @@ type DepositProcedure struct {
// Procedure around Tallying votes in governance
type TallyingProcedure struct {
Threshold sdk.Rat `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Rat `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Rat `json:"governance_penalty"` // Penalty if validator does not vote
Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Dec `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Dec `json:"governance_penalty"` // Penalty if validator does not vote
}
// Procedure around Voting in governance

View File

@ -297,19 +297,19 @@ func (status ProposalStatus) Format(s fmt.State, verb rune) {
//-----------------------------------------------------------
// Tally Results
type TallyResult struct {
Yes sdk.Rat `json:"yes"`
Abstain sdk.Rat `json:"abstain"`
No sdk.Rat `json:"no"`
NoWithVeto sdk.Rat `json:"no_with_veto"`
Yes sdk.Dec `json:"yes"`
Abstain sdk.Dec `json:"abstain"`
No sdk.Dec `json:"no"`
NoWithVeto sdk.Dec `json:"no_with_veto"`
}
// checks if two proposals are equal
func EmptyTallyResult() TallyResult {
return TallyResult{
Yes: sdk.ZeroRat(),
Abstain: sdk.ZeroRat(),
No: sdk.ZeroRat(),
NoWithVeto: sdk.ZeroRat(),
Yes: sdk.ZeroDec(),
Abstain: sdk.ZeroDec(),
No: sdk.ZeroDec(),
NoWithVeto: sdk.ZeroDec(),
}
}

View File

@ -7,28 +7,28 @@ import (
// validatorGovInfo used for tallying
type validatorGovInfo struct {
Address sdk.AccAddress // sdk.AccAddress of the validator owner
Power sdk.Rat // Power of a Validator
DelegatorShares sdk.Rat // Total outstanding delegator shares
Minus sdk.Rat // Minus of validator, used to compute validator's voting power
Power sdk.Dec // Power of a Validator
DelegatorShares sdk.Dec // Total outstanding delegator shares
Minus sdk.Dec // Minus of validator, used to compute validator's voting power
Vote VoteOption // Vote of the validator
}
func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.AccAddress) {
results := make(map[VoteOption]sdk.Rat)
results[OptionYes] = sdk.ZeroRat()
results[OptionAbstain] = sdk.ZeroRat()
results[OptionNo] = sdk.ZeroRat()
results[OptionNoWithVeto] = sdk.ZeroRat()
results := make(map[VoteOption]sdk.Dec)
results[OptionYes] = sdk.ZeroDec()
results[OptionAbstain] = sdk.ZeroDec()
results[OptionNo] = sdk.ZeroDec()
results[OptionNoWithVeto] = sdk.ZeroDec()
totalVotingPower := sdk.ZeroRat()
totalVotingPower := sdk.ZeroDec()
currValidators := make(map[string]validatorGovInfo)
keeper.vs.IterateValidatorsBonded(ctx, func(index int64, validator sdk.Validator) (stop bool) {
currValidators[validator.GetOwner().String()] = validatorGovInfo{
Address: validator.GetOwner(),
currValidators[validator.GetOperator().String()] = validatorGovInfo{
Address: validator.GetOperator(),
Power: validator.GetPower(),
DelegatorShares: validator.GetDelegatorShares(),
Minus: sdk.ZeroRat(),
Minus: sdk.ZeroDec(),
Vote: OptionEmpty,
}
return false
@ -91,7 +91,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
}
// If no one votes, proposal fails
if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroRat()) {
if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroDec()) {
return false, tallyResults, nonVoting
}
// If more than 1/3 of voters veto, proposal fails

View File

@ -64,7 +64,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk
mapp.InitChainer(ctx, req)
stakeGenesis := stake.DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
validators, err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis)
if err != nil {

View File

@ -183,8 +183,8 @@ func (k Getter) GetUint(ctx sdk.Context, key string) (res sdk.Uint, err error) {
return
}
// GetRat is helper function for rat params
func (k Getter) GetRat(ctx sdk.Context, key string) (res sdk.Rat, err error) {
// GetDec is helper function for decimal params
func (k Getter) GetDec(ctx sdk.Context, key string) (res sdk.Dec, err error) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
err = k.k.cdc.UnmarshalBinary(bz, &res)
@ -301,8 +301,8 @@ func (k Getter) GetUintWithDefault(ctx sdk.Context, key string, def sdk.Uint) (r
return
}
// GetRatWithDefault is helper function for sdk.Rat params with default value
func (k Getter) GetRatWithDefault(ctx sdk.Context, key string, def sdk.Rat) (res sdk.Rat) {
// GetDecWithDefault is helper function for sdk.Dec params with default value
func (k Getter) GetDecWithDefault(ctx sdk.Context, key string, def sdk.Dec) (res sdk.Dec) {
store := ctx.KVStore(k.k.key)
bz := store.Get([]byte(key))
if bz == nil {
@ -397,8 +397,8 @@ func (k Setter) SetUint(ctx sdk.Context, key string, param sdk.Uint) {
}
}
// SetRat is helper function for rat params
func (k Setter) SetRat(ctx sdk.Context, key string, param sdk.Rat) {
// SetDec is helper function for decimal params
func (k Setter) SetDec(ctx sdk.Context, key string, param sdk.Dec) {
if err := k.k.set(ctx, key, param); err != nil {
panic(err)
}

View File

@ -94,7 +94,7 @@ func TestGetter(t *testing.T) {
{"uint64", uint64(1)},
{"int", sdk.NewInt(1)},
{"uint", sdk.NewUint(1)},
{"rat", sdk.NewRat(1)},
{"rat", sdk.NewDec(1)},
}
assert.NotPanics(t, func() { s.SetString(ctx, kvs[0].key, "test") })
@ -107,7 +107,7 @@ func TestGetter(t *testing.T) {
assert.NotPanics(t, func() { s.SetUint64(ctx, kvs[7].key, uint64(1)) })
assert.NotPanics(t, func() { s.SetInt(ctx, kvs[8].key, sdk.NewInt(1)) })
assert.NotPanics(t, func() { s.SetUint(ctx, kvs[9].key, sdk.NewUint(1)) })
assert.NotPanics(t, func() { s.SetRat(ctx, kvs[10].key, sdk.NewRat(1)) })
assert.NotPanics(t, func() { s.SetDec(ctx, kvs[10].key, sdk.NewDec(1)) })
var res interface{}
var err error
@ -263,18 +263,18 @@ func TestGetter(t *testing.T) {
assert.Equal(t, def9, res)
// Rat
def10 := sdk.NewRat(0)
res, err = g.GetRat(ctx, kvs[10].key)
def10 := sdk.NewDec(0)
res, err = g.GetDec(ctx, kvs[10].key)
assert.Nil(t, err)
assert.Equal(t, kvs[10].param, res)
_, err = g.GetRat(ctx, "invalid")
_, err = g.GetDec(ctx, "invalid")
assert.NotNil(t, err)
res = g.GetRatWithDefault(ctx, kvs[10].key, def10)
res = g.GetDecWithDefault(ctx, kvs[10].key, def10)
assert.Equal(t, kvs[10].param, res)
res = g.GetRatWithDefault(ctx, "invalid", def10)
res = g.GetDecWithDefault(ctx, "invalid", def10)
assert.Equal(t, def10, res)
}

View File

@ -58,7 +58,7 @@ func getInitChainer(mapp *mock.App, keeper stake.Keeper) sdk.InitChainer {
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
mapp.InitChainer(ctx, req)
stakeGenesis := stake.DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
validators, err := stake.InitGenesis(ctx, keeper, stakeGenesis)
if err != nil {
panic(err)
@ -107,9 +107,9 @@ func TestSlashingMsgs(t *testing.T) {
mapp.BeginBlock(abci.RequestBeginBlock{})
validator := checkValidator(t, mapp, stakeKeeper, addr1, true)
require.Equal(t, addr1, validator.Owner)
require.Equal(t, addr1, validator.Operator)
require.Equal(t, sdk.Bonded, validator.Status)
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens()))
require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
unrevokeMsg := MsgUnrevoke{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())}
// no signing info yet

View File

@ -2,5 +2,5 @@ package cli
// nolint
const (
FlagAddressValidator = "address-validator"
FlagAddressValidator = "validator"
)

View File

@ -20,7 +20,7 @@ func TestCannotUnrevokeUnlessRevoked(t *testing.T) {
require.True(t, got.IsOK())
stake.EndBlocker(ctx, sk)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
// assert non-revoked validator can't be unrevoked
got = slh(ctx, NewMsgUnrevoke(addr))

View File

@ -31,7 +31,7 @@ func TestHandleDoubleSign(t *testing.T) {
validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
// handle a signature to set signing info
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
@ -44,12 +44,12 @@ func TestHandleDoubleSign(t *testing.T) {
// unrevoke to measure power
sk.Unrevoke(ctx, val)
// power should be reduced
require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower())
require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower())
ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))})
// double sign past max age
keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt)
require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower())
require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower())
}
// Test a validator through uptime, downtime, revocation,
@ -67,7 +67,7 @@ func TestHandleAbsentValidator(t *testing.T) {
validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address()))
require.False(t, found)
require.Equal(t, int64(0), info.StartHeight)
@ -131,7 +131,7 @@ func TestHandleAbsentValidator(t *testing.T) {
// validator should have been slashed
pool = sk.GetPool(ctx)
slashAmt := sdk.NewRat(amtInt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64()
slashAmt := sdk.NewDec(amtInt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64()
require.Equal(t, int64(amtInt)-slashAmt, pool.BondedTokens.RoundInt64())
// validator start height should have been changed
@ -177,7 +177,7 @@ func TestHandleNewValidator(t *testing.T) {
validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}})
require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower())
require.Equal(t, sdk.NewDec(amt), sk.Validator(ctx, addr).GetPower())
// 1000 first blocks not a validator
ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1)

View File

@ -30,9 +30,9 @@ func (k Keeper) SignedBlocksWindow(ctx sdk.Context) int64 {
// Downtime slashing thershold - default 50%
func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 {
minSignedPerWindow := k.params.GetRatWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow)
minSignedPerWindow := k.params.GetDecWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow)
signedBlocksWindow := k.SignedBlocksWindow(ctx)
return sdk.NewRat(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
return sdk.NewDec(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64()
}
// Double-sign unbond duration
@ -46,13 +46,13 @@ func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) time.Duration {
}
// SlashFractionDoubleSign - currently default 5%
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Rat {
return k.params.GetRatWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Dec {
return k.params.GetDecWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign)
}
// SlashFractionDowntime - currently default 1%
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Rat {
return k.params.GetRatWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Dec {
return k.params.GetDecWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime)
}
// declared as var because of keeper_test.go
@ -72,9 +72,9 @@ var (
// TODO Temporarily set to 10 minutes for testnets
defaultDowntimeUnbondDuration int64 = 60 * 10
defaultMinSignedPerWindow = sdk.NewRat(1, 2)
defaultMinSignedPerWindow = sdk.NewDecWithPrec(5, 1)
defaultSlashFractionDoubleSign = sdk.NewRat(1).Quo(sdk.NewRat(20))
defaultSlashFractionDoubleSign = sdk.NewDec(1).Quo(sdk.NewDec(20))
defaultSlashFractionDowntime = sdk.NewRat(1).Quo(sdk.NewRat(100))
defaultSlashFractionDowntime = sdk.NewDec(1).Quo(sdk.NewDec(100))
)

View File

@ -69,7 +69,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
genesis := stake.DefaultGenesisState()
genesis.Pool.LooseTokens = sdk.NewRat(initCoins.MulRaw(int64(len(addrs))).Int64())
genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64())
_, err = stake.InitGenesis(ctx, sk, genesis)
require.Nil(t, err)

View File

@ -22,7 +22,7 @@ func TestBeginBlocker(t *testing.T) {
validatorUpdates := stake.EndBlocker(ctx, sk)
keeper.AddValidators(ctx, validatorUpdates)
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}})
require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
val := abci.Validator{
Address: pk.Address(),

View File

@ -63,7 +63,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer {
mapp.InitChainer(ctx, req)
stakeGenesis := DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000)
validators, err := InitGenesis(ctx, keeper, stakeGenesis)
if err != nil {
@ -90,14 +90,14 @@ func checkValidator(t *testing.T, mapp *mock.App, keeper Keeper,
func checkDelegation(
t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr,
validatorAddr sdk.AccAddress, expFound bool, expShares sdk.Rat,
validatorAddr sdk.AccAddress, expFound bool, expShares sdk.Dec,
) {
ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
delegation, found := keeper.GetDelegation(ctxCheck, delegatorAddr, validatorAddr)
if expFound {
require.True(t, found)
require.True(sdk.RatEq(t, expShares, delegation.Shares))
require.True(sdk.DecEq(t, expShares, delegation.Shares))
return
}
@ -136,9 +136,9 @@ func TestStakeMsgs(t *testing.T) {
mApp.BeginBlock(abci.RequestBeginBlock{})
validator := checkValidator(t, mApp, keeper, addr1, true)
require.Equal(t, addr1, validator.Owner)
require.Equal(t, addr1, validator.Operator)
require.Equal(t, sdk.Bonded, validator.Status)
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens()))
require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
// addr1 create validator on behalf of addr2
createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(addr1, addr2, priv2.PubKey(), bondCoin, description)
@ -148,12 +148,12 @@ func TestStakeMsgs(t *testing.T) {
mApp.BeginBlock(abci.RequestBeginBlock{})
validator = checkValidator(t, mApp, keeper, addr2, true)
require.Equal(t, addr2, validator.Owner)
require.Equal(t, addr2, validator.Operator)
require.Equal(t, sdk.Bonded, validator.Status)
require.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
require.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
// check the bond that should have been created as well
checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewRat(10))
checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewDec(10))
// edit the validator
description = NewDescription("bar_moniker", "", "", "")
@ -169,14 +169,14 @@ func TestStakeMsgs(t *testing.T) {
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{1}, true, priv2)
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewRat(10))
checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewDec(10))
// begin unbonding
beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewRat(10))
beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewDec(10))
mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []int64{1}, []int64{2}, true, priv2)
// delegation should exist anymore
checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Rat{})
checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Dec{})
// balance should be the same because bonding not yet complete
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})

View File

@ -9,7 +9,7 @@ import (
// nolint
const (
FlagAddressDelegator = "address-delegator"
FlagAddressValidator = "address-validator"
FlagAddressValidator = "validator"
FlagAddressValidatorSrc = "addr-validator-source"
FlagAddressValidatorDst = "addr-validator-dest"
FlagPubKey = "pubkey"

View File

@ -139,7 +139,10 @@ func GetCmdQueryDelegation(storeName string, cdc *wire.Codec) *cobra.Command {
}
// parse out the delegation
delegation := types.MustUnmarshalDelegation(cdc, key, res)
delegation, err := types.UnmarshalDelegation(cdc, key, res)
if err != nil {
return err
}
switch viper.Get(cli.OutputFlag) {
case "text":

View File

@ -239,27 +239,27 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command {
func getShares(
storeName string, cdc *wire.Codec, sharesAmountStr,
sharesPercentStr string, delegatorAddr, validatorAddr sdk.AccAddress,
) (sharesAmount sdk.Rat, err error) {
) (sharesAmount sdk.Dec, err error) {
switch {
case sharesAmountStr != "" && sharesPercentStr != "":
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
case sharesAmountStr == "" && sharesPercentStr == "":
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
case sharesAmountStr != "":
sharesAmount, err = sdk.NewRatFromDecimal(sharesAmountStr, types.MaxBondDenominatorPrecision)
sharesAmount, err = sdk.NewDecFromStr(sharesAmountStr)
if err != nil {
return sharesAmount, err
}
if !sharesAmount.GT(sdk.ZeroRat()) {
if !sharesAmount.GT(sdk.ZeroDec()) {
return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)")
}
case sharesPercentStr != "":
var sharesPercent sdk.Rat
sharesPercent, err = sdk.NewRatFromDecimal(sharesPercentStr, types.MaxBondDenominatorPrecision)
var sharesPercent sdk.Dec
sharesPercent, err = sdk.NewDecFromStr(sharesPercentStr)
if err != nil {
return sharesAmount, err
}
if !sharesPercent.GT(sdk.ZeroRat()) || !sharesPercent.LTE(sdk.OneRat()) {
if !sharesPercent.GT(sdk.ZeroDec()) || !sharesPercent.LTE(sdk.OneDec()) {
return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)")
}
@ -273,11 +273,12 @@ func getShares(
if err != nil {
return sharesAmount, errors.Errorf("cannot find delegation to determine percent Error: %v", err)
}
delegation := types.MustUnmarshalDelegation(cdc, key, resQuery)
delegation, err := types.UnmarshalDelegation(cdc, key, resQuery)
if err != nil {
return sdk.ZeroDec(), err
}
sharesAmount = sharesPercent.Mul(delegation.Shares)
}
return
}

View File

@ -20,41 +20,54 @@ const storeName = "stake"
func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *wire.Codec) {
// GET /stake/delegators/{delegatorAddr} // Get all delegations (delegation, undelegation and redelegation) from a delegator
// Get all delegations (delegation, undelegation and redelegation) from a delegator
r.HandleFunc(
"/stake/delegators/{delegatorAddr}",
delegatorHandlerFn(cliCtx, cdc),
).Methods("GET")
// GET /stake/delegators/{delegatorAddr}/txs?type=<bond/unbond/redelegate> // Get all staking txs (i.e msgs) from a delegator
// Get all staking txs (i.e msgs) from a delegator
r.HandleFunc(
"/stake/delegators/{delegatorAddr}/txs",
delegatorTxsHandlerFn(cliCtx, cdc),
).Methods("GET")
// GET /stake/delegators/{delegatorAddr}/delegations/{validatorAddr} // Query a delegation between a delegator and a validator
// Query all validators that a delegator is bonded to
r.HandleFunc(
"/stake/delegators/{delegatorAddr}/validators",
delegatorValidatorsHandlerFn(cliCtx, cdc),
).Methods("GET")
// Query a validator that a delegator is bonded to
r.HandleFunc(
"/stake/delegators/{delegatorAddr}/validators/{validatorAddr}",
delegatorValidatorHandlerFn(cliCtx, cdc),
).Methods("GET")
// Query a delegation between a delegator and a validator
r.HandleFunc(
"/stake/delegators/{delegatorAddr}/delegations/{validatorAddr}",
delegationHandlerFn(cliCtx, cdc),
).Methods("GET")
// GET /stake/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr} // Query all unbonding_delegations between a delegator and a validator
// Query all unbonding_delegations between a delegator and a validator
r.HandleFunc(
"/stake/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr}",
unbondingDelegationsHandlerFn(cliCtx, cdc),
).Methods("GET")
// GET /stake/validators/
// Get all validators
r.HandleFunc(
"/stake/validators",
validatorsHandlerFn(cliCtx, cdc),
).Methods("GET")
// GET /stake/validators/{addr}
// Get a single validator info
r.HandleFunc(
"/stake/validators/{addr}",
validatorHandlerFn(cliCtx, cdc),
).Methods("GET")
}
// already resolve the rational shares to not handle this in the client
@ -101,7 +114,7 @@ func delegatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler
}
for _, validator := range validators {
validatorAddr = validator.Owner
validatorAddr = validator.Operator
// Delegations
delegations, statusCode, errMsg, err := getDelegatorDelegations(cliCtx, cdc, delegatorAddr, validatorAddr)
@ -334,7 +347,7 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handle
DelegatorAddr: delegation.DelegatorAddr,
ValidatorAddr: delegation.ValidatorAddr,
Height: delegation.Height,
Shares: delegation.Shares.FloatString(),
Shares: delegation.Shares.String(),
}
output, err := cdc.MarshalJSON(outputDelegation)
@ -387,7 +400,7 @@ func delegatorValidatorsHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) ht
for _, validator := range validators {
// get all transactions from the delegator to val and append
validatorAccAddr = validator.Owner
validatorAccAddr = validator.Operator
validator, statusCode, errMsg, errRes := getDelegatorValidator(cliCtx, cdc, delegatorAddr, validatorAccAddr)
if errRes != nil {
@ -494,25 +507,40 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler
valAddress, err := sdk.AccAddressFromBech32(bech32validatorAddr)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Error: %s", err.Error())))
w.Write([]byte(fmt.Sprintf("error: %s", err.Error())))
return
}
kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName)
key := stake.GetValidatorKey(valAddress)
res, err := cliCtx.QueryStore(key, storeName)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Error: %s", err.Error())))
w.Write([]byte(fmt.Sprintf("couldn't query validator, error: %s", err.Error())))
return
}
validator, err := getValidator(valAddress, kvs, cdc)
// the query will return empty if there is no data for this record
if len(res) == 0 {
w.WriteHeader(http.StatusNoContent)
return
}
validator, err := types.UnmarshalValidator(cdc, valAddress, res)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("couldn't query validator. Error: %s", err.Error())))
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
output, err = cdc.MarshalJSON(validator)
bech32Validator, err := validator.Bech32Validator()
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
output, err = cdc.MarshalJSON(bech32Validator)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Error: %s", err.Error())))

View File

@ -12,7 +12,6 @@ import (
"github.com/cosmos/cosmos-sdk/wire"
authcliCtx "github.com/cosmos/cosmos-sdk/x/auth/client/context"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/gorilla/mux"
@ -160,7 +159,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
return
}
shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision)
shares, err := sdk.NewDecFromStr(msg.SharesAmount)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())))
@ -234,7 +233,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
return
}
shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision)
shares, err := sdk.NewDecFromStr(msg.SharesAmount)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error())))

View File

@ -1,7 +1,6 @@
package rest
import (
"bytes"
"fmt"
"net/http"
@ -12,7 +11,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/cosmos-sdk/x/stake/tags"
"github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/pkg/errors"
rpcclient "github.com/tendermint/tendermint/rpc/client"
)
@ -26,35 +24,36 @@ func contains(stringSlice []string, txType string) bool {
return false
}
func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAccAddr sdk.AccAddress) (
validator types.BechValidator, httpStatusCode int, errMsg string, err error) {
func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) (
bech32Validator types.BechValidator, httpStatusCode int, errMsg string, err error) {
// check if the delegator is bonded or redelegated to the validator
keyDel := stake.GetDelegationKey(delegatorAddr, validatorAccAddr)
res, err := cliCtx.QueryStore(keyDel, storeName)
key := stake.GetDelegationKey(delegatorAddr, validatorAddr)
res, err := cliCtx.QueryStore(key, storeName)
if err != nil {
return types.BechValidator{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err
}
if len(res) == 0 {
return types.BechValidator{}, http.StatusNoContent, "", nil
}
kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName)
key = stake.GetValidatorKey(validatorAddr)
res, err = cliCtx.QueryStore(key, storeName)
if err != nil {
return types.BechValidator{}, http.StatusInternalServerError, "Error: ", err
return types.BechValidator{}, http.StatusInternalServerError, "couldn't query validator. Error: ", err
}
if len(kvs) == 0 {
// the query will return empty if there are no delegations
if len(res) == 0 {
return types.BechValidator{}, http.StatusNoContent, "", nil
}
validator, errVal := getValidatorFromAccAdrr(validatorAccAddr, kvs, cdc)
if errVal != nil {
return types.BechValidator{}, http.StatusInternalServerError, "Couldn't get info from validator. Error: ", errVal
validator, err := types.UnmarshalValidator(cdc, validatorAddr, res)
if err != nil {
return types.BechValidator{}, http.StatusBadRequest, "", err
}
return validator, http.StatusOK, "", nil
bech32Validator, err = validator.Bech32Validator()
if err != nil {
return types.BechValidator{}, http.StatusBadRequest, "", err
}
return bech32Validator, http.StatusOK, "", nil
}
func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) (
@ -65,7 +64,6 @@ func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegat
return DelegationWithoutRat{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err
}
// the query will return empty if there is no data for this record
if len(marshalledDelegation) == 0 {
return DelegationWithoutRat{}, http.StatusNoContent, "", nil
}
@ -79,7 +77,7 @@ func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegat
DelegatorAddr: delegation.DelegatorAddr,
ValidatorAddr: delegation.ValidatorAddr,
Height: delegation.Height,
Shares: delegation.Shares.FloatString(),
Shares: delegation.Shares.String(),
}
return outputDelegation, http.StatusOK, "", nil
@ -93,7 +91,6 @@ func getDelegatorUndelegations(cliCtx context.CLIContext, cdc *wire.Codec, deleg
return types.UnbondingDelegation{}, http.StatusInternalServerError, "couldn't query unbonding-delegation. Error: ", err
}
// the query will return empty if there is no data for this record
if len(marshalledUnbondingDelegation) == 0 {
return types.UnbondingDelegation{}, http.StatusNoContent, "", nil
}
@ -108,8 +105,8 @@ func getDelegatorUndelegations(cliCtx context.CLIContext, cdc *wire.Codec, deleg
func getDelegatorRedelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) (
regelegations types.Redelegation, httpStatusCode int, errMsg string, err error) {
keyRedelegateTo := stake.GetREDsByDelToValDstIndexKey(delegatorAddr, validatorAddr)
marshalledRedelegations, err := cliCtx.QueryStore(keyRedelegateTo, storeName)
key := stake.GetREDsByDelToValDstIndexKey(delegatorAddr, validatorAddr)
marshalledRedelegations, err := cliCtx.QueryStore(key, storeName)
if err != nil {
return types.Redelegation{}, http.StatusInternalServerError, "couldn't query redelegation. Error: ", err
}
@ -118,7 +115,7 @@ func getDelegatorRedelegations(cliCtx context.CLIContext, cdc *wire.Codec, deleg
return types.Redelegation{}, http.StatusNoContent, "", nil
}
redelegations, err := types.UnmarshalRED(cdc, keyRedelegateTo, marshalledRedelegations)
redelegations, err := types.UnmarshalRED(cdc, key, marshalledRedelegations)
if err != nil {
return types.Redelegation{}, http.StatusInternalServerError, "couldn't unmarshall redelegations. Error: ", err
}
@ -160,55 +157,10 @@ func getValidators(validatorKVs []sdk.KVPair, cdc *wire.Codec) ([]types.BechVali
return validators, nil
}
// gets a validator given a ValAddress
func getValidator(address sdk.AccAddress, validatorKVs []sdk.KVPair, cdc *wire.Codec) (stake.BechValidator, error) {
// parse out the validators
for _, kv := range validatorKVs {
addr := kv.Key[1:]
validator, err := types.UnmarshalValidator(cdc, addr, kv.Value)
if err != nil {
return stake.BechValidator{}, err
}
ownerAddress := validator.PubKey.Address()
if bytes.Equal(ownerAddress.Bytes(), address.Bytes()) {
bech32Validator, err := validator.Bech32Validator()
if err != nil {
return stake.BechValidator{}, err
}
return bech32Validator, nil
}
}
return stake.BechValidator{}, errors.Errorf("Couldn't find validator")
}
// gets a validator given an AccAddress
func getValidatorFromAccAdrr(address sdk.AccAddress, validatorKVs []sdk.KVPair, cdc *wire.Codec) (stake.BechValidator, error) {
// parse out the validators
for _, kv := range validatorKVs {
addr := kv.Key[1:]
validator, err := types.UnmarshalValidator(cdc, addr, kv.Value)
if err != nil {
return stake.BechValidator{}, err
}
ownerAddress := validator.PubKey.Address()
if bytes.Equal(ownerAddress.Bytes(), address.Bytes()) {
bech32Validator, err := validator.Bech32Validator()
if err != nil {
return stake.BechValidator{}, err
}
return bech32Validator, nil
}
}
return stake.BechValidator{}, errors.Errorf("Couldn't find validator")
}
// gets all Bech32 validators from a key
func getBech32Validators(storeName string, cliCtx context.CLIContext, cdc *wire.Codec) (
validators []types.BechValidator, httpStatusCode int, errMsg string, err error) {
// Get all validators using key
kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName)
if err != nil {

View File

@ -17,7 +17,7 @@ func TestInitGenesis(t *testing.T) {
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
pool := keeper.GetPool(ctx)
pool.BondedTokens = sdk.NewRat(2)
pool.BondedTokens = sdk.NewDec(2)
params := keeper.GetParams(ctx)
var delegations []Delegation
@ -32,11 +32,11 @@ func TestInitGenesis(t *testing.T) {
// initialize the validators
validators[0].Status = sdk.Bonded
validators[0].Tokens = sdk.OneRat()
validators[0].DelegatorShares = sdk.OneRat()
validators[0].Tokens = sdk.OneDec()
validators[0].DelegatorShares = sdk.OneDec()
validators[1].Status = sdk.Bonded
validators[1].Tokens = sdk.OneRat()
validators[1].DelegatorShares = sdk.OneRat()
validators[1].Tokens = sdk.OneDec()
validators[1].DelegatorShares = sdk.OneDec()
genesisState = types.NewGenesisState(pool, params, validators, delegations)
vals, err := InitGenesis(ctx, keeper, genesisState)
@ -69,7 +69,7 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) {
// Assigning 2 to the first 100 vals, 1 to the rest
pool := keeper.GetPool(ctx)
pool.BondedTokens = sdk.NewRat(int64(200 + (size - 100)))
pool.BondedTokens = sdk.NewDec(int64(200 + (size - 100)))
params := keeper.GetParams(ctx)
delegations := []Delegation{}
@ -80,11 +80,11 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) {
validators[i].Status = sdk.Bonded
if i < 100 {
validators[i].Tokens = sdk.NewRat(2)
validators[i].DelegatorShares = sdk.NewRat(2)
validators[i].Tokens = sdk.NewDec(2)
validators[i].DelegatorShares = sdk.NewDec(2)
} else {
validators[i].Tokens = sdk.OneRat()
validators[i].DelegatorShares = sdk.OneRat()
validators[i].Tokens = sdk.OneDec()
validators[i].DelegatorShares = sdk.OneDec()
}
}

View File

@ -81,7 +81,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
// slash and revoke the first validator
keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewRat(1, 2))
keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewDecWithPrec(5, 1))
keeper.Revoke(ctx, keep.PKs[0])
validator, found = keeper.GetValidator(ctx, validatorAddr)
require.True(t, found)
@ -110,7 +110,7 @@ func TestValidatorByPowerIndex(t *testing.T) {
require.Equal(t, power2, power3)
// unbond self-delegation
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(1000000))
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(1000000))
msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg to be ok, got %v", got)
@ -136,13 +136,13 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
require.True(t, found)
assert.Equal(t, sdk.Bonded, validator.Status)
assert.Equal(t, addr1, validator.Owner)
assert.Equal(t, addr1, validator.Operator)
assert.Equal(t, pk1, validator.PubKey)
assert.Equal(t, sdk.NewRat(10), validator.BondedTokens())
assert.Equal(t, sdk.NewRat(10), validator.DelegatorShares)
assert.Equal(t, sdk.NewDec(10), validator.BondedTokens())
assert.Equal(t, sdk.NewDec(10), validator.DelegatorShares)
assert.Equal(t, Description{}, validator.Description)
// two validators can't have the same owner address
// two validators can't have the same operator address
msgCreateValidator2 := newTestMsgCreateValidator(addr1, pk2, 10)
got = handleMsgCreateValidator(ctx, msgCreateValidator2, keeper)
require.False(t, got.IsOK(), "%v", got)
@ -152,7 +152,7 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
got = handleMsgCreateValidator(ctx, msgCreateValidator3, keeper)
require.False(t, got.IsOK(), "%v", got)
// must have different pubkey and owner
// must have different pubkey and operator
msgCreateValidator4 := newTestMsgCreateValidator(addr2, pk2, 10)
got = handleMsgCreateValidator(ctx, msgCreateValidator4, keeper)
require.True(t, got.IsOK(), "%v", got)
@ -160,10 +160,10 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
require.True(t, found)
assert.Equal(t, sdk.Bonded, validator.Status)
assert.Equal(t, addr2, validator.Owner)
assert.Equal(t, addr2, validator.Operator)
assert.Equal(t, pk2, validator.PubKey)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
assert.Equal(t, Description{}, validator.Description)
}
@ -180,10 +180,10 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) {
require.True(t, found)
assert.Equal(t, sdk.Bonded, validator.Status)
assert.Equal(t, validatorAddr, validator.Owner)
assert.Equal(t, validatorAddr, validator.Operator)
assert.Equal(t, pk, validator.PubKey)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
assert.Equal(t, Description{}, validator.Description)
// one validator cannot be created twice even from different delegator
@ -221,7 +221,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
pool := keeper.GetPool(ctx)
exRate := validator.DelegatorShareExRate()
require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v", exRate)
require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v", exRate)
require.Equal(t, bondAmount, pool.BondedTokens.RoundInt64())
// just send the same msgbond multiple times
@ -240,7 +240,7 @@ func TestIncrementsMsgDelegate(t *testing.T) {
require.True(t, found)
exRate := validator.DelegatorShareExRate()
require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v, i = %v", exRate, i)
require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v, i = %v", exRate, i)
expBond := int64(i+1) * bondAmount
expDelegatorShares := int64(i+2) * bondAmount // (1 self delegation)
@ -295,7 +295,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
// just send the same msgUnbond multiple times
// TODO use decimals here
unbondShares := sdk.NewRat(10)
unbondShares := sdk.NewDec(10)
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
numUnbonds := 5
@ -339,7 +339,7 @@ func TestIncrementsMsgUnbond(t *testing.T) {
initBond,
}
for _, c := range errorCases {
unbondShares := sdk.NewRat(int64(c))
unbondShares := sdk.NewDec(int64(c))
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.False(t, got.IsOK(), "expected unbond msg to fail")
@ -348,14 +348,14 @@ func TestIncrementsMsgUnbond(t *testing.T) {
leftBonded := initBond - int64(numUnbonds)*unbondShares.RoundInt64()
// should be unable to unbond one more than we have
unbondShares = sdk.NewRat(leftBonded + 1)
unbondShares = sdk.NewDec(leftBonded + 1)
msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.False(t, got.IsOK(),
"got: %v\nmsgUnbond: %v\nshares: %v\nleftBonded: %v\n", got, msgBeginUnbonding, unbondShares.String(), leftBonded)
// should be able to unbond just what we have
unbondShares = sdk.NewRat(leftBonded)
unbondShares = sdk.NewDec(leftBonded)
msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(),
@ -391,7 +391,7 @@ func TestMultipleMsgCreateValidator(t *testing.T) {
for i, validatorAddr := range validatorAddrs {
_, found := keeper.GetValidator(ctx, validatorAddr)
require.True(t, found)
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddrs[i], validatorAddr, sdk.NewRat(10)) // remove delegation
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddrs[i], validatorAddr, sdk.NewDec(10)) // remove delegation
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddrs[i], validatorAddr)
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
@ -436,7 +436,7 @@ func TestMultipleMsgDelegate(t *testing.T) {
// unbond them all
for i, delegatorAddr := range delegatorAddrs {
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewRat(10))
msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10))
msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
@ -467,7 +467,7 @@ func TestRevokeValidator(t *testing.T) {
validator, _ := keeper.GetValidator(ctx, validatorAddr)
// unbond the validators bond portion
msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10))
msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10))
msgCompleteUnbondingValidator := NewMsgCompleteUnbonding(validatorAddr, validatorAddr)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper)
require.True(t, got.IsOK(), "expected no error")
@ -483,7 +483,7 @@ func TestRevokeValidator(t *testing.T) {
require.False(t, got.IsOK(), "expected error, got %v", got)
// test that the delegator can still withdraw their bonds
msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewRat(10))
msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10))
msgCompleteUnbondingDelegator := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr)
got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingDelegator, keeper)
require.True(t, got.IsOK(), "expected no error")
@ -510,7 +510,7 @@ func TestUnbondingPeriod(t *testing.T) {
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
// begin unbonding
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10))
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error")
@ -565,7 +565,7 @@ func TestRedelegationPeriod(t *testing.T) {
bal1 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins()
// begin redelegate
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10))
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10))
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
require.True(t, got.IsOK(), "expected no error, %v", got)
@ -617,12 +617,12 @@ func TestTransitiveRedelegation(t *testing.T) {
require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator")
// begin redelegate
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10))
msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10))
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
require.True(t, got.IsOK(), "expected no error, %v", got)
// cannot redelegation to next validator while first delegation exists
msgBeginRedelegate = NewMsgBeginRedelegate(validatorAddr, validatorAddr2, validatorAddr3, sdk.NewRat(10))
msgBeginRedelegate = NewMsgBeginRedelegate(validatorAddr, validatorAddr2, validatorAddr3, sdk.NewDec(10))
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate)
@ -663,7 +663,7 @@ func TestUnbondingWhenExcessValidators(t *testing.T) {
require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx)))
// unbond the valdator-2
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30))
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
@ -785,7 +785,7 @@ func TestCliffValidator(t *testing.T) {
require.Equal(t, validatorAddr2.Bytes(), cliffVal)
// unbond valdator-2
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30))
msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
@ -798,7 +798,7 @@ func TestCliffValidator(t *testing.T) {
require.Equal(t, validatorAddr3.Bytes(), cliffVal)
// unbond valdator-1
msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewRat(50))
msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewDec(50))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
@ -832,22 +832,22 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
ctx = ctx.WithBlockHeight(1)
// begin unbonding 4 stake
msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewRat(4))
msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewDec(4))
got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding")
// begin redelegate 6 stake
msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, sdk.NewRat(6))
msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, sdk.NewDec(6))
got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper)
require.True(t, got.IsOK(), "expected no error on runMsgBeginRedelegate")
// destination delegation should have 6 shares
delegation, found := keeper.GetDelegation(ctx, del, valB)
require.True(t, found)
require.Equal(t, sdk.NewRat(6), delegation.Shares)
require.Equal(t, sdk.NewDec(6), delegation.Shares)
// slash the validator by half
keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewRat(1, 2))
keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewDecWithPrec(5, 1))
// unbonding delegation should have been slashed by half
unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA)
@ -862,16 +862,16 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
// destination delegation should have been slashed by half
delegation, found = keeper.GetDelegation(ctx, del, valB)
require.True(t, found)
require.Equal(t, sdk.NewRat(3), delegation.Shares)
require.Equal(t, sdk.NewDec(3), delegation.Shares)
// validator power should have been reduced by half
validator, found := keeper.GetValidator(ctx, valA)
require.True(t, found)
require.Equal(t, sdk.NewRat(5), validator.GetPower())
require.Equal(t, sdk.NewDec(5), validator.GetPower())
// slash the validator for an infraction committed after the unbonding and redelegation begin
ctx = ctx.WithBlockHeight(3)
keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewRat(1, 2))
keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewDecWithPrec(5, 1))
// unbonding delegation should be unchanged
unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA)
@ -886,7 +886,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
// destination delegation should be unchanged
delegation, found = keeper.GetDelegation(ctx, del, valB)
require.True(t, found)
require.Equal(t, sdk.NewRat(3), delegation.Shares)
require.Equal(t, sdk.NewDec(3), delegation.Shares)
// validator power should have been reduced to zero
// ergo validator should have been removed from the store

View File

@ -4,18 +4,18 @@ This document provided a bit more insight as to the purpose of several related
prefixed areas of the staking store which are accessed in `x/stake/keeper.go`.
## Validators
## Validators
- Prefix Key Space: ValidatorsKey
- Key/Sort: Validator Owner Address
- Key/Sort: Validator Operator Address
- Value: Validator Object
- Contains: All Validator records independent of being bonded or not
- Used For: Retrieve validator from owner address, general validator retrieval
- Used For: Retrieve validator from operator address, general validator retrieval
## Validators By Power
- Prefix Key Space: ValidatorsByPowerKey
- Key/Sort: Validator Power (equivalent bonded shares) then Block
Height then Transaction Order
- Value: Validator Owner Address
- Value: Validator Operator Address
- Contains: All Validator records independent of being bonded or not
- Used For: Determining who the top validators are whom should be bonded
@ -26,19 +26,19 @@ prefixed areas of the staking store which are accessed in `x/stake/keeper.go`.
- Contains: The cliff validator (ex. 100th validator) power
- Used For: Efficient updates to validator status
## Validators Bonded
## Validators Bonded
- Prefix Key Space: ValidatorsBondedKey
- Key/Sort: Validator PubKey Address (NOTE same as Tendermint)
- Value: Validator Owner Address
- Value: Validator Operator Address
- Contains: Only currently bonded Validators
- Used For: Retrieving the list of all currently bonded validators when updating
for a new validator entering the validator set we may want to loop
- Used For: Retrieving the list of all currently bonded validators when updating
for a new validator entering the validator set we may want to loop
through this set to determine who we've kicked out.
retrieving validator by tendermint index
## Tendermint Updates
- Prefix Key Space: TendermintUpdatesKey
- Key/Sort: Validator Owner Address
- Key/Sort: Validator Operator Address
- Value: Tendermint ABCI Validator
- Contains: Validators are queued to affect the consensus validation set in Tendermint
- Used For: Informing Tendermint of the validator set updates, is used only intra-block, as the

View File

@ -218,15 +218,15 @@ func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) {
// Perform a delegation, set/update everything necessary within the store.
func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt sdk.Coin,
validator types.Validator, subtractAccount bool) (newShares sdk.Rat, err sdk.Error) {
validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) {
// Get or create the delegator delegation
delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Owner)
delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Operator)
if !found {
delegation = types.Delegation{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validator.Owner,
Shares: sdk.ZeroRat(),
ValidatorAddr: validator.Operator,
Shares: sdk.ZeroDec(),
}
}
@ -254,7 +254,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt
// unbond the the delegation return
func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress,
shares sdk.Rat) (amount sdk.Rat, err sdk.Error) {
shares sdk.Dec) (amount sdk.Dec, err sdk.Error) {
// check if delegation has any shares in it unbond
delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr)
@ -282,9 +282,9 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr
// remove the delegation
if delegation.Shares.IsZero() {
// if the delegation is the owner of the validator then
// if the delegation is the operator of the validator then
// trigger a revoke validator
if bytes.Equal(delegation.DelegatorAddr, validator.Owner) && validator.Revoked == false {
if bytes.Equal(delegation.DelegatorAddr, validator.Operator) && validator.Revoked == false {
validator.Revoked = true
}
k.RemoveDelegation(ctx, delegation)
@ -303,7 +303,7 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr
// update then remove validator if necessary
validator = k.UpdateValidator(ctx, validator)
if validator.DelegatorShares.IsZero() {
k.RemoveValidator(ctx, validator.Owner)
k.RemoveValidator(ctx, validator.Operator)
}
return
@ -312,7 +312,7 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr
//______________________________________________________________________________________________________
// complete unbonding an unbonding record
func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Rat) sdk.Error {
func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error {
// TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402
_, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr)
@ -365,7 +365,7 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr
// complete unbonding an unbonding record
func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAddr,
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Rat) sdk.Error {
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error {
// check if this is a transitive redelegation
if k.HasReceivingRedelegation(ctx, delegatorAddr, validatorSrcAddr) {

View File

@ -32,7 +32,7 @@ func TestDelegation(t *testing.T) {
bond1to1 := types.Delegation{
DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[0],
Shares: sdk.NewRat(9),
Shares: sdk.NewDec(9),
}
// check the empty keeper first
@ -46,18 +46,18 @@ func TestDelegation(t *testing.T) {
require.True(t, bond1to1.Equal(resBond))
// modify a records, save, and retrieve
bond1to1.Shares = sdk.NewRat(99)
bond1to1.Shares = sdk.NewDec(99)
keeper.SetDelegation(ctx, bond1to1)
resBond, found = keeper.GetDelegation(ctx, addrDels[0], addrVals[0])
require.True(t, found)
require.True(t, bond1to1.Equal(resBond))
// add some more records
bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewRat(9), 0}
bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewRat(9), 1}
bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewRat(9), 2}
bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewRat(9), 3}
bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewRat(9), 4}
bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewDec(9), 0}
bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewDec(9), 1}
bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewDec(9), 2}
bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewDec(9), 3}
bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewDec(9), 4}
keeper.SetDelegation(ctx, bond1to2)
keeper.SetDelegation(ctx, bond1to3)
keeper.SetDelegation(ctx, bond2to1)
@ -142,7 +142,7 @@ func TestUnbondingDelegation(t *testing.T) {
func TestUnbondDelegation(t *testing.T) {
ctx, _, keeper := CreateTestInput(t, false, 0)
pool := keeper.GetPool(ctx)
pool.LooseTokens = sdk.NewRat(10)
pool.LooseTokens = sdk.NewDec(10)
//create a validator and a delegator to that validator
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
@ -163,8 +163,8 @@ func TestUnbondDelegation(t *testing.T) {
keeper.SetDelegation(ctx, delegation)
var err error
var amount sdk.Rat
amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewRat(6))
var amount sdk.Dec
amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewDec(6))
require.NoError(t, err)
require.Equal(t, int64(6), amount.RoundInt64()) // shares to be added to an unbonding delegation / redelegation
@ -190,8 +190,8 @@ func TestGetRedelegationsFromValidator(t *testing.T) {
ValidatorDstAddr: addrVals[1],
CreationHeight: 0,
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(5),
SharesDst: sdk.NewRat(5),
SharesSrc: sdk.NewDec(5),
SharesDst: sdk.NewDec(5),
}
// set and retrieve a record
@ -220,8 +220,8 @@ func TestRedelegation(t *testing.T) {
ValidatorDstAddr: addrVals[1],
CreationHeight: 0,
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(5),
SharesDst: sdk.NewRat(5),
SharesSrc: sdk.NewDec(5),
SharesDst: sdk.NewDec(5),
}
// test shouldn't have and redelegations
@ -242,8 +242,8 @@ func TestRedelegation(t *testing.T) {
require.True(t, has)
// modify a records, save, and retrieve
rd.SharesSrc = sdk.NewRat(21)
rd.SharesDst = sdk.NewRat(21)
rd.SharesSrc = sdk.NewDec(21)
rd.SharesDst = sdk.NewDec(21)
keeper.SetRedelegation(ctx, rd)
resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])

View File

@ -33,7 +33,7 @@ func TestPool(t *testing.T) {
require.True(t, expPool.Equal(resPool))
//modify a params, save, and retrieve
expPool.BondedTokens = sdk.NewRat(777)
expPool.BondedTokens = sdk.NewDec(777)
keeper.SetPool(ctx, expPool)
resPool = keeper.GetPool(ctx)
require.True(t, expPool.Equal(resPool))

View File

@ -69,7 +69,7 @@ func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Val
}
// total power from the bond
func (k Keeper) TotalPower(ctx sdk.Context) sdk.Rat {
func (k Keeper) TotalPower(ctx sdk.Context) sdk.Dec {
pool := k.GetPool(ctx)
return pool.BondedTokens
}

View File

@ -20,15 +20,15 @@ import (
// CONTRACT:
// Infraction committed at the current height or at a past height,
// not at a height in the future
func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Rat) {
func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Dec) {
logger := ctx.Logger().With("module", "x/stake")
if slashFactor.LT(sdk.ZeroRat()) {
if slashFactor.LT(sdk.ZeroDec()) {
panic(fmt.Errorf("attempted to slash with a negative slashFactor: %v", slashFactor))
}
// Amount of slashing = slash slashFactor * power at time of infraction
slashAmount := sdk.NewRat(power).Mul(slashFactor)
slashAmount := sdk.NewDec(power).Mul(slashFactor)
// ref https://github.com/cosmos/cosmos-sdk/issues/1348
// ref https://github.com/cosmos/cosmos-sdk/issues/1471
@ -43,7 +43,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
pubkey.Address()))
return
}
ownerAddress := validator.GetOwner()
operatorAddress := validator.GetOperator()
// Track remaining slash amount for the validator
// This will decrease when we slash unbondings and
@ -68,7 +68,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
case infractionHeight < ctx.BlockHeight():
// Iterate through unbonding delegations from slashed validator
unbondingDelegations := k.GetUnbondingDelegationsFromValidator(ctx, ownerAddress)
unbondingDelegations := k.GetUnbondingDelegationsFromValidator(ctx, operatorAddress)
for _, unbondingDelegation := range unbondingDelegations {
amountSlashed := k.slashUnbondingDelegation(ctx, unbondingDelegation, infractionHeight, slashFactor)
if amountSlashed.IsZero() {
@ -78,7 +78,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
}
// Iterate through redelegations from slashed validator
redelegations := k.GetRedelegationsFromValidator(ctx, ownerAddress)
redelegations := k.GetRedelegationsFromValidator(ctx, operatorAddress)
for _, redelegation := range redelegations {
amountSlashed := k.slashRedelegation(ctx, validator, redelegation, infractionHeight, slashFactor)
if amountSlashed.IsZero() {
@ -89,7 +89,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
}
// Cannot decrease balance below zero
tokensToBurn := sdk.MinRat(remainingSlashAmount, validator.Tokens)
tokensToBurn := sdk.MinDec(remainingSlashAmount, validator.Tokens)
// Get the current pool
pool := k.GetPool(ctx)
@ -103,7 +103,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
validator = k.UpdateValidator(ctx, validator)
// remove validator if it has been reduced to zero shares
if validator.Tokens.IsZero() {
k.RemoveValidator(ctx, validator.Owner)
k.RemoveValidator(ctx, validator.Operator)
}
// Log that a slash occurred!
@ -150,23 +150,23 @@ func (k Keeper) setRevoked(ctx sdk.Context, pubkey crypto.PubKey, revoked bool)
// (the amount actually slashed may be less if there's
// insufficient stake remaining)
func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation types.UnbondingDelegation,
infractionHeight int64, slashFactor sdk.Rat) (slashAmount sdk.Rat) {
infractionHeight int64, slashFactor sdk.Dec) (slashAmount sdk.Dec) {
now := ctx.BlockHeader().Time
// If unbonding started before this height, stake didn't contribute to infraction
if unbondingDelegation.CreationHeight < infractionHeight {
return sdk.ZeroRat()
return sdk.ZeroDec()
}
if unbondingDelegation.MinTime.Before(now) {
// Unbonding delegation no longer eligible for slashing, skip it
// TODO Settle and delete it automatically?
return sdk.ZeroRat()
return sdk.ZeroDec()
}
// Calculate slash amount proportional to stake contributing to infraction
slashAmount = sdk.NewRatFromInt(unbondingDelegation.InitialBalance.Amount, sdk.OneInt()).Mul(slashFactor)
slashAmount = sdk.NewDecFromInt(unbondingDelegation.InitialBalance.Amount).Mul(slashFactor)
// Don't slash more tokens than held
// Possible since the unbonding delegation may already
@ -194,23 +194,23 @@ func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation ty
// (the amount actually slashed may be less if there's
// insufficient stake remaining)
func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, redelegation types.Redelegation,
infractionHeight int64, slashFactor sdk.Rat) (slashAmount sdk.Rat) {
infractionHeight int64, slashFactor sdk.Dec) (slashAmount sdk.Dec) {
now := ctx.BlockHeader().Time
// If redelegation started before this height, stake didn't contribute to infraction
if redelegation.CreationHeight < infractionHeight {
return sdk.ZeroRat()
return sdk.ZeroDec()
}
if redelegation.MinTime.Before(now) {
// Redelegation no longer eligible for slashing, skip it
// TODO Delete it automatically?
return sdk.ZeroRat()
return sdk.ZeroDec()
}
// Calculate slash amount proportional to stake contributing to infraction
slashAmount = sdk.NewRatFromInt(redelegation.InitialBalance.Amount, sdk.OneInt()).Mul(slashFactor)
slashAmount = sdk.NewDecFromInt(redelegation.InitialBalance.Amount).Mul(slashFactor)
// Don't slash more tokens than held
// Possible since the redelegation may already

View File

@ -19,7 +19,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) {
params := keeper.GetParams(ctx)
pool := keeper.GetPool(ctx)
numVals := 3
pool.LooseTokens = sdk.NewRat(amt * int64(numVals))
pool.LooseTokens = sdk.NewDec(amt * int64(numVals))
// add numVals validators
for i := 0; i < numVals; i++ {
@ -63,7 +63,7 @@ func TestRevocation(t *testing.T) {
// tests slashUnbondingDelegation
func TestSlashUnbondingDelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10)
fraction := sdk.NewRat(1, 2)
fraction := sdk.NewDecWithPrec(5, 1)
// set an unbonding delegation
ubd := types.UnbondingDelegation{
@ -106,7 +106,7 @@ func TestSlashUnbondingDelegation(t *testing.T) {
// tests slashRedelegation
func TestSlashRedelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10)
fraction := sdk.NewRat(1, 2)
fraction := sdk.NewDecWithPrec(5, 1)
// set a redelegation
rd := types.Redelegation{
@ -116,8 +116,8 @@ func TestSlashRedelegation(t *testing.T) {
CreationHeight: 0,
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(10),
SharesDst: sdk.NewRat(10),
SharesSrc: sdk.NewDec(10),
SharesDst: sdk.NewDec(10),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 10),
Balance: sdk.NewInt64Coin(params.BondDenom, 10),
}
@ -127,7 +127,7 @@ func TestSlashRedelegation(t *testing.T) {
del := types.Delegation{
DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[1],
Shares: sdk.NewRat(10),
Shares: sdk.NewDec(10),
}
keeper.SetDelegation(ctx, del)
@ -172,7 +172,7 @@ func TestSlashRedelegation(t *testing.T) {
func TestSlashAtFutureHeight(t *testing.T) {
ctx, keeper, _ := setupHelper(t, 10)
pk := PKs[0]
fraction := sdk.NewRat(1, 2)
fraction := sdk.NewDecWithPrec(5, 1)
require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) })
}
@ -180,7 +180,7 @@ func TestSlashAtFutureHeight(t *testing.T) {
func TestSlashAtCurrentHeight(t *testing.T) {
ctx, keeper, _ := setupHelper(t, 10)
pk := PKs[0]
fraction := sdk.NewRat(1, 2)
fraction := sdk.NewDecWithPrec(5, 1)
oldPool := keeper.GetPool(ctx)
validator, found := keeper.GetValidatorByPubKey(ctx, pk)
@ -193,16 +193,16 @@ func TestSlashAtCurrentHeight(t *testing.T) {
newPool := keeper.GetPool(ctx)
// power decreased
require.Equal(t, sdk.NewRat(5), validator.GetPower())
require.Equal(t, sdk.NewDec(5), validator.GetPower())
// pool bonded shares decreased
require.Equal(t, sdk.NewRat(5).RoundInt64(), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
require.Equal(t, sdk.NewDec(5).RoundInt64(), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
}
// tests Slash at a previous height with an unbonding delegation
func TestSlashWithUnbondingDelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10)
pk := PKs[0]
fraction := sdk.NewRat(1, 2)
fraction := sdk.NewDecWithPrec(5, 1)
// set an unbonding delegation
ubd := types.UnbondingDelegation{
@ -239,7 +239,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
// was still bonded at the time of discovery and was slashed by half, 4 stake
// bonded at the time of discovery hadn't been bonded at the time of infraction
// and wasn't slashed
require.Equal(t, sdk.NewRat(7), validator.GetPower())
require.Equal(t, sdk.NewDec(7), validator.GetPower())
// slash validator again
ctx = ctx.WithBlockHeight(13)
@ -256,7 +256,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found)
// power decreased by 3 again
require.Equal(t, sdk.NewRat(4), validator.GetPower())
require.Equal(t, sdk.NewDec(4), validator.GetPower())
// slash validator again
// all originally bonded stake has been slashed, so this will have no effect
@ -276,7 +276,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found)
// power decreased by 3 again
require.Equal(t, sdk.NewRat(1), validator.GetPower())
require.Equal(t, sdk.NewDec(1), validator.GetPower())
// slash validator again
// all originally bonded stake has been slashed, so this will have no effect
@ -303,7 +303,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
func TestSlashWithRedelegation(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10)
pk := PKs[0]
fraction := sdk.NewRat(1, 2)
fraction := sdk.NewDecWithPrec(5, 1)
// set a redelegation
rd := types.Redelegation{
@ -312,8 +312,8 @@ func TestSlashWithRedelegation(t *testing.T) {
ValidatorDstAddr: addrVals[1],
CreationHeight: 11,
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(6),
SharesDst: sdk.NewRat(6),
SharesSrc: sdk.NewDec(6),
SharesDst: sdk.NewDec(6),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
Balance: sdk.NewInt64Coin(params.BondDenom, 6),
}
@ -323,13 +323,13 @@ func TestSlashWithRedelegation(t *testing.T) {
del := types.Delegation{
DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[1],
Shares: sdk.NewRat(6),
Shares: sdk.NewDec(6),
}
keeper.SetDelegation(ctx, del)
// update bonded tokens
pool := keeper.GetPool(ctx)
pool.BondedTokens = pool.BondedTokens.Add(sdk.NewRat(6))
pool.BondedTokens = pool.BondedTokens.Add(sdk.NewDec(6))
keeper.SetPool(ctx, pool)
// slash validator
@ -355,13 +355,13 @@ func TestSlashWithRedelegation(t *testing.T) {
// was still bonded at the time of discovery and was slashed by half, 4 stake
// bonded at the time of discovery hadn't been bonded at the time of infraction
// and wasn't slashed
require.Equal(t, sdk.NewRat(8), validator.GetPower())
require.Equal(t, sdk.NewDec(8), validator.GetPower())
// slash the validator again
ctx = ctx.WithBlockHeight(12)
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found)
require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneRat()) })
require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) })
// read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -376,13 +376,13 @@ func TestSlashWithRedelegation(t *testing.T) {
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found)
// power decreased by 4
require.Equal(t, sdk.NewRat(4), validator.GetPower())
require.Equal(t, sdk.NewDec(4), validator.GetPower())
// slash the validator again, by 100%
ctx = ctx.WithBlockHeight(12)
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
require.True(t, found)
keeper.Slash(ctx, pk, 10, 10, sdk.OneRat())
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
// read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -404,7 +404,7 @@ func TestSlashWithRedelegation(t *testing.T) {
// validator no longer in the store
_, found = keeper.GetValidatorByPubKey(ctx, pk)
require.False(t, found)
keeper.Slash(ctx, pk, 10, 10, sdk.OneRat())
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
// read updating redelegation
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
@ -424,7 +424,7 @@ func TestSlashWithRedelegation(t *testing.T) {
// tests Slash at a previous height with both an unbonding delegation and a redelegation
func TestSlashBoth(t *testing.T) {
ctx, keeper, params := setupHelper(t, 10)
fraction := sdk.NewRat(1, 2)
fraction := sdk.NewDecWithPrec(5, 1)
// set a redelegation
rdA := types.Redelegation{
@ -434,8 +434,8 @@ func TestSlashBoth(t *testing.T) {
CreationHeight: 11,
// expiration timestamp (beyond which the redelegation shouldn't be slashed)
MinTime: time.Unix(0, 0),
SharesSrc: sdk.NewRat(6),
SharesDst: sdk.NewRat(6),
SharesSrc: sdk.NewDec(6),
SharesDst: sdk.NewDec(6),
InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6),
Balance: sdk.NewInt64Coin(params.BondDenom, 6),
}
@ -445,7 +445,7 @@ func TestSlashBoth(t *testing.T) {
delA := types.Delegation{
DelegatorAddr: addrDels[0],
ValidatorAddr: addrVals[1],
Shares: sdk.NewRat(6),
Shares: sdk.NewDec(6),
}
keeper.SetDelegation(ctx, delA)
@ -483,5 +483,5 @@ func TestSlashBoth(t *testing.T) {
validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0])
require.True(t, found)
// power not decreased, all stake was bonded since
require.Equal(t, sdk.NewRat(10), validator.GetPower())
require.Equal(t, sdk.NewDec(10), validator.GetPower())
}

View File

@ -77,10 +77,10 @@ func MakeTestCodec() *wire.Codec {
// default params without inflation
func ParamsNoInflation() types.Params {
return types.Params{
InflationRateChange: sdk.ZeroRat(),
InflationMax: sdk.ZeroRat(),
InflationMin: sdk.ZeroRat(),
GoalBonded: sdk.NewRat(67, 100),
InflationRateChange: sdk.ZeroDec(),
InflationMax: sdk.ZeroDec(),
InflationMin: sdk.ZeroDec(),
GoalBonded: sdk.NewDecWithPrec(67, 2),
MaxValidators: 100,
BondDenom: "steak",
}
@ -119,7 +119,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
{keeper.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)},
})
require.Nil(t, err)
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(initCoins))
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(initCoins))
keeper.SetPool(ctx, pool)
}

View File

@ -36,25 +36,25 @@ func (k Keeper) GetValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) (val
func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
store := ctx.KVStore(k.storeKey)
bz := types.MustMarshalValidator(k.cdc, validator)
store.Set(GetValidatorKey(validator.Owner), bz)
store.Set(GetValidatorKey(validator.Operator), bz)
}
// validator index
func (k Keeper) SetValidatorByPubKeyIndex(ctx sdk.Context, validator types.Validator) {
store := ctx.KVStore(k.storeKey)
store.Set(GetValidatorByPubKeyIndexKey(validator.PubKey), validator.Owner)
store.Set(GetValidatorByPubKeyIndexKey(validator.PubKey), validator.Operator)
}
// validator index
func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator, pool types.Pool) {
store := ctx.KVStore(k.storeKey)
store.Set(GetValidatorsByPowerIndexKey(validator, pool), validator.Owner)
store.Set(GetValidatorsByPowerIndexKey(validator, pool), validator.Operator)
}
// validator index
func (k Keeper) SetValidatorBondedIndex(ctx sdk.Context, validator types.Validator) {
store := ctx.KVStore(k.storeKey)
store.Set(GetValidatorsBondedIndexKey(validator.Owner), []byte{})
store.Set(GetValidatorsBondedIndexKey(validator.Operator), []byte{})
}
// used in testing
@ -203,7 +203,7 @@ func (k Keeper) ClearTendermintUpdates(ctx sdk.Context) {
func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) types.Validator {
store := ctx.KVStore(k.storeKey)
pool := k.GetPool(ctx)
oldValidator, oldFound := k.GetValidator(ctx, validator.Owner)
oldValidator, oldFound := k.GetValidator(ctx, validator.Operator)
validator = k.updateForRevoking(ctx, oldFound, oldValidator, validator)
powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator)
@ -220,11 +220,11 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type
(oldFound && oldValidator.Status == sdk.Bonded):
bz := k.cdc.MustMarshalBinary(validator.ABCIValidator())
store.Set(GetTendermintUpdatesKey(validator.Owner), bz)
store.Set(GetTendermintUpdatesKey(validator.Operator), bz)
if cliffPower != nil {
cliffAddr := sdk.AccAddress(k.GetCliffValidator(ctx))
if bytes.Equal(cliffAddr, validator.Owner) {
if bytes.Equal(cliffAddr, validator.Operator) {
k.updateCliffValidator(ctx, validator)
}
}
@ -255,7 +255,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type
// if decreased in power but still bonded, update Tendermint validator
if oldFound && oldValidator.BondedTokens().GT(validator.BondedTokens()) {
bz := k.cdc.MustMarshalBinary(validator.ABCIValidator())
store.Set(GetTendermintUpdatesKey(validator.Owner), bz)
store.Set(GetTendermintUpdatesKey(validator.Operator), bz)
}
}
@ -306,7 +306,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato
affectedValRank := GetValidatorsByPowerIndexKey(affectedVal, pool)
newCliffValRank := GetValidatorsByPowerIndexKey(newCliffVal, pool)
if bytes.Equal(affectedVal.Owner, newCliffVal.Owner) {
if bytes.Equal(affectedVal.Operator, newCliffVal.Operator) {
// The affected validator remains the cliff validator, however, since
// the store does not contain the new power, update the new power rank.
store.Set(ValidatorPowerCliffKey, affectedValRank)
@ -364,7 +364,7 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato
store.Delete(GetValidatorsByPowerIndexKey(oldValidator, pool))
}
valPower = GetValidatorsByPowerIndexKey(newValidator, pool)
store.Set(valPower, newValidator.Owner)
store.Set(valPower, newValidator.Operator)
return valPower
}
@ -406,7 +406,7 @@ func (k Keeper) UpdateBondedValidators(
// situation that this is the "affected validator" just use the
// validator provided because it has not yet been updated in the store
ownerAddr := iterator.Value()
if bytes.Equal(ownerAddr, affectedValidator.Owner) {
if bytes.Equal(ownerAddr, affectedValidator.Operator) {
validator = affectedValidator
} else {
var found bool
@ -426,19 +426,23 @@ func (k Keeper) UpdateBondedValidators(
newValidatorBonded = true
}
bondedValidatorsCount++
// sanity check
} else if validator.Status == sdk.Bonded {
panic(fmt.Sprintf("revoked validator cannot be bonded, address: %v\n", ownerAddr))
break
}
// increment the total number of bonded validators and potentially mark
// the validator to bond
if validator.Status != sdk.Bonded {
validatorToBond = validator
newValidatorBonded = true
}
bondedValidatorsCount++
iterator.Next()
}
iterator.Close()
if newValidatorBonded && bytes.Equal(oldCliffValidatorAddr, validator.Owner) {
if newValidatorBonded && bytes.Equal(oldCliffValidatorAddr, validator.Operator) {
panic("cliff validator has not been changed, yet we bonded a new validator")
}
@ -458,7 +462,7 @@ func (k Keeper) UpdateBondedValidators(
panic(fmt.Sprintf("validator record not found for address: %v\n", oldCliffValidatorAddr))
}
if bytes.Equal(validatorToBond.Owner, affectedValidator.Owner) {
if bytes.Equal(validatorToBond.Operator, affectedValidator.Operator) {
// unbond the old cliff validator iff the affected validator was
// newly bonded and has greater power
k.unbondValidator(ctx, oldCliffVal)
@ -470,7 +474,7 @@ func (k Keeper) UpdateBondedValidators(
}
validator = k.bondValidator(ctx, validatorToBond)
if bytes.Equal(validator.Owner, affectedValidator.Owner) {
if bytes.Equal(validator.Operator, affectedValidator.Operator) {
return validator, true
}
@ -482,7 +486,6 @@ func (k Keeper) UpdateBondedValidators(
// full update of the bonded validator set, many can be added/kicked
func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) {
store := ctx.KVStore(k.storeKey)
// clear the current validators store, add to the ToKickOut temp store
@ -490,27 +493,26 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) {
iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey)
for ; iterator.Valid(); iterator.Next() {
ownerAddr := GetAddressFromValBondedIndexKey(iterator.Key())
toKickOut[string(ownerAddr)] = 0 // set anything
toKickOut[string(ownerAddr)] = 0
}
iterator.Close()
var validator types.Validator
oldCliffValidatorAddr := k.GetCliffValidator(ctx)
maxValidators := k.GetParams(ctx).MaxValidators
bondedValidatorsCount := 0
iterator = sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey) // largest to smallest
var validator types.Validator
iterator = sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey)
for {
if !iterator.Valid() || bondedValidatorsCount > int(maxValidators-1) {
break
}
// either retrieve the original validator from the store,
// or under the situation that this is the "new validator" just
// use the validator provided because it has not yet been updated
// in the main validator store
ownerAddr := iterator.Value()
var found bool
ownerAddr := iterator.Value()
validator, found = k.GetValidator(ctx, ownerAddr)
if !found {
panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr))
@ -520,23 +522,26 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) {
if found {
delete(toKickOut, string(ownerAddr))
} else {
// if it wasn't in the toKickOut group it means
// this wasn't a previously a validator, therefor
// update the validator to enter the validator group
// If the validator wasn't in the toKickOut group it means it wasn't
// previously a validator, therefor update the validator to enter
// the validator group.
validator = k.bondValidator(ctx, validator)
}
if !validator.Revoked {
bondedValidatorsCount++
} else {
if validator.Revoked {
// we should no longer consider jailed validators as they are ranked
// lower than any non-jailed/bonded validators
if validator.Status == sdk.Bonded {
panic(fmt.Sprintf("revoked validator cannot be bonded, address: %v\n", ownerAddr))
panic(fmt.Sprintf("revoked validator cannot be bonded for address: %s\n", ownerAddr))
}
break
}
bondedValidatorsCount++
iterator.Next()
}
iterator.Close()
// clear or set the cliff validator
@ -546,7 +551,6 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) {
k.clearCliffValidator(ctx)
}
// perform the actual kicks
kickOutValidators(k, ctx, toKickOut)
return
}
@ -582,10 +586,10 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type
// add to accumulated changes for tendermint
bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero())
store.Set(GetTendermintUpdatesKey(validator.Owner), bzABCI)
store.Set(GetTendermintUpdatesKey(validator.Operator), bzABCI)
// also remove from the Bonded types.Validators Store
store.Delete(GetValidatorsBondedIndexKey(validator.Owner))
store.Delete(GetValidatorsBondedIndexKey(validator.Operator))
return validator
}
@ -606,11 +610,11 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
// save the now bonded validator record to the three referenced stores
k.SetValidator(ctx, validator)
store.Set(GetValidatorsBondedIndexKey(validator.Owner), []byte{})
store.Set(GetValidatorsBondedIndexKey(validator.Operator), []byte{})
// add to accumulated changes for tendermint
bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator())
store.Set(GetTendermintUpdatesKey(validator.Owner), bzABCI)
store.Set(GetTendermintUpdatesKey(validator.Operator), bzABCI)
return validator
}
@ -633,10 +637,10 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.AccAddress) {
// delete from the current and power weighted validator groups if the validator
// is bonded - and add validator with zero power to the validator updates
if store.Get(GetValidatorsBondedIndexKey(validator.Owner)) == nil {
if store.Get(GetValidatorsBondedIndexKey(validator.Operator)) == nil {
return
}
store.Delete(GetValidatorsBondedIndexKey(validator.Owner))
store.Delete(GetValidatorsBondedIndexKey(validator.Operator))
bz := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero())
store.Set(GetTendermintUpdatesKey(address), bz)
@ -661,7 +665,7 @@ func (k Keeper) setCliffValidator(ctx sdk.Context, validator types.Validator, po
store := ctx.KVStore(k.storeKey)
bz := GetValidatorsByPowerIndexKey(validator, pool)
store.Set(ValidatorPowerCliffKey, bz)
store.Set(ValidatorCliffIndexKey, validator.Owner)
store.Set(ValidatorCliffIndexKey, validator.Operator)
}
// clear the current validator and power of the validator on the cliff

View File

@ -20,8 +20,8 @@ func TestSetValidator(t *testing.T) {
validator := types.NewValidator(addrVals[0], PKs[0], types.Description{})
validator, pool, _ = validator.AddTokensFromDel(pool, 10)
require.Equal(t, sdk.Unbonded, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
keeper.SetPool(ctx, pool)
keeper.UpdateValidator(ctx, validator)
@ -29,8 +29,8 @@ func TestSetValidator(t *testing.T) {
validator, found := keeper.GetValidator(ctx, addrVals[0])
require.True(t, found)
require.Equal(t, sdk.Bonded, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares))
// Check each store for being saved
resVal, found := keeper.GetValidator(ctx, addrVals[0])
@ -55,8 +55,8 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
pool := keeper.GetPool(ctx)
// create a random pool
pool.LooseTokens = sdk.NewRat(10000)
pool.BondedTokens = sdk.NewRat(1234)
pool.LooseTokens = sdk.NewDec(10000)
pool.BondedTokens = sdk.NewDec(1234)
keeper.SetPool(ctx, pool)
// add a validator
@ -75,7 +75,7 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) {
require.True(t, keeper.validatorByPowerIndexExists(ctx, power))
// burn half the delegator shares
validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewRat(2)))
validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewDec(2)))
require.Equal(t, int64(50), burned.RoundInt64())
keeper.SetPool(ctx, pool) // update the pool
keeper.UpdateValidator(ctx, validator) // update the validator, possibly kicking it out
@ -165,8 +165,8 @@ func TestCliffValidatorChange(t *testing.T) {
keeper.SetParams(ctx, params)
// create a random pool
pool.LooseTokens = sdk.NewRat(10000)
pool.BondedTokens = sdk.NewRat(1234)
pool.LooseTokens = sdk.NewDec(10000)
pool.BondedTokens = sdk.NewDec(1234)
keeper.SetPool(ctx, pool)
validators := make([]types.Validator, numVals)
@ -190,7 +190,7 @@ func TestCliffValidatorChange(t *testing.T) {
// assert new cliff validator to be set to the second lowest bonded validator by power
newCliffVal := validators[numVals-maxVals+1]
require.Equal(t, newCliffVal.Owner, sdk.AccAddress(keeper.GetCliffValidator(ctx)))
require.Equal(t, newCliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx)))
// assert cliff validator power should have been updated
cliffPower := keeper.GetCliffValidatorPower(ctx)
@ -203,7 +203,7 @@ func TestCliffValidatorChange(t *testing.T) {
// assert cliff validator has not change but increased in power
cliffPower = keeper.GetCliffValidatorPower(ctx)
require.Equal(t, newCliffVal.Owner, sdk.AccAddress(keeper.GetCliffValidator(ctx)))
require.Equal(t, newCliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx)))
require.Equal(t, GetValidatorsByPowerIndexKey(newCliffVal, pool), cliffPower)
// add enough power to cliff validator to be equal in rank to next validator
@ -236,7 +236,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) {
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
// slash the validator by 100%
keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneRat())
keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneDec())
// validator should have been deleted
_, found := keeper.GetValidator(ctx, addrVals[0])
require.False(t, found)
@ -253,13 +253,13 @@ func TestValidatorBasics(t *testing.T) {
for i, amt := range amts {
validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{})
validators[i].Status = sdk.Unbonded
validators[i].Tokens = sdk.ZeroRat()
validators[i].Tokens = sdk.ZeroDec()
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt)
keeper.SetPool(ctx, pool)
}
assert.True(sdk.RatEq(t, sdk.NewRat(9), validators[0].Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(8), validators[1].Tokens))
assert.True(sdk.RatEq(t, sdk.NewRat(7), validators[2].Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(8), validators[1].Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(7), validators[2].Tokens))
// check the empty keeper first
_, found := keeper.GetValidator(ctx, addrVals[0])
@ -268,7 +268,7 @@ func TestValidatorBasics(t *testing.T) {
assert.Zero(t, len(resVals))
pool = keeper.GetPool(ctx)
assert.True(sdk.RatEq(t, sdk.ZeroRat(), pool.BondedTokens))
assert.True(sdk.DecEq(t, sdk.ZeroDec(), pool.BondedTokens))
// set and retrieve a record
validators[0] = keeper.UpdateValidator(ctx, validators[0])
@ -280,15 +280,15 @@ func TestValidatorBasics(t *testing.T) {
require.Equal(t, 1, len(resVals))
assert.True(ValEq(t, validators[0], resVals[0]))
assert.Equal(t, sdk.Bonded, validators[0].Status)
assert.True(sdk.RatEq(t, sdk.NewRat(9), validators[0].BondedTokens()))
assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].BondedTokens()))
pool = keeper.GetPool(ctx)
assert.True(sdk.RatEq(t, pool.BondedTokens, validators[0].BondedTokens()))
assert.True(sdk.DecEq(t, pool.BondedTokens, validators[0].BondedTokens()))
// modify a records, save, and retrieve
validators[0].Status = sdk.Bonded
validators[0].Tokens = sdk.NewRat(10)
validators[0].DelegatorShares = sdk.NewRat(10)
validators[0].Tokens = sdk.NewDec(10)
validators[0].DelegatorShares = sdk.NewDec(10)
validators[0] = keeper.UpdateValidator(ctx, validators[0])
resVal, found = keeper.GetValidator(ctx, addrVals[0])
require.True(t, found)
@ -315,7 +315,7 @@ func TestValidatorBasics(t *testing.T) {
assert.True(ValEq(t, validators[2], resVals[2]))
// remove a record
keeper.RemoveValidator(ctx, validators[1].Owner)
keeper.RemoveValidator(ctx, validators[1].Operator)
_, found = keeper.GetValidator(ctx, addrVals[1])
require.False(t, found)
}
@ -331,34 +331,34 @@ func GetValidatorSortingUnmixed(t *testing.T) {
for i, amt := range amts {
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
validators[i].Status = sdk.Bonded
validators[i].Tokens = sdk.NewRat(amt)
validators[i].DelegatorShares = sdk.NewRat(amt)
validators[i].Tokens = sdk.NewDec(amt)
validators[i].DelegatorShares = sdk.NewDec(amt)
keeper.UpdateValidator(ctx, validators[i])
}
// first make sure everything made it in to the gotValidator group
resValidators := keeper.GetValidatorsByPower(ctx)
assert.Equal(t, n, len(resValidators))
assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators)
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
assert.Equal(t, validators[2].Owner, resValidators[3].Owner, "%v", resValidators)
assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators)
assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators)
assert.Equal(t, validators[3].Operator, resValidators[0].Operator, "%v", resValidators)
assert.Equal(t, validators[4].Operator, resValidators[1].Operator, "%v", resValidators)
assert.Equal(t, validators[1].Operator, resValidators[2].Operator, "%v", resValidators)
assert.Equal(t, validators[2].Operator, resValidators[3].Operator, "%v", resValidators)
assert.Equal(t, validators[0].Operator, resValidators[4].Operator, "%v", resValidators)
// test a basic increase in voting power
validators[3].Tokens = sdk.NewRat(500)
validators[3].Tokens = sdk.NewDec(500)
keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx)
require.Equal(t, len(resValidators), n)
assert.True(ValEq(t, validators[3], resValidators[0]))
// test a decrease in voting power
validators[3].Tokens = sdk.NewRat(300)
validators[3].Tokens = sdk.NewDec(300)
keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx)
require.Equal(t, len(resValidators), n)
@ -366,7 +366,7 @@ func GetValidatorSortingUnmixed(t *testing.T) {
assert.True(ValEq(t, validators[4], resValidators[1]))
// test equal voting power, different age
validators[3].Tokens = sdk.NewRat(200)
validators[3].Tokens = sdk.NewDec(200)
ctx = ctx.WithBlockHeight(10)
keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx)
@ -385,8 +385,8 @@ func GetValidatorSortingUnmixed(t *testing.T) {
assert.True(ValEq(t, validators[4], resValidators[1]))
// change in voting power of both validators, both still in v-set, no age change
validators[3].Tokens = sdk.NewRat(300)
validators[4].Tokens = sdk.NewRat(300)
validators[3].Tokens = sdk.NewDec(300)
validators[4].Tokens = sdk.NewDec(300)
keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx)
require.Equal(t, len(resValidators), n)
@ -413,20 +413,20 @@ func GetValidatorSortingMixed(t *testing.T) {
var validators [5]types.Validator
for i, amt := range amts {
validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{})
validators[i].DelegatorShares = sdk.NewRat(amt)
validators[i].DelegatorShares = sdk.NewDec(amt)
}
validators[0].Status = sdk.Bonded
validators[1].Status = sdk.Bonded
validators[2].Status = sdk.Bonded
validators[0].Tokens = sdk.NewRat(amts[0])
validators[1].Tokens = sdk.NewRat(amts[1])
validators[2].Tokens = sdk.NewRat(amts[2])
validators[0].Tokens = sdk.NewDec(amts[0])
validators[1].Tokens = sdk.NewDec(amts[1])
validators[2].Tokens = sdk.NewDec(amts[2])
validators[3].Status = sdk.Bonded
validators[4].Status = sdk.Bonded
validators[3].Tokens = sdk.NewRat(amts[3])
validators[4].Tokens = sdk.NewRat(amts[4])
validators[3].Tokens = sdk.NewDec(amts[3])
validators[4].Tokens = sdk.NewDec(amts[4])
for i := range amts {
keeper.UpdateValidator(ctx, validators[i])
@ -450,16 +450,16 @@ func GetValidatorSortingMixed(t *testing.T) {
// first make sure everything made it in to the gotValidator group
resValidators := keeper.GetValidatorsByPower(ctx)
assert.Equal(t, n, len(resValidators))
assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators)
assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators)
assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators)
assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators)
assert.Equal(t, validators[2].Owner, resValidators[3].Owner, "%v", resValidators)
assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators)
assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators)
assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators)
assert.Equal(t, validators[3].Operator, resValidators[0].Operator, "%v", resValidators)
assert.Equal(t, validators[4].Operator, resValidators[1].Operator, "%v", resValidators)
assert.Equal(t, validators[1].Operator, resValidators[2].Operator, "%v", resValidators)
assert.Equal(t, validators[2].Operator, resValidators[3].Operator, "%v", resValidators)
assert.Equal(t, validators[0].Operator, resValidators[4].Operator, "%v", resValidators)
}
// TODO separate out into multiple tests
@ -486,7 +486,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
}
for i := range amts {
validators[i], found = keeper.GetValidator(ctx, validators[i].Owner)
validators[i], found = keeper.GetValidator(ctx, validators[i].Operator)
require.True(t, found)
}
resValidators := keeper.GetValidatorsByPower(ctx)
@ -510,7 +510,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
// validator 3 enters bonded validator set
ctx = ctx.WithBlockHeight(40)
validators[3], found = keeper.GetValidator(ctx, validators[3].Owner)
validators[3], found = keeper.GetValidator(ctx, validators[3].Operator)
require.True(t, found)
validators[3], pool, _ = validators[3].AddTokensFromDel(pool, 1)
keeper.SetPool(ctx, pool)
@ -521,7 +521,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
assert.True(ValEq(t, validators[3], resValidators[1]))
// validator 3 kicked out temporarily
validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewRat(201))
validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewDec(201))
keeper.SetPool(ctx, pool)
validators[3] = keeper.UpdateValidator(ctx, validators[3])
resValidators = keeper.GetValidatorsByPower(ctx)
@ -537,7 +537,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) {
require.Equal(t, nMax, uint16(len(resValidators)))
assert.True(ValEq(t, validators[0], resValidators[0]))
assert.True(ValEq(t, validators[2], resValidators[1]))
validator, exists := keeper.GetValidator(ctx, validators[3].Owner)
validator, exists := keeper.GetValidator(ctx, validators[3].Operator)
require.Equal(t, exists, true)
require.Equal(t, int64(40), validator.BondHeight)
}
@ -607,7 +607,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) {
}
for i := range amts {
var found bool
validators[i], found = keeper.GetValidator(ctx, validators[i].Owner)
validators[i], found = keeper.GetValidator(ctx, validators[i].Operator)
require.True(t, found)
}
assert.Equal(t, sdk.Unbonded, validators[0].Status)
@ -680,8 +680,8 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) {
keeper.ClearTendermintUpdates(ctx)
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
keeper.RemoveValidator(ctx, validators[0].Owner)
keeper.RemoveValidator(ctx, validators[1].Owner)
keeper.RemoveValidator(ctx, validators[0].Operator)
keeper.RemoveValidator(ctx, validators[1].Operator)
updates = keeper.GetTendermintUpdates(ctx)
assert.Equal(t, 2, len(updates))
@ -733,7 +733,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) {
// test single value change
// tendermintUpdate set: {} -> {c1'}
validators[0].Status = sdk.Bonded
validators[0].Tokens = sdk.NewRat(600)
validators[0].Tokens = sdk.NewDec(600)
validators[0] = keeper.UpdateValidator(ctx, validators[0])
updates := keeper.GetTendermintUpdates(ctx)
@ -871,21 +871,21 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) {
require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx)))
// check initial power
require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[0].GetPower().RoundInt64())
require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[1].GetPower().RoundInt64())
require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[0].GetPower().RoundInt64())
require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[1].GetPower().RoundInt64())
// test multiple value change
// tendermintUpdate set: {c1, c3} -> {c1', c3'}
pool := keeper.GetPool(ctx)
validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewRat(20))
validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewRat(30))
validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewDec(20))
validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewDec(30))
keeper.SetPool(ctx, pool)
validators[0] = keeper.UpdateValidator(ctx, validators[0])
validators[1] = keeper.UpdateValidator(ctx, validators[1])
// power has changed
require.Equal(t, sdk.NewRat(80).RoundInt64(), validators[0].GetPower().RoundInt64())
require.Equal(t, sdk.NewRat(70).RoundInt64(), validators[1].GetPower().RoundInt64())
require.Equal(t, sdk.NewDec(80).RoundInt64(), validators[0].GetPower().RoundInt64())
require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64())
// Tendermint updates should reflect power change
updates := keeper.GetTendermintUpdates(ctx)

View File

@ -31,7 +31,7 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) sim
//pool := k.GetPool(ctx)
loose := sdk.ZeroInt()
bonded := sdk.ZeroRat()
bonded := sdk.ZeroDec()
am.IterateAccounts(ctx, func(acc auth.Account) bool {
loose = loose.Add(acc.GetCoins().AmountOf("steak"))
return false
@ -70,7 +70,7 @@ func PositivePowerInvariant(k stake.Keeper) simulation.Invariant {
return func(t *testing.T, app *baseapp.BaseApp, log string) {
ctx := app.NewContext(false, abci.Header{})
k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool {
require.True(t, validator.GetPower().GT(sdk.ZeroRat()), "validator with non-positive power stored")
require.True(t, validator.GetPower().GT(sdk.ZeroDec()), "validator with non-positive power stored")
return false
})
}

View File

@ -132,7 +132,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.
msg := stake.MsgBeginUnbonding{
DelegatorAddr: delegatorAddress,
ValidatorAddr: validatorAddress,
SharesAmount: sdk.NewRatFromInt(amount),
SharesAmount: sdk.NewDecFromInt(amount),
}
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
ctx, write := ctx.CacheContext()
@ -191,7 +191,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation
DelegatorAddr: delegatorAddress,
ValidatorSrcAddr: sourceValidatorAddress,
ValidatorDstAddr: destValidatorAddress,
SharesAmount: sdk.NewRatFromInt(amount),
SharesAmount: sdk.NewDecFromInt(amount),
}
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
ctx, write := ctx.CacheContext()
@ -250,7 +250,7 @@ func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup {
return false
})
pool := k.GetPool(ctx)
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(loose.Int64(), 1))
pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(loose.Int64()))
k.SetPool(ctx, pool)
}
}

View File

@ -2,7 +2,6 @@ package types
import (
"bytes"
"errors"
"fmt"
"time"
@ -16,12 +15,12 @@ import (
type Delegation struct {
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
ValidatorAddr sdk.AccAddress `json:"validator_addr"`
Shares sdk.Rat `json:"shares"`
Shares sdk.Dec `json:"shares"`
Height int64 `json:"height"` // Last height bond updated
}
type delegationValue struct {
Shares sdk.Rat
Shares sdk.Dec
Height int64
}
@ -48,12 +47,13 @@ func UnmarshalDelegation(cdc *wire.Codec, key, value []byte) (delegation Delegat
var storeValue delegationValue
err = cdc.UnmarshalBinary(value, &storeValue)
if err != nil {
err = fmt.Errorf("%v: %v", ErrNoDelegation(DefaultCodespace).Data(), err)
return
}
addrs := key[1:] // remove prefix bytes
if len(addrs) != 2*sdk.AddrLen {
err = errors.New("unexpected key length")
err = fmt.Errorf("%v", ErrBadDelegationAddr(DefaultCodespace).Data())
return
}
delAddr := sdk.AccAddress(addrs[:sdk.AddrLen])
@ -81,7 +81,7 @@ var _ sdk.Delegation = Delegation{}
// nolint - for sdk.Delegation
func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr }
func (d Delegation) GetValidator() sdk.AccAddress { return d.ValidatorAddr }
func (d Delegation) GetBondShares() sdk.Rat { return d.Shares }
func (d Delegation) GetBondShares() sdk.Dec { return d.Shares }
// HumanReadableString returns a human readable string representation of a
// Delegation. An error is returned if the Delegation's delegator or validator
@ -143,7 +143,7 @@ func UnmarshalUBD(cdc *wire.Codec, key, value []byte) (ubd UnbondingDelegation,
addrs := key[1:] // remove prefix bytes
if len(addrs) != 2*sdk.AddrLen {
err = errors.New("unexpected key length")
err = fmt.Errorf("%v", ErrBadDelegationAddr(DefaultCodespace).Data())
return
}
delAddr := sdk.AccAddress(addrs[:sdk.AddrLen])
@ -190,8 +190,8 @@ type Redelegation struct {
MinTime time.Time `json:"min_time"` // unix time for redelegation completion
InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started
Balance sdk.Coin `json:"balance"` // current balance
SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating
SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating
SharesSrc sdk.Dec `json:"shares_src"` // amount of source shares redelegating
SharesDst sdk.Dec `json:"shares_dst"` // amount of destination shares redelegating
}
type redValue struct {
@ -199,8 +199,8 @@ type redValue struct {
MinTime time.Time
InitialBalance sdk.Coin
Balance sdk.Coin
SharesSrc sdk.Rat
SharesDst sdk.Rat
SharesSrc sdk.Dec
SharesDst sdk.Dec
}
// return the redelegation without fields contained within the key for the store
@ -235,7 +235,7 @@ func UnmarshalRED(cdc *wire.Codec, key, value []byte) (red Redelegation, err err
addrs := key[1:] // remove prefix bytes
if len(addrs) != 3*sdk.AddrLen {
err = errors.New("unexpected key length")
err = fmt.Errorf("%v", ErrBadRedelegationAddr(DefaultCodespace).Data())
return
}
delAddr := sdk.AccAddress(addrs[:sdk.AddrLen])

View File

@ -12,19 +12,19 @@ func TestDelegationEqual(t *testing.T) {
d1 := Delegation{
DelegatorAddr: addr1,
ValidatorAddr: addr2,
Shares: sdk.NewRat(100),
Shares: sdk.NewDec(100),
}
d2 := Delegation{
DelegatorAddr: addr1,
ValidatorAddr: addr2,
Shares: sdk.NewRat(100),
Shares: sdk.NewDec(100),
}
ok := d1.Equal(d2)
require.True(t, ok)
d2.ValidatorAddr = addr3
d2.Shares = sdk.NewRat(200)
d2.Shares = sdk.NewDec(200)
ok = d1.Equal(d2)
require.False(t, ok)
@ -34,7 +34,7 @@ func TestDelegationHumanReadableString(t *testing.T) {
d := Delegation{
DelegatorAddr: addr1,
ValidatorAddr: addr2,
Shares: sdk.NewRat(100),
Shares: sdk.NewDec(100),
}
// NOTE: Being that the validator's keypair is random, we cannot test the
@ -58,8 +58,8 @@ func TestUnbondingDelegationEqual(t *testing.T) {
require.True(t, ok)
ud2.ValidatorAddr = addr3
ud2.MinTime = time.Unix(20*20*2, 0)
ud2.MinTime = time.Unix(20*20*2, 0)
ok = ud1.Equal(ud2)
require.False(t, ok)
}
@ -92,8 +92,8 @@ func TestRedelegationEqual(t *testing.T) {
ok := r1.Equal(r2)
require.True(t, ok)
r2.SharesDst = sdk.NewRat(10)
r2.SharesSrc = sdk.NewRat(20)
r2.SharesDst = sdk.NewDec(10)
r2.SharesSrc = sdk.NewDec(20)
r2.MinTime = time.Unix(20*20*2, 0)
ok = r1.Equal(r2)
@ -105,8 +105,8 @@ func TestRedelegationHumanReadableString(t *testing.T) {
DelegatorAddr: addr1,
ValidatorSrcAddr: addr2,
ValidatorDstAddr: addr3,
SharesDst: sdk.NewRat(10),
SharesSrc: sdk.NewRat(20),
SharesDst: sdk.NewDec(10),
SharesSrc: sdk.NewDec(20),
}
// NOTE: Being that the validator's keypair is random, we cannot test the

View File

@ -17,6 +17,7 @@ const (
CodeInvalidDelegation CodeType = 102
CodeInvalidInput CodeType = 103
CodeValidatorJailed CodeType = 104
CodeInvalidAddress CodeType = sdk.CodeInvalidAddress
CodeUnauthorized CodeType = sdk.CodeUnauthorized
CodeInternal CodeType = sdk.CodeInternal
CodeUnknownRequest CodeType = sdk.CodeUnknownRequest
@ -27,6 +28,10 @@ func ErrNilValidatorAddr(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "validator address is nil")
}
func ErrBadValidatorAddr(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidAddress, "validator address is invalid")
}
func ErrNoValidatorFound(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidValidator, "validator does not exist for that address")
}
@ -68,6 +73,10 @@ func ErrBadDenom(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation, "invalid coin denomination")
}
func ErrBadDelegationAddr(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "unexpected address length for this (address, validator) pair")
}
func ErrBadDelegationAmount(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation, "amount must be > 0")
}
@ -100,13 +109,6 @@ func ErrBadSharesAmount(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation, "shares must be > 0")
}
func ErrBadSharesPrecision(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation,
fmt.Sprintf("shares denominator must be < %s, try reducing the number of decimal points",
maximumBondingRationalDenominator.String()),
)
}
func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1")
}
@ -125,6 +127,10 @@ func ErrExistingUnbondingDelegation(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation, "existing unbonding delegation found")
}
func ErrBadRedelegationAddr(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "unexpected address length for this (address, srcValidator, dstValidator) tuple")
}
func ErrNoRedelegation(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidDelegation, "no redelegation found")
}

View File

@ -23,30 +23,30 @@ func TestGetInflation(t *testing.T) {
tests := []struct {
name string
setBondedTokens, setLooseTokens,
setInflation, expectedChange sdk.Rat
setInflation, expectedChange sdk.Dec
}{
// with 0% bonded atom supply the inflation should increase by InflationRateChange
{"test 1", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), params.InflationRateChange.Quo(hrsPerYrRat).Round(precision)},
{"test 1", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), params.InflationRateChange.Quo(hrsPerYrDec)},
// 100% bonded, starting at 20% inflation and being reduced
// (1 - (1/0.67))*(0.13/8667)
{"test 2", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(20, 100),
sdk.OneRat().Sub(sdk.OneRat().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)},
{"test 2", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2),
sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
// 50% bonded, starting at 10% inflation and being increased
{"test 3", sdk.OneRat(), sdk.OneRat(), sdk.NewRat(10, 100),
sdk.OneRat().Sub(sdk.NewRat(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)},
{"test 3", sdk.OneDec(), sdk.OneDec(), sdk.NewDecWithPrec(10, 2),
sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)},
// test 7% minimum stop (testing with 100% bonded)
{"test 4", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), sdk.ZeroRat()},
{"test 5", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000)},
{"test 4", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()},
{"test 5", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(70001, 6), sdk.NewDecWithPrec(-1, 6)},
// test 20% maximum stop (testing with 0% bonded)
{"test 6", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(20, 100), sdk.ZeroRat()},
{"test 7", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000)},
{"test 6", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()},
{"test 7", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(199999, 6), sdk.NewDecWithPrec(1, 6)},
// perfect balance shouldn't change inflation
{"test 8", sdk.NewRat(67), sdk.NewRat(33), sdk.NewRat(15, 100), sdk.ZeroRat()},
{"test 8", sdk.NewDec(67), sdk.NewDec(33), sdk.NewDecWithPrec(15, 2), sdk.ZeroDec()},
}
for _, tc := range tests {
pool.BondedTokens, pool.LooseTokens = tc.setBondedTokens, tc.setLooseTokens
@ -67,77 +67,80 @@ func TestProcessProvisions(t *testing.T) {
var (
initialTotalTokens int64 = 550000000
cumulativeExpProvs = sdk.ZeroRat()
cumulativeExpProvs = sdk.ZeroDec()
)
pool.LooseTokens = sdk.NewRat(initialTotalTokens)
pool.LooseTokens = sdk.NewDec(initialTotalTokens)
// process the provisions for a year
for hr := 0; hr < 100; hr++ {
var expProvisions sdk.Rat
var expProvisions sdk.Dec
_, expProvisions, pool = updateProvisions(t, pool, params, hr)
cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions)
}
//get the pool and do the final value checks from checkFinalPoolValues
checkFinalPoolValues(t, pool, sdk.NewRat(initialTotalTokens), cumulativeExpProvs)
checkFinalPoolValues(t, pool, sdk.NewDec(initialTotalTokens), cumulativeExpProvs)
}
//_________________________________________________________________________________________
////////////////////////////////HELPER FUNCTIONS BELOW/////////////////////////////////////
// Final check on the global pool values for what the total tokens accumulated from each hour of provisions
func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs sdk.Rat) {
func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs sdk.Dec) {
calculatedTotalTokens := initialTotalTokens.Add(cumulativeExpProvs)
require.True(sdk.RatEq(t, calculatedTotalTokens, pool.TokenSupply()))
require.True(sdk.DecEq(t, calculatedTotalTokens, pool.TokenSupply()))
}
// Processes provisions are added to the pool correctly every hour
// Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests
func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Rat, sdk.Rat, Pool) {
func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Dec, sdk.Dec, Pool) {
expInflation := pool.NextInflation(params)
expProvisions := expInflation.Mul(pool.TokenSupply().Round(precision)).Quo(hrsPerYrRat)
expProvisions := expInflation.Mul(pool.TokenSupply()).Quo(hrsPerYrDec)
startTotalSupply := pool.TokenSupply()
pool = pool.ProcessProvisions(params)
//check provisions were added to pool
require.True(sdk.RatEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply()))
require.True(sdk.DecEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply()))
return expInflation, expProvisions, pool
}
// Checks that The inflation will correctly increase or decrease after an update to the pool
// nolint: gocyclo
func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Rat, msg string) {
func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Dec, msg string) {
inflationChange := updatedInflation.Sub(previousInflation)
switch {
//BELOW 67% - Rate of change positive and increasing, while we are between 7% <= and < 20% inflation
case pool.BondedRatio().LT(sdk.NewRat(67, 100)) && updatedInflation.LT(sdk.NewRat(20, 100)):
require.Equal(t, true, inflationChange.GT(sdk.ZeroRat()), msg)
case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.LT(sdk.NewDecWithPrec(20, 2)):
require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg)
//BELOW 67% - Rate of change should be 0 while inflation continually stays at 20% until we reach 67% bonded ratio
case pool.BondedRatio().LT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(20, 100)):
if previousInflation.Equal(sdk.NewRat(20, 100)) {
case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.Equal(sdk.NewDecWithPrec(20, 2)):
if previousInflation.Equal(sdk.NewDecWithPrec(20, 2)) {
require.Equal(t, true, inflationChange.IsZero(), msg)
//This else statement covers the one off case where we first hit 20%, but we still needed a positive ROC to get to 67% bonded ratio (i.e. we went from 19.99999% to 20%)
} else {
require.Equal(t, true, inflationChange.GT(sdk.ZeroRat()), msg)
require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg)
}
//ABOVE 67% - Rate of change should be negative while the bond is above 67, and should stay negative until we reach inflation of 7%
case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.LT(sdk.NewRat(20, 100)) && updatedInflation.GT(sdk.NewRat(7, 100)):
require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg)
case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
updatedInflation.LT(sdk.NewDecWithPrec(20, 2)) && updatedInflation.GT(sdk.NewDecWithPrec(7, 2)):
require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg)
//ABOVE 67% - Rate of change should be 0 while inflation continually stays at 7%.
case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(7, 100)):
if previousInflation.Equal(sdk.NewRat(7, 100)) {
case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) &&
updatedInflation.Equal(sdk.NewDecWithPrec(7, 2)):
if previousInflation.Equal(sdk.NewDecWithPrec(7, 2)) {
require.Equal(t, true, inflationChange.IsZero(), msg)
//This else statement covers the one off case where we first hit 7%, but we still needed a negative ROC to continue to get down to 67%. (i.e. we went from 7.00001% to 7%)
} else {
require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg)
require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg)
}
}
}

View File

@ -1,7 +1,6 @@
package types
import (
"math"
"reflect"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -11,18 +10,11 @@ import (
// name to idetify transaction types
const MsgType = "stake"
// Maximum amount of decimal points in the decimal representation of rationals
// used in MsgBeginUnbonding / MsgBeginRedelegate
const MaxBondDenominatorPrecision = 8
// Verify interface at compile time
var _, _, _ sdk.Msg = &MsgCreateValidator{}, &MsgEditValidator{}, &MsgDelegate{}
var _, _ sdk.Msg = &MsgBeginUnbonding{}, &MsgCompleteUnbonding{}
var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{}
// Initialize Int for the denominator
var maximumBondingRationalDenominator = sdk.NewInt(int64(math.Pow10(MaxBondDenominatorPrecision)))
//______________________________________________________________________
// MsgCreateValidator - struct for unbonding transactions
@ -211,11 +203,11 @@ type MsgBeginRedelegate struct {
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"`
ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"`
SharesAmount sdk.Rat `json:"shares_amount"`
SharesAmount sdk.Dec `json:"shares_amount"`
}
func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr,
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Rat) MsgBeginRedelegate {
validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginRedelegate {
return MsgBeginRedelegate{
DelegatorAddr: delegatorAddr,
@ -261,12 +253,9 @@ func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error {
if msg.ValidatorDstAddr == nil {
return ErrNilValidatorAddr(DefaultCodespace)
}
if msg.SharesAmount.LTE(sdk.ZeroRat()) {
if msg.SharesAmount.LTE(sdk.ZeroDec()) {
return ErrBadSharesAmount(DefaultCodespace)
}
if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) {
return ErrBadSharesPrecision(DefaultCodespace)
}
return nil
}
@ -322,10 +311,10 @@ func (msg MsgCompleteRedelegate) ValidateBasic() sdk.Error {
type MsgBeginUnbonding struct {
DelegatorAddr sdk.AccAddress `json:"delegator_addr"`
ValidatorAddr sdk.AccAddress `json:"validator_addr"`
SharesAmount sdk.Rat `json:"shares_amount"`
SharesAmount sdk.Dec `json:"shares_amount"`
}
func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Rat) MsgBeginUnbonding {
func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginUnbonding {
return MsgBeginUnbonding{
DelegatorAddr: delegatorAddr,
ValidatorAddr: validatorAddr,
@ -362,12 +351,9 @@ func (msg MsgBeginUnbonding) ValidateBasic() sdk.Error {
if msg.ValidatorAddr == nil {
return ErrNilValidatorAddr(DefaultCodespace)
}
if msg.SharesAmount.LTE(sdk.ZeroRat()) {
if msg.SharesAmount.LTE(sdk.ZeroDec()) {
return ErrBadSharesAmount(DefaultCodespace)
}
if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) {
return ErrBadSharesPrecision(DefaultCodespace)
}
return nil
}

View File

@ -143,15 +143,15 @@ func TestMsgBeginRedelegate(t *testing.T) {
delegatorAddr sdk.AccAddress
validatorSrcAddr sdk.AccAddress
validatorDstAddr sdk.AccAddress
sharesAmount sdk.Rat
sharesAmount sdk.Dec
expectPass bool
}{
{"regular", addr1, addr2, addr3, sdk.NewRat(1, 10), true},
{"negative decimal", addr1, addr2, addr3, sdk.NewRat(-1, 10), false},
{"zero amount", addr1, addr2, addr3, sdk.ZeroRat(), false},
{"empty delegator", emptyAddr, addr1, addr3, sdk.NewRat(1, 10), false},
{"empty source validator", addr1, emptyAddr, addr3, sdk.NewRat(1, 10), false},
{"empty destination validator", addr1, addr2, emptyAddr, sdk.NewRat(1, 10), false},
{"regular", addr1, addr2, addr3, sdk.NewDecWithPrec(1, 1), true},
{"negative decimal", addr1, addr2, addr3, sdk.NewDecWithPrec(-1, 1), false},
{"zero amount", addr1, addr2, addr3, sdk.ZeroDec(), false},
{"empty delegator", emptyAddr, addr1, addr3, sdk.NewDecWithPrec(1, 1), false},
{"empty source validator", addr1, emptyAddr, addr3, sdk.NewDecWithPrec(1, 1), false},
{"empty destination validator", addr1, addr2, emptyAddr, sdk.NewDecWithPrec(1, 1), false},
}
for _, tc := range tests {
@ -195,14 +195,14 @@ func TestMsgBeginUnbonding(t *testing.T) {
name string
delegatorAddr sdk.AccAddress
validatorAddr sdk.AccAddress
sharesAmount sdk.Rat
sharesAmount sdk.Dec
expectPass bool
}{
{"regular", addr1, addr2, sdk.NewRat(1, 10), true},
{"negative decimal", addr1, addr2, sdk.NewRat(-1, 10), false},
{"zero amount", addr1, addr2, sdk.ZeroRat(), false},
{"empty delegator", emptyAddr, addr1, sdk.NewRat(1, 10), false},
{"empty validator", addr1, emptyAddr, sdk.NewRat(1, 10), false},
{"regular", addr1, addr2, sdk.NewDecWithPrec(1, 1), true},
{"negative decimal", addr1, addr2, sdk.NewDecWithPrec(-1, 1), false},
{"zero amount", addr1, addr2, sdk.ZeroDec(), false},
{"empty delegator", emptyAddr, addr1, sdk.NewDecWithPrec(1, 1), false},
{"empty validator", addr1, emptyAddr, sdk.NewDecWithPrec(1, 1), false},
}
for _, tc := range tests {

View File

@ -13,10 +13,10 @@ const defaultUnbondingTime time.Duration = 60 * 60 * 24 * 3 * time.Second
// Params defines the high level settings for staking
type Params struct {
InflationRateChange sdk.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate
InflationMax sdk.Rat `json:"inflation_max"` // maximum inflation rate
InflationMin sdk.Rat `json:"inflation_min"` // minimum inflation rate
GoalBonded sdk.Rat `json:"goal_bonded"` // Goal of percent bonded atoms
InflationRateChange sdk.Dec `json:"inflation_rate_change"` // maximum annual change in inflation rate
InflationMax sdk.Dec `json:"inflation_max"` // maximum inflation rate
InflationMin sdk.Dec `json:"inflation_min"` // minimum inflation rate
GoalBonded sdk.Dec `json:"goal_bonded"` // Goal of percent bonded atoms
UnbondingTime time.Duration `json:"unbonding_time"`
@ -34,10 +34,10 @@ func (p Params) Equal(p2 Params) bool {
// DefaultParams returns a default set of parameters.
func DefaultParams() Params {
return Params{
InflationRateChange: sdk.NewRat(13, 100),
InflationMax: sdk.NewRat(20, 100),
InflationMin: sdk.NewRat(7, 100),
GoalBonded: sdk.NewRat(67, 100),
InflationRateChange: sdk.NewDecWithPrec(13, 2),
InflationMax: sdk.NewDecWithPrec(20, 2),
InflationMin: sdk.NewDecWithPrec(7, 2),
GoalBonded: sdk.NewDecWithPrec(67, 2),
UnbondingTime: defaultUnbondingTime,
MaxValidators: 100,
BondDenom: "steak",

View File

@ -10,15 +10,15 @@ import (
// Pool - dynamic parameters of the current state
type Pool struct {
LooseTokens sdk.Rat `json:"loose_tokens"` // tokens which are not bonded in a validator
BondedTokens sdk.Rat `json:"bonded_tokens"` // reserve of bonded tokens
InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed
Inflation sdk.Rat `json:"inflation"` // current annual inflation rate
LooseTokens sdk.Dec `json:"loose_tokens"` // tokens which are not bonded in a validator
BondedTokens sdk.Dec `json:"bonded_tokens"` // reserve of bonded tokens
InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time
Inflation sdk.Dec `json:"inflation"` // current annual inflation rate
DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily)
// Fee Related
PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // last recorded bonded shares - for fee calculations
PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // last recorded bonded shares - for fee calculations
}
// nolint
@ -31,48 +31,48 @@ func (p Pool) Equal(p2 Pool) bool {
// initial pool for testing
func InitialPool() Pool {
return Pool{
LooseTokens: sdk.ZeroRat(),
BondedTokens: sdk.ZeroRat(),
LooseTokens: sdk.ZeroDec(),
BondedTokens: sdk.ZeroDec(),
InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewRat(7, 100),
Inflation: sdk.NewDecWithPrec(7, 2),
DateLastCommissionReset: 0,
PrevBondedShares: sdk.ZeroRat(),
PrevBondedShares: sdk.ZeroDec(),
}
}
//____________________________________________________________________
// Sum total of all staking tokens in the pool
func (p Pool) TokenSupply() sdk.Rat {
func (p Pool) TokenSupply() sdk.Dec {
return p.LooseTokens.Add(p.BondedTokens)
}
//____________________________________________________________________
// get the bond ratio of the global state
func (p Pool) BondedRatio() sdk.Rat {
func (p Pool) BondedRatio() sdk.Dec {
supply := p.TokenSupply()
if supply.GT(sdk.ZeroRat()) {
if supply.GT(sdk.ZeroDec()) {
return p.BondedTokens.Quo(supply)
}
return sdk.ZeroRat()
return sdk.ZeroDec()
}
//_______________________________________________________________________
func (p Pool) looseTokensToBonded(bondedTokens sdk.Rat) Pool {
func (p Pool) looseTokensToBonded(bondedTokens sdk.Dec) Pool {
p.BondedTokens = p.BondedTokens.Add(bondedTokens)
p.LooseTokens = p.LooseTokens.Sub(bondedTokens)
if p.LooseTokens.LT(sdk.ZeroRat()) {
if p.LooseTokens.LT(sdk.ZeroDec()) {
panic(fmt.Sprintf("sanity check: loose tokens negative, pool: %v", p))
}
return p
}
func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool {
func (p Pool) bondedTokensToLoose(bondedTokens sdk.Dec) Pool {
p.BondedTokens = p.BondedTokens.Sub(bondedTokens)
p.LooseTokens = p.LooseTokens.Add(bondedTokens)
if p.BondedTokens.LT(sdk.ZeroRat()) {
if p.BondedTokens.LT(sdk.ZeroDec()) {
panic(fmt.Sprintf("sanity check: bonded tokens negative, pool: %v", p))
}
return p
@ -82,14 +82,14 @@ func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool {
// Inflation
const precision = 10000 // increased to this precision for accuracy
var hrsPerYrRat = sdk.NewRat(8766) // as defined by a julian year of 365.25 days
var hrsPerYrDec = sdk.NewDec(8766) // as defined by a julian year of 365.25 days
// process provisions for an hour period
func (p Pool) ProcessProvisions(params Params) Pool {
p.Inflation = p.NextInflation(params)
provisions := p.Inflation.
Mul(p.TokenSupply().Round(precision)).
Quo(hrsPerYrRat)
Mul(p.TokenSupply()).
Quo(hrsPerYrDec)
// TODO add to the fees provisions
p.LooseTokens = p.LooseTokens.Add(provisions)
@ -97,7 +97,7 @@ func (p Pool) ProcessProvisions(params Params) Pool {
}
// get the next inflation rate for the hour
func (p Pool) NextInflation(params Params) (inflation sdk.Rat) {
func (p Pool) NextInflation(params Params) (inflation sdk.Dec) {
// The target annual inflation rate is recalculated for each previsions cycle. The
// inflation is also subject to a rate change (positive or negative) depending on
@ -106,11 +106,11 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) {
// 7% and 20%.
// (1 - bondedRatio/GoalBonded) * InflationRateChange
inflationRateChangePerYear := sdk.OneRat().
Sub(p.BondedRatio().Round(precision).
inflationRateChangePerYear := sdk.OneDec().
Sub(p.BondedRatio().
Quo(params.GoalBonded)).
Mul(params.InflationRateChange)
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrRat)
inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrDec)
// increase the new annual inflation for this next cycle
inflation = p.Inflation.Add(inflationRateChange)
@ -121,5 +121,5 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) {
inflation = params.InflationMin
}
return inflation.Round(precision)
return inflation
}

View File

@ -11,28 +11,28 @@ func TestPoolEqual(t *testing.T) {
p1 := InitialPool()
p2 := InitialPool()
require.True(t, p1.Equal(p2))
p2.BondedTokens = sdk.NewRat(3)
p2.BondedTokens = sdk.NewDec(3)
require.False(t, p1.Equal(p2))
}
func TestAddBondedTokens(t *testing.T) {
pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10)
pool.BondedTokens = sdk.NewRat(10)
pool.LooseTokens = sdk.NewDec(10)
pool.BondedTokens = sdk.NewDec(10)
pool = pool.looseTokensToBonded(sdk.NewRat(10))
pool = pool.looseTokensToBonded(sdk.NewDec(10))
require.True(sdk.RatEq(t, sdk.NewRat(20), pool.BondedTokens))
require.True(sdk.RatEq(t, sdk.NewRat(0), pool.LooseTokens))
require.True(sdk.DecEq(t, sdk.NewDec(20), pool.BondedTokens))
require.True(sdk.DecEq(t, sdk.NewDec(0), pool.LooseTokens))
}
func TestRemoveBondedTokens(t *testing.T) {
pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10)
pool.BondedTokens = sdk.NewRat(10)
pool.LooseTokens = sdk.NewDec(10)
pool.BondedTokens = sdk.NewDec(10)
pool = pool.bondedTokensToLoose(sdk.NewRat(5))
pool = pool.bondedTokensToLoose(sdk.NewDec(5))
require.True(sdk.RatEq(t, sdk.NewRat(5), pool.BondedTokens))
require.True(sdk.RatEq(t, sdk.NewRat(15), pool.LooseTokens))
require.True(sdk.DecEq(t, sdk.NewDec(5), pool.BondedTokens))
require.True(sdk.DecEq(t, sdk.NewDec(15), pool.LooseTokens))
}

View File

@ -2,7 +2,6 @@ package types
import (
"bytes"
"errors"
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
@ -21,46 +20,46 @@ import (
// exchange rate. Voting power can be calculated as total bonds multiplied by
// exchange rate.
type Validator struct {
Owner sdk.AccAddress `json:"owner"` // sender of BondTx - UnbondTx returns here
PubKey crypto.PubKey `json:"pub_key"` // pubkey of validator
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
Operator sdk.AccAddress `json:"operator"` // sender of BondTx - UnbondTx returns here
PubKey crypto.PubKey `json:"pub_key"` // pubkey of validator
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators
Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
Description Description `json:"description"` // description terms for the validator
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators
CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators
CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
// fee related
LastBondedTokens sdk.Rat `json:"prev_bonded_tokens"` // Previous bonded tokens held
LastBondedTokens sdk.Dec `json:"prev_bonded_tokens"` // Previous bonded tokens held
}
// NewValidator - initialize a new validator
func NewValidator(owner sdk.AccAddress, pubKey crypto.PubKey, description Description) Validator {
func NewValidator(operator sdk.AccAddress, pubKey crypto.PubKey, description Description) Validator {
return Validator{
Owner: owner,
Operator: operator,
PubKey: pubKey,
Revoked: false,
Status: sdk.Unbonded,
Tokens: sdk.ZeroRat(),
DelegatorShares: sdk.ZeroRat(),
Tokens: sdk.ZeroDec(),
DelegatorShares: sdk.ZeroDec(),
Description: description,
BondHeight: int64(0),
BondIntraTxCounter: int16(0),
ProposerRewardPool: sdk.Coins{},
Commission: sdk.ZeroRat(),
CommissionMax: sdk.ZeroRat(),
CommissionChangeRate: sdk.ZeroRat(),
CommissionChangeToday: sdk.ZeroRat(),
LastBondedTokens: sdk.ZeroRat(),
Commission: sdk.ZeroDec(),
CommissionMax: sdk.ZeroDec(),
CommissionChangeRate: sdk.ZeroDec(),
CommissionChangeToday: sdk.ZeroDec(),
LastBondedTokens: sdk.ZeroDec(),
}
}
@ -69,17 +68,17 @@ type validatorValue struct {
PubKey crypto.PubKey
Revoked bool
Status sdk.BondStatus
Tokens sdk.Rat
DelegatorShares sdk.Rat
Tokens sdk.Dec
DelegatorShares sdk.Dec
Description Description
BondHeight int64
BondIntraTxCounter int16
ProposerRewardPool sdk.Coins
Commission sdk.Rat
CommissionMax sdk.Rat
CommissionChangeRate sdk.Rat
CommissionChangeToday sdk.Rat
LastBondedTokens sdk.Rat
Commission sdk.Dec
CommissionMax sdk.Dec
CommissionChangeRate sdk.Dec
CommissionChangeToday sdk.Dec
LastBondedTokens sdk.Dec
}
// return the redelegation without fields contained within the key for the store
@ -104,8 +103,8 @@ func MustMarshalValidator(cdc *wire.Codec, validator Validator) []byte {
}
// unmarshal a redelegation from a store key and value
func MustUnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) Validator {
validator, err := UnmarshalValidator(cdc, ownerAddr, value)
func MustUnmarshalValidator(cdc *wire.Codec, operatorAddr, value []byte) Validator {
validator, err := UnmarshalValidator(cdc, operatorAddr, value)
if err != nil {
panic(err)
}
@ -114,20 +113,19 @@ func MustUnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) Validator
}
// unmarshal a redelegation from a store key and value
func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) (validator Validator, err error) {
func UnmarshalValidator(cdc *wire.Codec, operatorAddr, value []byte) (validator Validator, err error) {
if len(operatorAddr) != sdk.AddrLen {
err = fmt.Errorf("%v", ErrBadValidatorAddr(DefaultCodespace).Data())
return
}
var storeValue validatorValue
err = cdc.UnmarshalBinary(value, &storeValue)
if err != nil {
return
}
if len(ownerAddr) != 20 {
err = errors.New("unexpected address length")
return
}
return Validator{
Owner: ownerAddr,
Operator: operatorAddr,
PubKey: storeValue.PubKey,
Revoked: storeValue.Revoked,
Tokens: storeValue.Tokens,
@ -146,7 +144,7 @@ func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) (validator Val
}
// HumanReadableString returns a human readable string representation of a
// validator. An error is returned if the owner or the owner's public key
// validator. An error is returned if the operator or the operator's public key
// cannot be converted to Bech32 format.
func (v Validator) HumanReadableString() (string, error) {
bechVal, err := sdk.Bech32ifyValPub(v.PubKey)
@ -155,12 +153,12 @@ func (v Validator) HumanReadableString() (string, error) {
}
resp := "Validator \n"
resp += fmt.Sprintf("Owner: %s\n", v.Owner)
resp += fmt.Sprintf("Operator: %s\n", v.Operator)
resp += fmt.Sprintf("Validator: %s\n", bechVal)
resp += fmt.Sprintf("Revoked: %v\n", v.Revoked)
resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status))
resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.FloatString())
resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.FloatString())
resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.String())
resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.String())
resp += fmt.Sprintf("Description: %s\n", v.Description)
resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight)
resp += fmt.Sprintf("Proposer Reward Pool: %s\n", v.ProposerRewardPool.String())
@ -177,26 +175,26 @@ func (v Validator) HumanReadableString() (string, error) {
// validator struct for bech output
type BechValidator struct {
Owner sdk.AccAddress `json:"owner"` // in bech32
PubKey string `json:"pub_key"` // in bech32
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
Operator sdk.AccAddress `json:"operator"` // in bech32
PubKey string `json:"pub_key"` // in bech32
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded)
Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators
Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators
Description Description `json:"description"` // description terms for the validator
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators
CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators
CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
// fee related
LastBondedTokens sdk.Rat `json:"prev_bonded_shares"` // last bonded token amount
LastBondedTokens sdk.Dec `json:"prev_bonded_shares"` // last bonded token amount
}
// get the bech validator from the the regular validator
@ -207,9 +205,9 @@ func (v Validator) Bech32Validator() (BechValidator, error) {
}
return BechValidator{
Owner: v.Owner,
PubKey: bechValPubkey,
Revoked: v.Revoked,
Operator: v.Operator,
PubKey: bechValPubkey,
Revoked: v.Revoked,
Status: v.Status,
Tokens: v.Tokens,
@ -235,7 +233,7 @@ func (v Validator) Bech32Validator() (BechValidator, error) {
// nolint gocyclo - why dis fail?
func (v Validator) Equal(c2 Validator) bool {
return v.PubKey.Equals(c2.PubKey) &&
bytes.Equal(v.Owner, c2.Owner) &&
bytes.Equal(v.Operator, c2.Operator) &&
v.Status.Equal(c2.Status) &&
v.Tokens.Equal(c2.Tokens) &&
v.DelegatorShares.Equal(c2.DelegatorShares) &&
@ -366,7 +364,7 @@ func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (Validator,
}
// removes tokens from a validator
func (v Validator) RemoveTokens(pool Pool, tokens sdk.Rat) (Validator, Pool) {
func (v Validator) RemoveTokens(pool Pool, tokens sdk.Dec) (Validator, Pool) {
if v.Status == sdk.Bonded {
pool = pool.bondedTokensToLoose(tokens)
}
@ -378,25 +376,25 @@ func (v Validator) RemoveTokens(pool Pool, tokens sdk.Rat) (Validator, Pool) {
//_________________________________________________________________________________________________________
// AddTokensFromDel adds tokens to a validator
func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Rat) {
func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Dec) {
// bondedShare/delegatedShare
exRate := v.DelegatorShareExRate()
amountRat := sdk.NewRat(amount)
amountDec := sdk.NewDec(amount)
if v.Status == sdk.Bonded {
pool = pool.looseTokensToBonded(amountRat)
pool = pool.looseTokensToBonded(amountDec)
}
v.Tokens = v.Tokens.Add(amountRat)
issuedShares := amountRat.Quo(exRate)
v.Tokens = v.Tokens.Add(amountDec)
issuedShares := amountDec.Quo(exRate)
v.DelegatorShares = v.DelegatorShares.Add(issuedShares)
return v, pool, issuedShares
}
// RemoveDelShares removes delegator shares from a validator.
func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Rat) (Validator, Pool, sdk.Rat) {
func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Dec) (Validator, Pool, sdk.Dec) {
issuedTokens := v.DelegatorShareExRate().Mul(delShares)
v.Tokens = v.Tokens.Sub(issuedTokens)
v.DelegatorShares = v.DelegatorShares.Sub(delShares)
@ -410,19 +408,19 @@ func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Rat) (Validator, Poo
// DelegatorShareExRate gets the exchange rate of tokens over delegator shares.
// UNITS: tokens/delegator-shares
func (v Validator) DelegatorShareExRate() sdk.Rat {
func (v Validator) DelegatorShareExRate() sdk.Dec {
if v.DelegatorShares.IsZero() {
return sdk.OneRat()
return sdk.OneDec()
}
return v.Tokens.Quo(v.DelegatorShares)
}
// Get the bonded tokens which the validator holds
func (v Validator) BondedTokens() sdk.Rat {
func (v Validator) BondedTokens() sdk.Dec {
if v.Status == sdk.Bonded {
return v.Tokens
}
return sdk.ZeroRat()
return sdk.ZeroDec()
}
//______________________________________________________________________
@ -434,9 +432,9 @@ var _ sdk.Validator = Validator{}
func (v Validator) GetRevoked() bool { return v.Revoked }
func (v Validator) GetMoniker() string { return v.Description.Moniker }
func (v Validator) GetStatus() sdk.BondStatus { return v.Status }
func (v Validator) GetOwner() sdk.AccAddress { return v.Owner }
func (v Validator) GetOperator() sdk.AccAddress { return v.Operator }
func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey }
func (v Validator) GetPower() sdk.Rat { return v.BondedTokens() }
func (v Validator) GetTokens() sdk.Rat { return v.Tokens }
func (v Validator) GetDelegatorShares() sdk.Rat { return v.DelegatorShares }
func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() }
func (v Validator) GetTokens() sdk.Dec { return v.Tokens }
func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }
func (v Validator) GetBondHeight() int64 { return v.BondHeight }

View File

@ -72,22 +72,22 @@ func TestABCIValidatorZero(t *testing.T) {
func TestRemoveTokens(t *testing.T) {
validator := Validator{
Owner: addr1,
Operator: addr1,
PubKey: pk1,
Status: sdk.Bonded,
Tokens: sdk.NewRat(100),
DelegatorShares: sdk.NewRat(100),
Tokens: sdk.NewDec(100),
DelegatorShares: sdk.NewDec(100),
}
pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10)
pool.LooseTokens = sdk.NewDec(10)
pool.BondedTokens = validator.BondedTokens()
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
require.Equal(t, sdk.Bonded, validator.Status)
// remove tokens and test check everything
validator, pool = validator.RemoveTokens(pool, sdk.NewRat(10))
validator, pool = validator.RemoveTokens(pool, sdk.NewDec(10))
require.Equal(t, int64(90), validator.Tokens.RoundInt64())
require.Equal(t, int64(90), pool.BondedTokens.RoundInt64())
require.Equal(t, int64(20), pool.LooseTokens.RoundInt64())
@ -98,7 +98,7 @@ func TestRemoveTokens(t *testing.T) {
require.Equal(t, int64(0), pool.BondedTokens.RoundInt64())
require.Equal(t, int64(110), pool.LooseTokens.RoundInt64())
validator, pool = validator.RemoveTokens(pool, sdk.NewRat(10))
validator, pool = validator.RemoveTokens(pool, sdk.NewDec(10))
require.Equal(t, int64(80), validator.Tokens.RoundInt64())
require.Equal(t, int64(0), pool.BondedTokens.RoundInt64())
require.Equal(t, int64(110), pool.LooseTokens.RoundInt64())
@ -106,61 +106,61 @@ func TestRemoveTokens(t *testing.T) {
func TestAddTokensValidatorBonded(t *testing.T) {
pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10)
pool.LooseTokens = sdk.NewDec(10)
validator := NewValidator(addr1, pk1, Description{})
validator, pool = validator.UpdateStatus(pool, sdk.Bonded)
validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate())
require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate())
assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares))
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens()))
assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens()))
}
func TestAddTokensValidatorUnbonding(t *testing.T) {
pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10)
pool.LooseTokens = sdk.NewDec(10)
validator := NewValidator(addr1, pk1, Description{})
validator, pool = validator.UpdateStatus(pool, sdk.Unbonding)
validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate())
require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate())
assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares))
assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
assert.Equal(t, sdk.Unbonding, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
}
func TestAddTokensValidatorUnbonded(t *testing.T) {
pool := InitialPool()
pool.LooseTokens = sdk.NewRat(10)
pool.LooseTokens = sdk.NewDec(10)
validator := NewValidator(addr1, pk1, Description{})
validator, pool = validator.UpdateStatus(pool, sdk.Unbonded)
validator, pool, delShares := validator.AddTokensFromDel(pool, 10)
require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate())
require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate())
assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares))
assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares))
assert.Equal(t, sdk.Unbonded, validator.Status)
assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens))
assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens))
}
// TODO refactor to make simpler like the AddToken tests above
func TestRemoveDelShares(t *testing.T) {
valA := Validator{
Owner: addr1,
Operator: addr1,
PubKey: pk1,
Status: sdk.Bonded,
Tokens: sdk.NewRat(100),
DelegatorShares: sdk.NewRat(100),
Tokens: sdk.NewDec(100),
DelegatorShares: sdk.NewDec(100),
}
poolA := InitialPool()
poolA.LooseTokens = sdk.NewRat(10)
poolA.LooseTokens = sdk.NewDec(10)
poolA.BondedTokens = valA.BondedTokens()
require.Equal(t, valA.DelegatorShareExRate(), sdk.OneRat())
require.Equal(t, valA.DelegatorShareExRate(), sdk.OneDec())
// Remove delegator shares
valB, poolB, coinsB := valA.RemoveDelShares(poolA, sdk.NewRat(10))
valB, poolB, coinsB := valA.RemoveDelShares(poolA, sdk.NewDec(10))
assert.Equal(t, int64(10), coinsB.RoundInt64())
assert.Equal(t, int64(90), valB.DelegatorShares.RoundInt64())
assert.Equal(t, int64(90), valB.BondedTokens().RoundInt64())
@ -168,37 +168,42 @@ func TestRemoveDelShares(t *testing.T) {
assert.Equal(t, int64(20), poolB.LooseTokens.RoundInt64())
// conservation of tokens
require.True(sdk.RatEq(t,
require.True(sdk.DecEq(t,
poolB.LooseTokens.Add(poolB.BondedTokens),
poolA.LooseTokens.Add(poolA.BondedTokens)))
// specific case from random tests
poolTokens := sdk.NewRat(5102)
delShares := sdk.NewRat(115)
poolTokens := sdk.NewDec(5102)
delShares := sdk.NewDec(115)
validator := Validator{
Owner: addr1,
Operator: addr1,
PubKey: pk1,
Status: sdk.Bonded,
Tokens: poolTokens,
DelegatorShares: delShares,
}
pool := Pool{
BondedTokens: sdk.NewRat(248305),
LooseTokens: sdk.NewRat(232147),
BondedTokens: sdk.NewDec(248305),
LooseTokens: sdk.NewDec(232147),
InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewRat(7, 100),
Inflation: sdk.NewDecWithPrec(7, 2),
}
shares := sdk.NewRat(29)
shares := sdk.NewDec(29)
_, newPool, tokens := validator.RemoveDelShares(pool, shares)
require.True(sdk.RatEq(t, sdk.NewRat(147958, 115), tokens))
require.True(sdk.RatEq(t,
exp, err := sdk.NewDecFromStr("1286.5913043477")
require.NoError(t, err)
require.True(sdk.DecEq(t, exp, tokens))
require.True(sdk.DecEq(t,
newPool.LooseTokens.Add(newPool.BondedTokens),
pool.LooseTokens.Add(pool.BondedTokens)))
}
func TestUpdateStatus(t *testing.T) {
pool := InitialPool()
pool.LooseTokens = sdk.NewRat(100)
pool.LooseTokens = sdk.NewDec(100)
validator := NewValidator(addr1, pk1, Description{})
validator, pool, _ = validator.AddTokensFromDel(pool, 100)
@ -221,27 +226,27 @@ func TestUpdateStatus(t *testing.T) {
}
func TestPossibleOverflow(t *testing.T) {
poolTokens := sdk.NewRat(2159)
delShares := sdk.NewRat(391432570689183511).Quo(sdk.NewRat(40113011844664))
poolTokens := sdk.NewDec(2159)
delShares := sdk.NewDec(391432570689183511).Quo(sdk.NewDec(40113011844664))
validator := Validator{
Owner: addr1,
Operator: addr1,
PubKey: pk1,
Status: sdk.Bonded,
Tokens: poolTokens,
DelegatorShares: delShares,
}
pool := Pool{
LooseTokens: sdk.NewRat(100),
LooseTokens: sdk.NewDec(100),
BondedTokens: poolTokens,
InflationLastTime: time.Unix(0, 0),
Inflation: sdk.NewRat(7, 100),
Inflation: sdk.NewDecWithPrec(7, 2),
}
tokens := int64(71)
msg := fmt.Sprintf("validator %#v", validator)
newValidator, _, _ := validator.AddTokensFromDel(pool, tokens)
msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg)
require.False(t, newValidator.DelegatorShareExRate().LT(sdk.ZeroRat()),
require.False(t, newValidator.DelegatorShareExRate().LT(sdk.ZeroDec()),
"Applying operation \"%s\" resulted in negative DelegatorShareExRate(): %v",
msg, newValidator.DelegatorShareExRate())
}