From f18c01d2919d867b631a6d868c5fa725606fc437 Mon Sep 17 00:00:00 2001 From: Zach Date: Mon, 13 Aug 2018 07:15:01 -0400 Subject: [PATCH 01/19] Merge PR #1994: Delete install.md --- docs/install.md | 59 ------------------------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 docs/install.md diff --git a/docs/install.md b/docs/install.md deleted file mode 100644 index bafdfc4bd..000000000 --- a/docs/install.md +++ /dev/null @@ -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 -``` From 1a64c8747cbe1d0717aa93dabe393997f99e2027 Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Mon, 13 Aug 2018 13:21:05 +0200 Subject: [PATCH 02/19] Merge PR #1995: upgrading ledger goclient lib --- Gopkg.lock | 4 ++-- Gopkg.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 8fcb2fb5e..3383e6659 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -490,11 +490,11 @@ version = "v0.23.0" [[projects]] - digest = "1:5bd938386bd1f61a581bf8cd6ff2b7b2f79c542929176db4ceb44965440dae07" + digest = "1:2ea7665579c64cda1873a395de97a2af02df1d06f4cb52128caf57f13249303c" name = "github.com/zondax/ledger-goclient" packages = ["."] pruneopts = "UT" - revision = "39ba4728c137c75718a21f9b4b3280fa31b9139b" + revision = "a05312e1c998ad831b70eea41d009654f7f95985" [[projects]] branch = "master" diff --git a/Gopkg.toml b/Gopkg.toml index 1c7019ae6..63356c240 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -65,7 +65,7 @@ [[constraint]] name = "github.com/zondax/ledger-goclient" - revision = "39ba4728c137c75718a21f9b4b3280fa31b9139b" + revision = "a05312e1c998ad831b70eea41d009654f7f95985" [prune] go-tests = true From 36b54e190f9e902b8a1610a29bf7ae00920d9bb3 Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Mon, 13 Aug 2018 18:15:55 +0200 Subject: [PATCH 03/19] Merge PR #2003: Update upstream Ledger Go client --- Gopkg.lock | 4 ++-- Gopkg.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 3383e6659..6e45f42b0 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -490,11 +490,11 @@ version = "v0.23.0" [[projects]] - digest = "1:2ea7665579c64cda1873a395de97a2af02df1d06f4cb52128caf57f13249303c" + digest = "1:4dcb0dd65feecb068ce23a234d1a07c7868a1e39f52a6defcae0bb371d03abf6" name = "github.com/zondax/ledger-goclient" packages = ["."] pruneopts = "UT" - revision = "a05312e1c998ad831b70eea41d009654f7f95985" + revision = "4296ee5701e945f9b3a7dbe51f402e0b9be57259" [[projects]] branch = "master" diff --git a/Gopkg.toml b/Gopkg.toml index 63356c240..0651fe1f5 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -65,7 +65,7 @@ [[constraint]] name = "github.com/zondax/ledger-goclient" - revision = "a05312e1c998ad831b70eea41d009654f7f95985" + revision = "4296ee5701e945f9b3a7dbe51f402e0b9be57259" [prune] go-tests = true From 1854430e7b66381400edf6f965d6a3fe18270393 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Mon, 13 Aug 2018 11:42:38 -0700 Subject: [PATCH 04/19] makefile: Improve error message when LEDGER_ENABLED=True & no gcc (#2008) Closes #2005 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 208b59ade..a280a5f1f 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ 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") +$(error "gcc not installed for ledger support, please install or set LEDGER_ENABLED to false in the Makefile") endif else TMP_BUILD_TAGS := $(BUILD_TAGS) From 63713c9378b4d6092669c3542ba106470ec7eaf7 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Tue, 14 Aug 2018 00:06:48 +0200 Subject: [PATCH 05/19] Merge pull request #2000: tests for staking lcd * Added tests for Delegator Validators routes * Updated tests for undelegations * Updated Gaia-lite docs * Updated PENDING.md * Updated comments * Deleted more comments * Add spacing --- PENDING.md | 17 +++-- client/lcd/lcd_test.go | 131 ++++++++++++++++++++------------- docs/clients/lcd-rest-api.yaml | 43 +++++++++++ docs/light/api.md | 56 ++++++++++++++ docs/light/specification.md | 8 ++ x/stake/client/rest/query.go | 25 +++++-- x/stake/client/rest/utils.go | 4 - 7 files changed, 214 insertions(+), 70 deletions(-) diff --git a/PENDING.md b/PENDING.md index 4ca3e6df5..be173d531 100644 --- a/PENDING.md +++ b/PENDING.md @@ -1,15 +1,15 @@ -## v0.24.0 PENDING +## v0.24.0 PENDING ^--- PENDING wasn't purged on sdk v0.23.0 release. BREAKING CHANGES -* Update to tendermint v0.23.0. This involves removing crypto.Pubkey, +* Update to tendermint v0.23.0. This involves removing crypto.Pubkey, maintaining a validator address to pubkey map, and using time.Time instead of int64 for time. [SDK PR](https://github.com/cosmos/cosmos-sdk/pull/1927) ## PENDING BREAKING CHANGES * API - - \#1880 [x/stake] changed the endpoints to be more REST-ful + - \#1880 and \#2000 [x/stake] changed the endpoints to be more REST-ful * Update to tendermint v0.22.5. This involves changing all of the cryptography imports. [Ref](https://github.com/tendermint/tendermint/pull/1966) * [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()` * [x/gov] CLI flag changed from `proposalID` to `proposal-id` @@ -32,7 +32,7 @@ BREAKING CHANGES * `gaiacli gov submit-proposal --proposer` * `gaiacli gov deposit --depositer` * `gaiacli gov vote --voter` -* [x/gov] Added tags sub-package, changed tags to use dash-case +* [x/gov] Added tags sub-package, changed tags to use dash-case * [x/gov] Governance parameters are now stored in globalparams store * [lcd] \#1866 Updated lcd /slashing/signing_info endpoint to take cosmosvalpub instead of cosmosvaladdr * [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64 @@ -46,7 +46,7 @@ FEATURES * Modules can test random combinations of their own operations * Applications can integrate operations and invariants from modules together for an integrated simulation * [baseapp] Initialize validator set on ResponseInitChain -* [cosmos-sdk-cli] Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd +* [cosmos-sdk-cli] Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd * This allows SDK users to initialize a new project repository. * [tests] Remotenet commands for AWS (awsnet) * [networks] Added ansible scripts to upgrade seed nodes on a network @@ -62,7 +62,7 @@ IMPROVEMENTS * [cli] Improve error messages for all txs when the account doesn't exist * [tools] Remove `rm -rf vendor/` from `make get_vendor_deps` * [x/auth] Recover ErrorOutOfGas panic in order to set sdk.Result attributes correctly -* [x/stake] Add revoked to human-readable validator +* [x/stake] Add revoked to human-readable validator * [spec] \#967 Inflation and distribution specs drastically improved * [tests] Add tests to example apps in docs * [x/gov] Votes on a proposal can now be queried @@ -70,8 +70,9 @@ IMPROVEMENTS * [tests] Fixes ansible scripts to work with AWS too * [tests] \#1806 CLI tests are now behind the build flag 'cli_test', so go test works on a new repo * [x/gov] Initial governance parameters can now be set in the genesis file -* [x/stake] \#1815 Sped up the processing of `EditValidator` txs. +* [x/stake] \#1815 Sped up the processing of `EditValidator` txs. * [server] \#1930 Transactions indexer indexes all tags by default. +* [x/stake] \#2000 Added tests for new staking endpoints BUG FIXES * \#1666 Add intra-tx counter to the genesis validators @@ -83,7 +84,7 @@ BUG FIXES * \#1828 Force user to specify amount on create-validator command by removing default * \#1839 Fixed bug where intra-tx counter wasn't set correctly for genesis validators * [staking] [#1858](https://github.com/cosmos/cosmos-sdk/pull/1858) Fixed bug where the cliff validator was not be updated correctly -* [tests] \#1675 Fix non-deterministic `test_cover` +* [tests] \#1675 Fix non-deterministic `test_cover` * [client] \#1551: Refactored `CoreContext` * Renamed `CoreContext` to `QueryContext` * Removed all tx related fields and logic (building & signing) to separate diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index cbc1a2c20..9b8c5e439 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -385,64 +385,70 @@ func TestValidatorQuery(t *testing.T) { 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()) + validator := getValidator(t, port, validator1Owner) - // create bond TX - resultTx := doDelegate(t, port, seed, name, password, addr, validator1Owner) + resultTx := doDelegate(t, port, seed, name, password, addr, validator1Owner, 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) 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, validator1Owner, bondedValidators[0].Owner) + require.Equal(t, validator.DelegatorShares.Add(sdk.NewRat(60)).FloatString(), bondedValidators[0].DelegatorShares.FloatString()) + + bondedValidator := getDelegatorValidator(t, port, addr, validator1Owner) + require.Equal(t, validator1Owner, bondedValidator.Owner) + ////////////////////// // testing unbonding - // create unbond TX - resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Owner) + resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Owner, 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, validator1Owner) + 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() diff --git a/docs/clients/lcd-rest-api.yaml b/docs/clients/lcd-rest-api.yaml index 063e3a55b..3b8349f4b 100644 --- a/docs/clients/lcd-rest-api.yaml +++ b/docs/clients/lcd-rest-api.yaml @@ -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 diff --git a/docs/light/api.md b/docs/light/api.md index 41abed5da..d4e66eaf1 100644 --- a/docs/light/api.md +++ b/docs/light/api.md @@ -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 diff --git a/docs/light/specification.md b/docs/light/specification.md index d8897b244..15f36b014 100644 --- a/docs/light/specification.md +++ b/docs/light/specification.md @@ -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 diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index ac660f98f..1741f8823 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -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= // 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 diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index 86e714662..da00eda0b 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -29,7 +29,6 @@ func contains(stringSlice []string, txType string) bool { func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAccAddr sdk.AccAddress) ( validator 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) @@ -46,7 +45,6 @@ func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegator return types.BechValidator{}, http.StatusInternalServerError, "Error: ", err } if len(kvs) == 0 { - // the query will return empty if there are no delegations return types.BechValidator{}, http.StatusNoContent, "", nil } @@ -65,7 +63,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 } @@ -93,7 +90,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 } From 8fa2c3b4ea422940628d2813007b8d486b83ca3c Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 14 Aug 2018 01:23:42 -0700 Subject: [PATCH 06/19] Merge PR #1984: Replace _ with - in command names Closes #1955 --- PENDING.md | 1 + cmd/gaia/cli_test/cli_test.go | 6 +++--- docs/getting-started/full-node.md | 2 +- docs/sdk/clients.md | 10 +++++----- docs/validators/validator-setup.md | 6 +++--- examples/README.md | 2 +- .../remote/ansible/roles/upgrade-gaiad/tasks/main.yml | 2 +- server/tm_cmds.go | 6 +++--- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/PENDING.md b/PENDING.md index be173d531..a20dac238 100644 --- a/PENDING.md +++ b/PENDING.md @@ -38,6 +38,7 @@ BREAKING CHANGES * [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64 * [cli] #1551: Officially removed `--name` from CLI commands * [cli] Genesis/key creation (`init`) now supports user-provided key passwords +* [cli] unsafe_reset_all, show_validator, and show_node_id have been renamed to unsafe-reset-all, show-validator, and show-node-id FEATURES * [lcd] Can now query governance proposals by ProposalStatus diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 8d652bc43..ea4f2e47d 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -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)) @@ -153,7 +153,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { } 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)) diff --git a/docs/getting-started/full-node.md b/docs/getting-started/full-node.md index 1add3f8c0..87c28581b 100644 --- a/docs/getting-started/full-node.md +++ b/docs/getting-started/full-node.md @@ -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, diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index f24f5b46d..5d02548a2 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -29,7 +29,7 @@ There are three types of key representations that are used: - `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 @@ -59,7 +59,7 @@ gaiacli keys list View the validator pubkey for your node by typing: ```bash -gaiad tendermint show_validator +gaiad tendermint show-validator ``` ::: danger Warning @@ -120,7 +120,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) \ + --address-validator=$(gaiad tendermint show-validator) \ --name= \ --chain-id=gaia-7005 ``` @@ -137,7 +137,7 @@ If for any reason the validator misbehaves, or you want to unbond a certain amou ```bash gaiacli stake unbond begin \ - --address-validator=$(gaiad tendermint show_validator) \ + --address-validator=$(gaiad tendermint show-validator) \ --shares=MAX \ --name= \ --chain-id=gaia-7005 @@ -152,7 +152,7 @@ gaiacli account gaiacli stake delegation \ --address-delegator= \ - --address-validator=$(gaiad tendermint show_validator) \ + --address-validator=$(gaiad tendermint show-validator) \ --chain-id=gaia-7005 ``` diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index bac2c441d..dc3bf147f 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -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= --moniker="choose a moniker" \ --chain-id=gaia-7005 \ @@ -70,7 +70,7 @@ gaiacli stake validator \ 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. diff --git a/examples/README.md b/examples/README.md index 8625cead6..33af1b328 100644 --- a/examples/README.md +++ b/examples/README.md @@ -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 ``` diff --git a/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml b/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml index 03bdf40e0..ad705ada5 100644 --- a/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml +++ b/networks/remote/ansible/roles/upgrade-gaiad/tasks/main.yml @@ -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 diff --git a/server/tm_cmds.go b/server/tm_cmds.go index 25d417a66..f852b4029 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -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 From 9997ea22439bdaf374a163716e33f5aa09302662 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 14 Aug 2018 01:35:08 -0700 Subject: [PATCH 07/19] Merge PR #2016: dep: Fix error with scratch directory If dep already sees its scratch directory (.vendor-new), dep ensure fails. This rm -rf's that directory so make get_vendor_deps doesn't fail. --- Makefile | 1 + PENDING.md | 1 + 2 files changed, 2 insertions(+) diff --git a/Makefile b/Makefile index a280a5f1f..e0336aeb4 100644 --- a/Makefile +++ b/Makefile @@ -100,6 +100,7 @@ get_dev_tools: get_vendor_deps: @echo "--> Running dep ensure" + @rm -rf .vendor-new @dep ensure -v draw_deps: diff --git a/PENDING.md b/PENDING.md index a20dac238..d52799496 100644 --- a/PENDING.md +++ b/PENDING.md @@ -74,6 +74,7 @@ IMPROVEMENTS * [x/stake] \#1815 Sped up the processing of `EditValidator` txs. * [server] \#1930 Transactions indexer indexes all tags by default. * [x/stake] \#2000 Added tests for new staking endpoints +* [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. BUG FIXES * \#1666 Add intra-tx counter to the genesis validators From 0adbd60dfa9f0e851c1b2d3f7ada5392b5469ff4 Mon Sep 17 00:00:00 2001 From: Avi Saranga Date: Tue, 14 Aug 2018 01:39:27 -0700 Subject: [PATCH 08/19] Merge PR #1989: Openbsd support --- Makefile | 17 ++++++++++++----- PENDING.md | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index e0336aeb4..28b4256fb 100644 --- a/Makefile +++ b/Makefile @@ -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 or set LEDGER_ENABLED to false in the Makefile") -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 diff --git a/PENDING.md b/PENDING.md index d52799496..c9df61865 100644 --- a/PENDING.md +++ b/PENDING.md @@ -77,6 +77,7 @@ IMPROVEMENTS * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. BUG FIXES +* \#1988 Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988) * \#1666 Add intra-tx counter to the genesis validators * \#1797 Fix off-by-one error in slashing for downtime * \#1787 Fixed bug where Tally fails due to revoked/unbonding validator From d9dc061b4fdc823b852bb2404837d9b7a89fa44c Mon Sep 17 00:00:00 2001 From: Rigel Date: Tue, 14 Aug 2018 20:15:02 -0400 Subject: [PATCH 09/19] Merge pull request #1819: rational -> decimal * changelog * ... * decimal func working * decimal complete, untested * fixing tests * decimal compile errors resolved * test compile errors * precision multiplier test * 1% laptop battery * fixed TestNewDecFromStr * equalities working * fix bankers round chop * ... * working, some decimal issues resolved * fix rounding error * rounding works * decimal works * ... * deleted rational * rational conversion working * revert changelog * code compiles (not tests) * went through all NewDec, made sure they were converted from NewRat properly * test debugging * all testing bugs besides the json marshalling fixed * json unmarshal * lint * document update * fix lcd test * cli test fix * mostly undo Dece -> Rate * val comments * Efficiency improvements This now caches all of the precision multipliers (as they were all used in non-mutative functions), and caches the precisionInt calculation. (Now it just copies the already calculated value) * Cache another precisionInt() call. * Improve banker rounding efficiency * remove defer, make negation in-place. * chris val comments * bez comments * Aditya comments * ... * val comments * rebasing start * ... * compiling * tests pass * cli fix * anton, cwgoes, val comments * val and jae comments * type * undo reuse quo --- PENDING.md | 1 + client/lcd/test_helpers.go | 2 +- cmd/gaia/app/genesis.go | 6 +- cmd/gaia/app/sim_test.go | 2 +- cmd/gaia/cli_test/cli_test.go | 4 +- docs/spec/governance/state.md | 18 +- docs/spec/inflation/state.md | 2 +- docs/spec/staking/end_block.md | 1 - docs/spec/staking/state.md | 30 +- docs/spec/staking/transactions.md | 12 +- examples/democoin/mock/validator.go | 18 +- .../democoin/x/assoc/validator_set_test.go | 4 +- examples/democoin/x/oracle/README.md | 2 +- examples/democoin/x/oracle/handler.go | 2 +- examples/democoin/x/oracle/keeper.go | 8 +- examples/democoin/x/oracle/oracle_test.go | 10 +- types/decimal.go | 418 ++++++++++++++++++ types/decimal_test.go | 301 +++++++++++++ types/rational.go | 262 ----------- types/rational_test.go | 402 ----------------- types/stake.go | 12 +- x/distribution/keeper.go | 4 +- x/distribution/keeper_test.go | 8 +- x/distribution/movement.go | 14 +- x/distribution/types.go | 22 +- x/gov/genesis.go | 6 +- x/gov/procedures.go | 6 +- x/gov/proposals.go | 16 +- x/gov/tally.go | 22 +- x/gov/test_common.go | 2 +- x/params/keeper.go | 12 +- x/params/keeper_test.go | 14 +- x/slashing/app_test.go | 4 +- x/slashing/handler_test.go | 2 +- x/slashing/keeper_test.go | 12 +- x/slashing/params.go | 18 +- x/slashing/test_common.go | 2 +- x/slashing/tick_test.go | 2 +- x/stake/app_test.go | 18 +- x/stake/client/cli/tx.go | 12 +- x/stake/client/rest/query.go | 2 +- x/stake/client/rest/tx.go | 5 +- x/stake/client/rest/utils.go | 2 +- x/stake/genesis_test.go | 20 +- x/stake/handler_test.go | 66 +-- x/stake/keeper/delegation.go | 10 +- x/stake/keeper/delegation_test.go | 32 +- x/stake/keeper/keeper_test.go | 2 +- x/stake/keeper/sdk_types.go | 2 +- x/stake/keeper/slash.go | 24 +- x/stake/keeper/slash_test.go | 58 +-- x/stake/keeper/test_common.go | 10 +- x/stake/keeper/validator_test.go | 100 ++--- x/stake/simulation/invariants.go | 4 +- x/stake/simulation/msgs.go | 6 +- x/stake/types/delegation.go | 14 +- x/stake/types/delegation_test.go | 18 +- x/stake/types/errors.go | 7 - x/stake/types/inflation_test.go | 65 +-- x/stake/types/msg.go | 26 +- x/stake/types/msg_test.go | 26 +- x/stake/types/params.go | 16 +- x/stake/types/pool.go | 50 +-- x/stake/types/pool_test.go | 22 +- x/stake/types/validator.go | 88 ++-- x/stake/types/validator_test.go | 79 ++-- 66 files changed, 1254 insertions(+), 1213 deletions(-) create mode 100644 types/decimal.go create mode 100644 types/decimal_test.go delete mode 100644 types/rational.go delete mode 100644 types/rational_test.go diff --git a/PENDING.md b/PENDING.md index c9df61865..4fcc0c6a9 100644 --- a/PENDING.md +++ b/PENDING.md @@ -34,6 +34,7 @@ BREAKING CHANGES * `gaiacli gov vote --voter` * [x/gov] Added tags sub-package, changed tags to use dash-case * [x/gov] Governance parameters are now stored in globalparams store +* [core] \#1807 Switch from use of rational to decimal * [lcd] \#1866 Updated lcd /slashing/signing_info endpoint to take cosmosvalpub instead of cosmosvaladdr * [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64 * [cli] #1551: Officially removed `--name` from CLI commands diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index ee46b267d..818eae1e8 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -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) diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 1731fe2dc..e35b21c4b 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -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,10 +193,10 @@ 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) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index f0bea1e17..6369b4ca6 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -48,7 +48,7 @@ func appStateFn(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage { // Default genesis state stakeGenesis := stake.DefaultGenesisState() - stakeGenesis.Pool.LooseTokens = sdk.NewRat(1000) + stakeGenesis.Pool.LooseTokens = sdk.NewDec(1000) genesis := GenesisState{ Accounts: genesisAccounts, StakeData: stakeGenesis, diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index ea4f2e47d..244a9eb83 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -132,7 +132,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { 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.True(sdk.DecEq(t, sdk.NewDec(2), validator.Tokens)) // unbond a single share unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags) @@ -149,7 +149,7 @@ 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) { diff --git a/docs/spec/governance/state.md b/docs/spec/governance/state.md index c61fd1e3f..728ded371 100644 --- a/docs/spec/governance/state.md +++ b/docs/spec/governance/state.md @@ -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 diff --git a/docs/spec/inflation/state.md b/docs/spec/inflation/state.md index dea10c046..c16286804 100644 --- a/docs/spec/inflation/state.md +++ b/docs/spec/inflation/state.md @@ -7,7 +7,7 @@ The current annual inflation rate. ```golang -type Inflation sdk.Rat +type Inflation sdk.Dec ``` ### InflationLastTime diff --git a/docs/spec/staking/end_block.md b/docs/spec/staking/end_block.md index b40b06b92..0eb557fec 100644 --- a/docs/spec/staking/end_block.md +++ b/docs/spec/staking/end_block.md @@ -16,4 +16,3 @@ EndBlock() ValidatorSetChanges ClearTendermintUpdates() return vsc ``` - diff --git a/docs/spec/staking/state.md b/docs/spec/staking/state.md index 376a38ced..46f18ed78 100644 --- a/docs/spec/staking/state.md +++ b/docs/spec/staking/state.md @@ -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 } ``` diff --git a/docs/spec/staking/transactions.md b/docs/spec/staking/transactions.md index 4f2567958..d1b6a3626 100644 --- a/docs/spec/staking/transactions.md +++ b/docs/spec/staking/transactions.md @@ -18,7 +18,7 @@ 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 @@ -34,9 +34,9 @@ type TxCreateValidator struct { SelfDelegation coin.Coin Description Description - Commission sdk.Rat - CommissionMax sdk.Rat - CommissionMaxChange sdk.Rat + Commission sdk.Dec + CommissionMax sdk.Dec + CommissionMaxChange sdk.Dec } @@ -65,7 +65,7 @@ If either the `Description` (excluding `DateBonded` which is constant), ```golang type TxEditCandidacy struct { GovernancePubKey crypto.PubKey - Commission sdk.Rat + Commission sdk.Dec Description Description } @@ -199,7 +199,7 @@ type TxRedelegate struct { DelegatorAddr Address ValidatorFrom Validator ValidatorTo Validator - Shares sdk.Rat + Shares sdk.Dec CompletedTime int64 } diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index 0ef0a2391..789a1cb6a 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -10,7 +10,7 @@ import ( // Validator implements sdk.Validator type Validator struct { Address sdk.AccAddress - Power sdk.Rat + Power sdk.Dec } // Implements sdk.Validator @@ -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") } diff --git a/examples/democoin/x/assoc/validator_set_test.go b/examples/democoin/x/assoc/validator_set_test.go index 2fead3ad2..eac23b25e 100644 --- a/examples/democoin/x/assoc/validator_set_test.go +++ b/examples/democoin/x/assoc/validator_set_test.go @@ -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) diff --git a/examples/democoin/x/oracle/README.md b/examples/democoin/x/oracle/README.md index eec02d724..0cfcb820d 100644 --- a/examples/democoin/x/oracle/README.md +++ b/examples/democoin/x/oracle/README.md @@ -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, diff --git a/examples/democoin/x/oracle/handler.go b/examples/democoin/x/oracle/handler.go index 079f7680f..3c78fc566 100644 --- a/examples/democoin/x/oracle/handler.go +++ b/examples/democoin/x/oracle/handler.go @@ -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) diff --git a/examples/democoin/x/oracle/keeper.go b/examples/democoin/x/oracle/keeper.go index 25554faa8..0406f560a 100644 --- a/examples/democoin/x/oracle/keeper.go +++ b/examples/democoin/x/oracle/keeper.go @@ -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, diff --git a/examples/democoin/x/oracle/oracle_test.go b/examples/democoin/x/oracle/oracle_test.go index c476290f8..f4971c8b1 100644 --- a/examples/democoin/x/oracle/oracle_test.go +++ b/examples/democoin/x/oracle/oracle_test.go @@ -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}) diff --git a/types/decimal.go b/types/decimal.go new file mode 100644 index 000000000..cd5c048e3 --- /dev/null +++ b/types/decimal.go @@ -0,0 +1,418 @@ +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 := chopPrecisionAndRound(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. +// +// TODO We should make this function mutate the input. The functions here +// don't need to allocate different memory for chopped after computing the +// result +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 := big.NewInt(0), 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) + } +} + +// RoundInt64 rounds the decimal using bankers rounding +func (d Dec) RoundInt64() int64 { + chopped := chopPrecisionAndRound(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(chopPrecisionAndRound(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 +} diff --git a/types/decimal_test.go b/types/decimal_test.go new file mode 100644 index 000000000..115eeacb0 --- /dev/null +++ b/types/decimal_test.go @@ -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(), + ) +} diff --git a/types/rational.go b/types/rational.go deleted file mode 100644 index 89cc76968..000000000 --- a/types/rational.go +++ /dev/null @@ -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 -} diff --git a/types/rational_test.go b/types/rational_test.go deleted file mode 100644 index 940de23dc..000000000 --- a/types/rational_test.go +++ /dev/null @@ -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)) - } - -} diff --git a/types/stake.go b/types/stake.go index 4e3cf38a3..acd24a154 100644 --- a/types/stake.go +++ b/types/stake.go @@ -42,9 +42,9 @@ type Validator interface { GetStatus() BondStatus // status of the validator GetOwner() 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 } @@ -68,10 +68,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 } @@ -82,7 +82,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 diff --git a/x/distribution/keeper.go b/x/distribution/keeper.go index 145071719..aba07eaca 100644 --- a/x/distribution/keeper.go +++ b/x/distribution/keeper.go @@ -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() { diff --git a/x/distribution/keeper_test.go b/x/distribution/keeper_test.go index 0d732f8a1..890268060 100644 --- a/x/distribution/keeper_test.go +++ b/x/distribution/keeper_test.go @@ -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) //} diff --git a/x/distribution/movement.go b/x/distribution/movement.go index 03c4de72c..399a25a68 100644 --- a/x/distribution/movement.go +++ b/x/distribution/movement.go @@ -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) diff --git a/x/distribution/types.go b/x/distribution/types.go index f9d4f905f..223410471 100644 --- a/x/distribution/types.go +++ b/x/distribution/types.go @@ -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 //} diff --git a/x/gov/genesis.go b/x/gov/genesis.go index 78b39ff1c..15f952c00 100644 --- a/x/gov/genesis.go +++ b/x/gov/genesis.go @@ -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), }, } } diff --git a/x/gov/procedures.go b/x/gov/procedures.go index f46c2149f..f74091c74 100644 --- a/x/gov/procedures.go +++ b/x/gov/procedures.go @@ -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 diff --git a/x/gov/proposals.go b/x/gov/proposals.go index 0a7f5de70..f05dabd08 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -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(), } } diff --git a/x/gov/tally.go b/x/gov/tally.go index f8a341e1e..fc5b4317b 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -7,20 +7,20 @@ 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) { @@ -28,7 +28,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall Address: validator.GetOwner(), 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 diff --git a/x/gov/test_common.go b/x/gov/test_common.go index df66fa40c..5e7977b50 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -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 { diff --git a/x/params/keeper.go b/x/params/keeper.go index 8817b7c6c..69bcc05ea 100644 --- a/x/params/keeper.go +++ b/x/params/keeper.go @@ -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) } diff --git a/x/params/keeper_test.go b/x/params/keeper_test.go index 4bb5744ea..626d68c7d 100644 --- a/x/params/keeper_test.go +++ b/x/params/keeper_test.go @@ -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) } diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 523a2e220..1e6a4e89d 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -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) @@ -109,7 +109,7 @@ func TestSlashingMsgs(t *testing.T) { validator := checkValidator(t, mapp, stakeKeeper, addr1, true) require.Equal(t, addr1, validator.Owner) 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 diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index 89c1e11a6..41cb5d199 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -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)) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index d3d6b06ed..68de7a43c 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -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) diff --git a/x/slashing/params.go b/x/slashing/params.go index 9d1bc3960..a25d121c9 100644 --- a/x/slashing/params.go +++ b/x/slashing/params.go @@ -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)) ) diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index 7b3ab0436..50c501d7e 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -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) diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index 8e0d66ed6..b230f9c94 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -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(), diff --git a/x/stake/app_test.go b/x/stake/app_test.go index 4e1b2c2ac..9847ed290 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -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 } @@ -138,7 +138,7 @@ func TestStakeMsgs(t *testing.T) { validator := checkValidator(t, mApp, keeper, addr1, true) require.Equal(t, addr1, validator.Owner) 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) @@ -150,10 +150,10 @@ func TestStakeMsgs(t *testing.T) { validator = checkValidator(t, mApp, keeper, addr2, true) require.Equal(t, addr2, validator.Owner) 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)}) diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index 4c86777f3..bf2df4913 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -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)") } diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 1741f8823..b7d2b10a4 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -347,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) diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index fbefc7f21..d8b9b6011 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -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()))) diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index da00eda0b..1a0809089 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -76,7 +76,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 diff --git a/x/stake/genesis_test.go b/x/stake/genesis_test.go index 2febd2c6a..9cdbe1982 100644 --- a/x/stake/genesis_test.go +++ b/x/stake/genesis_test.go @@ -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() } } diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index edad64f44..a06be0f88 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -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) @@ -138,8 +138,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { assert.Equal(t, sdk.Bonded, validator.Status) assert.Equal(t, addr1, validator.Owner) 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 @@ -162,8 +162,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { assert.Equal(t, sdk.Bonded, validator.Status) assert.Equal(t, addr2, validator.Owner) 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) } @@ -182,8 +182,8 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) { assert.Equal(t, sdk.Bonded, validator.Status) assert.Equal(t, validatorAddr, validator.Owner) 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 diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 484e85ad5..4b4d267aa 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -218,7 +218,7 @@ 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) @@ -226,7 +226,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt delegation = types.Delegation{ DelegatorAddr: delegatorAddr, ValidatorAddr: validator.Owner, - Shares: sdk.ZeroRat(), + 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) @@ -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) { diff --git a/x/stake/keeper/delegation_test.go b/x/stake/keeper/delegation_test.go index 5d512f0cf..4333a7494 100644 --- a/x/stake/keeper/delegation_test.go +++ b/x/stake/keeper/delegation_test.go @@ -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]) diff --git a/x/stake/keeper/keeper_test.go b/x/stake/keeper/keeper_test.go index 3f763ea25..9307ddddf 100644 --- a/x/stake/keeper/keeper_test.go +++ b/x/stake/keeper/keeper_test.go @@ -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)) diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 9c3311474..aeec44fae 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -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 } diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index a741b5a85..c1fabe441 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -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 @@ -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) @@ -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 diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index 878c44d1e..444858f29 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -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()) } diff --git a/x/stake/keeper/test_common.go b/x/stake/keeper/test_common.go index 010963034..0470c2898 100644 --- a/x/stake/keeper/test_common.go +++ b/x/stake/keeper/test_common.go @@ -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) } diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index b9e61a101..7b15a9c7f 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -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]) @@ -56,8 +56,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 @@ -76,7 +76,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 @@ -103,8 +103,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) @@ -161,7 +161,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) @@ -178,13 +178,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]) @@ -193,7 +193,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]) @@ -205,15 +205,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) @@ -256,19 +256,19 @@ 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, 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].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) @@ -276,14 +276,14 @@ func GetValidatorSortingUnmixed(t *testing.T) { assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%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) @@ -291,7 +291,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) @@ -310,8 +310,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) @@ -338,20 +338,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]) @@ -375,11 +375,11 @@ 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, 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].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) @@ -444,7 +444,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) @@ -656,7 +656,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) @@ -794,21 +794,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) diff --git a/x/stake/simulation/invariants.go b/x/stake/simulation/invariants.go index e4869693c..654d5560b 100644 --- a/x/stake/simulation/invariants.go +++ b/x/stake/simulation/invariants.go @@ -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 @@ -67,7 +67,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 }) } diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index e4077a749..f402d765f 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -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() @@ -247,7 +247,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) } } diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 77fd327a5..78111c030 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -16,12 +16,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 } @@ -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 @@ -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 diff --git a/x/stake/types/delegation_test.go b/x/stake/types/delegation_test.go index 69823db14..5624b7101 100644 --- a/x/stake/types/delegation_test.go +++ b/x/stake/types/delegation_test.go @@ -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 diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index b3e279c8e..1595a70d9 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -100,13 +100,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") } diff --git a/x/stake/types/inflation_test.go b/x/stake/types/inflation_test.go index 0114b1e05..fd181af3c 100644 --- a/x/stake/types/inflation_test.go +++ b/x/stake/types/inflation_test.go @@ -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) } } } diff --git a/x/stake/types/msg.go b/x/stake/types/msg.go index 27edad5dd..282000294 100644 --- a/x/stake/types/msg.go +++ b/x/stake/types/msg.go @@ -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 } diff --git a/x/stake/types/msg_test.go b/x/stake/types/msg_test.go index 82f92d9f3..2be34fb20 100644 --- a/x/stake/types/msg_test.go +++ b/x/stake/types/msg_test.go @@ -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 { diff --git a/x/stake/types/params.go b/x/stake/types/params.go index 0ae1ade09..f297f3105 100644 --- a/x/stake/types/params.go +++ b/x/stake/types/params.go @@ -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", diff --git a/x/stake/types/pool.go b/x/stake/types/pool.go index 5aab4294b..d59c1ed25 100644 --- a/x/stake/types/pool.go +++ b/x/stake/types/pool.go @@ -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 } diff --git a/x/stake/types/pool_test.go b/x/stake/types/pool_test.go index 43a2eac06..4541edd3d 100644 --- a/x/stake/types/pool_test.go +++ b/x/stake/types/pool_test.go @@ -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)) } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 837b8f8e8..c9626b5ec 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -26,21 +26,21 @@ type Validator struct { 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 @@ -50,17 +50,17 @@ func NewValidator(owner sdk.AccAddress, pubKey crypto.PubKey, description Descri 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 +69,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 @@ -159,8 +159,8 @@ func (v Validator) HumanReadableString() (string, error) { 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()) @@ -182,21 +182,21 @@ type BechValidator struct { 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 @@ -364,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) } @@ -376,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) @@ -408,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,7 +434,7 @@ 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) 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 } diff --git a/x/stake/types/validator_test.go b/x/stake/types/validator_test.go index f0dff4732..3981f5754 100644 --- a/x/stake/types/validator_test.go +++ b/x/stake/types/validator_test.go @@ -75,19 +75,19 @@ func TestRemoveTokens(t *testing.T) { Owner: 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,43 +106,43 @@ 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 @@ -151,16 +151,16 @@ func TestRemoveDelShares(t *testing.T) { Owner: 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,13 +168,13 @@ 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, PubKey: pk1, @@ -183,22 +183,27 @@ func TestRemoveDelShares(t *testing.T) { 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,8 +226,8 @@ 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, PubKey: pk1, @@ -231,17 +236,17 @@ func TestPossibleOverflow(t *testing.T) { 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()) } From 4b13529f2d40fa17713451cc50756eb8fe53453f Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 14 Aug 2018 18:10:57 -0700 Subject: [PATCH 10/19] Merge pull request #2029: fix build error --- client/lcd/lcd_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 9b8c5e439..c5d567e13 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -415,7 +415,7 @@ func TestBonding(t *testing.T) { bondedValidators := getDelegatorValidators(t, port, addr) require.Len(t, bondedValidators, 1) require.Equal(t, validator1Owner, bondedValidators[0].Owner) - require.Equal(t, validator.DelegatorShares.Add(sdk.NewRat(60)).FloatString(), bondedValidators[0].DelegatorShares.FloatString()) + require.Equal(t, validator.DelegatorShares.Add(sdk.NewDec(60)).String(), bondedValidators[0].DelegatorShares.String()) bondedValidator := getDelegatorValidator(t, port, addr, validator1Owner) require.Equal(t, validator1Owner, bondedValidator.Owner) From d37de06762e0187ada484efc407575d99f193ac3 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 14 Aug 2018 18:49:40 -0700 Subject: [PATCH 11/19] decimal: Remove unnecessary allocation in bankers round chop (#2030) This is done by making the function mutative. A non-mutative variant is created for functions that depend on it being non-mutative. --- types/decimal.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/types/decimal.go b/types/decimal.go index cd5c048e3..baf2d9573 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -249,7 +249,7 @@ func (d Dec) ToLeftPaddedWithDecimals(totalDigits int8) string { // 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 := chopPrecisionAndRound(d.Int) + chopped := chopPrecisionAndRoundNonMutative(d.Int) intStr := chopped.String() fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s` return fmt.Sprintf(fcode, intStr) @@ -268,9 +268,7 @@ func (d Dec) ToLeftPadded(totalDigits int8) string { // Remove a Precision amount of rightmost digits and perform bankers rounding // on the remainder (gaussian rounding) on the digits which have been removed. // -// TODO We should make this function mutate the input. The functions here -// don't need to allocate different memory for chopped after computing the -// result +// 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 @@ -283,7 +281,7 @@ func chopPrecisionAndRound(d *big.Int) *big.Int { } // get the trucated quotient and remainder - quo, rem := big.NewInt(0), big.NewInt(0) + quo, rem := d, big.NewInt(0) quo, rem = quo.QuoRem(d, precisionReuse, rem) if rem.Sign() == 0 { // remainder is zero @@ -304,9 +302,14 @@ func chopPrecisionAndRound(d *big.Int) *big.Int { } } +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 := chopPrecisionAndRound(d.Int) + chopped := chopPrecisionAndRoundNonMutative(d.Int) if !chopped.IsInt64() { panic("Int64() out of bound") } @@ -315,7 +318,7 @@ func (d Dec) RoundInt64() int64 { // RoundInt round the decimal using bankers rounding func (d Dec) RoundInt() Int { - return NewIntFromBigInt(chopPrecisionAndRound(d.Int)) + return NewIntFromBigInt(chopPrecisionAndRoundNonMutative(d.Int)) } //___________________________________________________________________________________ From a4bcbc972e8e73d661f6cce5179f31a6082fa6ff Mon Sep 17 00:00:00 2001 From: Max Levy <35595512+maxim-levy@users.noreply.github.com> Date: Wed, 15 Aug 2018 19:04:16 +0900 Subject: [PATCH 12/19] Merge PR #2036: Update examples to bech32 Using the addresses in Bech32 form --- examples/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/README.md b/examples/README.md index 33af1b328..d12e3d3fc 100644 --- a/examples/README.md +++ b/examples/README.md @@ -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 ``` From 5fff217e9b5ccdfa665590e4ba6fdf2db1679e95 Mon Sep 17 00:00:00 2001 From: Rigel Date: Wed, 15 Aug 2018 09:04:01 -0400 Subject: [PATCH 13/19] Merge PR #2033: staking lcd uses owner address not pubkey address --- client/lcd/lcd_test.go | 5 +-- x/stake/client/rest/query.go | 29 +++++++++--- x/stake/client/rest/utils.go | 86 +++++++++--------------------------- 3 files changed, 44 insertions(+), 76 deletions(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index c5d567e13..db584834a 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -376,11 +376,8 @@ func TestValidatorQuery(t *testing.T) { 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") + assert.Equal(t, validator.Owner, validator1Owner, "The returned validator does not hold the correct data") } func TestBonding(t *testing.T) { diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index b7d2b10a4..4dfaa0f7f 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -507,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()))) diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index 1a0809089..96588f73b 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -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,33 +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) { - 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 { + 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) ( @@ -104,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 } @@ -114,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 } @@ -156,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 { From 97ea51a3357da5041948312b1149f62672af5df9 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk Date: Wed, 15 Aug 2018 14:51:19 -0400 Subject: [PATCH 14/19] Merge pull request #2023: Terminate Update Bonded Validators Iteration Properly --- Gopkg.lock | 23 +++++++------- PENDING.md | 1 + x/stake/keeper/validator.go | 60 ++++++++++++++++++++----------------- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 6e45f42b0..de244c162 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -38,7 +38,7 @@ name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" - revision = "cf05f92c3f815bbd5091ed6c73eff51f7b1945e8" + revision = "f899737d7f2764dc13e4d01ff00108ec58f766a9" [[projects]] digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" @@ -165,12 +165,13 @@ [[projects]] branch = "master" - digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" + digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", + "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -340,19 +341,19 @@ [[projects]] branch = "master" - digest = "1:080e5f630945ad754f4b920e60b4d3095ba0237ebf88dc462eb28002932e3805" + digest = "1:8a020f916b23ff574845789daee6818daf8d25a4852419aae3f0b12378ba432a" name = "github.com/spf13/jwalterweatherman" packages = ["."] pruneopts = "UT" - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] - digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7" + digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" name = "github.com/spf13/pflag" packages = ["."] pruneopts = "UT" - revision = "583c0c0531f06d5278b7d917446061adc344b5cd" - version = "v1.0.1" + revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" + version = "v1.0.2" [[projects]] digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96" @@ -517,7 +518,7 @@ "salsa20/salsa", ] pruneopts = "UT" - revision = "f027049dab0ad238e394a753dba2d14753473a04" + revision = "de0752318171da717af4ce24d0a2e8626afaeb11" [[projects]] digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" @@ -537,14 +538,14 @@ [[projects]] branch = "master" - digest = "1:4d64ef38a30b73db6e8e7a2824b7fd356d921e0ee3fdd3248658996821d3b47d" + digest = "1:4bd75b1a219bc590b05c976bbebf47f4e993314ebb5c7cbf2efe05a09a184d54" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945" + revision = "4e1fef5609515ec7a2cee7b5de30ba6d9b438cbf" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" @@ -575,7 +576,7 @@ name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "daca94659cb50e9f37c1b834680f2e46358f10b0" + revision = "383e8b2c3b9e36c4076b235b32537292176bae20" [[projects]] digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" diff --git a/PENDING.md b/PENDING.md index 4fcc0c6a9..8cf301a01 100644 --- a/PENDING.md +++ b/PENDING.md @@ -75,6 +75,7 @@ IMPROVEMENTS * [x/stake] \#1815 Sped up the processing of `EditValidator` txs. * [server] \#1930 Transactions indexer indexes all tags by default. * [x/stake] \#2000 Added tests for new staking endpoints +* [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. * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. BUG FIXES diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index eaaf3df9e..ce5a19061 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -417,20 +417,24 @@ func (k Keeper) UpdateBondedValidators( } } - // increment bondedValidatorsCount / get the validator to bond - if !validator.Revoked { - if validator.Status != sdk.Bonded { - validatorToBond = validator - newValidatorBonded = true + 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 for address: %s\n", ownerAddr)) } - 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() } @@ -468,7 +472,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 @@ -476,27 +479,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)) @@ -506,23 +508,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 @@ -532,7 +537,6 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) { k.clearCliffValidator(ctx) } - // perform the actual kicks kickOutValidators(k, ctx, toKickOut) return } From 4fbaee205f4802e929ad3b24b3520332209b15f7 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 15 Aug 2018 21:49:06 +0200 Subject: [PATCH 15/19] Merge pull request #1997: Handle unmarshalling failures gracefully in x/stake commands * Handle panic gracefully when unbond begin fails See #1831 * Handle failure to query delegation gracefully. Closes #1907 * Update PENDING.md * Reuse stake's error functions * New ErrBadValidatorAddr error UnmarshalValidator() checks the address length first; it does not make sense to attempt unmarshalling if the address is wrong. * New ErrBadDelegationAddr error * Introduce ErrBad{Redelegation,UnbondingDelegation}Addr custom errors to replace errors.New() calls * Replace ErrBadUnbondingDelegationAddr with ErrBadDelegationAddr to avoid duplication Thanks: @melekes for pointing this out * Use sdk.AddrLen instead of hardcoded address length * s/triple/tuple/ ## mention PR id in PENDING.md --- PENDING.md | 1 + x/stake/client/cli/query.go | 5 ++++- x/stake/client/cli/tx.go | 7 ++++--- x/stake/types/delegation.go | 8 ++++---- x/stake/types/errors.go | 13 +++++++++++++ x/stake/types/validator.go | 10 ++++------ 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/PENDING.md b/PENDING.md index 8cf301a01..fc3c674f4 100644 --- a/PENDING.md +++ b/PENDING.md @@ -101,3 +101,4 @@ BUG FIXES * \#1787 Fixed bug where Tally fails due to revoked/unbonding validator * \#1787 Fixed bug where Tally fails due to revoked/unbonding validator * [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) +* [cli] \#1997 Handle panics gracefully when `gaiacli stake {delegation,unbond}` fail to unmarshal delegation. diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index 5ac303f9f..dc2c8e30d 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -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": diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index bf2df4913..5c1eec834 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -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.ZeroRat(), err + } sharesAmount = sharesPercent.Mul(delegation.Shares) } - return } diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 78111c030..e3227c3ed 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -2,7 +2,6 @@ package types import ( "bytes" - "errors" "fmt" "time" @@ -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]) @@ -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]) @@ -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]) diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index 1595a70d9..d44ed411c 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -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") } @@ -118,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") } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index c9626b5ec..bd7d76993 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -2,7 +2,6 @@ package types import ( "bytes" - "errors" "fmt" abci "github.com/tendermint/tendermint/abci/types" @@ -115,17 +114,16 @@ 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) { + if len(ownerAddr) != 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, PubKey: storeValue.PubKey, From 422dfa3de958eb8a009efb8a7940e140cc33f912 Mon Sep 17 00:00:00 2001 From: Rigel Date: Wed, 15 Aug 2018 18:35:17 -0400 Subject: [PATCH 16/19] Merge pr #2051: smol compile bug --- x/stake/client/cli/tx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index 5c1eec834..9f04f2ed2 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -275,7 +275,7 @@ func getShares( } delegation, err := types.UnmarshalDelegation(cdc, key, resQuery) if err != nil { - return sdk.ZeroRat(), err + return sdk.ZeroDec(), err } sharesAmount = sharesPercent.Mul(delegation.Shares) } From 7b5ca5adbdbda0123d389d0866fa9ee415aefe8d Mon Sep 17 00:00:00 2001 From: Zach Date: Thu, 16 Aug 2018 04:16:41 -0700 Subject: [PATCH 17/19] duplicate/old CODEOWNERS (#2055) --- CODEOWNERS | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index 2992bcf66..000000000 --- a/CODEOWNERS +++ /dev/null @@ -1,2 +0,0 @@ -* @jaekwon -* @ebuchman From 187bc1972a73436ef0dcad2deaf8ae03a5206f6e Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 16 Aug 2018 22:47:59 +0200 Subject: [PATCH 18/19] Merge PR #1950: Validator.Owner -> .Operator * Rename --address-validator flag to --validator See #1901 * Update PENDING.md * Rename Validator.Owner -> Validator.Operator See #1901 --- PENDING.md | 3 + client/lcd/lcd_test.go | 31 +++++---- cmd/gaia/app/genesis.go | 4 +- cmd/gaia/cli_test/cli_test.go | 4 +- docs/sdk/clients.md | 10 +-- docs/spec/staking/transactions.md | 100 ++++++++++++++-------------- docs/validators/validator-setup.md | 12 +++- examples/democoin/mock/validator.go | 2 +- types/stake.go | 2 +- x/gov/tally.go | 4 +- x/slashing/app_test.go | 2 +- x/slashing/client/cli/flags.go | 2 +- x/stake/app_test.go | 4 +- x/stake/client/cli/flags.go | 2 +- x/stake/client/rest/query.go | 4 +- x/stake/handler_test.go | 10 +-- x/stake/keeper/_store.md | 18 ++--- x/stake/keeper/delegation.go | 10 +-- x/stake/keeper/slash.go | 8 +-- x/stake/keeper/validator.go | 38 +++++------ x/stake/keeper/validator_test.go | 38 +++++------ x/stake/types/validator.go | 40 +++++------ x/stake/types/validator_test.go | 8 +-- 23 files changed, 186 insertions(+), 170 deletions(-) diff --git a/PENDING.md b/PENDING.md index fc3c674f4..dafd653fe 100644 --- a/PENDING.md +++ b/PENDING.md @@ -40,6 +40,9 @@ BREAKING CHANGES * [cli] #1551: Officially removed `--name` from CLI commands * [cli] Genesis/key creation (`init`) now supports user-provided key passwords * [cli] unsafe_reset_all, show_validator, and show_node_id have been renamed to unsafe-reset-all, show-validator, and show-node-id +* [cli] \#1901 Flag --address-validator renamed to --validator in stake and slashing commands +* [types] \#1901 Validator interface's GetOwner() renamed to GetOperator() +* [x/stake] \#1901 Validator type's Owner field renamed to Operator; Validator's GetOwner() renamed accordingly to comply with the SDK's Validator interface. FEATURES * [lcd] Can now query governance proposals by ProposalStatus diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index db584834a..09c0eddd1 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -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,9 +375,9 @@ func TestValidatorQuery(t *testing.T) { defer cleanup() require.Equal(t, 1, len(pks)) - validator1Owner := sdk.AccAddress(pks[0].Address()) - validator := getValidator(t, port, validator1Owner) - assert.Equal(t, validator.Owner, validator1Owner, "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) { @@ -386,10 +386,11 @@ func TestBonding(t *testing.T) { cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) defer cleanup() - validator1Owner := sdk.AccAddress(pks[0].Address()) - validator := getValidator(t, port, validator1Owner) + validator1Operator := sdk.AccAddress(pks[0].Address()) + validator := getValidator(t, port, validator1Operator) - resultTx := doDelegate(t, port, seed, name, password, addr, validator1Owner, 60) + // create bond TX + resultTx := doDelegate(t, port, seed, name, password, addr, validator1Operator, 60) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) @@ -400,7 +401,8 @@ func TestBonding(t *testing.T) { require.Equal(t, int64(40), coins.AmountOf(denom).Int64()) - bond := getDelegation(t, port, addr, validator1Owner) + // query validator + bond := getDelegation(t, port, addr, validator1Operator) require.Equal(t, "60.0000000000", bond.Shares) summary := getDelegationSummary(t, port, addr) @@ -411,16 +413,17 @@ func TestBonding(t *testing.T) { bondedValidators := getDelegatorValidators(t, port, addr) require.Len(t, bondedValidators, 1) - require.Equal(t, validator1Owner, bondedValidators[0].Owner) + 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, validator1Owner) - require.Equal(t, validator1Owner, bondedValidator.Owner) + bondedValidator := getDelegatorValidator(t, port, addr, validator1Operator) + require.Equal(t, validator1Operator, bondedValidator.Operator) ////////////////////// // testing unbonding - resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Owner, 60) + // create unbond TX + resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Operator, 60) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) @@ -431,7 +434,7 @@ func TestBonding(t *testing.T) { coins = acc.GetCoins() require.Equal(t, int64(40), coins.AmountOf("steak").Int64()) - unbondings := getUndelegations(t, port, addr, validator1Owner) + 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()) diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index e35b21c4b..0399d6652 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -202,8 +202,8 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState // 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, } diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 244a9eb83..4f041d848 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -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.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) diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 5d02548a2..17190d90a 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -120,9 +120,9 @@ 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= \ - --chain-id=gaia-7005 + --chain-id=gaia-6002 ``` While tokens are bonded, they are pooled with all the other bonded tokens in the network. Validators and delegators obtain a percentage of shares that equal their stake in this pool. @@ -137,9 +137,9 @@ If for any reason the validator misbehaves, or you want to unbond a certain amou ```bash gaiacli stake unbond begin \ - --address-validator=$(gaiad tendermint show-validator) \ + --validator=$(gaiad tendermint show-validator) \ --shares=MAX \ - --name= \ + --from= \ --chain-id=gaia-7005 ``` @@ -152,7 +152,7 @@ gaiacli account gaiacli stake delegation \ --address-delegator= \ - --address-validator=$(gaiad tendermint show-validator) \ + --validator=$(gaiad tendermint show-validator) \ --chain-id=gaia-7005 ``` diff --git a/docs/spec/staking/transactions.md b/docs/spec/staking/transactions.md index d1b6a3626..ee2b976ae 100644 --- a/docs/spec/staking/transactions.md +++ b/docs/spec/staking/transactions.md @@ -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 @@ -19,7 +19,7 @@ Other notes: - `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and modify objects from the store - `sdk.Dec` refers to a decimal type specified by the SDK. - + ### TxCreateValidator - triggers: `distribution.CreateValidatorDistribution` @@ -28,39 +28,39 @@ 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.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 { @@ -68,34 +68,34 @@ type TxEditCandidacy struct { 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 @@ -206,20 +206,20 @@ type TxRedelegate struct { 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 diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index dc3bf147f..1af796b37 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -31,8 +31,13 @@ Don't use more `steak` thank you have! You can always get more by using the [Fau ```bash gaiacli stake create-validator \ --amount=5steak \ +<<<<<<< HEAD --pubkey=$(gaiad tendermint show-validator) \ --address-validator= +======= + --pubkey=$(gaiad tendermint show_validator) \ + --validator= +>>>>>>> 6f19f2ed... Rename --address-validator flag to --validator --moniker="choose a moniker" \ --chain-id=gaia-7005 \ --name= @@ -46,7 +51,7 @@ The `--identity` can be used as to verify identity with systems like Keybase or ```bash gaiacli stake edit-validator - --address-validator= + --validator= --moniker="choose a moniker" \ --website="https://cosmos.network" \ --identity=6A0D65E29A4CBC8E @@ -61,8 +66,13 @@ View the validator's information with this command: ```bash gaiacli stake validator \ +<<<<<<< HEAD --address-validator= \ --chain-id=gaia-7005 +======= + --validator= \ + --chain-id=gaia-6002 +>>>>>>> 6f19f2ed... Rename --address-validator flag to --validator ``` ### Confirm Your Validator is Running diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index 789a1cb6a..f76f14803 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -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 } diff --git a/types/stake.go b/types/stake.go index acd24a154..ef7388f3b 100644 --- a/types/stake.go +++ b/types/stake.go @@ -40,7 +40,7 @@ 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() Dec // validation power GetTokens() Dec // validation tokens diff --git a/x/gov/tally.go b/x/gov/tally.go index fc5b4317b..d8d4c7870 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -24,8 +24,8 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall 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.ZeroDec(), diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 1e6a4e89d..e018c43e8 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -107,7 +107,7 @@ 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.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) unrevokeMsg := MsgUnrevoke{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())} diff --git a/x/slashing/client/cli/flags.go b/x/slashing/client/cli/flags.go index 43f8fa90a..09db8e825 100644 --- a/x/slashing/client/cli/flags.go +++ b/x/slashing/client/cli/flags.go @@ -2,5 +2,5 @@ package cli // nolint const ( - FlagAddressValidator = "address-validator" + FlagAddressValidator = "validator" ) diff --git a/x/stake/app_test.go b/x/stake/app_test.go index 9847ed290..65c64fdef 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -136,7 +136,7 @@ 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.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) @@ -148,7 +148,7 @@ 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.DecEq(t, sdk.NewDec(10), validator.Tokens)) diff --git a/x/stake/client/cli/flags.go b/x/stake/client/cli/flags.go index 3d5e90b35..d0e83ab3c 100644 --- a/x/stake/client/cli/flags.go +++ b/x/stake/client/cli/flags.go @@ -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" diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 4dfaa0f7f..036a3b451 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -114,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) @@ -400,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 { diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index a06be0f88..9ff72090e 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -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.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,7 +160,7 @@ 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.DecEq(t, sdk.NewDec(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) @@ -180,7 +180,7 @@ 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.DecEq(t, sdk.NewDec(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) diff --git a/x/stake/keeper/_store.md b/x/stake/keeper/_store.md index 1c95ffe87..818b17ac0 100644 --- a/x/stake/keeper/_store.md +++ b/x/stake/keeper/_store.md @@ -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 diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 4b4d267aa..4256df4b5 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -221,11 +221,11 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt 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, + ValidatorAddr: validator.Operator, Shares: sdk.ZeroDec(), } } @@ -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 diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index c1fabe441..471886c26 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -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() { @@ -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! diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index ce5a19061..5f880ebab 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -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) } } @@ -307,7 +307,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato panic("failed to create valid validator power iterator") } - 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, set the new cliff // validator to the affected validator. @@ -365,7 +365,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 } @@ -407,7 +407,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 @@ -462,7 +462,7 @@ func (k Keeper) UpdateBondedValidators( // bond the new validator validator = k.bondValidator(ctx, validatorToBond) - if bytes.Equal(validator.Owner, affectedValidator.Owner) { + if bytes.Equal(validator.Operator, affectedValidator.Operator) { return validator, true } } @@ -572,10 +572,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 } @@ -596,11 +596,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 } @@ -623,10 +623,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) @@ -651,7 +651,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 diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index 7b15a9c7f..7f17b391b 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -128,7 +128,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) @@ -141,7 +141,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) } @@ -240,7 +240,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) } @@ -269,11 +269,11 @@ func GetValidatorSortingUnmixed(t *testing.T) { 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].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, 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.NewDec(500) @@ -380,11 +380,11 @@ func GetValidatorSortingMixed(t *testing.T) { 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].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, 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 @@ -409,7 +409,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { validators[i] = keeper.UpdateValidator(ctx, validators[i]) } 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) @@ -433,7 +433,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) @@ -460,7 +460,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) } @@ -530,7 +530,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) @@ -603,8 +603,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)) diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index bd7d76993..7f40c57f5 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -20,9 +20,9 @@ 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.Dec `json:"tokens"` // delegated tokens (incl. self-delegation) @@ -43,9 +43,9 @@ type Validator struct { } // 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, @@ -103,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) } @@ -113,8 +113,8 @@ 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) { - if len(ownerAddr) != sdk.AddrLen { +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 } @@ -125,7 +125,7 @@ func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) (validator Val } return Validator{ - Owner: ownerAddr, + Operator: operatorAddr, PubKey: storeValue.PubKey, Revoked: storeValue.Revoked, Tokens: storeValue.Tokens, @@ -144,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) @@ -153,7 +153,7 @@ 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)) @@ -175,9 +175,9 @@ 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.Dec `json:"tokens"` // delegated tokens (incl. self-delegation) @@ -205,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, @@ -233,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) && @@ -430,7 +430,7 @@ 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.Dec { return v.BondedTokens() } func (v Validator) GetTokens() sdk.Dec { return v.Tokens } diff --git a/x/stake/types/validator_test.go b/x/stake/types/validator_test.go index 3981f5754..f4c874057 100644 --- a/x/stake/types/validator_test.go +++ b/x/stake/types/validator_test.go @@ -72,7 +72,7 @@ func TestABCIValidatorZero(t *testing.T) { func TestRemoveTokens(t *testing.T) { validator := Validator{ - Owner: addr1, + Operator: addr1, PubKey: pk1, Status: sdk.Bonded, Tokens: sdk.NewDec(100), @@ -148,7 +148,7 @@ func TestAddTokensValidatorUnbonded(t *testing.T) { // 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.NewDec(100), @@ -176,7 +176,7 @@ func TestRemoveDelShares(t *testing.T) { poolTokens := sdk.NewDec(5102) delShares := sdk.NewDec(115) validator := Validator{ - Owner: addr1, + Operator: addr1, PubKey: pk1, Status: sdk.Bonded, Tokens: poolTokens, @@ -229,7 +229,7 @@ func TestPossibleOverflow(t *testing.T) { 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, From bce09055b2b66f4ba6c81d6e1bc67d7f27793beb Mon Sep 17 00:00:00 2001 From: Max Levy <35595512+maxim-levy@users.noreply.github.com> Date: Fri, 17 Aug 2018 05:56:15 +0900 Subject: [PATCH 19/19] Merge PR #2058: comment fix An outdated comment fixed to be less confusing. --- examples/basecoin/types/account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/basecoin/types/account.go b/examples/basecoin/types/account.go index 671494311..45774ae43 100644 --- a/examples/basecoin/types/account.go +++ b/examples/basecoin/types/account.go @@ -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